pax_global_header00006660000000000000000000000064135551254320014517gustar00rootroot0000000000000052 comment=bfb35bc73a8f97614bb4b64c319f68d20c1c6ddb pvr.hts-4.4.20-Leia/000077500000000000000000000000001355512543200140625ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/.gitignore000066400000000000000000000006521355512543200160550ustar00rootroot00000000000000# build artifacts build/ debian/changelog debian/files debian/kodi-pvr-hts-dbg.debhelper.log debian/kodi-pvr-hts-dbg.substvars debian/kodi-pvr-hts-dbg/ debian/kodi-pvr-hts.debhelper.log debian/kodi-pvr-hts.postinst.debhelper debian/kodi-pvr-hts.postrm.debhelper debian/kodi-pvr-hts.substvars debian/kodi-pvr-hts/ debian/tmp/ obj-x86_64-linux-gnu/ pvr.hts/addon.xml # clion .idea/ # Eclipse/CDT .cproject .project .settings/ pvr.hts-4.4.20-Leia/.travis.yml000066400000000000000000000022201355512543200161670ustar00rootroot00000000000000language: 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.hts 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.hts-4.4.20-Leia/CMakeLists.txt000066400000000000000000000103351355512543200166240ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.5) project(pvr.hts) find_package(Kodi REQUIRED) find_package(kodiplatform REQUIRED) find_package(p8-platform REQUIRED) include_directories(${kodiplatform_INCLUDE_DIRS} ${p8-platform_INCLUDE_DIRS} ${KODI_INCLUDE_DIR}/.. # Hack way with "/..", need bigger Kodi cmake rework to match right include ways ${PROJECT_SOURCE_DIR}/lib) add_definitions(-DUSE_DEMUX) # Sources and headers set(HTS_SOURCES src/client.h src/client.cpp src/Tvheadend.cpp src/Tvheadend.h) set(HTS_SOURCES_TVHEADEND src/tvheadend/AutoRecordings.cpp src/tvheadend/AutoRecordings.h src/tvheadend/ChannelTuningPredictor.h src/tvheadend/ChannelTuningPredictor.cpp src/tvheadend/HTSPConnection.h src/tvheadend/HTSPConnection.cpp src/tvheadend/HTSPDemuxer.h src/tvheadend/HTSPDemuxer.cpp src/tvheadend/HTSPMessage.h src/tvheadend/HTSPTypes.h src/tvheadend/HTSPVFS.h src/tvheadend/HTSPVFS.cpp src/tvheadend/IHTSPConnectionListener.h src/tvheadend/Profile.h src/tvheadend/Settings.cpp src/tvheadend/Settings.h src/tvheadend/Subscription.cpp src/tvheadend/Subscription.h src/tvheadend/TimeRecordings.cpp src/tvheadend/TimeRecordings.h src/tvheadend/xbmc_codec_descriptor.hpp) set(HTS_SOURCES_TVHEADEND_ENTITY src/tvheadend/entity/AutoRecording.h src/tvheadend/entity/AutoRecording.cpp src/tvheadend/entity/Channel.h src/tvheadend/entity/Entity.h src/tvheadend/entity/Event.h src/tvheadend/entity/Event.cpp src/tvheadend/entity/Recording.h src/tvheadend/entity/RecordingBase.h src/tvheadend/entity/RecordingBase.cpp src/tvheadend/entity/Schedule.h src/tvheadend/entity/Schedule.cpp src/tvheadend/entity/Tag.h src/tvheadend/entity/Tag.cpp src/tvheadend/entity/TimeRecording.h src/tvheadend/entity/TimeRecording.cpp) set(HTS_SOURCES_TVHEADEND_STATUS src/tvheadend/status/DescrambleInfo.h src/tvheadend/status/DescrambleInfo.cpp src/tvheadend/status/Quality.h src/tvheadend/status/QueueStatus.h src/tvheadend/status/SourceInfo.h src/tvheadend/status/TimeshiftStatus.h) set(HTS_SOURCES_TVHEADEND_UTILITIES src/tvheadend/utilities/Utilities.h src/tvheadend/utilities/Logger.h src/tvheadend/utilities/Logger.cpp src/tvheadend/utilities/LocalizedString.h src/tvheadend/utilities/LifetimeMapper.h src/tvheadend/utilities/AsyncState.cpp src/tvheadend/utilities/AsyncState.h) source_group("Source Files" FILES ${HTS_SOURCES}) source_group("Source Files\\tvheadend" FILES ${HTS_SOURCES_TVHEADEND}) source_group("Source Files\\tvheadend\\entity" FILES ${HTS_SOURCES_TVHEADEND_ENTITY}) source_group("Source Files\\tvheadend\\status" FILES ${HTS_SOURCES_TVHEADEND_STATUS}) source_group("Source Files\\tvheadend\\utilities" FILES ${HTS_SOURCES_TVHEADEND_UTILITIES}) # Resource files set(HTS_RESOURCES README.md pvr.hts/addon.xml pvr.hts/changelog.txt pvr.hts/icon.png pvr.hts/resources/settings.xml pvr.hts/resources/language/resource.language.en_gb/strings.po) source_group("Resource Files" FILES ${HTS_RESOURCES}) # Combine the file lists list(APPEND HTS_SOURCES ${HTS_SOURCES_TVHEADEND} ${HTS_SOURCES_TVHEADEND_ENTITY} ${HTS_SOURCES_TVHEADEND_STATUS} ${HTS_SOURCES_TVHEADEND_UTILITIES}) add_subdirectory(lib/libhts) set(DEPLIBS ${p8-platform_LIBRARIES} hts) if(WIN32) list(APPEND DEPLIBS ws2_32) endif() build_addon(pvr.hts HTS DEPLIBS) include(CPack) pvr.hts-4.4.20-Leia/Jenkinsfile000066400000000000000000000000351355512543200162440ustar00rootroot00000000000000buildPlugin(version: "Leia") pvr.hts-4.4.20-Leia/README.md000066400000000000000000000032311355512543200153400ustar00rootroot00000000000000# Tvheadend PVR addon for Kodi This is a [Kodi](http://kodi.tv) PVR addon for connecting to a [tvheadend](https://tvheadend.org) backend. [![Build Status](https://travis-ci.org/kodi-pvr/pvr.hts.svg?branch=master)](https://travis-ci.org/kodi-pvr/pvr.hts) [![Build status](https://ci.appveyor.com/api/projects/status/9mh6hi08j00pto6x?svg=true)](https://ci.appveyor.com/project/MartijnKaijser/pvr-hts) [![Coverity Scan Build Status](https://scan.coverity.com/projects/5120/badge.svg)](https://scan.coverity.com/projects/5120) ## Build instructions When building the addon you have to use the correct branch depending on which version of Kodi you're building against. For example, if you're building the `Jarvis` branch of Kodi you should checkout the `Jarvis` branch of this repository. Also make sure you follow this README from the branch in question. ### Linux The following instructions assume you will have built Kodi already in the `kodi-build` directory suggested by the README. 1. `git clone --branch Leia https://github.com/xbmc/xbmc.git` 2. `git clone https://github.com/kodi-pvr/pvr.hts.git` 3. `cd pvr.hts && mkdir build && cd build` 4. `cmake -DADDONS_TO_BUILD=pvr.hts -DADDON_SRC_PREFIX=../.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=../../xbmc/kodi-build/addons -DPACKAGE_ZIP=1 ../../xbmc/cmake/addons` 5. `make` The addon files will be placed in `../../xbmc/kodi-build/addons` so if you build Kodi from source and run it directly the addon will be available as a system addon. ##### Useful links * [Kodi's PVR user support] (http://forum.kodi.tv/forumdisplay.php?fid=167) * [Kodi's PVR development support] (http://forum.kodi.tv/forumdisplay.php?fid=136) pvr.hts-4.4.20-Leia/appveyor.yml000066400000000000000000000023631355512543200164560ustar00rootroot00000000000000version: BuildNr.{build} init: - ps: $commit = $env:appveyor_repo_commit.SubString(0,7) - ps: $timestamp = $env:appveyor_repo_commit_timestamp.SubString(0,10) - ps: Update-AppveyorBuild -Version ("{0}-{1}-{2}" -f $env:appveyor_repo_branch, $commit, $timestamp) image: Visual Studio 2015 shallow_clone: true clone_folder: c:\projects\pvr.hts environment: app_id: pvr.hts 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" 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.hts-4.4.20-Leia/debian/000077500000000000000000000000001355512543200153045ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/debian/changelog.in000066400000000000000000000002611355512543200175620ustar00rootroot00000000000000kodi-pvr-hts (#PACKAGEVERSION#-#TAGREV#~#DIST#) #DIST#; urgency=low [ kodi ] * autogenerated dummy changelog -- Nobody Sat, 01 Jun 2013 00:59:22 +0200 pvr.hts-4.4.20-Leia/debian/compat000066400000000000000000000000021355512543200165020ustar00rootroot000000000000009 pvr.hts-4.4.20-Leia/debian/control000066400000000000000000000017161355512543200167140ustar00rootroot00000000000000Source: kodi-pvr-hts Priority: extra Maintainer: Arne Morten Kvarving Build-Depends: debhelper (>= 9.0.0), cmake, libkodiplatform-dev (>= 16.0.0), kodi-addon-dev Standards-Version: 3.9.4 Section: libs Package: kodi-pvr-hts Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Replaces: kodi-pvr-tvheadend-hts (<< 2.2) Provides: kodi-pvr-hts, kodi-pvr-tvheadend-hts Breaks: kodi-pvr-tvheadend-hts (<< 2.2) Description: TVHeadEnd PVR for Kodi TVHeadEnd PVR for Kodi Package: kodi-pvr-hts-dbg Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: debugging symbols for TVHeadEnd PVR for Kodi debugging symbols for TVHeadEnd PVR for Kodi Package: kodi-pvr-tvheadend-hts Depends: kodi-pvr-hts, ${misc:Depends} Architecture: all Priority: extra Section: oldlibs Description: transitional dummy package This is a transitional dummy package. It can safely be removed. pvr.hts-4.4.20-Leia/debian/copyright000066400000000000000000000027451355512543200172470ustar00rootroot00000000000000Format: http://dep.debian.net/deps/dep5 Upstream-Name: pvr.hts Source: Files: * Copyright: License: . # If you want to use GPL v2 or later for the /debian/* files use # the following clauses, or change it to suit. Delete these two lines Files: debian/* Copyright: 2013 Arne Morten Kvarving 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". # Please also look if there are files or directories which have a # different copyright/license attached and list them here. pvr.hts-4.4.20-Leia/debian/kodi-pvr-hts.install000066400000000000000000000000261355512543200212210ustar00rootroot00000000000000usr/lib/* usr/share/* pvr.hts-4.4.20-Leia/debian/rules000077500000000000000000000012541355512543200163660ustar00rootroot00000000000000#!/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 override_dh_strip: dh_strip -pkodi-pvr-hts --dbg-package=kodi-pvr-hts-dbg override_dh_installdocs: dh_installdocs --link-doc=kodi-pvr-hts pvr.hts-4.4.20-Leia/debian/source/000077500000000000000000000000001355512543200166045ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/debian/source/format000066400000000000000000000000151355512543200200130ustar00rootroot000000000000003.0 (native) pvr.hts-4.4.20-Leia/lib/000077500000000000000000000000001355512543200146305ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/lib/libhts/000077500000000000000000000000001355512543200161155ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/lib/libhts/CMakeLists.txt000066400000000000000000000006741355512543200206640ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.5) PROJECT(hts) SET(SOURCES htsbuf.c htsmsg_binary.c htsmsg.c htsstr.c sha1.c) if(WIN32) LIST(APPEND SOURCES net_winsock.c) include_directories("${PROJECT_SOURCE_DIR}/Win32/include") else() LIST(APPEND SOURCES net_posix.c) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -fPIC") endif() ADD_DEFINITIONS(-D_GNU_SOURCE) ADD_LIBRARY(hts STATIC ${SOURCES}) pvr.hts-4.4.20-Leia/lib/libhts/OSXGNUReplacements.h000066400000000000000000000047131355512543200216610ustar00rootroot00000000000000#ifndef __OSXPLATFORM_H__ #define __OSXPLATFORM_H__ /* * Copyright (C) 2005-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 * */ // This is a catch all for GNU routines that do not exist under OSX. #include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ size_t strnlen(const char *s, size_t n); char* strndup(char const *s, size_t n); int gethostbyname_r(const char *name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result, int *h_errnop); #ifdef __cplusplus } #endif /* __cplusplus */ /* getdelim.h --- Prototype for replacement getdelim function. Copyright (C) 2005 Free Software Foundation, Inc. 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /* Written by Simon Josefsson. */ # include # include # include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ ssize_t getdelim(char **lineptr, size_t *n, int delimiter, FILE *stream); ssize_t getline (char **lineptr, size_t *n, FILE *stream); int strverscmp (const char *s1, const char *s2); #ifdef __cplusplus } #endif /* __cplusplus */ #endif pvr.hts-4.4.20-Leia/lib/libhts/Win32/000077500000000000000000000000001355512543200170175ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/lib/libhts/Win32/include/000077500000000000000000000000001355512543200204425ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/lib/libhts/Win32/include/getopt.h000066400000000000000000000054641355512543200221260ustar00rootroot00000000000000/* * Copyright (c) 1987, 1993, 1994, 1996 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef __GETOPT_H__ #define __GETOPT_H__ #ifdef __cplusplus extern "C" { #endif extern int opterr; /* if error message should be printed */ extern int optind; /* index into parent argv vector */ extern int optopt; /* character checked for validity */ extern int optreset; /* reset getopt */ extern char *optarg; /* argument associated with option */ int getopt (int, char * const *, const char *); #ifdef __cplusplus } #endif #endif /* __GETOPT_H__ */ #ifndef __UNISTD_GETOPT__ #ifndef __GETOPT_LONG_H__ #define __GETOPT_LONG_H__ #ifdef __cplusplus extern "C" { #endif struct option { const char *name; int has_arg; int *flag; int val; }; int getopt_long (int, char *const *, const char *, const struct option *, int *); #ifndef HAVE_DECL_GETOPT #define HAVE_DECL_GETOPT 1 #endif #define no_argument 0 #define required_argument 1 #define optional_argument 2 #ifdef __cplusplus } #endif #endif /* __GETOPT_LONG_H__ */ #endif /* __UNISTD_GETOPT__ */ pvr.hts-4.4.20-Leia/lib/libhts/Win32/include/inttypes.h000066400000000000000000000175171355512543200225050ustar00rootroot00000000000000// ISO C9x compliant inttypes.h for Microsoft Visual Studio // Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 // // Copyright (c) 2006 Alexander Chemeris // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. The name of the author may be used to endorse or promote products // derived from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; // OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // /////////////////////////////////////////////////////////////////////////////// #ifndef _MSC_VER // [ #error "Use this header only with Microsoft Visual C++ compilers!" #endif // _MSC_VER ] #ifndef _MSC_INTTYPES_H_ // [ #define _MSC_INTTYPES_H_ #if _MSC_VER > 1000 #pragma once #endif #include // 7.8 Format conversion of integer types typedef struct { intmax_t quot; intmax_t rem; } imaxdiv_t; // 7.8.1 Macros for format specifiers #if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198 // The fprintf macros for signed integers are: #define PRId8 "d" #define PRIi8 "i" #define PRIdLEAST8 "d" #define PRIiLEAST8 "i" #define PRIdFAST8 "d" #define PRIiFAST8 "i" #define PRId16 "hd" #define PRIi16 "hi" #define PRIdLEAST16 "hd" #define PRIiLEAST16 "hi" #define PRIdFAST16 "hd" #define PRIiFAST16 "hi" #define PRId32 "I32d" #define PRIi32 "I32i" #define PRIdLEAST32 "I32d" #define PRIiLEAST32 "I32i" #define PRIdFAST32 "I32d" #define PRIiFAST32 "I32i" #define PRId64 "I64d" #define PRIi64 "I64i" #define PRIdLEAST64 "I64d" #define PRIiLEAST64 "I64i" #define PRIdFAST64 "I64d" #define PRIiFAST64 "I64i" #define PRIdMAX "I64d" #define PRIiMAX "I64i" #define PRIdPTR "Id" #define PRIiPTR "Ii" // The fprintf macros for unsigned integers are: #define PRIo8 "o" #define PRIu8 "u" #define PRIx8 "x" #define PRIX8 "X" #define PRIoLEAST8 "o" #define PRIuLEAST8 "u" #define PRIxLEAST8 "x" #define PRIXLEAST8 "X" #define PRIoFAST8 "o" #define PRIuFAST8 "u" #define PRIxFAST8 "x" #define PRIXFAST8 "X" #define PRIo16 "ho" #define PRIu16 "hu" #define PRIx16 "hx" #define PRIX16 "hX" #define PRIoLEAST16 "ho" #define PRIuLEAST16 "hu" #define PRIxLEAST16 "hx" #define PRIXLEAST16 "hX" #define PRIoFAST16 "ho" #define PRIuFAST16 "hu" #define PRIxFAST16 "hx" #define PRIXFAST16 "hX" #define PRIo32 "I32o" #define PRIu32 "I32u" #define PRIx32 "I32x" #define PRIX32 "I32X" #define PRIoLEAST32 "I32o" #define PRIuLEAST32 "I32u" #define PRIxLEAST32 "I32x" #define PRIXLEAST32 "I32X" #define PRIoFAST32 "I32o" #define PRIuFAST32 "I32u" #define PRIxFAST32 "I32x" #define PRIXFAST32 "I32X" #define PRIo64 "I64o" #define PRIu64 "I64u" #define PRIx64 "I64x" #define PRIX64 "I64X" #define PRIoLEAST64 "I64o" #define PRIuLEAST64 "I64u" #define PRIxLEAST64 "I64x" #define PRIXLEAST64 "I64X" #define PRIoFAST64 "I64o" #define PRIuFAST64 "I64u" #define PRIxFAST64 "I64x" #define PRIXFAST64 "I64X" #define PRIoMAX "I64o" #define PRIuMAX "I64u" #define PRIxMAX "I64x" #define PRIXMAX "I64X" #define PRIoPTR "Io" #define PRIuPTR "Iu" #define PRIxPTR "Ix" #define PRIXPTR "IX" // The fscanf macros for signed integers are: #define SCNd8 "d" #define SCNi8 "i" #define SCNdLEAST8 "d" #define SCNiLEAST8 "i" #define SCNdFAST8 "d" #define SCNiFAST8 "i" #define SCNd16 "hd" #define SCNi16 "hi" #define SCNdLEAST16 "hd" #define SCNiLEAST16 "hi" #define SCNdFAST16 "hd" #define SCNiFAST16 "hi" #define SCNd32 "ld" #define SCNi32 "li" #define SCNdLEAST32 "ld" #define SCNiLEAST32 "li" #define SCNdFAST32 "ld" #define SCNiFAST32 "li" #define SCNd64 "I64d" #define SCNi64 "I64i" #define SCNdLEAST64 "I64d" #define SCNiLEAST64 "I64i" #define SCNdFAST64 "I64d" #define SCNiFAST64 "I64i" #define SCNdMAX "I64d" #define SCNiMAX "I64i" #ifdef _WIN64 // [ # define SCNdPTR "I64d" # define SCNiPTR "I64i" #else // _WIN64 ][ # define SCNdPTR "ld" # define SCNiPTR "li" #endif // _WIN64 ] // The fscanf macros for unsigned integers are: #define SCNo8 "o" #define SCNu8 "u" #define SCNx8 "x" #define SCNX8 "X" #define SCNoLEAST8 "o" #define SCNuLEAST8 "u" #define SCNxLEAST8 "x" #define SCNXLEAST8 "X" #define SCNoFAST8 "o" #define SCNuFAST8 "u" #define SCNxFAST8 "x" #define SCNXFAST8 "X" #define SCNo16 "ho" #define SCNu16 "hu" #define SCNx16 "hx" #define SCNX16 "hX" #define SCNoLEAST16 "ho" #define SCNuLEAST16 "hu" #define SCNxLEAST16 "hx" #define SCNXLEAST16 "hX" #define SCNoFAST16 "ho" #define SCNuFAST16 "hu" #define SCNxFAST16 "hx" #define SCNXFAST16 "hX" #define SCNo32 "lo" #define SCNu32 "lu" #define SCNx32 "lx" #define SCNX32 "lX" #define SCNoLEAST32 "lo" #define SCNuLEAST32 "lu" #define SCNxLEAST32 "lx" #define SCNXLEAST32 "lX" #define SCNoFAST32 "lo" #define SCNuFAST32 "lu" #define SCNxFAST32 "lx" #define SCNXFAST32 "lX" #define SCNo64 "I64o" #define SCNu64 "I64u" #define SCNx64 "I64x" #define SCNX64 "I64X" #define SCNoLEAST64 "I64o" #define SCNuLEAST64 "I64u" #define SCNxLEAST64 "I64x" #define SCNXLEAST64 "I64X" #define SCNoFAST64 "I64o" #define SCNuFAST64 "I64u" #define SCNxFAST64 "I64x" #define SCNXFAST64 "I64X" #define SCNoMAX "I64o" #define SCNuMAX "I64u" #define SCNxMAX "I64x" #define SCNXMAX "I64X" #ifdef _WIN64 // [ # define SCNoPTR "I64o" # define SCNuPTR "I64u" # define SCNxPTR "I64x" # define SCNXPTR "I64X" #else // _WIN64 ][ # define SCNoPTR "lo" # define SCNuPTR "lu" # define SCNxPTR "lx" # define SCNXPTR "lX" #endif // _WIN64 ] #endif // __STDC_FORMAT_MACROS ] // 7.8.2 Functions for greatest-width integer types // 7.8.2.1 The imaxabs function #define imaxabs _abs64 // 7.8.2.2 The imaxdiv function // This is modified version of div() function from Microsoft's div.c found // in %MSVC.NET%\crt\src\div.c #ifdef STATIC_IMAXDIV // [ static #else // STATIC_IMAXDIV ][ _inline #endif // STATIC_IMAXDIV ] imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) { imaxdiv_t result; result.quot = numer / denom; result.rem = numer % denom; if (numer < 0 && result.rem > 0) { // did division wrong; must fix up ++result.quot; result.rem -= denom; } return result; } // 7.8.2.3 The strtoimax and strtoumax functions #define strtoimax _strtoi64 #define strtoumax _strtoui64 // 7.8.2.4 The wcstoimax and wcstoumax functions #define wcstoimax _wcstoi64 #define wcstoumax _wcstoui64 #define ssize_t int #endif // _MSC_INTTYPES_H_ ] pvr.hts-4.4.20-Leia/lib/libhts/Win32/include/msvc.h000066400000000000000000000011231355512543200215600ustar00rootroot00000000000000#ifdef WIN32 #define strtoll(p, e, b) _strtoi64(p, e, b) #define snprintf _snprintf #define strcasecmp stricmp #define strncasecmp strnicmp #define strdup _strdup #if _MSC_VER < 1500 #define vsnprintf _vsnprintf #endif static char * strndup(const char* str, size_t len) { size_t i = 0; char* p = (char*)str; while(*p != 0 && i < len) { p++; i++; } p = malloc(len+1); memcpy(p, str, len); p[len] = 0; return p; } #ifndef M_PI #define M_PI 3.1415926535897932384626433832795 #endif #define S_IFREG 0100000 #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif pvr.hts-4.4.20-Leia/lib/libhts/Win32/include/sys/000077500000000000000000000000001355512543200212605ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/lib/libhts/Win32/include/sys/queue.h000066400000000000000000000461221355512543200225620ustar00rootroot00000000000000/* * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)queue.h 8.5 (Berkeley) 8/20/94 */ #ifndef _SYS_QUEUE_H_ #define _SYS_QUEUE_H_ /* * This file defines five types of data structures: singly-linked lists, * lists, simple queues, tail queues, and circular queues. * * A singly-linked list is headed by a single forward pointer. The * elements are singly linked for minimum space and pointer manipulation * overhead at the expense of O(n) removal for arbitrary elements. New * elements can be added to the list after an existing element or at the * head of the list. Elements being removed from the head of the list * should use the explicit macro for this purpose for optimum * efficiency. A singly-linked list may only be traversed in the forward * direction. Singly-linked lists are ideal for applications with large * datasets and few or no removals or for implementing a LIFO queue. * * A list is headed by a single forward pointer (or an array of forward * pointers for a hash table header). The elements are doubly linked * so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before * or after an existing element or at the head of the list. A list * may only be traversed in the forward direction. * * A simple queue is headed by a pair of pointers, one the head of the * list and the other to the tail of the list. The elements are singly * linked to save space, so elements can only be removed from the * head of the list. New elements can be added to the list after * an existing element, at the head of the list, or at the end of the * list. A simple queue may only be traversed in the forward direction. * * A tail queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly * linked so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before or * after an existing element, at the head of the list, or at the end of * the list. A tail queue may be traversed in either direction. * * A circle queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly * linked so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before or after * an existing element, at the head of the list, or at the end of the list. * A circle queue may be traversed in either direction, but has a more * complex end of list detection. * * For details on the use of these macros, see the queue(3) manual page. */ /* * List definitions. */ #define LIST_HEAD(name, type) \ struct name { \ struct type *lh_first; /* first element */ \ } #define LIST_HEAD_INITIALIZER(head) \ { NULL } #define LIST_ENTRY(type) \ struct { \ struct type *le_next; /* next element */ \ struct type **le_prev; /* address of previous next element */ \ } /* * List functions. */ #define LIST_INIT(head) do { \ (head)->lh_first = NULL; \ } while (/*CONSTCOND*/0) #define LIST_INSERT_AFTER(listelm, elm, field) do { \ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ (listelm)->field.le_next->field.le_prev = \ &(elm)->field.le_next; \ (listelm)->field.le_next = (elm); \ (elm)->field.le_prev = &(listelm)->field.le_next; \ } while (/*CONSTCOND*/0) #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.le_prev = (listelm)->field.le_prev; \ (elm)->field.le_next = (listelm); \ *(listelm)->field.le_prev = (elm); \ (listelm)->field.le_prev = &(elm)->field.le_next; \ } while (/*CONSTCOND*/0) #define LIST_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.le_next = (head)->lh_first) != NULL) \ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ (head)->lh_first = (elm); \ (elm)->field.le_prev = &(head)->lh_first; \ } while (/*CONSTCOND*/0) #define LIST_REMOVE(elm, field) do { \ if ((elm)->field.le_next != NULL) \ (elm)->field.le_next->field.le_prev = \ (elm)->field.le_prev; \ *(elm)->field.le_prev = (elm)->field.le_next; \ } while (/*CONSTCOND*/0) #define LIST_FOREACH(var, head, field) \ for ((var) = ((head)->lh_first); \ (var); \ (var) = ((var)->field.le_next)) /* * List access methods. */ #define LIST_EMPTY(head) ((head)->lh_first == NULL) #define LIST_FIRST(head) ((head)->lh_first) #define LIST_NEXT(elm, field) ((elm)->field.le_next) /* * Singly-linked List definitions. */ #define SLIST_HEAD(name, type) \ struct name { \ struct type *slh_first; /* first element */ \ } #define SLIST_HEAD_INITIALIZER(head) \ { NULL } #define SLIST_ENTRY(type) \ struct { \ struct type *sle_next; /* next element */ \ } /* * Singly-linked List functions. */ #define SLIST_INIT(head) do { \ (head)->slh_first = NULL; \ } while (/*CONSTCOND*/0) #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ (elm)->field.sle_next = (slistelm)->field.sle_next; \ (slistelm)->field.sle_next = (elm); \ } while (/*CONSTCOND*/0) #define SLIST_INSERT_HEAD(head, elm, field) do { \ (elm)->field.sle_next = (head)->slh_first; \ (head)->slh_first = (elm); \ } while (/*CONSTCOND*/0) #define SLIST_REMOVE_HEAD(head, field) do { \ (head)->slh_first = (head)->slh_first->field.sle_next; \ } while (/*CONSTCOND*/0) #define SLIST_REMOVE(head, elm, type, field) do { \ if ((head)->slh_first == (elm)) { \ SLIST_REMOVE_HEAD((head), field); \ } \ else { \ struct type *curelm = (head)->slh_first; \ while(curelm->field.sle_next != (elm)) \ curelm = curelm->field.sle_next; \ curelm->field.sle_next = \ curelm->field.sle_next->field.sle_next; \ } \ } while (/*CONSTCOND*/0) #define SLIST_FOREACH(var, head, field) \ for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) /* * Singly-linked List access methods. */ #define SLIST_EMPTY(head) ((head)->slh_first == NULL) #define SLIST_FIRST(head) ((head)->slh_first) #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) /* * Singly-linked Tail queue declarations. */ #define STAILQ_HEAD(name, type) \ struct name { \ struct type *stqh_first; /* first element */ \ struct type **stqh_last; /* addr of last next element */ \ } #define STAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).stqh_first } #define STAILQ_ENTRY(type) \ struct { \ struct type *stqe_next; /* next element */ \ } /* * Singly-linked Tail queue functions. */ #define STAILQ_INIT(head) do { \ (head)->stqh_first = NULL; \ (head)->stqh_last = &(head)->stqh_first; \ } while (/*CONSTCOND*/0) #define STAILQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \ (head)->stqh_last = &(elm)->field.stqe_next; \ (head)->stqh_first = (elm); \ } while (/*CONSTCOND*/0) #define STAILQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.stqe_next = NULL; \ *(head)->stqh_last = (elm); \ (head)->stqh_last = &(elm)->field.stqe_next; \ } while (/*CONSTCOND*/0) #define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\ (head)->stqh_last = &(elm)->field.stqe_next; \ (listelm)->field.stqe_next = (elm); \ } while (/*CONSTCOND*/0) #define STAILQ_REMOVE_HEAD(head, field) do { \ if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \ (head)->stqh_last = &(head)->stqh_first; \ } while (/*CONSTCOND*/0) #define STAILQ_REMOVE(head, elm, type, field) do { \ if ((head)->stqh_first == (elm)) { \ STAILQ_REMOVE_HEAD((head), field); \ } else { \ struct type *curelm = (head)->stqh_first; \ while (curelm->field.stqe_next != (elm)) \ curelm = curelm->field.stqe_next; \ if ((curelm->field.stqe_next = \ curelm->field.stqe_next->field.stqe_next) == NULL) \ (head)->stqh_last = &(curelm)->field.stqe_next; \ } \ } while (/*CONSTCOND*/0) #define STAILQ_FOREACH(var, head, field) \ for ((var) = ((head)->stqh_first); \ (var); \ (var) = ((var)->field.stqe_next)) #define STAILQ_CONCAT(head1, head2) do { \ if (!STAILQ_EMPTY((head2))) { \ *(head1)->stqh_last = (head2)->stqh_first; \ (head1)->stqh_last = (head2)->stqh_last; \ STAILQ_INIT((head2)); \ } \ } while (/*CONSTCOND*/0) /* * Singly-linked Tail queue access methods. */ #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) #define STAILQ_FIRST(head) ((head)->stqh_first) #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) /* * Simple queue definitions. */ #define SIMPLEQ_HEAD(name, type) \ struct name { \ struct type *sqh_first; /* first element */ \ struct type **sqh_last; /* addr of last next element */ \ } #define SIMPLEQ_HEAD_INITIALIZER(head) \ { NULL, &(head).sqh_first } #define SIMPLEQ_ENTRY(type) \ struct { \ struct type *sqe_next; /* next element */ \ } /* * Simple queue functions. */ #define SIMPLEQ_INIT(head) do { \ (head)->sqh_first = NULL; \ (head)->sqh_last = &(head)->sqh_first; \ } while (/*CONSTCOND*/0) #define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ (head)->sqh_last = &(elm)->field.sqe_next; \ (head)->sqh_first = (elm); \ } while (/*CONSTCOND*/0) #define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.sqe_next = NULL; \ *(head)->sqh_last = (elm); \ (head)->sqh_last = &(elm)->field.sqe_next; \ } while (/*CONSTCOND*/0) #define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ (head)->sqh_last = &(elm)->field.sqe_next; \ (listelm)->field.sqe_next = (elm); \ } while (/*CONSTCOND*/0) #define SIMPLEQ_REMOVE_HEAD(head, field) do { \ if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ (head)->sqh_last = &(head)->sqh_first; \ } while (/*CONSTCOND*/0) #define SIMPLEQ_REMOVE(head, elm, type, field) do { \ if ((head)->sqh_first == (elm)) { \ SIMPLEQ_REMOVE_HEAD((head), field); \ } else { \ struct type *curelm = (head)->sqh_first; \ while (curelm->field.sqe_next != (elm)) \ curelm = curelm->field.sqe_next; \ if ((curelm->field.sqe_next = \ curelm->field.sqe_next->field.sqe_next) == NULL) \ (head)->sqh_last = &(curelm)->field.sqe_next; \ } \ } while (/*CONSTCOND*/0) #define SIMPLEQ_FOREACH(var, head, field) \ for ((var) = ((head)->sqh_first); \ (var); \ (var) = ((var)->field.sqe_next)) /* * Simple queue access methods. */ #define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL) #define SIMPLEQ_FIRST(head) ((head)->sqh_first) #define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) /* * Tail queue definitions. */ #define _TAILQ_HEAD(name, type, qual) \ struct name { \ qual type *tqh_first; /* first element */ \ qual type *qual *tqh_last; /* addr of last next element */ \ } #define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,) #define TAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).tqh_first } #define _TAILQ_ENTRY(type, qual) \ struct { \ qual type *tqe_next; /* next element */ \ qual type *qual *tqe_prev; /* address of previous next element */\ } #define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,) /* * Tail queue functions. */ #define TAILQ_INIT(head) do { \ (head)->tqh_first = NULL; \ (head)->tqh_last = &(head)->tqh_first; \ } while (/*CONSTCOND*/0) #define TAILQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ (head)->tqh_first->field.tqe_prev = \ &(elm)->field.tqe_next; \ else \ (head)->tqh_last = &(elm)->field.tqe_next; \ (head)->tqh_first = (elm); \ (elm)->field.tqe_prev = &(head)->tqh_first; \ } while (/*CONSTCOND*/0) #define TAILQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.tqe_next = NULL; \ (elm)->field.tqe_prev = (head)->tqh_last; \ *(head)->tqh_last = (elm); \ (head)->tqh_last = &(elm)->field.tqe_next; \ } while (/*CONSTCOND*/0) #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ (elm)->field.tqe_next->field.tqe_prev = \ &(elm)->field.tqe_next; \ else \ (head)->tqh_last = &(elm)->field.tqe_next; \ (listelm)->field.tqe_next = (elm); \ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ } while (/*CONSTCOND*/0) #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ (elm)->field.tqe_next = (listelm); \ *(listelm)->field.tqe_prev = (elm); \ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ } while (/*CONSTCOND*/0) #define TAILQ_REMOVE(head, elm, field) do { \ if (((elm)->field.tqe_next) != NULL) \ (elm)->field.tqe_next->field.tqe_prev = \ (elm)->field.tqe_prev; \ else \ (head)->tqh_last = (elm)->field.tqe_prev; \ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ } while (/*CONSTCOND*/0) #define TAILQ_FOREACH(var, head, field) \ for ((var) = ((head)->tqh_first); \ (var); \ (var) = ((var)->field.tqe_next)) #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ (var); \ (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) #define TAILQ_CONCAT(head1, head2, field) do { \ if (!TAILQ_EMPTY(head2)) { \ *(head1)->tqh_last = (head2)->tqh_first; \ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ (head1)->tqh_last = (head2)->tqh_last; \ TAILQ_INIT((head2)); \ } \ } while (/*CONSTCOND*/0) /* * Tail queue access methods. */ #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) #define TAILQ_FIRST(head) ((head)->tqh_first) #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) #define TAILQ_LAST(head, headname) \ (*(((struct headname *)((head)->tqh_last))->tqh_last)) #define TAILQ_PREV(elm, headname, field) \ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) /* * Circular queue definitions. */ #define CIRCLEQ_HEAD(name, type) \ struct name { \ struct type *cqh_first; /* first element */ \ struct type *cqh_last; /* last element */ \ } #define CIRCLEQ_HEAD_INITIALIZER(head) \ { (void *)&head, (void *)&head } #define CIRCLEQ_ENTRY(type) \ struct { \ struct type *cqe_next; /* next element */ \ struct type *cqe_prev; /* previous element */ \ } /* * Circular queue functions. */ #define CIRCLEQ_INIT(head) do { \ (head)->cqh_first = (void *)(head); \ (head)->cqh_last = (void *)(head); \ } while (/*CONSTCOND*/0) #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ (elm)->field.cqe_next = (listelm)->field.cqe_next; \ (elm)->field.cqe_prev = (listelm); \ if ((listelm)->field.cqe_next == (void *)(head)) \ (head)->cqh_last = (elm); \ else \ (listelm)->field.cqe_next->field.cqe_prev = (elm); \ (listelm)->field.cqe_next = (elm); \ } while (/*CONSTCOND*/0) #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ (elm)->field.cqe_next = (listelm); \ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ if ((listelm)->field.cqe_prev == (void *)(head)) \ (head)->cqh_first = (elm); \ else \ (listelm)->field.cqe_prev->field.cqe_next = (elm); \ (listelm)->field.cqe_prev = (elm); \ } while (/*CONSTCOND*/0) #define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ (elm)->field.cqe_next = (head)->cqh_first; \ (elm)->field.cqe_prev = (void *)(head); \ if ((head)->cqh_last == (void *)(head)) \ (head)->cqh_last = (elm); \ else \ (head)->cqh_first->field.cqe_prev = (elm); \ (head)->cqh_first = (elm); \ } while (/*CONSTCOND*/0) #define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.cqe_next = (void *)(head); \ (elm)->field.cqe_prev = (head)->cqh_last; \ if ((head)->cqh_first == (void *)(head)) \ (head)->cqh_first = (elm); \ else \ (head)->cqh_last->field.cqe_next = (elm); \ (head)->cqh_last = (elm); \ } while (/*CONSTCOND*/0) #define CIRCLEQ_REMOVE(head, elm, field) do { \ if ((elm)->field.cqe_next == (void *)(head)) \ (head)->cqh_last = (elm)->field.cqe_prev; \ else \ (elm)->field.cqe_next->field.cqe_prev = \ (elm)->field.cqe_prev; \ if ((elm)->field.cqe_prev == (void *)(head)) \ (head)->cqh_first = (elm)->field.cqe_next; \ else \ (elm)->field.cqe_prev->field.cqe_next = \ (elm)->field.cqe_next; \ } while (/*CONSTCOND*/0) #define CIRCLEQ_FOREACH(var, head, field) \ for ((var) = ((head)->cqh_first); \ (var) != (const void *)(head); \ (var) = ((var)->field.cqe_next)) #define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ for ((var) = ((head)->cqh_last); \ (var) != (const void *)(head); \ (var) = ((var)->field.cqe_prev)) /* * Circular queue access methods. */ #define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) #define CIRCLEQ_FIRST(head) ((head)->cqh_first) #define CIRCLEQ_LAST(head) ((head)->cqh_last) #define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) #define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) #define CIRCLEQ_LOOP_NEXT(head, elm, field) \ (((elm)->field.cqe_next == (void *)(head)) \ ? ((head)->cqh_first) \ : (elm->field.cqe_next)) #define CIRCLEQ_LOOP_PREV(head, elm, field) \ (((elm)->field.cqe_prev == (void *)(head)) \ ? ((head)->cqh_last) \ : (elm->field.cqe_prev)) #endif /* sys/queue.h */pvr.hts-4.4.20-Leia/lib/libhts/Win32/include/unistd.h000066400000000000000000000013311355512543200221170ustar00rootroot00000000000000/* * This file is part of the Mingw32 package. * * unistd.h maps (roughly) to io.h */ #ifndef _UNISTD_H #define _UNISTD_H #include #include #define __UNISTD_GETOPT__ #include #undef __UNISTD_GETOPT__ /* These are also defined in stdio.h. */ #ifndef SEEK_SET #define SEEK_SET 0 #endif #ifndef SEEK_CUR #define SEEK_CUR 1 #endif #ifndef SEEK_END #define SEEK_END 2 #endif #ifdef __cplusplus extern "C" { #endif /* This is defined as a real library function to allow autoconf to verify its existence. */ //int ftruncate(int, off_t); //__CRT_INLINE int ftruncate(int __fd, off_t __length) //{ // return _chsize (__fd, __length); //} #ifdef __cplusplus } #endif #endif /* _UNISTD_H */ pvr.hts-4.4.20-Leia/lib/libhts/Win32/libhts_2010.vcxproj000066400000000000000000000113601355512543200223640ustar00rootroot00000000000000 Debug Win32 Release Win32 libhts {00700E12-A63B-4E54-B962-4011A90584BD} libhts Win32Proj StaticLibrary Unicode true StaticLibrary Unicode <_ProjectFileVersion>10.0.30319.1 $(SolutionDir)libs\$(TargetName)\$(Configuration)\ $(SolutionDir)objs\$(TargetName)\$(Configuration)\ $(SolutionDir)libs\$(TargetName)\$(Configuration)\ $(SolutionDir)objs\$(TargetName)\$(Configuration)\ Disabled $(ProjectDir)include;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreadedDebug Level3 EditAndContinue true %(IgnoreSpecificDefaultLibraries) MaxSpeed true $(ProjectDir)include;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) MultiThreaded true Level3 ProgramDatabase StreamingSIMDExtensions true pvr.hts-4.4.20-Leia/lib/libhts/Win32/libhts_2010.vcxproj.filters000066400000000000000000000034271355512543200240400ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files pvr.hts-4.4.20-Leia/lib/libhts/hts_strtab.h000066400000000000000000000031221355512543200204410ustar00rootroot00000000000000/* * tvheadend * Copyright (C) 2007 Andreas man * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef STRTAB_H_ #define STRTAB_H_ #include struct strtab { const char *str; int val; }; static int str2val0(const char *str, struct strtab tab[], int l) __attribute((unused)); static int str2val0(const char *str, struct strtab tab[], int l) { int i; for(i = 0; i < l; i++) if(!strcasecmp(str, tab[i].str)) return tab[i].val; return -1; } #define str2val(str, tab) str2val0(str, tab, sizeof(tab) / sizeof(tab[0])) static const char * val2str0(int val, struct strtab tab[], int l) __attribute__((unused)); static const char * val2str0(int val, struct strtab tab[], int l) { int i; for(i = 0; i < l; i++) if(tab[i].val == val) return tab[i].str; return NULL; } #define val2str(val, tab) val2str0(val, tab, sizeof(tab) / sizeof(tab[0])) #endif /* STRTAB_H_ */ pvr.hts-4.4.20-Leia/lib/libhts/htsbuf.c000066400000000000000000000110301355512543200175470ustar00rootroot00000000000000/* * Buffer management functions * Copyright (C) 2008 Andreas man * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include "htsbuf.h" #ifdef _MSC_VER #include "msvc.h" #endif #ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif #ifndef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif /** * */ void htsbuf_queue_init(htsbuf_queue_t *hq, unsigned int maxsize) { if(maxsize == 0) maxsize = INT32_MAX; TAILQ_INIT(&hq->hq_q); hq->hq_size = 0; hq->hq_maxsize = maxsize; } /** * */ void htsbuf_data_free(htsbuf_queue_t *hq, htsbuf_data_t *hd) { TAILQ_REMOVE(&hq->hq_q, hd, hd_link); free(hd->hd_data); free(hd); } /** * */ void htsbuf_queue_flush(htsbuf_queue_t *hq) { htsbuf_data_t *hd; hq->hq_size = 0; while((hd = TAILQ_FIRST(&hq->hq_q)) != NULL) htsbuf_data_free(hq, hd); } /** * */ void htsbuf_append(htsbuf_queue_t *hq, const char *buf, size_t len) { htsbuf_data_t *hd = TAILQ_LAST(&hq->hq_q, htsbuf_data_queue); int c; hq->hq_size += len; if(hd != NULL) { /* Fill out any previous buffer */ c = MIN(hd->hd_data_size - hd->hd_data_len, len); memcpy(hd->hd_data + hd->hd_data_len, buf, c); hd->hd_data_len += c; buf += c; len -= c; } if(len == 0) return; hd = malloc(sizeof(htsbuf_data_t)); TAILQ_INSERT_TAIL(&hq->hq_q, hd, hd_link); c = MAX(len, 1000); /* Allocate 1000 bytes to support lots of small writes */ hd->hd_data = malloc(c); hd->hd_data_size = c; hd->hd_data_len = len; hd->hd_data_off = 0; memcpy(hd->hd_data, buf, len); } /** * */ void htsbuf_append_prealloc(htsbuf_queue_t *hq, const char *buf, size_t len) { htsbuf_data_t *hd; hq->hq_size += len; hd = malloc(sizeof(htsbuf_data_t)); TAILQ_INSERT_TAIL(&hq->hq_q, hd, hd_link); hd->hd_data = (void *)buf; hd->hd_data_size = len; hd->hd_data_len = len; hd->hd_data_off = 0; } /** * */ size_t htsbuf_read(htsbuf_queue_t *hq, char *buf, size_t len) { size_t r = 0; int c; htsbuf_data_t *hd; while(len > 0) { hd = TAILQ_FIRST(&hq->hq_q); if(hd == NULL) break; c = MIN(hd->hd_data_len - hd->hd_data_off, len); memcpy(buf, hd->hd_data + hd->hd_data_off, c); r += c; buf += c; len -= c; hd->hd_data_off += c; hq->hq_size -= c; if(hd->hd_data_off == hd->hd_data_len) htsbuf_data_free(hq, hd); } return r; } /** * */ size_t htsbuf_find(htsbuf_queue_t *hq, uint8_t v) { htsbuf_data_t *hd; unsigned int i, o = 0; TAILQ_FOREACH(hd, &hq->hq_q, hd_link) { for(i = hd->hd_data_off; i < hd->hd_data_len; i++) { if(hd->hd_data[i] == v) return o + i - hd->hd_data_off; } o += hd->hd_data_len - hd->hd_data_off; } return -1; } /** * */ size_t htsbuf_peek(htsbuf_queue_t *hq, char *buf, size_t len) { size_t r = 0; int c; htsbuf_data_t *hd = TAILQ_FIRST(&hq->hq_q); while(len > 0 && hd != NULL) { c = MIN(hd->hd_data_len - hd->hd_data_off, len); memcpy(buf, hd->hd_data + hd->hd_data_off, c); buf += c; len -= c; hd = TAILQ_NEXT(hd, hd_link); } return r; } /** * */ size_t htsbuf_drop(htsbuf_queue_t *hq, size_t len) { size_t r = 0; int c; htsbuf_data_t *hd; while(len > 0) { hd = TAILQ_FIRST(&hq->hq_q); if(hd == NULL) break; c = MIN(hd->hd_data_len - hd->hd_data_off, len); len -= c; hd->hd_data_off += c; if(hd->hd_data_off == hd->hd_data_len) htsbuf_data_free(hq, hd); } return r; } /** * */ void htsbuf_vqprintf(htsbuf_queue_t *hq, const char *fmt, va_list ap) { char buf[5000]; htsbuf_append(hq, buf, vsnprintf(buf, sizeof(buf), fmt, ap)); } /** * */ void htsbuf_qprintf(htsbuf_queue_t *hq, const char *fmt, ...) { va_list ap; va_start(ap, fmt); htsbuf_vqprintf(hq, fmt, ap); va_end(ap); } pvr.hts-4.4.20-Leia/lib/libhts/htsbuf.h000066400000000000000000000041051355512543200175610ustar00rootroot00000000000000/* * Buffer management functions * Copyright (C) 2008 Andreas man * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef HTSBUF_H__ #define HTSBUF_H__ #include #include "htsq.h" #include TAILQ_HEAD(htsbuf_data_queue, htsbuf_data); typedef struct htsbuf_data { TAILQ_ENTRY(htsbuf_data) hd_link; uint8_t *hd_data; unsigned int hd_data_size; /* Size of allocation hb_data */ unsigned int hd_data_len; /* Number of valid bytes from hd_data */ unsigned int hd_data_off; /* Offset in data, used for partial writes */ } htsbuf_data_t; typedef struct htsbuf_queue { struct htsbuf_data_queue hq_q; unsigned int hq_size; unsigned int hq_maxsize; } htsbuf_queue_t; void htsbuf_queue_init(htsbuf_queue_t *hq, unsigned int maxsize); void htsbuf_queue_flush(htsbuf_queue_t *hq); void htsbuf_vqprintf(htsbuf_queue_t *hq, const char *fmt, va_list ap); void htsbuf_qprintf(htsbuf_queue_t *hq, const char *fmt, ...); void htsbuf_append(htsbuf_queue_t *hq, const char *buf, size_t len); void htsbuf_append_prealloc(htsbuf_queue_t *hq, const char *buf, size_t len); void htsbuf_data_free(htsbuf_queue_t *hq, htsbuf_data_t *hd); size_t htsbuf_read(htsbuf_queue_t *hq, char *buf, size_t len); size_t htsbuf_peek(htsbuf_queue_t *hq, char *buf, size_t len); size_t htsbuf_drop(htsbuf_queue_t *hq, size_t len); size_t htsbuf_find(htsbuf_queue_t *hq, uint8_t v); #endif /* HTSBUF_H__ */ pvr.hts-4.4.20-Leia/lib/libhts/htsmsg.c000066400000000000000000000246241355512543200175760ustar00rootroot00000000000000/* * Functions for manipulating HTS messages * Copyright (C) 2007 Andreas �man * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #ifdef _MSC_VER #include "msvc.h" #endif #include "htsmsg.h" static void htsmsg_clear(htsmsg_t *msg); /* * */ static void htsmsg_field_destroy(htsmsg_t *msg, htsmsg_field_t *f) { TAILQ_REMOVE(&msg->hm_fields, f, hmf_link); switch(f->hmf_type) { case HMF_MAP: case HMF_LIST: htsmsg_clear(&f->hmf_msg); break; case HMF_STR: if(f->hmf_flags & HMF_ALLOCED) free((void *)f->hmf_str); break; case HMF_BIN: if(f->hmf_flags & HMF_ALLOCED) free((void *)f->hmf_bin); break; default: break; } if(f->hmf_flags & HMF_NAME_ALLOCED) free((void *)f->hmf_name); free(f); } /* * */ static void htsmsg_clear(htsmsg_t *msg) { htsmsg_field_t *f; while((f = TAILQ_FIRST(&msg->hm_fields)) != NULL) htsmsg_field_destroy(msg, f); } /* * */ htsmsg_field_t * htsmsg_field_add(htsmsg_t *msg, const char *name, int type, int flags) { htsmsg_field_t *f = malloc(sizeof(htsmsg_field_t)); TAILQ_INSERT_TAIL(&msg->hm_fields, f, hmf_link); if(msg->hm_islist) { assert(name == NULL); } else { assert(name != NULL); } if(flags & HMF_NAME_ALLOCED) f->hmf_name = name ? strdup(name) : NULL; else f->hmf_name = name; f->hmf_type = type; f->hmf_flags = flags; return f; } /* * */ static htsmsg_field_t * htsmsg_field_find(htsmsg_t *msg, const char *name) { htsmsg_field_t *f; TAILQ_FOREACH(f, &msg->hm_fields, hmf_link) { if(f->hmf_name != NULL && !strcmp(f->hmf_name, name)) return f; } return NULL; } /** * */ int htsmsg_delete_field(htsmsg_t *msg, const char *name) { htsmsg_field_t *f; if((f = htsmsg_field_find(msg, name)) == NULL) return HTSMSG_ERR_FIELD_NOT_FOUND; htsmsg_field_destroy(msg, f); return 0; } /* * */ htsmsg_t * htsmsg_create_map(void) { htsmsg_t *msg; msg = malloc(sizeof(htsmsg_t)); TAILQ_INIT(&msg->hm_fields); msg->hm_data = NULL; msg->hm_islist = 0; return msg; } /* * */ htsmsg_t * htsmsg_create_list(void) { htsmsg_t *msg; msg = malloc(sizeof(htsmsg_t)); TAILQ_INIT(&msg->hm_fields); msg->hm_data = NULL; msg->hm_islist = 1; return msg; } /* * */ void htsmsg_destroy(htsmsg_t *msg) { if(msg == NULL) return; htsmsg_clear(msg); free((void *)msg->hm_data); free(msg); msg = NULL; } /* * */ void htsmsg_add_u32(htsmsg_t *msg, const char *name, uint32_t u32) { htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_S64, HMF_NAME_ALLOCED); f->hmf_s64 = u32; } /* * */ void htsmsg_add_s64(htsmsg_t *msg, const char *name, int64_t s64) { htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_S64, HMF_NAME_ALLOCED); f->hmf_s64 = s64; } /* * */ void htsmsg_add_s32(htsmsg_t *msg, const char *name, int32_t s32) { htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_S64, HMF_NAME_ALLOCED); f->hmf_s64 = s32; } /* * */ void htsmsg_add_str(htsmsg_t *msg, const char *name, const char *str) { htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_STR, HMF_ALLOCED | HMF_NAME_ALLOCED); f->hmf_str = strdup(str); } /* * */ void htsmsg_add_bin(htsmsg_t *msg, const char *name, const void *bin, size_t len) { htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_BIN, HMF_ALLOCED | HMF_NAME_ALLOCED); void *v; f->hmf_bin = v = malloc(len); f->hmf_binsize = len; memcpy(v, bin, len); } /* * */ void htsmsg_add_binptr(htsmsg_t *msg, const char *name, const void *bin, size_t len) { htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_BIN, HMF_NAME_ALLOCED); f->hmf_bin = bin; f->hmf_binsize = len; } /* * */ void htsmsg_add_msg(htsmsg_t *msg, const char *name, htsmsg_t *sub) { htsmsg_field_t *f; f = htsmsg_field_add(msg, name, sub->hm_islist ? HMF_LIST : HMF_MAP, HMF_NAME_ALLOCED); assert(sub->hm_data == NULL); TAILQ_MOVE(&f->hmf_msg.hm_fields, &sub->hm_fields, hmf_link); free(sub); } /* * */ void htsmsg_add_msg_extname(htsmsg_t *msg, const char *name, htsmsg_t *sub) { htsmsg_field_t *f; f = htsmsg_field_add(msg, name, sub->hm_islist ? HMF_LIST : HMF_MAP, 0); assert(sub->hm_data == NULL); TAILQ_MOVE(&f->hmf_msg.hm_fields, &sub->hm_fields, hmf_link); free(sub); } /** * */ int htsmsg_get_s64(htsmsg_t *msg, const char *name, int64_t *s64p) { htsmsg_field_t *f; if((f = htsmsg_field_find(msg, name)) == NULL) return HTSMSG_ERR_FIELD_NOT_FOUND; switch(f->hmf_type) { default: return HTSMSG_ERR_CONVERSION_IMPOSSIBLE; case HMF_STR: *s64p = strtoll(f->hmf_str, NULL, 0); break; case HMF_S64: *s64p = f->hmf_s64; break; } return 0; } /* * */ int htsmsg_get_u32(htsmsg_t *msg, const char *name, uint32_t *u32p) { int r; int64_t s64; if((r = htsmsg_get_s64(msg, name, &s64)) != 0) return r; if(s64 < 0 || s64 > 0xffffffffLL) return HTSMSG_ERR_CONVERSION_IMPOSSIBLE; *u32p = (uint32_t)s64; return 0; } /** * */ int htsmsg_get_u32_or_default(htsmsg_t *msg, const char *name, uint32_t def) { uint32_t u32; return htsmsg_get_u32(msg, name, &u32) ? def : u32; } /* * */ int htsmsg_get_s32(htsmsg_t *msg, const char *name, int32_t *s32p) { int r; int64_t s64; if((r = htsmsg_get_s64(msg, name, &s64)) != 0) return r; if(s64 < -0x80000000LL || s64 > 0x7fffffffLL) return HTSMSG_ERR_CONVERSION_IMPOSSIBLE; *s32p = (int32_t)s64; return 0; } /* * */ int htsmsg_get_bin(htsmsg_t *msg, const char *name, const void **binp, size_t *lenp) { htsmsg_field_t *f; if((f = htsmsg_field_find(msg, name)) == NULL) return HTSMSG_ERR_FIELD_NOT_FOUND; if(f->hmf_type != HMF_BIN) return HTSMSG_ERR_CONVERSION_IMPOSSIBLE; *binp = f->hmf_bin; *lenp = f->hmf_binsize; return 0; } /** * */ const char * htsmsg_field_get_string(htsmsg_field_t *f) { char buf[40]; switch(f->hmf_type) { default: return NULL; case HMF_STR: break; case HMF_S64: snprintf(buf, sizeof(buf), "%" PRId64, f->hmf_s64); f->hmf_str = strdup(buf); f->hmf_type = HMF_STR; break; } return f->hmf_str; } /* * */ const char * htsmsg_get_str(htsmsg_t *msg, const char *name) { htsmsg_field_t *f; if((f = htsmsg_field_find(msg, name)) == NULL) return NULL; return htsmsg_field_get_string(f); } /* * */ htsmsg_t * htsmsg_get_map(htsmsg_t *msg, const char *name) { htsmsg_field_t *f; if((f = htsmsg_field_find(msg, name)) == NULL || f->hmf_type != HMF_MAP) return NULL; return &f->hmf_msg; } /** * */ htsmsg_t * htsmsg_get_map_multi(htsmsg_t *msg, ...) { va_list ap; const char *n; va_start(ap, msg); while(msg != NULL && (n = va_arg(ap, char *)) != NULL) msg = htsmsg_get_map(msg, n); va_end(ap); return msg; } /* * */ htsmsg_t * htsmsg_get_list(htsmsg_t *msg, const char *name) { htsmsg_field_t *f; if((f = htsmsg_field_find(msg, name)) == NULL || f->hmf_type != HMF_LIST) return NULL; return &f->hmf_msg; } /** * */ htsmsg_t * htsmsg_detach_submsg(htsmsg_field_t *f) { htsmsg_t *r = htsmsg_create_map(); TAILQ_MOVE(&r->hm_fields, &f->hmf_msg.hm_fields, hmf_link); TAILQ_INIT(&f->hmf_msg.hm_fields); r->hm_islist = f->hmf_type == HMF_LIST; return r; } /* * */ static void htsmsg_print0(htsmsg_t *msg, int indent) { htsmsg_field_t *f; int i; TAILQ_FOREACH(f, &msg->hm_fields, hmf_link) { for(i = 0; i < indent; i++) printf("\t"); printf("%s (", f->hmf_name ? f->hmf_name : ""); switch(f->hmf_type) { case HMF_MAP: printf("MAP) = {\n"); htsmsg_print0(&f->hmf_msg, indent + 1); for(i = 0; i < indent; i++) printf("\t"); printf("}\n"); break; case HMF_LIST: printf("LIST) = {\n"); htsmsg_print0(&f->hmf_msg, indent + 1); for(i = 0; i < indent; i++) printf("\t"); printf("}\n"); break; case HMF_STR: printf("STR) = \"%s\"\n", f->hmf_str); break; case HMF_BIN: printf("BIN) = ["); for(i = 0; i < (int)f->hmf_binsize - 1; i++) printf("%02x.", ((uint8_t *)f->hmf_bin)[i]); printf("%02x]\n", ((uint8_t *)f->hmf_bin)[i]); break; case HMF_S64: printf("S64) = %" PRId64 "\n", f->hmf_s64); break; } } } /* * */ void htsmsg_print(htsmsg_t *msg) { htsmsg_print0(msg, 0); } /** * */ static void htsmsg_copy_i(htsmsg_t *src, htsmsg_t *dst) { htsmsg_field_t *f; htsmsg_t *sub; TAILQ_FOREACH(f, &src->hm_fields, hmf_link) { switch(f->hmf_type) { case HMF_MAP: case HMF_LIST: sub = f->hmf_type == HMF_LIST ? htsmsg_create_list() : htsmsg_create_map(); htsmsg_copy_i(&f->hmf_msg, sub); htsmsg_add_msg(dst, f->hmf_name, sub); break; case HMF_STR: htsmsg_add_str(dst, f->hmf_name, f->hmf_str); break; case HMF_S64: htsmsg_add_s64(dst, f->hmf_name, f->hmf_s64); break; case HMF_BIN: htsmsg_add_bin(dst, f->hmf_name, f->hmf_bin, f->hmf_binsize); break; } } } htsmsg_t * htsmsg_copy(htsmsg_t *src) { htsmsg_t *dst = src->hm_islist ? htsmsg_create_list() : htsmsg_create_map(); htsmsg_copy_i(src, dst); return dst; } int htsmsg_get_float(htsmsg_t *msg, const char *name, double *floatp) { htsmsg_field_t *f; if((f = htsmsg_field_find(msg, name)) == NULL) return HTSMSG_ERR_FIELD_NOT_FOUND; switch(f->hmf_type) { default: return HTSMSG_ERR_CONVERSION_IMPOSSIBLE; case HMF_STR: *floatp = atof(f->hmf_str); break; case HMF_FLOAT: *floatp = f->hmf_float; break; } return 0; } void htsmsg_add_float(htsmsg_t *msg, const char *name, double val) { htsmsg_field_t *f = htsmsg_field_add(msg, name, HMF_FLOAT, HMF_NAME_ALLOCED); f->hmf_float = val; } pvr.hts-4.4.20-Leia/lib/libhts/htsmsg.h000066400000000000000000000166501355512543200176030ustar00rootroot00000000000000/* * Functions for manipulating HTS messages * Copyright (C) 2007 Andreas man * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef HTSMSG_H_ #define HTSMSG_H_ #include #include "htsq.h" #define HTSMSG_ERR_FIELD_NOT_FOUND -1 #define HTSMSG_ERR_CONVERSION_IMPOSSIBLE -2 TAILQ_HEAD(htsmsg_field_queue, htsmsg_field); typedef struct htsmsg { /** * fields */ struct htsmsg_field_queue hm_fields; /** * Set if this message is a list, otherwise it is a map. */ int hm_islist; /** * Data to be free'd when the message is destroyed */ const void *hm_data; } htsmsg_t; #define HMF_MAP 1 #define HMF_S64 2 #define HMF_STR 3 #define HMF_BIN 4 #define HMF_LIST 5 #define HMF_FLOAT 6 typedef struct htsmsg_field { TAILQ_ENTRY(htsmsg_field) hmf_link; const char *hmf_name; uint8_t hmf_type; uint8_t hmf_flags; #define HMF_ALLOCED 0x1 #define HMF_NAME_ALLOCED 0x2 union { int64_t s64; const char *str; struct { const char *data; size_t len; } bin; double sf; htsmsg_t msg; } u; } htsmsg_field_t; #define hmf_s64 u.s64 #define hmf_msg u.msg #define hmf_str u.str #define hmf_bin u.bin.data #define hmf_binsize u.bin.len #define hmf_float u.sf #define htsmsg_get_map_by_field(f) \ ((f)->hmf_type == HMF_MAP ? &(f)->hmf_msg : NULL) #define HTSMSG_FOREACH(f, msg) TAILQ_FOREACH(f, &(msg)->hm_fields, hmf_link) /** * Create a new map */ htsmsg_t *htsmsg_create_map(void); /** * Create a new list */ htsmsg_t *htsmsg_create_list(void); /** * Destroys a message (map or list) */ void htsmsg_destroy(htsmsg_t *msg); /** * Add an integer field where source is unsigned 32 bit. */ void htsmsg_add_u32(htsmsg_t *msg, const char *name, uint32_t u32); /** * Add an integer field where source is signed 32 bit. */ void htsmsg_add_s32(htsmsg_t *msg, const char *name, int32_t s32); /** * Add an integer field where source is signed 64 bit. */ void htsmsg_add_s64(htsmsg_t *msg, const char *name, int64_t s64); /** * Add a string field. */ void htsmsg_add_str(htsmsg_t *msg, const char *name, const char *str); /** * Add an field where source is a list or map message. */ void htsmsg_add_msg(htsmsg_t *msg, const char *name, htsmsg_t *sub); /** * Add an field where source is a list or map message. * * This function will not strdup() \p name but relies on the caller * to keep the string allocated for as long as the message is valid. */ void htsmsg_add_msg_extname(htsmsg_t *msg, const char *name, htsmsg_t *sub); /** * Add an binary field. The data is copied to a malloced storage */ void htsmsg_add_bin(htsmsg_t *msg, const char *name, const void *bin, size_t len); /** * Add an binary field. The data is not copied, instead the caller * is responsible for keeping the data valid for as long as the message * is around. */ void htsmsg_add_binptr(htsmsg_t *msg, const char *name, const void *bin, size_t len); /** * Get an integer as an unsigned 32 bit integer. * * @return HTSMSG_ERR_FIELD_NOT_FOUND - Field does not exist * HTSMSG_ERR_CONVERSION_IMPOSSIBLE - Field is not an integer or * out of range for the requested storage. */ int htsmsg_get_u32(htsmsg_t *msg, const char *name, uint32_t *u32p); /** * Get an integer as an signed 32 bit integer. * * @return HTSMSG_ERR_FIELD_NOT_FOUND - Field does not exist * HTSMSG_ERR_CONVERSION_IMPOSSIBLE - Field is not an integer or * out of range for the requested storage. */ int htsmsg_get_s32(htsmsg_t *msg, const char *name, int32_t *s32p); /** * Get an integer as an signed 64 bit integer. * * @return HTSMSG_ERR_FIELD_NOT_FOUND - Field does not exist * HTSMSG_ERR_CONVERSION_IMPOSSIBLE - Field is not an integer or * out of range for the requested storage. */ int htsmsg_get_s64(htsmsg_t *msg, const char *name, int64_t *s64p); /** * Get pointer to a binary field. No copying of data is performed. * * @param binp Pointer to a void * that will be filled in with a pointer * to the data * @param lenp Pointer to a size_t that will be filled with the size of * the data * * @return HTSMSG_ERR_FIELD_NOT_FOUND - Field does not exist * HTSMSG_ERR_CONVERSION_IMPOSSIBLE - Field is not a binary blob. */ int htsmsg_get_bin(htsmsg_t *msg, const char *name, const void **binp, size_t *lenp); /** * Get a float. * * @return HTSMSG_ERR_FIELD_NOT_FOUND - Field does not exist * HTSMSG_ERR_CONVERSION_IMPOSSIBLE - Field is not an float. */ int htsmsg_get_float(htsmsg_t *msg, const char *name, double *floatp); /** * Add a float field. */ void htsmsg_add_float(htsmsg_t *msg, const char *name, double val); /** * Get a field of type 'list'. No copying is done. * * @return NULL if the field can not be found or not of list type. * Otherwise a htsmsg is returned. */ htsmsg_t *htsmsg_get_list(htsmsg_t *msg, const char *name); /** * Get a field of type 'string'. No copying is done. * * @return NULL if the field can not be found or not of string type. * Otherwise a pointer to the data is returned. */ const char *htsmsg_get_str(htsmsg_t *msg, const char *name); /** * Get a field of type 'map'. No copying is done. * * @return NULL if the field can not be found or not of map type. * Otherwise a htsmsg is returned. */ htsmsg_t *htsmsg_get_map(htsmsg_t *msg, const char *name); /** * Traverse a hierarchy of htsmsg's to find a specific child. */ htsmsg_t *htsmsg_get_map_multi(htsmsg_t *msg, ...); /** * Given the field \p f, return a string if it is of type string, otherwise * return NULL */ const char *htsmsg_field_get_string(htsmsg_field_t *f); /** * Return the field \p name as an u32. * * @return An unsigned 32 bit integer or NULL if the field can not be found * or if conversion is not possible. */ int htsmsg_get_u32_or_default(htsmsg_t *msg, const char *name, uint32_t def); /** * Remove the given field called \p name from the message \p msg. */ int htsmsg_delete_field(htsmsg_t *msg, const char *name); /** * Detach will remove the given field (and only if it is a list or map) * from the message and make it a 'standalone message'. This means * the the contents of the sub message will stay valid if the parent is * destroyed. The caller is responsible for freeing this new message. */ htsmsg_t *htsmsg_detach_submsg(htsmsg_field_t *f); /** * Print a message to stdout. */ void htsmsg_print(htsmsg_t *msg); /** * Create a new field. Primarily intended for htsmsg internal functions. */ htsmsg_field_t *htsmsg_field_add(htsmsg_t *msg, const char *name, int type, int flags); /** * Clone a message. */ htsmsg_t *htsmsg_copy(htsmsg_t *src); #define HTSMSG_FOREACH(f, msg) TAILQ_FOREACH(f, &(msg)->hm_fields, hmf_link) #endif /* HTSMSG_H_ */ pvr.hts-4.4.20-Leia/lib/libhts/htsmsg_binary.c000066400000000000000000000121201355512543200211260ustar00rootroot00000000000000/* * Functions converting HTSMSGs to/from a simple binary format * Copyright (C) 2007 Andreas man * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include "htsmsg_binary.h" /* * */ static int htsmsg_binary_des0(htsmsg_t *msg, const uint8_t *buf, size_t len) { unsigned type, namelen, datalen; htsmsg_field_t *f; htsmsg_t *sub; char *n; uint64_t u64; int i; while(len > 5) { type = buf[0]; namelen = buf[1]; datalen = (buf[2] << 24) | (buf[3] << 16) | (buf[4] << 8 ) | (buf[5] ); buf += 6; len -= 6; if(len < namelen + datalen) return -1; f = malloc(sizeof(htsmsg_field_t)); f->hmf_type = type; if(namelen > 0) { n = malloc(namelen + 1); memcpy(n, buf, namelen); n[namelen] = 0; buf += namelen; len -= namelen; f->hmf_flags = HMF_NAME_ALLOCED; } else { n = NULL; f->hmf_flags = 0; } f->hmf_name = n; switch(type) { case HMF_STR: f->hmf_str = n = malloc(datalen + 1); memcpy(n, buf, datalen); n[datalen] = 0; f->hmf_flags |= HMF_ALLOCED; break; case HMF_BIN: f->hmf_bin = (const void *)buf; f->hmf_binsize = datalen; break; case HMF_S64: u64 = 0; for(i = datalen - 1; i >= 0; i--) u64 = (u64 << 8) | buf[i]; f->hmf_s64 = u64; break; case HMF_MAP: case HMF_LIST: sub = &f->hmf_msg; TAILQ_INIT(&sub->hm_fields); sub->hm_data = NULL; if(htsmsg_binary_des0(sub, buf, datalen) < 0) return -1; break; default: free(n); free(f); return -1; } TAILQ_INSERT_TAIL(&msg->hm_fields, f, hmf_link); buf += datalen; len -= datalen; } return 0; } /* * */ htsmsg_t * htsmsg_binary_deserialize(const void *data, size_t len, const void *buf) { htsmsg_t *msg = htsmsg_create_map(); msg->hm_data = buf; if(htsmsg_binary_des0(msg, data, len) < 0) { htsmsg_destroy(msg); return NULL; } return msg; } /* * */ static size_t htsmsg_binary_count(htsmsg_t *msg) { htsmsg_field_t *f; size_t len = 0; uint64_t u64; TAILQ_FOREACH(f, &msg->hm_fields, hmf_link) { len += 6; len += f->hmf_name ? strlen(f->hmf_name) : 0; switch(f->hmf_type) { case HMF_MAP: case HMF_LIST: len += htsmsg_binary_count(&f->hmf_msg); break; case HMF_STR: len += strlen(f->hmf_str); break; case HMF_BIN: len += f->hmf_binsize; break; case HMF_S64: u64 = f->hmf_s64; while(u64 != 0) { len++; u64 = u64 >> 8; } break; } } return len; } /* * */ static void htsmsg_binary_write(htsmsg_t *msg, uint8_t *ptr) { htsmsg_field_t *f; uint64_t u64; int l, i, namelen; TAILQ_FOREACH(f, &msg->hm_fields, hmf_link) { namelen = f->hmf_name ? strlen(f->hmf_name) : 0; *ptr++ = f->hmf_type; *ptr++ = namelen; switch(f->hmf_type) { case HMF_MAP: case HMF_LIST: l = htsmsg_binary_count(&f->hmf_msg); break; case HMF_STR: l = strlen(f->hmf_str); break; case HMF_BIN: l = f->hmf_binsize; break; case HMF_S64: u64 = f->hmf_s64; l = 0; while(u64 != 0) { l++; u64 = u64 >> 8; } break; default: abort(); } *ptr++ = l >> 24; *ptr++ = l >> 16; *ptr++ = l >> 8; *ptr++ = l; if(namelen > 0) { memcpy(ptr, f->hmf_name, namelen); ptr += namelen; } switch(f->hmf_type) { case HMF_MAP: case HMF_LIST: htsmsg_binary_write(&f->hmf_msg, ptr); break; case HMF_STR: memcpy(ptr, f->hmf_str, l); break; case HMF_BIN: memcpy(ptr, f->hmf_bin, l); break; case HMF_S64: u64 = f->hmf_s64; for(i = 0; i < l; i++) { ptr[i] = (uint8_t)(u64 & 0xFF); u64 = u64 >> 8; } break; } ptr += l; } } /* * */ int htsmsg_binary_serialize(htsmsg_t *msg, void **datap, size_t *lenp, int maxlen) { size_t len; uint8_t *data; len = htsmsg_binary_count(msg); if(len + 4 > (size_t)maxlen) return -1; data = malloc(len + 4); data[0] = len >> 24; data[1] = len >> 16; data[2] = len >> 8; data[3] = len; htsmsg_binary_write(msg, data + 4); *datap = data; *lenp = len + 4; return 0; } pvr.hts-4.4.20-Leia/lib/libhts/htsmsg_binary.h000066400000000000000000000022151355512543200211370ustar00rootroot00000000000000/* * Functions converting HTSMSGs to/from a simple binary format * Copyright (C) 2007 Andreas man * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef HTSMSG_BINARY_H_ #define HTSMSG_BINARY_H_ #include "htsmsg.h" /** * htsmsg_binary_deserialize */ htsmsg_t *htsmsg_binary_deserialize(const void *data, size_t len, const void *buf); int htsmsg_binary_serialize(htsmsg_t *msg, void **datap, size_t *lenp, int maxlen); #endif /* HTSMSG_BINARY_H_ */ pvr.hts-4.4.20-Leia/lib/libhts/htsq.h000066400000000000000000000077601355512543200172570ustar00rootroot00000000000000/* * sys/queue.h wrappers and helpers */ #ifndef HTSQ_H #define HTSQ_H #ifdef _MSC_VER #undef SLIST_ENTRY #include "Win32/include/sys/queue.h" #else #include #endif /* * Complete missing LIST-ops */ #ifndef LIST_FOREACH #define LIST_FOREACH(var, head, field) \ for ((var) = ((head)->lh_first); \ (var); \ (var) = ((var)->field.le_next)) #endif #ifndef LIST_EMPTY #define LIST_EMPTY(head) ((head)->lh_first == NULL) #endif #ifndef LIST_FIRST #define LIST_FIRST(head) ((head)->lh_first) #endif #ifndef LIST_NEXT #define LIST_NEXT(elm, field) ((elm)->field.le_next) #endif #ifndef LIST_INSERT_BEFORE #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.le_prev = (listelm)->field.le_prev; \ (elm)->field.le_next = (listelm); \ *(listelm)->field.le_prev = (elm); \ (listelm)->field.le_prev = &(elm)->field.le_next; \ } while (/*CONSTCOND*/0) #endif /* * Complete missing TAILQ-ops */ #ifndef TAILQ_INSERT_BEFORE #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ (elm)->field.tqe_next = (listelm); \ *(listelm)->field.tqe_prev = (elm); \ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ } while (0) #endif #ifndef TAILQ_FOREACH #define TAILQ_FOREACH(var, head, field) \ for ((var) = ((head)->tqh_first); (var); (var) = ((var)->field.tqe_next)) #endif #ifndef TAILQ_FIRST #define TAILQ_FIRST(head) ((head)->tqh_first) #endif #ifndef TAILQ_NEXT #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) #endif #ifndef TAILQ_LAST #define TAILQ_LAST(head, headname) \ (*(((struct headname *)((head)->tqh_last))->tqh_last)) #endif #ifndef TAILQ_PREV #define TAILQ_PREV(elm, headname, field) \ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) #endif #ifndef TAILQ_FOREACH_REVERSE #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ (var); \ (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) #endif /* * Some extra functions for LIST manipulation */ #define LIST_MOVE(newhead, oldhead, field) do { \ if((oldhead)->lh_first) { \ (oldhead)->lh_first->field.le_prev = &(newhead)->lh_first; \ } \ (newhead)->lh_first = (oldhead)->lh_first; \ } while (0) #define LIST_INSERT_SORTED(head, elm, field, cmpfunc) do { \ if(LIST_EMPTY(head)) { \ LIST_INSERT_HEAD(head, elm, field); \ } else { \ typeof(elm) _tmp; \ LIST_FOREACH(_tmp,head,field) { \ if(cmpfunc(elm,_tmp) <= 0) { \ LIST_INSERT_BEFORE(_tmp,elm,field); \ break; \ } \ if(!LIST_NEXT(_tmp,field)) { \ LIST_INSERT_AFTER(_tmp,elm,field); \ break; \ } \ } \ } \ } while(0) #define TAILQ_INSERT_SORTED(head, elm, field, cmpfunc) do { \ if(TAILQ_FIRST(head) == NULL) { \ TAILQ_INSERT_HEAD(head, elm, field); \ } else { \ typeof(elm) _tmp; \ TAILQ_FOREACH(_tmp,head,field) { \ if(cmpfunc(elm,_tmp) <= 0) { \ TAILQ_INSERT_BEFORE(_tmp,elm,field); \ break; \ } \ if(!TAILQ_NEXT(_tmp,field)) { \ TAILQ_INSERT_AFTER(head,_tmp,elm,field); \ break; \ } \ } \ } \ } while(0) #define TAILQ_MOVE(newhead, oldhead, field) do { \ if(TAILQ_FIRST(oldhead)) { \ TAILQ_FIRST(oldhead)->field.tqe_prev = &(newhead)->tqh_first; \ } \ (newhead)->tqh_first = (oldhead)->tqh_first; \ (newhead)->tqh_last = (oldhead)->tqh_last; \ } while (/*CONSTCOND*/0) #endif /* HTSQ_H */ pvr.hts-4.4.20-Leia/lib/libhts/htsstr.c000066400000000000000000000075511355512543200176200ustar00rootroot00000000000000/* * String helper functions * Copyright (C) 2008 Andreas Öman * Copyright (C) 2008 Mattias Wadman * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #ifdef __APPLE__ #include "OSXGNUReplacements.h" #elif defined(_MSC_VER) #include "msvc.h" #endif #include "htsstr.h" static void htsstr_argsplit_add(char ***argv, int *argc, char *s); static int htsstr_format0(const char *str, char *out, char **map); char * htsstr_unescape(char *str) { char *s; for(s = str; *s; s++) { if(*s != '\\') continue; if(*(s + 1) == 'b') *s = '\b'; else if(*(s + 1) == 'f') *s = '\f'; else if(*(s + 1) == 'n') *s = '\n'; else if(*(s + 1) == 'r') *s = '\r'; else if(*(s + 1) == 't') *s = '\t'; else *s = *(s + 1); if(*(s + 1)) { /* shift string left, copies terminator too */ memmove(s + 1, s + 2, strlen(s + 2) + 1); } } return str; } static void htsstr_argsplit_add(char ***argv, int *argc, char *s) { *argv = realloc(*argv, sizeof((*argv)[0]) * (*argc + 1)); (*argv)[(*argc)++] = s; } char ** htsstr_argsplit(const char *str) { int quote = 0; int inarg = 0; const char *start = NULL; const char *stop = NULL; const char *s; char **argv = NULL; int argc = 0; for(s = str; *s; s++) { if(start && stop) { htsstr_argsplit_add(&argv, &argc, htsstr_unescape(strndup(start, stop - start))); start = stop = NULL; } if(inarg) { switch(*s) { case '\\': s++; break; case '"': if(quote) { inarg = 0; quote = 0; stop = s; } break; case ' ': if(quote) break; inarg = 0; stop = s; break; default: break; } } else { switch(*s) { case ' ': break; case '"': quote = 1; s++; /* fallthru */ default: inarg = 1; start = s; stop = NULL; break; } } } if(start) { if(!stop) stop = str + strlen(str); htsstr_argsplit_add(&argv, &argc, htsstr_unescape(strndup(start, stop - start))); } htsstr_argsplit_add(&argv, &argc, NULL); return argv; } void htsstr_argsplit_free(char **argv) { int i; for(i = 0; argv[i]; i++) free(argv[i]); free(argv); } static int htsstr_format0(const char *str, char *out, char **map) { const char *s = str; char *f; int n = 0; while(*s) { switch(*s) { case '%': f = map[(unsigned char)*(s + 1)]; if(*(s + 1) != '%' && f) { s += 2; /* skip %f * */ if(out) strcpy(&out[n], f); n += strlen(f); break; } /* fallthru */ default: if(out) out[n] = *s; s++; n++; break; } } if(out) out[n] = '\0'; return n + 1; /* + \0 */ } char * htsstr_format(const char *str, char **map) { char *s; s = malloc(htsstr_format0(str, NULL, map)); htsstr_format0(str, s, map); return s; } pvr.hts-4.4.20-Leia/lib/libhts/htsstr.h000066400000000000000000000020651355512543200176200ustar00rootroot00000000000000/* * String helper functions * Copyright (C) 2008 Andreas Öman * Copyright (C) 2008 Mattias Wadman * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef HTSSTR_H__ #define HTSSTR_H__ char *htsstr_unescape(char *str); char **htsstr_argsplit(const char *str); void htsstr_argsplit_free(char **argv); char *htsstr_format(const char *str, char **map); #endif /* HTSSTR_H__ */ pvr.hts-4.4.20-Leia/lib/libhts/net.h000066400000000000000000000027651355512543200170660ustar00rootroot00000000000000/* * Networking * Copyright (C) 2007-2008 Andreas Öman * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef NET_H__ #define NET_H__ #include #include #include "htsbuf.h" #ifdef _MSC_VER typedef SOCKET socket_t; #else typedef int socket_t; #endif socket_t htsp_tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize, int timeout); int htsp_tcp_write_queue(socket_t fd, htsbuf_queue_t *q); int htsp_tcp_read_line(socket_t fd, char *buf, const size_t bufsize, htsbuf_queue_t *spill); int htsp_tcp_read_data(socket_t fd, char *buf, const size_t bufsize, htsbuf_queue_t *spill); int htsp_tcp_read(socket_t fd, void *buf, size_t len); int htsp_tcp_read_timeout(socket_t fd, void *buf, size_t len, int timeout); void htsp_tcp_close(socket_t fd); #endif /* NET_H__ */ pvr.hts-4.4.20-Leia/lib/libhts/net_posix.c000066400000000000000000000151651355512543200203010ustar00rootroot00000000000000/* * Networking under POSIX * Copyright (C) 2007-2008 Andreas Öman * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #ifdef __APPLE__ /* Needed on Mac OS/X */ #ifndef SOL_TCP #define SOL_TCP IPPROTO_TCP #endif #include "OSXGNUReplacements.h" #elif defined(__FreeBSD__) #ifndef SOL_TCP #define SOL_TCP IPPROTO_TCP #endif #else #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__FreeBSD__) #include #endif #include "net.h" /** * */ socket_t htsp_tcp_connect_addr(struct addrinfo* addr, char *errbuf, size_t errbufsize, int timeout) { socket_t fd; int r, err, val; socklen_t errlen = sizeof(int); fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if(fd == -1) { snprintf(errbuf, errbufsize, "Unable to create socket: %s", strerror(errno)); return -1; } /** * Switch to nonblocking */ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); r = connect(fd, addr->ai_addr, addr->ai_addrlen); if(r == -1) { if(errno == EINPROGRESS) { struct pollfd pfd; pfd.fd = fd; pfd.events = POLLOUT; pfd.revents = 0; r = poll(&pfd, 1, timeout); if(r == 0) { /* Timeout */ snprintf(errbuf, errbufsize, "Connection attempt timed out"); close(fd); return -1; } if(r == -1) { snprintf(errbuf, errbufsize, "poll() error: %s", strerror(errno)); close(fd); return -1; } getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen); } else { err = errno; } } else { err = 0; } if(err != 0) { snprintf(errbuf, errbufsize, "%s", strerror(err)); close(fd); return -1; } fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK); val = 1; setsockopt(fd, SOL_TCP, TCP_NODELAY, &val, sizeof(val)); return fd; } socket_t htsp_tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize, int timeout) { struct addrinfo hints; struct addrinfo *result, *addr; char service[33]; int res; socket_t fd = -1; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; sprintf(service, "%d", port); res = getaddrinfo(hostname, service, &hints, &result); if(res) { switch(res) { case EAI_NONAME: snprintf(errbuf, errbufsize, "The specified host is unknown"); break; case EAI_FAIL: snprintf(errbuf, errbufsize, "A nonrecoverable failure in name resolution occurred"); break; case EAI_MEMORY: snprintf(errbuf, errbufsize, "A memory allocation failure occurred"); break; case EAI_AGAIN: snprintf(errbuf, errbufsize, "A temporary error occurred on an authoritative name server"); break; default: snprintf(errbuf, errbufsize, "Unknown error %d", res); break; } return -1; } for(addr = result; addr; addr = addr->ai_next) { fd = htsp_tcp_connect_addr(addr, errbuf, errbufsize, timeout); if(fd != -1) break; } freeaddrinfo(result); return fd; } /** * */ int htsp_tcp_write_queue(socket_t fd, htsbuf_queue_t *q) { htsbuf_data_t *hd; int l, r; while((hd = TAILQ_FIRST(&q->hq_q)) != NULL) { TAILQ_REMOVE(&q->hq_q, hd, hd_link); l = hd->hd_data_len - hd->hd_data_off; r = write(fd, hd->hd_data + hd->hd_data_off, l); free(hd->hd_data); free(hd); } q->hq_size = 0; return 0; } /** * */ static int tcp_fill_htsbuf_from_fd(socket_t fd, htsbuf_queue_t *hq) { htsbuf_data_t *hd = TAILQ_LAST(&hq->hq_q, htsbuf_data_queue); int c; if(hd != NULL) { /* Fill out any previous buffer */ c = hd->hd_data_size - hd->hd_data_len; if(c > 0) { c = read(fd, hd->hd_data + hd->hd_data_len, c); if(c < 1) return -1; hd->hd_data_len += c; hq->hq_size += c; return 0; } } hd = malloc(sizeof(htsbuf_data_t)); hd->hd_data_size = 1000; hd->hd_data = malloc(hd->hd_data_size); c = read(fd, hd->hd_data, hd->hd_data_size); if(c < 1) { free(hd->hd_data); free(hd); return -1; } hd->hd_data_len = c; hd->hd_data_off = 0; TAILQ_INSERT_TAIL(&hq->hq_q, hd, hd_link); hq->hq_size += c; return 0; } /** * */ int htsp_tcp_read_line(socket_t fd, char *buf, const size_t bufsize, htsbuf_queue_t *spill) { int len; while(1) { len = htsbuf_find(spill, 0xa); if(len == -1) { if(tcp_fill_htsbuf_from_fd(fd, spill) < 0) return -1; continue; } if(len >= (int)bufsize - 1) return -1; htsbuf_read(spill, buf, len); buf[len] = 0; while(len > 0 && buf[len - 1] < 32) buf[--len] = 0; htsbuf_drop(spill, 1); /* Drop the \n */ return 0; } } /** * */ int htsp_tcp_read_data(socket_t fd, char *buf, const size_t bufsize, htsbuf_queue_t *spill) { int x, tot = htsbuf_read(spill, buf, bufsize); if(tot == (int)bufsize) return 0; x = recv(fd, buf + tot, bufsize - tot, MSG_WAITALL); if(x != (int)bufsize - tot) return -1; return 0; } /** * */ int htsp_tcp_read(socket_t fd, void *buf, size_t len) { int x = recv(fd, buf, len, MSG_WAITALL); if(x == -1) return errno; if(x != (int)len) return ECONNRESET; return 0; } /** * */ int htsp_tcp_read_timeout(socket_t fd, void *buf, size_t len, int timeout) { int x, tot = 0; struct pollfd fds; assert(timeout > 0); fds.fd = fd; fds.events = POLLIN; fds.revents = 0; while(tot != (int)len) { x = poll(&fds, 1, timeout); if(x == 0) return ETIMEDOUT; x = recv(fd, buf + tot, len - tot, MSG_DONTWAIT); if(x == -1) { if(errno == EAGAIN) continue; return errno; } if(x == 0) return ECONNRESET; tot += x; } return 0; } /** * */ void htsp_tcp_close(socket_t fd) { close(fd); } pvr.hts-4.4.20-Leia/lib/libhts/net_winsock.c000066400000000000000000000172311355512543200206100ustar00rootroot00000000000000/* * Networking under WINDOWS * Copyright (C) 2007-2008 Andreas Öman * Copyright (C) 2007-2008 Joakim Plate * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include #include #include #include #include #include #include #include "msvc.h" #include "net.h" static int socket_errno() { int error = WSAGetLastError(); switch(error) { case WSAEINPROGRESS: return EINPROGRESS; case WSAECONNRESET : return ECONNRESET; case WSAETIMEDOUT : return ETIMEDOUT; case WSAEWOULDBLOCK: return EAGAIN; default : return error; } } #ifndef MSG_WAITALL #define MSG_WAITALL 0x8 #endif static int recv_fixed (SOCKET s, char * buf, int len, int flags) { char* org = buf; int res = 1; if((flags & MSG_WAITALL) == 0) return recv(s, buf, len, flags); flags &= ~MSG_WAITALL; while(len > 0 && res > 0) { res = recv(s, buf, len, flags); if(res < 0) return res; buf += res; len -= res; } return buf - org; } #define recv(s, buf, len, flags) recv_fixed(s, buf, len, flags) /** * */ socket_t htsp_tcp_connect_addr(struct addrinfo* addr, char *errbuf, size_t errbufsize, int timeout) { socket_t fd; int r, err, val; socklen_t errlen = sizeof(int); fd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if(fd == -1) { snprintf(errbuf, errbufsize, "Unable to create socket: %s", strerror(socket_errno())); return -1; } /** * Switch to nonblocking */ val = 1; ioctlsocket(fd, FIONBIO, &val); r = connect(fd, addr->ai_addr, addr->ai_addrlen); if(r == -1) { if(socket_errno() == EINPROGRESS || socket_errno() == EAGAIN) { fd_set fd_write, fd_except; struct timeval tv; tv.tv_sec = timeout / 1000; tv.tv_usec = 1000 * (timeout % 1000); FD_ZERO(&fd_write); FD_ZERO(&fd_except); FD_SET(fd, &fd_write); FD_SET(fd, &fd_except); r = select((int)fd+1, NULL, &fd_write, &fd_except, &tv); if(r == 0) { /* Timeout */ snprintf(errbuf, errbufsize, "Connection attempt timed out"); closesocket(fd); return -1; } if(r == -1) { snprintf(errbuf, errbufsize, "select() error: %s", strerror(socket_errno())); closesocket(fd); return -1; } getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&err, &errlen); } else { err = socket_errno(); } } else { err = 0; } if(err != 0) { snprintf(errbuf, errbufsize, "%s", strerror(err)); closesocket(fd); return -1; } val = 0; ioctlsocket(fd, FIONBIO, &val); val = 1; setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (const char*)&val, sizeof(val)); return fd; } socket_t htsp_tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize, int timeout) { struct addrinfo hints; struct addrinfo *result, *addr; char service[33]; int res; socket_t fd = INVALID_SOCKET; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; sprintf(service, "%d", port); res = getaddrinfo(hostname, service, &hints, &result); if(res) { switch(res) { case EAI_NONAME: snprintf(errbuf, errbufsize, "The specified host is unknown"); break; case EAI_FAIL: snprintf(errbuf, errbufsize, "A nonrecoverable failure in name resolution occurred"); break; case EAI_MEMORY: snprintf(errbuf, errbufsize, "A memory allocation failure occurred"); break; case EAI_AGAIN: snprintf(errbuf, errbufsize, "A temporary error occurred on an authoritative name server"); break; default: snprintf(errbuf, errbufsize, "Unknown error %d", res); break; } return -1; } for(addr = result; addr; addr = addr->ai_next) { fd = htsp_tcp_connect_addr(addr, errbuf, errbufsize, timeout); if(fd != INVALID_SOCKET) break; } freeaddrinfo(result); return fd; } /** * */ int htsp_tcp_write_queue(socket_t fd, htsbuf_queue_t *q) { htsbuf_data_t *hd; int l, r; while((hd = TAILQ_FIRST(&q->hq_q)) != NULL) { TAILQ_REMOVE(&q->hq_q, hd, hd_link); l = hd->hd_data_len - hd->hd_data_off; r = send(fd, hd->hd_data + hd->hd_data_off, l, 0); free(hd->hd_data); free(hd); } q->hq_size = 0; return 0; } /** * */ static int tcp_fill_htsbuf_from_fd(socket_t fd, htsbuf_queue_t *hq) { htsbuf_data_t *hd = TAILQ_LAST(&hq->hq_q, htsbuf_data_queue); int c; if(hd != NULL) { /* Fill out any previous buffer */ c = hd->hd_data_size - hd->hd_data_len; if(c > 0) { c = recv(fd, hd->hd_data + hd->hd_data_len, c, MSG_WAITALL); if(c < 1) return -1; hd->hd_data_len += c; hq->hq_size += c; return 0; } } hd = malloc(sizeof(htsbuf_data_t)); hd->hd_data_size = 1000; hd->hd_data = malloc(hd->hd_data_size); c = recv(fd, hd->hd_data, hd->hd_data_size, MSG_WAITALL); if(c < 1) { free(hd->hd_data); free(hd); return -1; } hd->hd_data_len = c; hd->hd_data_off = 0; TAILQ_INSERT_TAIL(&hq->hq_q, hd, hd_link); hq->hq_size += c; return 0; } /** * */ int htsp_tcp_read_line(socket_t fd, char *buf, const size_t bufsize, htsbuf_queue_t *spill) { int len; while(1) { len = htsbuf_find(spill, 0xa); if(len == -1) { if(tcp_fill_htsbuf_from_fd(fd, spill) < 0) return -1; continue; } if(len >= (int)bufsize - 1) return -1; htsbuf_read(spill, buf, len); buf[len] = 0; while(len > 0 && buf[len - 1] < 32) buf[--len] = 0; htsbuf_drop(spill, 1); /* Drop the \n */ return 0; } } /** * */ int htsp_tcp_read_data(socket_t fd, char *buf, const size_t bufsize, htsbuf_queue_t *spill) { int x, tot = htsbuf_read(spill, buf, bufsize); if(tot == bufsize) return 0; x = recv(fd, buf + tot, bufsize - tot, MSG_WAITALL); if(x != bufsize - tot) return -1; return 0; } /** * */ int htsp_tcp_read(socket_t fd, void *buf, size_t len) { int x = recv(fd, buf, len, MSG_WAITALL); if(x == -1) return socket_errno(); if(x != len) return ECONNRESET; return 0; } /** * */ int htsp_tcp_read_timeout(socket_t fd, char *buf, size_t len, int timeout) { int x, tot = 0, val, err; fd_set fd_read; struct timeval tv; assert(timeout > 0); while(tot != len) { tv.tv_sec = timeout / 1000; tv.tv_usec = 1000 * (timeout % 1000); FD_ZERO(&fd_read); FD_SET(fd, &fd_read); x = select((int)fd+1, &fd_read, NULL, NULL, &tv); if(x == 0) return ETIMEDOUT; val = 1; ioctlsocket(fd, FIONBIO, &val); x = recv(fd, buf + tot, len - tot, 0); err = socket_errno(); val = 0; ioctlsocket(fd, FIONBIO, &val); if(x == 0) return ECONNRESET; else if(x == -1) { if(err == EAGAIN) continue; return err; } tot += x; } return 0; } /** * */ void htsp_tcp_close(socket_t fd) { closesocket(fd); } pvr.hts-4.4.20-Leia/lib/libhts/sha1.c000066400000000000000000000146161355512543200171250ustar00rootroot00000000000000/* * Copyright (C) 2007 Michael Niedermayer * based on public domain SHA-1 code by Steve Reid * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Modified by Joakim Plate to be stand alone from libavutil */ #include "sha1.h" #include static uint16_t bswap_16(uint16_t x) { x= (x>>8) | (x<<8); return x; } static uint32_t bswap_32(uint32_t x) { x= ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF); x= (x>>16) | (x<<16); return x; } static uint64_t bswap_64(uint64_t x) { union { uint64_t ll; uint32_t l[2]; } w, r; w.ll = x; r.l[0] = bswap_32 (w.l[1]); r.l[1] = bswap_32 (w.l[0]); return r.ll; } // be2me ... big-endian to machine-endian // le2me ... little-endian to machine-endian #ifdef WORDS_BIGENDIAN #define be2me_16(x) (x) #define be2me_32(x) (x) #define be2me_64(x) (x) #define le2me_16(x) bswap_16(x) #define le2me_32(x) bswap_32(x) #define le2me_64(x) bswap_64(x) #else #define be2me_16(x) bswap_16(x) #define be2me_32(x) bswap_32(x) #define be2me_64(x) bswap_64(x) #define le2me_16(x) (x) #define le2me_32(x) (x) #define le2me_64(x) (x) #endif typedef struct HTSSHA1 { uint64_t count; uint8_t buffer[64]; uint32_t state[5]; } HTSSHA1; const int hts_sha1_size = sizeof(HTSSHA1); #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ #define blk0(i) (block[i] = be2me_32(((const uint32_t*)buffer)[i])) #define blk(i) (block[i] = rol(block[i-3]^block[i-8]^block[i-14]^block[i-16],1)) #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y) +blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y) +blk (i)+0x5A827999+rol(v,5);w=rol(w,30); #define R2(v,w,x,y,z,i) z+=( w^x ^y) +blk (i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk (i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); #define R4(v,w,x,y,z,i) z+=( w^x ^y) +blk (i)+0xCA62C1D6+rol(v,5);w=rol(w,30); /* Hash a single 512-bit block. This is the core of the algorithm. */ static void transform(uint32_t state[5], const uint8_t buffer[64]){ uint32_t block[80]; unsigned int i, a, b, c, d, e; a = state[0]; b = state[1]; c = state[2]; d = state[3]; e = state[4]; #if CONFIG_SMALL for(i=0; i<80; i++){ int t; if(i<16) t= be2me_32(((uint32_t*)buffer)[i]); else t= rol(block[i-3]^block[i-8]^block[i-14]^block[i-16],1); block[i]= t; t+= e+rol(a,5); if(i<40){ if(i<20) t+= ((b&(c^d))^d) +0x5A827999; else t+= ( b^c ^d) +0x6ED9EBA1; }else{ if(i<60) t+= (((b|c)&d)|(b&c))+0x8F1BBCDC; else t+= ( b^c ^d) +0xCA62C1D6; } e= d; d= c; c= rol(b,30); b= a; a= t; } #else for(i=0; i<15; i+=5){ R0(a,b,c,d,e,0+i); R0(e,a,b,c,d,1+i); R0(d,e,a,b,c,2+i); R0(c,d,e,a,b,3+i); R0(b,c,d,e,a,4+i); } R0(a,b,c,d,e,15); R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); for(i=20; i<40; i+=5){ R2(a,b,c,d,e,0+i); R2(e,a,b,c,d,1+i); R2(d,e,a,b,c,2+i); R2(c,d,e,a,b,3+i); R2(b,c,d,e,a,4+i); } for(; i<60; i+=5){ R3(a,b,c,d,e,0+i); R3(e,a,b,c,d,1+i); R3(d,e,a,b,c,2+i); R3(c,d,e,a,b,3+i); R3(b,c,d,e,a,4+i); } for(; i<80; i+=5){ R4(a,b,c,d,e,0+i); R4(e,a,b,c,d,1+i); R4(d,e,a,b,c,2+i); R4(c,d,e,a,b,3+i); R4(b,c,d,e,a,4+i); } #endif state[0] += a; state[1] += b; state[2] += c; state[3] += d; state[4] += e; } void hts_sha1_init(HTSSHA1* ctx){ ctx->state[0] = 0x67452301; ctx->state[1] = 0xEFCDAB89; ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; ctx->state[4] = 0xC3D2E1F0; ctx->count = 0; } void hts_sha1_update(HTSSHA1* ctx, const uint8_t* data, unsigned int len){ unsigned int i, j; j = ctx->count & 63; ctx->count += len; #if CONFIG_SMALL for( i = 0; i < len; i++ ){ ctx->buffer[ j++ ] = data[i]; if( 64 == j ){ transform(ctx->state, ctx->buffer); j = 0; } } #else if ((j + len) > 63) { memcpy(&ctx->buffer[j], data, (i = 64-j)); transform(ctx->state, ctx->buffer); for ( ; i + 63 < len; i += 64) { transform(ctx->state, &data[i]); } j=0; } else i = 0; memcpy(&ctx->buffer[j], &data[i], len - i); #endif } void hts_sha1_final(HTSSHA1* ctx, uint8_t digest[20]){ int i; uint64_t finalcount= be2me_64(ctx->count<<3); hts_sha1_update(ctx, (const uint8_t*)"\200", 1); while ((ctx->count & 63) != 56) { hts_sha1_update(ctx, (const uint8_t*)"", 1); } hts_sha1_update(ctx, (uint8_t *)&finalcount, 8); /* Should cause a transform() */ for(i=0; i<5; i++) ((uint32_t*)digest)[i]= be2me_32(ctx->state[i]); } #ifdef TEST #include #undef printf int main(void){ int i, k; HTSSHA1 ctx; unsigned char digest[20]; for(k=0; k<3; k++){ av_sha1_init(&ctx); if(k==0) av_sha1_update(&ctx, "abc", 3); else if(k==1) av_sha1_update(&ctx, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56); else for(i=0; i<1000*1000; i++) av_sha1_update(&ctx, "a", 1); av_sha1_final(&ctx, digest); for (i = 0; i < 20; i++) printf("%02X", digest[i]); putchar('\n'); } //test vectors (from FIPS PUB 180-1) printf("A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D\n" "84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1\n" "34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F\n"); return 0; } #endif pvr.hts-4.4.20-Leia/lib/libhts/sha1.h000066400000000000000000000023321355512543200171220ustar00rootroot00000000000000/* * Copyright (C) 2007 Michael Niedermayer * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Modified by Joakim Plate to be stand alone from libavutil */ #ifndef HTS_SHA1_H #define HTS_SHA1_H #include extern const int hts_sha1_size; struct HTSSHA1; void hts_sha1_init(struct HTSSHA1* context); void hts_sha1_update(struct HTSSHA1* context, const uint8_t* data, unsigned int len); void hts_sha1_final(struct HTSSHA1* context, uint8_t digest[20]); #endif /* HTS_SHA1_H */ pvr.hts-4.4.20-Leia/pvr.hts/000077500000000000000000000000001355512543200154665ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/addon.xml.in000066400000000000000000000311001355512543200176750ustar00rootroot00000000000000 @ADDON_DEPENDS@ Kodi se voorprogram vir Tvheadend Kodi's frontend for Tvheadend Клиент за „Tvheadend“ Frontal de Kodi per a Tvheadend Rozhraní Kodi pro Tvheadend Blaen Kodi ar gyfer Tvheadend Kodis brugerflade til Tvheadend Kodi-PVR-Client für Tvheadend Το frontend του Kodi για το Tvheadend Kodi's frontend for Tvheadend Kodi's frontend for Tvheadend Kodi's frontend for Tvheadend Kodi's frontend for Tvheadend Interfaz Kodi para Tvheadend Interfaz Kodi para Tvheadend El frontend de Kodi para Tvheadend Kodi liides Tvheadend'ile Kodin Tvheadend-asiakasohjelma Frontale Kodi pour Tvheadend Interface logicielle pour Tvheadend Interface do Kodi para Tvheadend לקוח טלוויזיה חיה עבור Tvheadend Kodi sučelje za Tvheadend Kodi előtét a TVHeadend-hez Frontend Kodi untuk Tvheadend Kodi framendi fyrir Tvheadend Frontend di Kodi per Tvheadend TVheadend 用 Kodi フロントエンド Tvheadend 을 위한 Kodi 프론트엔드 Kodi naudotojo sąsaja skirta Tvheadend Kodi galasistēma Tvheadend Kodi's frontend for Tvheadend Tvheadend зориулагдсан Kodi-ийн нүүр Bahagian hadapan Kodi untuk Faċċata ta' Kodi għat- TVheadend Kodis grenseflate for Tvheadend Kodi's frontend voor Tvheadend Klient telewizji dla Tvheadend Frontend Kodi para Tvheadend Interface Kodi para Tvheadend Interfața Kodi pentru Tvheadend Интерфейс Kodi для Tvheadend Kodi rozhranie pre Tvheadend Kodijev vmesnik za Tvheadend Frontend i Kodi'së për Tvheadend Kodi-јев интерфејс за Tvheadend Kodijev interfejs za Tvheadend Kodi's frontend för Tvheadend Frontend do Tvheadend ôd Kodi Tvheadend కోసం కోడి యొక్క ఫ్రంటెండ్ Интерфейси Kodi барои Tvheadend Tvheadend için Kodi ön ucu Інтерфейс Kodi для Tvheadend Giao tiếp Kodi cho Tvheadend Kodi 的 Tvheadend 前端 Kodi的Tvheadend前端介面 Tvheadend voorprogram; ondersteun stroom van Lewendige TV & Opnames, EPG, Tydhouers Tvheadend frontend; supporting streaming of Live TV & Recordings, EPG, Timers Клиент за „Tvheadend“. Поддържа телевизия на живо, записване, електронен програмен справочник и броячи. Frontal de Tvheadend; compatible amb la transmissió de TV en directe i enregistraments, guia electrònica de programació (EPG), temporitzadors Rozhraní Tvheadend; podporuje streamování živého vysílání a nahrávání, televizní program, časovače. Blaen Tvheadend: cefnogi ffrydio Teledu Byw a Recordio, Amserlenni, Amseryddion Tvheadend-brugerflade; understøtter streaming af direkte tv og optagelser, EPG og timere PVR-Client für Tvheadend. Unterstützt TV & Aufnahmen, Programm-Guide (EPG) und Timer. Frontend για το Tvheadend. Υποστηρίζει ροές Live TV & Εγγραφές, EPG, Χρονοδιακόπτες Tvheadend frontend; supporting streaming of Live TV & Recordings, EPG, Timers Tvheadend frontend; supporting streaming of Live TV & Recordings, EPG, Timers Tvheadend frontend; supporting streaming of Live TV & Recordings, EPG, Timers Tvheadend frontend; supporting streaming of Live TV & Recordings, EPG, Timers Interfaz Tvheadend; soporta la reproducción de TV en vivo, grabación, guía de programación, temporizadores Interfaz Tvheadend; soporta la reproducción de TV en vivo, grabación, guía de programación, temporizadores Frontend de Tvheadend; Compatible con la transmisión de TV en directo y Grabaciones, EPG, Temporizadores Tvheadend'i liides. Toetab telekanalite striimimist ja salvestamist ning elektroonilist saatekava. Tvheadend-asiakasohjelma. Tukee suorien tv-lähetysten ja tallennusten katsomista, ohjelmaopasta ja ohjelmien ajastamista. Frontale pour Tvheadend, prenant en charge la diffusion en continu des télés en direct et les enregistrements, le GÉP et les minuteries Interface logicielle pour Tvheadend gérant la lecture en continu de la TV en direct et des enregistrements, le guide électronique des programmes TV et les programmations. Interface Tvheadend; soporta a transmisión de TV en directo e Gravacións, Guía, temporizadores לקוח טלוויזיה חיה של Tvheadend. תומך בהזרמת שידורים חיים והקלטות, האזנה לרדיו, הצגת לוח שידורים ותזמון הקלטות. Tvheadend pozadinski softver podržava gledanje i snimanje TV programa, elektronski programski vodič (EPG) i zakazano snimanje. TVHeadend előtét. Élő adások és felvételek támogatása EPG-vel és időzítéssel Frontend Tvheadend; mendukung menangkap siaran TV Live & Rekaman, EPG, Timer Tvheadend framendi; styður streymingu á beinum útsendingum og upptökum, rafrænum sjónvarpsvísum (EGP), tímatökur Frontend di Tvheadend; supporta lo streaming di Live TV & Registrazione, EPG, Timers TVheadend フロントエンドです。ライブTVストリーミング、録画、EPG、タイマーをサポートしています。 Tvheadend 프론트엔드; TV 시청 & 녹화, EPG, 타이머 지원 Tvheadend naudotojo sąsaja; palaiko televizijos transliacijas ir įrašus, EPG, laikmačius Tvheadend galasistēma; atbalsta tieštaides TV un ierakstu straumēšanu, EPG, taimerus Tvheadend frontend; supporting streaming of Live TV & Recordings, EPG, Timers Tvheadend нүүр; Live TV & бичлэг дамжуулалт, EPG, Timer Bahagian hadapan Tvheadend; menyokong penstriman Langsung & Rakaman, EPG, Pemasa TV Faċċata ta' TVheadend; jiflaħ għal streaming ta' TV Lajv u rekordings, EPG, Arloġġi Tvheadend-grenseflate; støtte for visning av direkte-TV og opptak, EPG, tidsur Tvheadend frontend. Ondersteuning van streaming, Live-TV & opnames, EPG, Timers Klient telewizji dla Tvheadend obsługuje transmisję kanałów radiowych i telewizyjnych, nagrywanie i harmonogram nagrań oraz funkcje przewodnika telewizyjnego. Tvheadend; suporta streaming de TV Ao Vivo e Gravada, EPG, Agendamentos Interface Tvheadend. Suporta transmissão e gravação de TV em direto, EPG e temporizadores. Partea din față pentru Tvheadend; suportă difuzarea în flux a televiziunii în direct și a înregistrăriilor, EPG, Cronometre Интерфейс для Tvheadend. Поддерживает просмотр и запись ТВ, EPG и таймеры Rozhranie pre Tvheadend; je podporované streamovanie živého televízneho vysielania a nahrávok, EPG, časovačov Vmesnik za Tvheadend; podpira pretakanje televizije v živo & posnetkov, EPG, časovnike Tvheadend frotnend përkrahën transmetimin e Live TV'së, EPG'së dhe "timer'ë" Tvheadend интерфејс; подржава стримовање ТВ Уживо & Снимака, EPG, Тајмере Tvheadend interfejs; podržava strimovanje TV Uživo & Snimaka, EPG, Tajmere Tvheadend frontend; stödjer strömning av Live-TV & inspelningar, EPG, Timers Frontend Tvheadend; podpiyrŏ strumiyniowaniy TV, nagrań, EPG i minutnikōw Tvheadend ఫ్రంటెండ్; Live TV & రికార్డింగ్స్, EPG, టైమర్లు , స్ట్రీమింగ్ మద్దతు కలదు Интерфейси Tvheadend; дастгирии ҷараёни Сабтҳо, Вақтсанҷҳо, Live TV ва EPG Tvheadend ön ucu; Canlı TV akışı ve kayıt yapabilme, EPG ve zamanlayıcıları destekler Інтерфейс для Tvheadend; підтримує передачу і запис потокового телебачення, EPG (телегід) і таймери. Giao tiếp cho Tvheadend; hỗ trợ truyền phát và thu chương trình Live TV, hẹn giờ, và hiển thị lịch chiếu (EPG) Tvheadend 前端,支持直播电视和录像流媒体、电子节目单、定时器 Tvheadend前端,支援的串流媒體包含有直播電視和錄製節目,電子節目表,定時器 等 @PLATFORM@ pvr.hts-4.4.20-Leia/pvr.hts/changelog.txt000066400000000000000000000367761355512543200202010ustar00rootroot000000000000004.4.20 - Fixed: 'Stop recording' no longer aborts in-progress recordings (HTSP v26) 4.4.19 - Update build system version and cleanup - Change kodi header include way 4.4.18 - Predictive tuning: Fix unability to retune to a channel that was closed immediately before. 4.4.17 - Fix playback when skipping an in progress recording to real-time. 4.4.16 - Fix auto close of timeshifted subscriptions if predictive tuning is activated - Increase packet queuedepth size for subscriptions to workaround timeshift stuttering problems 4.4.15 - Fix/improve HTSPDemuxer timeshift support 4.4.14 - Fix HTSPDemuxer::IsRealTimeStream to always return true if subscription is active. 4.4.13 - Fixed missing description in EPG and DVR tags. 4.4.12 - Fixed missing summary in EPG tags. 4.4.11 - Increase the maximum stream chunk size to 512 KB 4.4.10 - Updated language files from Transifex 4.4.9 - Fix a link in the README 4.4.7 - Add support for recent tvheadend 4.3 image URL changes (HTSP v34) 4.4.6 - updated language files from Transifex 4.4.5 - Fixed buffer overflow in Logger::Log 4.4.4 - updated language files from Transifex 4.4.3 - updated language files from Transifex 4.4.2 - Fix RDS stream support. Only mpeg2 audio streams can contain embedded RDS data and there can be at most one RDS stream at a time. 4.4.1 - Fix creation of RDS streams. Must only be done if audio stream actually contains RDS data. 4.4.0 - Add support for Radio Data System (RDS) - Enable async EPG data transfer by default 4.3.11 - updated language files from Transifex 4.3.10 - Add support for fanart image for recordings if supplied by tvheadend (tvh4.3+). 4.3.9 - PVR Addon API 5.10.2: Implemented support for PVR_ADDON_CAPABILITIES.bSupportsAsyncEPGTransfer 4.3.8 - Add support for thumbnail image for recordings if supplied by tvheadend (tvh4.3+). 4.3.7 - Fixed an edge case where wrong times were displayed in Kodi video/audio OSD 4.3.6 - updated language files from Transifex 4.3.5 - demuxer: fix begin/end pts precision - predictive tuning: do not close paused subscriptions 4.3.4 - Add stub for "subscriptionGrace" HTSP method. - Add setting to ignore duplicate scheduled recordings (tvh4.3+) 4.3.3 - updated language files from Transifex 4.3.2 - updated language files from Transifex 4.3.1 - updated language files from Transifex 4.3.0 - PVR Addon API 5.10.0: Implemented recording stream read chunk size as addon setting. 4.2.17 - Fix predictive tuning (do not close subscriptions that never were active). 4.2.16 - updated language files from Transifex 4.2.15 - updated language files from Transifex 4.2.14 - PVR API 5.9.0 changes implemented 4.2.12 - Recordings: Use real start time and duration if available. - Recordings: Add support for season and episode number (tvh4.3+). - New addon logo. 4.2.11 - Fixed crashes on addon destruction 4.2.10 - PVR API v5.5.0: Implemented GetStreamTimes for recordings 4.2.9 - PVR API v5.5.0: Implemented GetStreamTimes for TV/radio streams - PVR API v5.8.0: Dropped GetPlayingTime, GetBufferTimeStart, GetBufferTimeEnd, PositionRecordedStream, PositionLiveStream, MoveChannel - PVR API v5.8.0: Added support for PVR_CHANNEL_GROUP_MEMBER::iSubChannelNumber 4.2.8 - updated language files from Transifex 4.2.7 - Fixed predictive tuning (was broken with removal of API function 'SwitchChannel') - Added support for subchannel numbers (ATSC) to predictive tuning 4.2.6 - More code cleanup - Fixed deadlock that may have occured when switching channels - Added support for new EPG tag attributes: 'credits' (actors, writers, directors), 'categories', 'year' (Thanks to azlm8t for testing and for a fix) - Added support for new autorec dedup types: 'max once per month', 'unique episode according to EPG/XMLTV' 4.2.5 - updated language files from Transifex 4.2.4 - updated language files from Transifex 4.2.3 - misc code cleanup 4.2.2 - fixed: memory leak. Localized strings obtained from Kodi never were freed. - optimized container usage: replace push_back by emplace_back to avoid unneeded copies (also fixes a stack overflow in function GetTimerTypes). 4.2.1 - updated language files from Transifex 4.2.0 - PVR API v5.7.0: Add stubs for IsEPGTagRecordable, IsEPGTagPlayable and GetEPGTagStreamProperties - PVR API v5.7.0: Remove EPG_TAG::iChannelNumber, add EPG_TAG::iChannelUniqueId. 4.1.3 - PVR API v5.6.0: Drop GetLiveStreamURL - PVR API v5.6.0: Drop PVR_RECORDING::strStreamURL - PVR API v5.6.0: Add stubs for GetChannelStreamProperties and GetRecordingStreamProperties 4.1.2 - PVR API v5.5.0: Add series link support - PVR API v5.5.0: Drop GetChannelSwitchDelay - PVR API v5.5.0: Add stub for GetStreamTimes (can be implemented later) 4.1.1 - PVR API v5.4.0: Drop SwitchChannel 4.1.0 - PVR API v5.3.0: Add implementation for GetDescrambleInfo - PVR API v5.3.0: Adapt definition of epg based timer rule (Added PVR_TIMER_TYPE_SUPPORTS_ANY_CHANNEL attribute) - PVR API v5.3.0: Add implementation for SetRecordingLifetime and for PVR_ADDON_CAPABILITIES lifetime values - PVR API v5.3.0: Add support for PVR_ADDON_CAPABILITIES.bSupportsRecordingsRename 4.0.17 - Fixed timer/recordings lifetime special values mapping ("until space needed", "forever") 4.0.16 - Added support for genre to recordings 4.0.15 - Added support for 'default' recording priority setting value 4.0.14 - Readded server based play count/position for recordings (HTSP v27 and up) 4.0.13 - PVR API: Removed unused addon interface function 4.0.12 - Updated Debian package control - PVR API: addon callback changes 4.0.11 - PVR API: Removed obsolete version functions 4.0.10 - set dependency version values automatically during build - PVR API: Removed unused addon interface functions 4.0.9 - fixed: timeshift state and data calculation if demuxer is not active (e.g. when playing a recording) 4.0.8 - revert server based playstatus, tvheadend is not compatible at the moment 4.0.7 - fixed duplicate 'prevent duplicate episodes' timer settings values 4.0.6 - added HTSP v26 support - added server based playstatus for recordings (HTSP v26 and up) 4.0.5 - fix CTvheadend::DemuxIsTimeShifting 4.0.4 - improved: use the default retention (from server configuration) - improved: buffering method when timeshifting - fixed: possible empty duplicate detection field when opening a timer rule - fixed: possible time offset when tuning a channel with predictive tuning enabled 4.0.3 - fixed unresponsiveness when wrong credentials are used 4.0.2 - updated build instructions in the README - fixed Travis CI and AppVeyor automated builds - fixed a bunch of cast warnings - cleanup stream handling somewhat 4.0.1 - updated language files from Transifex 4.0.0 - Initial Kodi v18 version 3.4.10 - Adpations for PVR API v5.2.1 3.4.9 - Updated to PVR API v5.2.1 (just made it compile again) 3.4.8 - improve EPG loading performance 3.4.7 - updated language files from Transifex 3.4.6 - updated language files from Transifex 3.4.5 - updated language files from Transifex 3.4.4 - fixed: setting channel type for 'early' htsp v25 servers - fixed: setting epg uid for timers 3.4.3 - improved: only show real radio and TV channels in Kodi - improved: recording handling when it's channel doesn't exist anymore (HTSP v25 and above) 3.4.2 - updated language files from Transifex 3.4.1 - Fix instant timers 3.4.0 - Cmake: rename find_package kodi to Kodi 3.3.2 - Fix includes 3.3.1 - Fixed a problem with async state handling that could happen when restoring a lost connection to tvheadend. 3.3.0 - Updated to PVR API v5.2.0 3.2.3 - fixed: potential crash in the channel tuning predictor 3.2.2 - Updated to PVR API v5.1.1 (added: support for PVR_CONNECTION_STATE_CONNECTING) - fixed: potential crash in connection state change callback 3.2.1 - fixed: lifetime 'forever' should be disabled for HTSP v24 and lower - improved: make lifetime settings translatable 3.2.0 - Updated to PVR API v5.1.0 3.1.0 - Updated to PVR API v5.0.0 3.0.2 - updated to PVR API v4.2.0 (implemented IsRealTimeStream) 3.0.1 - updated language files from Transifex 3.0.0 - Initial Kodi Krypton version. 2.2.12 - updated language files from Transifex 2.2.11 - updated language files from Transifex - added: proper autorec/timerec support for HTSP v25 and above 2.2.10 - updated language files from Transifex - fixed: approximate start time setting - fixed: invalid addon restart when closing the settings dialog - improved: limit the amount of timer lifetime values - improved: separate timer and streaming settings - added: default setting for timer lifetime, priority and duplicate detection - fixed: restart subscription after a connection restore - fixed: allow to abort active recordings also for timers created by timerec and autorec - fixed: enable/disable of timers created by timerec and autorec (HTSP v23 and above) - refactored the logging utility from a bunch of macros to a class 2.2.9 - refactored the code by factoring out lots of things into separate files - refactored the Settings class into a singleton to avoid having to include client.h everywhere - added: support for specifying which streaming profile to use - added: support for enabling/disabling oneshot timers (HTSP v23 and above) - added: timer lifetime will now remove the actual file instead of database entry only (HTSP v24 and above) 2.2.8 - Updated to PVR API v4.1.0 - simplified recording playback handling, fixes random skipping to the beginning of recordings - fixed: recordings from channels that have been deleted since were not available in Kodi - added: setting for start time window calculation (autorec) - simplified addon settings - added: support for episode name (subtitle) for recordings 2.2.7 - Updated to PVR API v4.0.0 2.2.6 - Minimal support for PVR API v3.0.0 incl. Repeating EPG Timer AnyTime Bool Change 2.2.5 - dropped CStdString usage - added: Implementation of GetBufferTimeStart and GetBufferTimeEnd (timeshifting). - fixed: Coverity warnings introduced by predictive tuning feature. - fixed: Autorec: Start and stop time handling. - fixed: LocaltimeToUTC conversion (timer settings clock display incorrect). - fixed: Several issues with predictive tuning. - added: build: Automatically fill in platform and library name. - fixed: Use epg data only for creation of epg-based timers. - improved: Do not try to reconnect to tvh while suspending or not fully awake again. 2.2.4 - added: Predictive tuning (thanks @martinwilli) - added: Include satpos in mux description (thanks @Glenn-1990) - fixed: Crashes due to memory corruption (stack overflow) 2.2.3 - Updated to PVR API v2.1.0 2.2.2 - Debian packaging: fix library install path - Miscellaneous backend fixes 2.2.1 - updated to PVR API v2.0.0 - fixed: a Coverity warning 2.2.0 - updated to PVR API v1.9.7 - added: support for series recordings (autorec, timerec) 2.1.13 - updated language files from Transifex 2.1.12 - fixed: channel icon compatibility issue with recent tvheadend servers. - fixed: EPG events update (some data was not updated correctly) 2.1.11 - fixed: do not show HTSP version mismatch error if tvheadend server is down. 2.1.10 - fixed: lowered required HTSP version to 10 to allow using Tvheadend 3.4 again. 2.1.9 - fixed: packaging issues - fixed: minor issues found by static analysis - added: support for season/episode/part numbers for EPG tags - added: check htsp version upon connect. Refuse to use servers with HTSP version not matching minimal HTSP version required by client. 2.1.8 - added: support for epg subtitles, aka episode names - added: support for creating repeating timers, aka time schedules - fixed: conditions for addon restart after settings changes - internal: fixed build system regressions introduced with move to cmake - internal: updated to use libplatform 2.1.7 - added: support for radio channel groups - added: support for star and parental rating (read only) 2.1.6 - updated to PVR API v1.9.6 - added: support for channel group sort index - fixed: crash while adding/updating timers on the client (double free of a htsp message) 2.1.5 - improved HTSP specification compliance 2.1.4 - updated to PVR API v1.9.5 - added: avahi discovery - fixed: lock on exit - fixed: race when seeking within recordings - fixed: CHTSPVFS::Read() needs the mutex locked - removed guilib dep 2.1.1 - updated to PVR API v1.9.4 - updated to GUI API v5.8.0 - updated to Codec API v1.0.1 2.0.5 - fixed incorrect timeout value when deleting recordings (thanks @ksooo) 2.0.4 - added a missing commit that somehow got lost when making v2.0.3 2.0.3 - rebrand of HTSP client identifier - improve the VFS slightly by doing reading and buffering on separate threads, as well as tweaking the read length 2.0.2 - language files from Transifex - minor changes to conform with C++11 2.0.0 - replaced by the newer pvr.tvh implementation 1.9.40 - added getBackendHostname function 1.9.38 - change library name to Kodi 1.9.37 - backport ATSC subchannel number support from pvr.tvh 1.9.36 - fixed deadlock when activating the addon on some darwin (osx, ios) runtimes 1.9.35 - improve sync after connection restore (@ksooo) - added support for getting and setting startExtra, stopExtra, retention, priority properties of recordings and timers (@ksooo) - backported GetPlayingTime from pvr.tvh (@ksooo) 1.9.31 - updated to API v1.9.2 1.9.27 - fix channel icons for recordings 1.9.24 - add EDL support 1.9.23 - add timeshift buffer functions 1.8.21 - fixed connection being dropped incorrectly, when a packet size timed out with a one or more bytes read, but less than 4 bytes read - tvheadend uses it's own byte order. don't use ntohl 1.8.20 - sync with PVR API v1.8.1 - use XBMC's new callback methods for codec ids 1.8.19 - sync with PVR API v1.8.0 1.7.19 - bump after PVR API version bump 1.6.19 - add timeshift skip support (FF/RW still not working) - fix bug in tvh webroot processing 1.6.18 - ensure channel count is not cleared after succesful sub - fix default webroot param - remove missing files from recordings list - expand dvr directories to full hierarchy 1.6.17 - fixed possible crash after reconnecting 1.6.16 - correct some signed/unsigned mixups - added imagecache support (icons on the backend) 1.6.15 - fix false disconnects by raising default (hardcoded) read timeout value when opening streams from 10 to 20 seconds. 1.6.14 - fix errors sent by client when fetching events for a channel with no epg data 1.6.13 - make channel.radio to not reset to false during update if tvheadend not provided channel services - change handling of EPG events to not fail all events if only one/few events were broken/malformed 1.6.12 - fix instant recordings when channel has no epg data 1.6.11 - disable read timeout check while the stream is paused 1.6.10 - fixed authentication - display an error message when an error is detected 1.6.9 - call to Close() didn't work in CHTSPData::Open() - don't delete and create CHTSPReconnect each time, just stop the thread - don't wait for an iframe but let tvheadend handle it - fixed missing htsmsg_destroy() call after processing an incoming message 1.6.8 - refactor CHTSPConnection - fixed disconnection checks and reconnect when needed - consider the connection dropped if no data has been received for a while - more efficient data reading - shared connection between CHTSPDemux and CHTSPData 1.6.7 - add support for servers with transcoding capabilities 1.6.6 - fixed radio playback 1.6.5 - fixed channel and channel group update triggers - ensure that the first demux is an I-frame - add CHTSPConnection::CheckConnection() that waits for a connection to be restored when it was dropped - cleaner CHTSPConnection::Connect() - removed unneeded member in CHTSPDemux - better handling of disconnect and reconnects 1.6.4 - initial release pvr.hts-4.4.20-Leia/pvr.hts/icon.png000066400000000000000000000134171355512543200171320ustar00rootroot00000000000000PNG  IHDR\rfgAMA a cHRMz&u0`:pQ<bKGD pHYsgRIDATxmeEy}̮QJ"QҊ"j(RDvvASĈoAZ&PjBo `Sh&laķEbLZew=}̝ٙٹs9_U;Kݧ` Eey*ZRn:"Rv+^ѱ!V"Ħx-[$'9{b%@,~(@ ~QEBHD!L _$0 ~(@("a$&QEHM @ ԍ/2B_dP  ~)("c$qPEH H #Hâ CHà cHE6/%GχGugأJUÁ.Йw~pśpQ|cT/8x+}|p=sGt5Hka7n~׀oΈ=98Lg' ?s;W7#nBu z Az%k`Rp؃ئJ$ p/ޭ_9'Ӈ5 Pcp ^gW`\W ,!!ev6@khlB^|FTI0%]$`v vR71?{$O/_1l.!eέ1j =hE 5DX$sCѺ2; ~km٧Ơ l v&+ῗ^' dM!eMinI k o?,6-0g6X_>FĴ 7s~e6XI!CElwo*q#W\S`/p9?LˣbPTk=8C!s.JQ9S۷x?)<,xyy8n,% QI@^ Dd:  Y$b:pSP]{D&I~wCαór]\@#|{5sgN6͐$нz]ppRqOpp5~Jd%q毁"^DZx42c{毎=zS$: fap M|)Mp]IN`*eÄG7I^S$ dWXk$P7H@05PK῅_,/ L Q}{ ' 4@t HF_I9J@0@XZh2gBH}u H@ȘU _=oމ[z,RYn_5Ep?CH8*+wosUT?H|p΁j_x-~HfxGx4c s6#عtg~Aj䗁c#DN#U:/أ 49,S../OA/c~PE,v6+&{5ۻ!"(d|L:+'~1jPAhn=9t^8I~ |`fwQ8O أ'V?.TWɘ;/En5M_:p[Az# s80eׂ=C;&QB<ŽY < ;  i߭ c(5aa++KWDk N&,$¿h;%7NaNI nՁ6K ~-+nB=Ձ;fo+馪蘭6/mC%7P>޸cJD@{V?pOYhuAߐa80@C$vwcNK@5?,wL=F?ht@5?~WG3VCoZuh~pJ `)9kUӁP s~eI12@9xk Zusn'"p8htՁAC8;CT;I k7?gظģ$Gx1CStCǣ{ƹN1@:p-UyTD7N풒@cj :𷀸%su[( j 6@6m_~+ `Ơ$Pӻazg+J/(mg%CE.YQX wq|Y]&_-<>ݟz6~ ;)[ˁ^ P!p'3c&q;ͬ"[K3ӗrOcTUY`Gs ;Fؿ:>={(YĖtXҕC=;m, $I2P:h7f@s ~o;`Y MmѲK9 %J%_᷂}VnLKma:м_lKMI`7I(C!-󯦝ַ:ny+F -PO`-o HX@} sTïuHX_|tap^VMpFCŹ_16EqNYdv{{5 `-vLs[F8 .U~JJdBٿ;Ua?܌cI>u!% ܎{CG8sE 3W q :'$C`DT ? @䌺c"\Dh_ F$ H"o @䀺 !QA$27 REHBH"5WVF)Y TX>' R@ᏄQ/"DLH"'&>FDP =z؃h )P<|7HBO )J,;أ?A$ p0pj CH vN vuGbHs z0@r GkҐh{oH)R7'&Q/$ɯP3Bȁ|$|tN5s`4x<fcpۯg*HP/S$HO H9~#JJ@71|WŸ5@đ`_M,0~Ɛм~Hhnu@ ?H֨P &5m n@~a 2K@ )eVNx`JhsFs+3*֑<O%T?@{:VRyR%tEXtdate:create2018-01-15T15:22:24+01:00;HP%tEXtdate:modify2018-01-15T15:22:24+01:00J(IENDB`pvr.hts-4.4.20-Leia/pvr.hts/resources/000077500000000000000000000000001355512543200175005ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/000077500000000000000000000000001355512543200212635ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.af_za/000077500000000000000000000000001355512543200257535ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.af_za/strings.po000066400000000000000000000167711355512543200300200ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Verbinding verstellings" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend gasheernaam of IP adres" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP poort" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP poort" msgctxt "#30004" msgid "Username" msgstr "Gebruikersnaam" msgctxt "#30005" msgid "Password" msgstr "Wagwoord" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Konneksie tydverstreke (sekondes)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Reageer tydverstreke (sekondes)" msgctxt "#30008" msgid "Advanced settings" msgstr "Gevorderde verstellings" msgctxt "#30009" msgid "Streaming settings" msgstr "Stroom verstellings" msgctxt "#30010" msgid "Timer settings" msgstr "Tydhouer verstellings" msgctxt "#30050" msgid "Auto recordings" msgstr "Outo opnames" msgctxt "#30051" msgid "Start time window calculation" msgstr "Begin tyd venster berekening" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Streng (begin tyd + eind tyd)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Ontspanne (begin tyd +/- marge)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Maksimum begin tyd marge (minute)" msgctxt "#30055" msgid "Default priority" msgstr "Verstek prioriteit" msgctxt "#30056" msgid "Default lifetime" msgstr "Verstek leeftyd" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Verstek duplikaat deteksie" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Verstek vir nuwe tydhouers" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Geskeduleerde opnames" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Ignoreer duplikate (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Data oordrag" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asinchrone EPG oordrag" msgctxt "#30200" msgid "Debugging" msgstr "Ontfouting" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Spoor na (gedetailleerd)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP weergawe stem nie ooreen (ondersteun: v%d, vereis: v%d). Opdateer asseblief tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Een keer (Geskeduleer deur tydhouer reël)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Belangrik (hoogste)" msgctxt "#30352" msgid "High" msgstr "Hoog" msgctxt "#30353" msgid "Normal" msgstr "Normaal" msgctxt "#30354" msgid "Low" msgstr "Laag" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Onbelangrik (laagste)" msgctxt "#30356" msgid "Record all episodes" msgstr "Neem alle episodes op" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Neem op as episode nommer verskil" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Neem op as episode naam verskil" msgctxt "#30359" msgid "Record if description differs" msgstr "Neem op as beskrywing verskil" msgctxt "#30360" msgid "Record max once per week" msgstr "Neem maks een keer per week op" msgctxt "#30361" msgid "Record max once per day" msgstr "Neem maks een keer per dag op" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Net hierdie reël: Neem op as episode nommer verskil" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Net hierdie reël: Neem op as episode naam verskil" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Net hierdie reël: Neem op as titel verskil" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Net hierdie reël: Neem op as beskrywing verskil" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Net hierdie reël: Neem maks een keer per week op" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Net hierdie reël: Neem maks een keer per dag op" msgctxt "#30368" msgid "Default" msgstr "Verstek" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Tydhouer reël (reeks skakel)" msgctxt "#30370" msgid "Record max once per month" msgstr "Neem maks een keer per maand op" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Net hierdie reël: Neem maks een keer per maand op" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Neem op as unieke episode volgens EPG/XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Tot spasie benodig" msgctxt "#30374" msgid "Forever" msgstr "Vir ewig" msgctxt "#30375" msgid "1 day" msgstr "1 dag" msgctxt "#30376" msgid "3 days" msgstr "3 dae" msgctxt "#30377" msgid "5 days" msgstr "5 dae" msgctxt "#30378" msgid "1 week" msgstr "1 week" msgctxt "#30379" msgid "2 weeks" msgstr "2 weke" msgctxt "#30380" msgid "3 weeks" msgstr "3 weke" msgctxt "#30381" msgid "1 month" msgstr "1 maand" msgctxt "#30382" msgid "2 months" msgstr "2 maande" msgctxt "#30383" msgid "3 months" msgstr "3 maande" msgctxt "#30384" msgid "6 months" msgstr "6 maande" msgctxt "#30385" msgid "1 year" msgstr "1 jaar" msgctxt "#30386" msgid "2 years" msgstr "2 jare" msgctxt "#30387" msgid "3 years" msgstr "3 jare" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Totdat spasie benodig (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Vir ewig (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Voorspellende instemming" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Hoeveelheid intekeninge om te gebruik" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Ongebruikte intekening toemaak vertraging (sekondes)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Gebruik voorspellende instemming om kanaal veranderinge te versnel" msgctxt "#30450" msgid "No free adapter available" msgstr "Geen vrye passtuk beskikbaar" msgctxt "#30451" msgid "Scrambled channel" msgstr "Vermengde kanaal" msgctxt "#30452" msgid "No signal" msgstr "Geen sein" msgctxt "#30453" msgid "Tuning failed" msgstr "Instem het gefaal" msgctxt "#30454" msgid "User limit reached" msgstr "Gebruiker limiet bereik" msgctxt "#30455" msgid "No access" msgstr "Geen toegang" msgctxt "#30456" msgid "Subscription error" msgstr "Intekening fout" msgctxt "#30500" msgid "Streaming profile" msgstr "Stroom profiel" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profiel om te gebruik (leeg = verstek)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Stroom profiel %s is nie beskikbaar nie" msgctxt "#30503" msgid "Data transfer" msgstr "Data oordrag" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Stroom lees stuk grootte vir opnames (KB)" msgctxt "#30510" msgid "Recordings" msgstr "Opnames" msgctxt "#30511" msgid "Server based play status" msgstr "Bediener gebaseerde speel status" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.am_et/000077500000000000000000000000001355512543200257605ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.am_et/strings.po000066400000000000000000000055371355512543200300230ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30000" msgid "Connection settings" msgstr "ግንኙነት ማሰናጃ" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP port" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP port" msgctxt "#30004" msgid "Username" msgstr "የ ተጠቃሚ ስም " msgctxt "#30005" msgid "Password" msgstr "የ መግቢያ ቃል" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "ግንኙነት ጊዜው አልፏል (ሰከንዶች)" msgctxt "#30008" msgid "Advanced settings" msgstr "የረቀቀ ማሰናጃ" msgctxt "#30009" msgid "Streaming settings" msgstr "ማስተላለፊያ ማሰናጃ" msgctxt "#30010" msgid "Timer settings" msgstr "ሰአት ማሰናጃ" msgctxt "#30050" msgid "Auto recordings" msgstr "በራሱ መቅረጫ " msgctxt "#30055" msgid "Default priority" msgstr "ነባር ቅድሚያ" msgctxt "#30100" msgid "Data transfer" msgstr "ዳታ ማስተላለፊያ " msgctxt "#30352" msgid "High" msgstr "ከፍተኛ " msgctxt "#30353" msgid "Normal" msgstr "መደበኛ " msgctxt "#30354" msgid "Low" msgstr "ዝቅተኛ " msgctxt "#30368" msgid "Default" msgstr "ነባር " msgctxt "#30374" msgid "Forever" msgstr "ለ ሁልጊዜ" msgctxt "#30375" msgid "1 day" msgstr "1 ቀን" msgctxt "#30376" msgid "3 days" msgstr "3 ቀኖች" msgctxt "#30377" msgid "5 days" msgstr "5 ቀኖች" msgctxt "#30378" msgid "1 week" msgstr "1 ሳምንት" msgctxt "#30379" msgid "2 weeks" msgstr "2 ሳምንቶች" msgctxt "#30380" msgid "3 weeks" msgstr "3 ሳምንቶች" msgctxt "#30381" msgid "1 month" msgstr "1 ወር" msgctxt "#30382" msgid "2 months" msgstr "2 ወሮች" msgctxt "#30383" msgid "3 months" msgstr "3 ወሮች" msgctxt "#30384" msgid "6 months" msgstr "6 ወሮች" msgctxt "#30385" msgid "1 year" msgstr "1 አመት" msgctxt "#30386" msgid "2 years" msgstr "2 አመቶች" msgctxt "#30387" msgid "3 years" msgstr "3 አመቶች" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "ለ ሁልጊዜ (tvh 4.1+)" msgctxt "#30452" msgid "No signal" msgstr "ምንም ምልክት የለም" msgctxt "#30503" msgid "Data transfer" msgstr "ዳታ ማስተላለፊያ " msgctxt "#30510" msgid "Recordings" msgstr "መቅረጫ " pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ar_sa/000077500000000000000000000000001355512543200257605ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ar_sa/strings.po000066400000000000000000000025321355512543200300130ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30002" msgid "HTTP port" msgstr "منفذ HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "منفذ HTSP" msgctxt "#30004" msgid "Username" msgstr "اسم المستخدم" msgctxt "#30005" msgid "Password" msgstr "كلمة المرور" msgctxt "#30200" msgid "Debugging" msgstr "التصحيح" msgctxt "#30352" msgid "High" msgstr "العظمى" msgctxt "#30353" msgid "Normal" msgstr "عادي" msgctxt "#30354" msgid "Low" msgstr "الصغرى" msgctxt "#30368" msgid "Default" msgstr "الافتراضية" msgctxt "#30510" msgid "Recordings" msgstr "التسجيلات" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.az_az/000077500000000000000000000000001355512543200257775ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.az_az/strings.po000066400000000000000000000016441355512543200300350ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30368" msgid "Default" msgstr "Normal" msgctxt "#30378" msgid "1 week" msgstr "1 həftə" msgctxt "#30381" msgid "1 month" msgstr "1 ay" msgctxt "#30385" msgid "1 year" msgstr "1 il" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.be_by/000077500000000000000000000000001355512543200257535ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.be_by/strings.po000066400000000000000000000030651355512543200300100ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend hostname or IP address" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP port" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP port" msgctxt "#30004" msgid "Username" msgstr "Карыстальнік" msgctxt "#30005" msgid "Password" msgstr "Password" msgctxt "#30010" msgid "Timer settings" msgstr "Налады таймера" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" msgctxt "#30352" msgid "High" msgstr "Высокая" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Нізкая" msgctxt "#30356" msgid "Record all episodes" msgstr "Запісваць усе эпізоды" msgctxt "#30368" msgid "Default" msgstr "Default" msgctxt "#30510" msgid "Recordings" msgstr "Recordings" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.bg_bg/000077500000000000000000000000001355512543200257335ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.bg_bg/strings.po000066400000000000000000000233441355512543200277720ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Настройки на връзката" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Име на хост или IP адрес на Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP порт" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP порт" msgctxt "#30004" msgid "Username" msgstr "Потребител" msgctxt "#30005" msgid "Password" msgstr "Парола" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Време на изчакване при свързване (секунди)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Време на изчакване за отговор (секунди)" msgctxt "#30008" msgid "Advanced settings" msgstr "Допълнителни настройки" msgctxt "#30009" msgid "Streaming settings" msgstr "Настройки за поточно излъчване" msgctxt "#30010" msgid "Timer settings" msgstr "Настройки на броячите" msgctxt "#30050" msgid "Auto recordings" msgstr "Автоматични записи" msgctxt "#30051" msgid "Start time window calculation" msgstr "Изчисление на времето за запис" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Строго (време за начало + време за край)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Нестрого (начално време +/- излишък)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Макс. време на излишък в началото (мин)" msgctxt "#30055" msgid "Default priority" msgstr "Стандартен приоритет" msgctxt "#30056" msgid "Default lifetime" msgstr "Стандартен срок за съхранение" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Стандартно разпознаване на еднаквите" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Стандартни настройки за новите броячи" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Планирани записи" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Пренебрегване на еднаквите (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Пренос на данни" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Асинхронно актуализиране на справочника" msgctxt "#30200" msgid "Debugging" msgstr "Дебъгване" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Проследяване (подробно)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Несъответствие във версиите на HTSP (поддържана версия:%d, нужна версия: %d). Моля, обновете „tvheadend“." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Еднократен (насрочено чрез правило на брояч)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Важен (най-високо)" msgctxt "#30352" msgid "High" msgstr "Висок" msgctxt "#30353" msgid "Normal" msgstr "Нормален" msgctxt "#30354" msgid "Low" msgstr "Нисъ" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Маловажен (най-нисък)" msgctxt "#30356" msgid "Record all episodes" msgstr "Запис на всички епизоди" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Запис само, ако номерът на епизода е различен" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Запис само, ако името на епизода е различно" msgctxt "#30359" msgid "Record if description differs" msgstr "Запис само, ако описанието е различно" msgctxt "#30360" msgid "Record max once per week" msgstr "Записване най-много веднъж в седмицата" msgctxt "#30361" msgid "Record max once per day" msgstr "Записване най-много веднъж през деня" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Само за това правило: Запис само, ако номерът на епизода е различен" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Само за това правило: Запис само, ако името на епизода е различно" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Само за това правило: Запис само, ако заглавието е различно" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Само за това правило: Запис само, ако описанието е различно" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Само за това правило: Записване най-много веднъж в седмицата" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Само за това правило: Записване най-много веднъж през деня" msgctxt "#30368" msgid "Default" msgstr "Стандартен" msgctxt "#30370" msgid "Record max once per month" msgstr "Записване най-много веднъж в месеца" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Само за това правило: Записване най-много веднъж в месеца" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Запис само, ако епизодът е уникален според справочника или XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Докато няма недостиг на място" msgctxt "#30374" msgid "Forever" msgstr "Завинаги" msgctxt "#30375" msgid "1 day" msgstr "1 ден" msgctxt "#30376" msgid "3 days" msgstr "3 дни" msgctxt "#30377" msgid "5 days" msgstr "5 дни" msgctxt "#30378" msgid "1 week" msgstr "1 седмица" msgctxt "#30379" msgid "2 weeks" msgstr "2 седмици" msgctxt "#30380" msgid "3 weeks" msgstr "3 седмици" msgctxt "#30381" msgid "1 month" msgstr "1 месец" msgctxt "#30382" msgid "2 months" msgstr "2 месеца" msgctxt "#30383" msgid "3 months" msgstr "3 месеца" msgctxt "#30384" msgid "6 months" msgstr "6 месеца" msgctxt "#30385" msgid "1 year" msgstr "1 година" msgctxt "#30386" msgid "2 years" msgstr "2 години" msgctxt "#30387" msgid "3 years" msgstr "3 години" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Докато няма недостиг на място (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Завинаги (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Предварително настройване" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Брой използвани абонаменти" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Забавяне при затваряне на неизползван абонамент (секунди)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Използване на предварително настройване на честотата за по-бърза смяна на каналите" msgctxt "#30450" msgid "No free adapter available" msgstr "Няма свободен адаптор" msgctxt "#30451" msgid "Scrambled channel" msgstr "Кодиран канал" msgctxt "#30452" msgid "No signal" msgstr "Няма сигнал" msgctxt "#30453" msgid "Tuning failed" msgstr "Настройването беше неуспешно" msgctxt "#30454" msgid "User limit reached" msgstr "Достигнато е ограничението за брой потребители" msgctxt "#30455" msgid "No access" msgstr "Няма достъп" msgctxt "#30456" msgid "Subscription error" msgstr "Грешка в абонамента" msgctxt "#30500" msgid "Streaming profile" msgstr "Профил за поточно излъчване" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Използван профил (празен = стандартният)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Профилът за поточно излъчване „%s“ не е наличен" msgctxt "#30503" msgid "Data transfer" msgstr "Пренос на данни" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Размер на частите на потока за четене при запис (КБ)" msgctxt "#30510" msgid "Recordings" msgstr "Записи" msgctxt "#30511" msgid "Server based play status" msgstr "Състояние на възпроизвеждане според сървъра" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.bs_ba/000077500000000000000000000000001355512543200257415ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.bs_ba/strings.po000066400000000000000000000022641355512543200277760ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30004" msgid "Username" msgstr "Korisničko ime" msgctxt "#30005" msgid "Password" msgstr "Lozinka" msgctxt "#30200" msgid "Debugging" msgstr "Traženje grešaka" msgctxt "#30352" msgid "High" msgstr "visok" msgctxt "#30353" msgid "Normal" msgstr "Normalno" msgctxt "#30354" msgid "Low" msgstr "nizak" msgctxt "#30368" msgid "Default" msgstr "Podrazumjevano" msgctxt "#30510" msgid "Recordings" msgstr "Snimci" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ca_es/000077500000000000000000000000001355512543200257455ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ca_es/strings.po000066400000000000000000000106071355512543200300020ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Opcions de la connexió" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Nom d'amfitrió o IP de Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "Port HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Port HTSP" msgctxt "#30004" msgid "Username" msgstr "Nom d'usuari" msgctxt "#30005" msgid "Password" msgstr "Contrasenya" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Temps d'expiració de la connexió (segons)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Temps d'expiració de la resposta (segons)" msgctxt "#30008" msgid "Advanced settings" msgstr "Opcions avançades" msgctxt "#30009" msgid "Streaming settings" msgstr "Opcions de la transmissió en línia" msgctxt "#30010" msgid "Timer settings" msgstr "Opcions del temporitzador" msgctxt "#30050" msgid "Auto recordings" msgstr "Enregistraments automàtics" msgctxt "#30051" msgid "Start time window calculation" msgstr "Inicia el càlcul de la finestra de temps" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Estricte (hora de començament + hora d'acabament)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Relaxat (hora de començament +/- marge)" msgctxt "#30055" msgid "Default priority" msgstr "Prioritat predeterminada" msgctxt "#30100" msgid "Data transfer" msgstr "Transferència de dades" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Transferència asíncrona de l'EPG" msgctxt "#30200" msgid "Debugging" msgstr "Depurant" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Traça (detallada)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "desajust de la versió HTSP (suportat: v%d, es requereix: v%d). Si us plau, actualitzi tvheadend." msgctxt "#30351" msgid "Important (Highest)" msgstr "Important (el més alt)" msgctxt "#30352" msgid "High" msgstr "Alt" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Baix" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "No important (el més baix)" msgctxt "#30356" msgid "Record all episodes" msgstr "Enregistra tots els episodis" msgctxt "#30368" msgid "Default" msgstr "Per defecte" msgctxt "#30373" msgid "Until space needed" msgstr "Fins que necessiti espai" msgctxt "#30374" msgid "Forever" msgstr "Per sempre" msgctxt "#30375" msgid "1 day" msgstr "1 dia" msgctxt "#30376" msgid "3 days" msgstr "3 dies" msgctxt "#30377" msgid "5 days" msgstr "5 dies" msgctxt "#30378" msgid "1 week" msgstr "1 setmana" msgctxt "#30379" msgid "2 weeks" msgstr "2 setmanes" msgctxt "#30380" msgid "3 weeks" msgstr "3 setmanes" msgctxt "#30381" msgid "1 month" msgstr "1 mes" msgctxt "#30382" msgid "2 months" msgstr "2 mesos" msgctxt "#30383" msgid "3 months" msgstr "3 mesos" msgctxt "#30384" msgid "6 months" msgstr "6 mesos" msgctxt "#30385" msgid "1 year" msgstr "1 any" msgctxt "#30386" msgid "2 years" msgstr "2 anys" msgctxt "#30387" msgid "3 years" msgstr "3 anys" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Per sempre (tvh 4.1+)" msgctxt "#30450" msgid "No free adapter available" msgstr "No hi ha cap adaptador disponible" msgctxt "#30452" msgid "No signal" msgstr "Sense senyal" msgctxt "#30455" msgid "No access" msgstr "Sense accés" msgctxt "#30456" msgid "Subscription error" msgstr "Error de subscripció" msgctxt "#30500" msgid "Streaming profile" msgstr "Perfil de la transmissió en línia" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "El perfil de la transmissió en línia %s no està disponible" msgctxt "#30503" msgid "Data transfer" msgstr "Transferència de dades" msgctxt "#30510" msgid "Recordings" msgstr "Enregistraments" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.cs_cz/000077500000000000000000000000001355512543200257745ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.cs_cz/strings.po000066400000000000000000000175141355512543200300350ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Nastavení připojení" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Název hostitele nebo adresa IP Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "Port HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Port HTSP" msgctxt "#30004" msgid "Username" msgstr "Uživatelské jméno" msgctxt "#30005" msgid "Password" msgstr "Heslo" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Časový limit spojení (sekundy)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Časový limit odpovědi (sekundy)" msgctxt "#30008" msgid "Advanced settings" msgstr "Rozšířená nastavení" msgctxt "#30009" msgid "Streaming settings" msgstr "Nastavení streamování" msgctxt "#30010" msgid "Timer settings" msgstr "Nastavení časovače" msgctxt "#30050" msgid "Auto recordings" msgstr "Automatické nahrávání" msgctxt "#30051" msgid "Start time window calculation" msgstr "Výpočet času spuštění" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Přesně (čas spuštění + čas ukončení)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Volně (čas spuštění +/- rezerva)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Maximální rezerva času spuštění (minuty)" msgctxt "#30055" msgid "Default priority" msgstr "Výchozí priorita" msgctxt "#30056" msgid "Default lifetime" msgstr "Výchozí doba platnosti" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Výchozí rozpoznávání duplicit" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Výchozí hodnoty pro nové časovače" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Naplánovaná nahrávání" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Ignorovat duplicity (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Přenos dat" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asynchronní přenos televizního programu" msgctxt "#30200" msgid "Debugging" msgstr "Ladění" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Sledování (podrobné)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Neshoda verze HTSP (podporováno: v%d, vyžadováno: v%d). Aktualizujte tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Jednou (naplánováno pravidlem časovače)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Důležité (Nejvyšší)" msgctxt "#30352" msgid "High" msgstr "Vysoká" msgctxt "#30353" msgid "Normal" msgstr "Normální" msgctxt "#30354" msgid "Low" msgstr "Nízká" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Nedůležité (nejnižší)" msgctxt "#30356" msgid "Record all episodes" msgstr "Nahrávat všechny epizody" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Nahrávat, pokud se liší číslo epizody" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Nahrávat, pokud se liší název epizody" msgctxt "#30359" msgid "Record if description differs" msgstr "Nahrávat, pokud se liší popis" msgctxt "#30360" msgid "Record max once per week" msgstr "Nahrávat max. jednou týdně" msgctxt "#30361" msgid "Record max once per day" msgstr "Nahrávat max. jednou denně" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Pouze toto pravidlo: Nahrávat, pokud se liší číslo epizody" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Pouze toto pravidlo: Nahrávat, pokud se liší název epizody" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Pouze toto pravidlo: Nahrávat, pokud se liší název" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Pouze toto pravidlo: Nahrávat, pokud se liší popis" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Pouze toto pravidlo: Nahrávat max. jednou týdně" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Pouze toto pravidlo: Nahrávat max. jednou denně" msgctxt "#30368" msgid "Default" msgstr "Výchozí" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Pravidlo časovače (odkaz na seriál)" msgctxt "#30370" msgid "Record max once per month" msgstr "Nahrát max. jednou za měsíc" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Pouze toto pravidlo: Nahrát nejvýše 1x za měsíc" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Nahrát, pokud jde o jedinečnou epizodu podle EPG nebo XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Dokud není potřeba místo" msgctxt "#30374" msgid "Forever" msgstr "Navždy" msgctxt "#30375" msgid "1 day" msgstr "1 den" msgctxt "#30376" msgid "3 days" msgstr "3 dny" msgctxt "#30377" msgid "5 days" msgstr "5 dnů" msgctxt "#30378" msgid "1 week" msgstr "1 týden" msgctxt "#30379" msgid "2 weeks" msgstr "2 týdny" msgctxt "#30380" msgid "3 weeks" msgstr "3 týdny" msgctxt "#30381" msgid "1 month" msgstr "1 měsíc" msgctxt "#30382" msgid "2 months" msgstr "2 měsíce" msgctxt "#30383" msgid "3 months" msgstr "3 měsíce" msgctxt "#30384" msgid "6 months" msgstr "6 měsíců" msgctxt "#30385" msgid "1 year" msgstr "1 rok" msgctxt "#30386" msgid "2 years" msgstr "2 roky" msgctxt "#30387" msgid "3 years" msgstr "3 roky" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Dokud není potřeba místo (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Navždy (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Prediktivní ladění" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Počet použitých odběrů" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Prodleva před uzavřením nepoužitého odběru (sekundy)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Použít prediktivní ladění pro zrychlení přepínání kanálů" msgctxt "#30450" msgid "No free adapter available" msgstr "Není dostupný žádný volný adaptér" msgctxt "#30451" msgid "Scrambled channel" msgstr "Kódovaný kanál" msgctxt "#30452" msgid "No signal" msgstr "Žádný signál" msgctxt "#30453" msgid "Tuning failed" msgstr "Ladění se nezdařilo" msgctxt "#30454" msgid "User limit reached" msgstr "Dosaženo omezení uživatele" msgctxt "#30455" msgid "No access" msgstr "Žádný přístup" msgctxt "#30456" msgid "Subscription error" msgstr "Chyba odběru" msgctxt "#30500" msgid "Streaming profile" msgstr "Profil streamování" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Použitý profil (prázdný = výchozí)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Profil streamování %s není dostupný" msgctxt "#30503" msgid "Data transfer" msgstr "Přenos dat" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Velikost bloku dat čtení streamu pro nahrávání (kB)" msgctxt "#30510" msgid "Recordings" msgstr "Nahrávky" msgctxt "#30511" msgid "Server based play status" msgstr "Stav přehrávání na základě serveru" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.cy_gb/000077500000000000000000000000001355512543200257565ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.cy_gb/strings.po000066400000000000000000000027651355512543200300210ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Enw gwesteiwr neu gyfeiriad IP Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "Porth HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Porth HTSP" msgctxt "#30004" msgid "Username" msgstr "Enw defnyddiwr" msgctxt "#30005" msgid "Password" msgstr "Cyfrinair" msgctxt "#30200" msgid "Debugging" msgstr "Dadfygio" msgctxt "#30352" msgid "High" msgstr "Uchel" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Isel" msgctxt "#30356" msgid "Record all episodes" msgstr "Recordio pob pennod" msgctxt "#30368" msgid "Default" msgstr "Rhagosodiad" msgctxt "#30373" msgid "Until space needed" msgstr "Nes bod angen y lle" msgctxt "#30510" msgid "Recordings" msgstr "Recordiadau" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.da_dk/000077500000000000000000000000001355512543200257355ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.da_dk/strings.po000066400000000000000000000122351355512543200277710ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Forbindelsesindstillinger" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend-værtsnavn eller IP-adresse" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP-port" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP-port" msgctxt "#30004" msgid "Username" msgstr "Brugernavn" msgctxt "#30005" msgid "Password" msgstr "Adgangskode" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Forbindelsestidsudløb (sekunder)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Svartidsudløb (sekunder)" msgctxt "#30008" msgid "Advanced settings" msgstr "Avancerede indstillinger" msgctxt "#30009" msgid "Streaming settings" msgstr "Streaming indstillinger" msgctxt "#30010" msgid "Timer settings" msgstr "Indstil Optagelse" msgctxt "#30050" msgid "Auto recordings" msgstr "Automatiske optagelser" msgctxt "#30051" msgid "Start time window calculation" msgstr "Starttidspunkt for vinduesberegning" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Streng (starttidspunkt + sluttidspunkt)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Afslappet (starttidspunkt +/- margen)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Maksimal starttidspunktmargen (minutter)" msgctxt "#30055" msgid "Default priority" msgstr "Standardprioritet" msgctxt "#30100" msgid "Data transfer" msgstr "Dataoverførsel" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asynkron EPG-overførsel" msgctxt "#30200" msgid "Debugging" msgstr "Foretag fejlretning" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Sporing (detaljeret)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP-versionen passer ikke (understøttet: v%d, krævet v%d). Opdater venligst tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "En gang (planlagt af tidsregel)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Vigtig (højest)" msgctxt "#30352" msgid "High" msgstr "Høj" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Lav" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Ikke vigtig (lavest)" msgctxt "#30356" msgid "Record all episodes" msgstr "Optag alle episoder" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Optag hvis episodenummer er et andet" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Optag hvis episodenavn er et andet" msgctxt "#30359" msgid "Record if description differs" msgstr "Optag hvis beskrivelse er et andet" msgctxt "#30360" msgid "Record max once per week" msgstr "Optag maks. en gang per uge" msgctxt "#30361" msgid "Record max once per day" msgstr "Optag maks. en gang per dag" msgctxt "#30368" msgid "Default" msgstr "Standard" msgctxt "#30373" msgid "Until space needed" msgstr "Indtil fri plads nødvendig" msgctxt "#30374" msgid "Forever" msgstr "Altid" msgctxt "#30375" msgid "1 day" msgstr "1 dag" msgctxt "#30376" msgid "3 days" msgstr "3 dage" msgctxt "#30378" msgid "1 week" msgstr "1 uge" msgctxt "#30379" msgid "2 weeks" msgstr "2 uger" msgctxt "#30380" msgid "3 weeks" msgstr "3 uger" msgctxt "#30385" msgid "1 year" msgstr "1 år" msgctxt "#30386" msgid "2 years" msgstr "2 år" msgctxt "#30387" msgid "3 years" msgstr "3 år" msgctxt "#30400" msgid "Predictive tuning" msgstr "Forudsigelsesindstilling" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Antallet af abonnementer at bruge" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Forsinkelse for ubrugt abonnementslukning (sekunder)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Brug forudsigelsesindstilling for at høje hastighed ved kanalskift" msgctxt "#30450" msgid "No free adapter available" msgstr "Ingen ledig adapter tilgængelig" msgctxt "#30451" msgid "Scrambled channel" msgstr "Kodet kanal" msgctxt "#30452" msgid "No signal" msgstr "Intet signal" msgctxt "#30453" msgid "Tuning failed" msgstr "Indstilling mislykkedes" msgctxt "#30454" msgid "User limit reached" msgstr "Brugerbegrænsning nået" msgctxt "#30455" msgid "No access" msgstr "Ingen adgang" msgctxt "#30456" msgid "Subscription error" msgstr "Abonnementsfejl" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Streamingprofilen %s er ikke tilgængelig" msgctxt "#30503" msgid "Data transfer" msgstr "Dataoverførsel" msgctxt "#30510" msgid "Recordings" msgstr "Optagelser" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.de_de/000077500000000000000000000000001355512543200257335ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.de_de/strings.po000066400000000000000000000173301355512543200277700ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Verbindung" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Hostname oder IP-Adresse des Tvheadend-Servers" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP-Port des Tvheadend-Servers" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP-Port des Tvheadend-Servers" msgctxt "#30004" msgid "Username" msgstr "Benutzername" msgctxt "#30005" msgid "Password" msgstr "Passwort" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Verbindungszeitüberschreitung (Sekunden)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Antwortzeitüberschreitung (Sekunden)" msgctxt "#30008" msgid "Advanced settings" msgstr "Erweitert" msgctxt "#30009" msgid "Streaming settings" msgstr "Streaming" msgctxt "#30010" msgid "Timer settings" msgstr "Timer" msgctxt "#30050" msgid "Auto recordings" msgstr "Auto-Aufnahmen" msgctxt "#30051" msgid "Start time window calculation" msgstr "Startfenster-Berechnung" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Strikt (Start- + Endzeit)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Entspannt (Startzeit +/- Zeitspanne)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Max. Startzeitspanne (Minuten)" msgctxt "#30055" msgid "Default priority" msgstr "Default für Aufnahme-Priorität" msgctxt "#30056" msgid "Default lifetime" msgstr "Default für Aufnahme-Lebensdauer" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Default für Duplikat-Erkennung" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Defaults für neue Timer" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Geplante Aufnahmen" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Duplikate ignorieren (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Datenübertragung" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asynchroner EPG-Transfer" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Protokollierung (Detailliert)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP-Versionskonflikt (unterstützt: v%d, benötigt: v%d). Bitte tvheadend aktualisieren." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Einmalig (Erzeugt von Timer-Regel)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Wichtig (höchste Prio)" msgctxt "#30352" msgid "High" msgstr "Hoch" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Niedrig" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Unwichtig (niedrigste Prio)" msgctxt "#30356" msgid "Record all episodes" msgstr "Alle Episoden aufnehmen" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Aufnehmen, wenn Episodennummer unterschiedlich ist" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Aufnehmen, wenn Episodenname unterschiedlich ist" msgctxt "#30359" msgid "Record if description differs" msgstr "Aufnehmen, wenn Episodenbeschreibung unterschiedlich ist" msgctxt "#30360" msgid "Record max once per week" msgstr "Maximal einmal pro Woche aufnehmen" msgctxt "#30361" msgid "Record max once per day" msgstr "Maximal einmal pro Tag aufnehmen" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Nur für diese Regel: Aufnehmen, wenn Episodennummer unterschiedlich ist" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Nur diese Regel: Aufnehmen, wenn Episodenname unterschiedlich ist" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Nur diese Regel: Aufnehmen, wenn Titel unterschiedlich ist" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Nur diese Regel: Aufnehmen, wenn Beschreibung unterschiedlich ist" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Nur diese Regel: Maximal einmal pro Woche aufnehmen" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Nur diese Regel: Maximal einmal pro Tag aufnehmen" msgctxt "#30368" msgid "Default" msgstr "Standard" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Timer-Regel (Serien-Link)" msgctxt "#30370" msgid "Record max once per month" msgstr "Maximal einmal pro Monat aufnehmen" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Nur diese Regel: Maximal einmal pro Monat aufnehmen" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Aufnehmen, wenn einzigartige Episode lt. EPG/XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Bis Speicherplatz benötigt wird" msgctxt "#30374" msgid "Forever" msgstr "Kein Limit" msgctxt "#30375" msgid "1 day" msgstr "1 Tag" msgctxt "#30376" msgid "3 days" msgstr "3 Tage" msgctxt "#30377" msgid "5 days" msgstr "5 Tage" msgctxt "#30378" msgid "1 week" msgstr "1 Woche" msgctxt "#30379" msgid "2 weeks" msgstr "2 Wochen" msgctxt "#30380" msgid "3 weeks" msgstr "3 Wochen" msgctxt "#30381" msgid "1 month" msgstr "1 Monat" msgctxt "#30382" msgid "2 months" msgstr "2 Monate" msgctxt "#30383" msgid "3 months" msgstr "3 Monate" msgctxt "#30384" msgid "6 months" msgstr "6 Monate" msgctxt "#30385" msgid "1 year" msgstr "1 Jahr" msgctxt "#30386" msgid "2 years" msgstr "2 Jahre" msgctxt "#30387" msgid "3 years" msgstr "3 Jahre" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Bis Platz benötigt wird (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Unbegrenzt (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Voraussagendes Tuning" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Anzahl zu verwendender Subscriptions" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Schließen unbenutzter Subscriptions nach: (Sekunden)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Kanalwechsel beschleunigen (Predictive Tuning)" msgctxt "#30450" msgid "No free adapter available" msgstr "Kein freier Adapter verfügbar" msgctxt "#30451" msgid "Scrambled channel" msgstr "Verschlüsselter Kanal" msgctxt "#30452" msgid "No signal" msgstr "Kein Signal" msgctxt "#30453" msgid "Tuning failed" msgstr "Tuning fehlgeschlagen" msgctxt "#30454" msgid "User limit reached" msgstr "Benutzer-Limit erreicht" msgctxt "#30455" msgid "No access" msgstr "Kein Zugriff" msgctxt "#30456" msgid "Subscription error" msgstr "Subscription-Fehler" msgctxt "#30500" msgid "Streaming profile" msgstr "Streaming-Profil" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profil (Leer = Standard)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Streaming-Profil %s ist nicht verfügbar" msgctxt "#30503" msgid "Data transfer" msgstr "Datenübertragung" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Blockgröße beim Lesen von Aufnahme-Streams (KB)" msgctxt "#30510" msgid "Recordings" msgstr "Aufnahmen" msgctxt "#30511" msgid "Server based play status" msgstr "Server-basierter Abspielstatus" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.el_gr/000077500000000000000000000000001355512543200257635ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.el_gr/strings.po000066400000000000000000000071341355512543200300210ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Ρυθμίσεις σύνδεσης" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Όνομα Υπολογιστή ή διεύθυνση IP του Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "Θύρα HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Θύρα HTSP" msgctxt "#30004" msgid "Username" msgstr "Όνομα χρήστη" msgctxt "#30005" msgid "Password" msgstr "Κωδικός πρόσβασης" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Χρονικό όριο σύνδεσης (δευτερόλεπτα)" msgctxt "#30008" msgid "Advanced settings" msgstr "Ρυθμίσεις για προχωρημένους" msgctxt "#30010" msgid "Timer settings" msgstr "Ρυθμίσεις χρονοδιακόπτη" msgctxt "#30050" msgid "Auto recordings" msgstr "Αυτόματες εγγραφές" msgctxt "#30055" msgid "Default priority" msgstr "προεπιλεγμένη προτεραιότητα" msgctxt "#30100" msgid "Data transfer" msgstr "Μεταφορά δεδομένων" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Ασύγχρονη μεταφορά EPG" msgctxt "#30200" msgid "Debugging" msgstr "Εντοπισμός σφαλμάτων" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Ανίχνευση (αναλυτικά)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Ασυμφωνία έκδοσης HTSP (υποστηρίζονται: ν%d, απαιτείται: v%d ). Παρακαλούμε ενημερώστε tvheadend." msgctxt "#30352" msgid "High" msgstr "Υψηλά" msgctxt "#30353" msgid "Normal" msgstr "Κανονική" msgctxt "#30354" msgid "Low" msgstr "Ελαχ." msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "ασήμαντο (χαμηλότερο)" msgctxt "#30356" msgid "Record all episodes" msgstr "Εγγραφή όλων των επεισοδίων" msgctxt "#30368" msgid "Default" msgstr "Προεπιλογή" msgctxt "#30373" msgid "Until space needed" msgstr "Μέχρι να απαιτηθεί χώρος" msgctxt "#30374" msgid "Forever" msgstr "Για πάντα" msgctxt "#30375" msgid "1 day" msgstr "1 πρώτη ημέρα" msgctxt "#30378" msgid "1 week" msgstr "1 εβδομάδα" msgctxt "#30381" msgid "1 month" msgstr "1 μήνας" msgctxt "#30385" msgid "1 year" msgstr "1 χρόνο" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Αριθμός των συνδρομών για χρήση" msgctxt "#30451" msgid "Scrambled channel" msgstr "Κωδικοποιημένο κανάλι" msgctxt "#30452" msgid "No signal" msgstr "Χωρίς σήμα" msgctxt "#30455" msgid "No access" msgstr "Χωρίς πρόσβαση" msgctxt "#30503" msgid "Data transfer" msgstr "Μεταφορά δεδομένων" msgctxt "#30510" msgid "Recordings" msgstr "Εγγραφές" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.en_au/000077500000000000000000000000001355512543200257625ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.en_au/strings.po000066400000000000000000000026551355512543200300230ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend hostname or IP address" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP port" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP port" msgctxt "#30004" msgid "Username" msgstr "Username" msgctxt "#30005" msgid "Password" msgstr "Password" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" msgctxt "#30352" msgid "High" msgstr "High" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Low" msgctxt "#30356" msgid "Record all episodes" msgstr "Record all episodes" msgctxt "#30368" msgid "Default" msgstr "Default" msgctxt "#30373" msgid "Until space needed" msgstr "Until space needed" msgctxt "#30510" msgid "Recordings" msgstr "Recordings" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.en_gb/000077500000000000000000000000001355512543200257455ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.en_gb/strings.po000066400000000000000000000205241355512543200300010ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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" #settings labels msgctxt "#30000" msgid "Connection settings" msgstr "" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "" msgctxt "#30002" msgid "HTTP port" msgstr "" msgctxt "#30003" msgid "HTSP port" msgstr "" msgctxt "#30004" msgid "Username" msgstr "" msgctxt "#30005" msgid "Password" msgstr "" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "" msgctxt "#30008" msgid "Advanced settings" msgstr "" msgctxt "#30009" msgid "Streaming settings" msgstr "" msgctxt "#30010" msgid "Timer settings" msgstr "" #empty strings from id 30011 to 30049 msgctxt "#30050" msgid "Auto recordings" msgstr "" msgctxt "#30051" msgid "Start time window calculation" msgstr "" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "" msgctxt "#30055" msgid "Default priority" msgstr "" msgctxt "#30056" msgid "Default lifetime" msgstr "" msgctxt "#30057" msgid "Default duplicate detection" msgstr "" msgctxt "#30058" msgid "Defaults for new timers" msgstr "" msgctxt "#30059" msgid "Scheduled recordings" msgstr "" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "" #empty strings from id 30061 to 30099 msgctxt "#30100" msgid "Data transfer" msgstr "" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "" #empty strings from id 30102 to 30199 msgctxt "#30200" msgid "Debugging" msgstr "" msgctxt "#30201" msgid "Trace (detailed)" msgstr "" #empty strings from id 30202 to 30299 msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "" #empty strings from id 30301 to 30349 #. Timer type representation #: src/Tvheadend.cpp msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "" #. Recording priority representation #: src/Tvheadend.cpp msgctxt "#30351" msgid "Important (Highest)" msgstr "" #. Recording priority representation #: src/Tvheadend.cpp msgctxt "#30352" msgid "High" msgstr "" #. Recording priority representation #: src/Tvheadend.cpp msgctxt "#30353" msgid "Normal" msgstr "" #. Recording priority representation #: src/Tvheadend.cpp msgctxt "#30354" msgid "Low" msgstr "" #. Recording priority representation #: src/Tvheadend.cpp msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30356" msgid "Record all episodes" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30357" msgid "Record if episode number differs" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30358" msgid "Record if episode name differs" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30359" msgid "Record if description differs" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30360" msgid "Record max once per week" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30361" msgid "Record max once per day" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "" #. Recording priority representation #: src/Tvheadend.cpp msgctxt "#30368" msgid "Default" msgstr "" #. Timer type representation #: src/Tvheadend.cpp msgctxt "#30369" msgid "Timer rule (series link)" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30370" msgid "Record max once per month" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "" #. Prevent duplicate episodes representation #: src/Tvheadend.cpp msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30373" msgid "Until space needed" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30374" msgid "Forever" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30375" msgid "1 day" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30376" msgid "3 days" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30377" msgid "5 days" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30378" msgid "1 week" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30379" msgid "2 weeks" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30380" msgid "3 weeks" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30381" msgid "1 month" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30382" msgid "2 months" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30383" msgid "3 months" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30384" msgid "6 months" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30385" msgid "1 year" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30386" msgid "2 years" msgstr "" #. Recording lifetime representation #: src/Tvheadend.cpp msgctxt "#30387" msgid "3 years" msgstr "" #. Recording lifetime representation (for setting dialog only) msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "" #. Recording lifetime representation (for setting dialog only) msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "" #empty strings from id 30390 to 30399 msgctxt "#30400" msgid "Predictive tuning" msgstr "" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "" #empty strings from id 30404 to 30449 msgctxt "#30450" msgid "No free adapter available" msgstr "" msgctxt "#30451" msgid "Scrambled channel" msgstr "" msgctxt "#30452" msgid "No signal" msgstr "" msgctxt "#30453" msgid "Tuning failed" msgstr "" msgctxt "#30454" msgid "User limit reached" msgstr "" msgctxt "#30455" msgid "No access" msgstr "" msgctxt "#30456" msgid "Subscription error" msgstr "" #empty strings from id 30457 to 30499 msgctxt "#30500" msgid "Streaming profile" msgstr "" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "" #. Check streaming profile validity during startup #: src/client.cpp msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "" msgctxt "#30503" msgid "Data transfer" msgstr "" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "" #empty strings from id 30505 to 30509 msgctxt "#30510" msgid "Recordings" msgstr "" msgctxt "#30511" msgid "Server based play status" msgstr "" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.en_nz/000077500000000000000000000000001355512543200260045ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.en_nz/strings.po000066400000000000000000000146661355512543200300520ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Connection settings" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend hostname or IP address" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP port" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP port" msgctxt "#30004" msgid "Username" msgstr "Username" msgctxt "#30005" msgid "Password" msgstr "Password" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Connection timeout (seconds)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Response timeout (seconds)" msgctxt "#30008" msgid "Advanced settings" msgstr "Advanced settings" msgctxt "#30009" msgid "Streaming settings" msgstr "Streaming settings" msgctxt "#30010" msgid "Timer settings" msgstr "Timer settings" msgctxt "#30050" msgid "Auto recordings" msgstr "Auto recordings" msgctxt "#30051" msgid "Start time window calculation" msgstr "Start time window calculation" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Strict (start time + end time)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Relaxed (start time +/- margin)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Maximum start time margin (minutes)" msgctxt "#30055" msgid "Default priority" msgstr "Default priority" msgctxt "#30056" msgid "Default lifetime" msgstr "Default lifetime" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Default duplicate detection" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Defaults for new timers" msgctxt "#30100" msgid "Data transfer" msgstr "Data transfer" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asynchronous EPG transfer" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Trace (detailed)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgctxt "#30351" msgid "Important (Highest)" msgstr "Important (Highest)" msgctxt "#30352" msgid "High" msgstr "High" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Low" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Unimportant (Lowest)" msgctxt "#30356" msgid "Record all episodes" msgstr "Record all episodes" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Record if episode number differs" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Record if episode name differs" msgctxt "#30359" msgid "Record if description differs" msgstr "Record if description differs" msgctxt "#30360" msgid "Record max once per week" msgstr "Record max once per week" msgctxt "#30361" msgid "Record max once per day" msgstr "Record max once per day" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "This rule only: Record if episode number differs" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "This rule only: Record if episode name differs" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "This rule only: Record if title differs" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "This rule only: Record if description differs" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "This rule only: Record max once per week" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "This rule only: Record max once per day" msgctxt "#30368" msgid "Default" msgstr "Default" msgctxt "#30373" msgid "Until space needed" msgstr "Until space needed" msgctxt "#30374" msgid "Forever" msgstr "Forever" msgctxt "#30375" msgid "1 day" msgstr "1 day" msgctxt "#30376" msgid "3 days" msgstr "3 days" msgctxt "#30377" msgid "5 days" msgstr "5 days" msgctxt "#30378" msgid "1 week" msgstr "1 week" msgctxt "#30379" msgid "2 weeks" msgstr "2 weeks" msgctxt "#30380" msgid "3 weeks" msgstr "3 weeks" msgctxt "#30381" msgid "1 month" msgstr "1 month" msgctxt "#30382" msgid "2 months" msgstr "2 months" msgctxt "#30383" msgid "3 months" msgstr "3 months" msgctxt "#30384" msgid "6 months" msgstr "6 months" msgctxt "#30385" msgid "1 year" msgstr "1 year" msgctxt "#30386" msgid "2 years" msgstr "2 years" msgctxt "#30387" msgid "3 years" msgstr "3 years" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Until space needed (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Forever (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Predictive tuning" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Number of subscriptions to use" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Unused subscription close delay (seconds)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Use predictive tuning to speedup channel switches" msgctxt "#30450" msgid "No free adapter available" msgstr "No free adapter available" msgctxt "#30451" msgid "Scrambled channel" msgstr "Scrambled channel" msgctxt "#30452" msgid "No signal" msgstr "No signal" msgctxt "#30453" msgid "Tuning failed" msgstr "Tuning failed" msgctxt "#30454" msgid "User limit reached" msgstr "User limit reached" msgctxt "#30455" msgid "No access" msgstr "No access" msgctxt "#30456" msgid "Subscription error" msgstr "Subscription error" msgctxt "#30500" msgid "Streaming profile" msgstr "Streaming profile" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profile to use (empty = default)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Streaming profile %s is not available" msgctxt "#30503" msgid "Data transfer" msgstr "Data transfer" msgctxt "#30510" msgid "Recordings" msgstr "Recordings" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.en_us/000077500000000000000000000000001355512543200260045ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.en_us/strings.po000066400000000000000000000164711355512543200300460ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Connection settings" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend hostname or IP address" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP port" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP port" msgctxt "#30004" msgid "Username" msgstr "Username" msgctxt "#30005" msgid "Password" msgstr "Password" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Connection timeout (seconds)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Response timeout (seconds)" msgctxt "#30008" msgid "Advanced settings" msgstr "Advanced settings" msgctxt "#30009" msgid "Streaming settings" msgstr "Streaming settings" msgctxt "#30010" msgid "Timer settings" msgstr "Timer settings" msgctxt "#30050" msgid "Auto recordings" msgstr "Auto recordings" msgctxt "#30051" msgid "Start time window calculation" msgstr "Start time window calculation" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Strict (start time + end time)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Relaxed (start time +/- margin)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Maximum start time margin (minutes)" msgctxt "#30055" msgid "Default priority" msgstr "Default priority" msgctxt "#30056" msgid "Default lifetime" msgstr "Default lifetime" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Default duplicate detection" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Defaults for new timers" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Scheduled recordings" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Ignore duplicates (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Data transfer" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asynchronous EPG transfer" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Trace (detailed)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "One Time (Scheduled by timer rule)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Important (Highest)" msgctxt "#30352" msgid "High" msgstr "High" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Low" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Unimportant (Lowest)" msgctxt "#30356" msgid "Record all episodes" msgstr "Record all episodes" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Record if episode number differs" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Record if episode name differs" msgctxt "#30359" msgid "Record if description differs" msgstr "Record if description differs" msgctxt "#30360" msgid "Record max once per week" msgstr "Record max once per week" msgctxt "#30361" msgid "Record max once per day" msgstr "Record max once per day" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "This rule only: Record if episode number differs" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "This rule only: Record if episode name differs" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "This rule only: Record if title differs" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "This rule only: Record if description differs" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "This rule only: Record max once per week" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "This rule only: Record max once per day" msgctxt "#30368" msgid "Default" msgstr "Default" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Timer rule (series link)" msgctxt "#30370" msgid "Record max once per month" msgstr "Record max once per month" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "This rule only: Record max once per month" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Record if unique episode according EPG/XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Until space needed" msgctxt "#30374" msgid "Forever" msgstr "Forever" msgctxt "#30375" msgid "1 day" msgstr "1 day" msgctxt "#30376" msgid "3 days" msgstr "3 days" msgctxt "#30377" msgid "5 days" msgstr "5 days" msgctxt "#30378" msgid "1 week" msgstr "1 week" msgctxt "#30379" msgid "2 weeks" msgstr "2 weeks" msgctxt "#30380" msgid "3 weeks" msgstr "3 weeks" msgctxt "#30381" msgid "1 month" msgstr "1 month" msgctxt "#30382" msgid "2 months" msgstr "2 months" msgctxt "#30383" msgid "3 months" msgstr "3 months" msgctxt "#30384" msgid "6 months" msgstr "6 months" msgctxt "#30385" msgid "1 year" msgstr "1 year" msgctxt "#30386" msgid "2 years" msgstr "2 years" msgctxt "#30387" msgid "3 years" msgstr "3 years" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Until space needed (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Forever (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Predictive tuning" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Number of subscriptions to use" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Unused subscription close delay (seconds)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Use predictive tuning to speedup channel switches" msgctxt "#30450" msgid "No free adapter available" msgstr "No free adapter available" msgctxt "#30451" msgid "Scrambled channel" msgstr "Scrambled channel" msgctxt "#30452" msgid "No signal" msgstr "No signal" msgctxt "#30453" msgid "Tuning failed" msgstr "Tuning failed" msgctxt "#30454" msgid "User limit reached" msgstr "User limit reached" msgctxt "#30455" msgid "No access" msgstr "No access" msgctxt "#30456" msgid "Subscription error" msgstr "Subscription error" msgctxt "#30500" msgid "Streaming profile" msgstr "Streaming profile" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profile to use (empty = default)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Streaming profile %s is not available" msgctxt "#30503" msgid "Data transfer" msgstr "Data transfer" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Stream read chunk size for recordings (KB)" msgctxt "#30510" msgid "Recordings" msgstr "Recordings" msgctxt "#30511" msgid "Server based play status" msgstr "Server based play status" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.eo/000077500000000000000000000000001355512543200252765ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.eo/strings.po000066400000000000000000000017151355512543200273330ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30004" msgid "Username" msgstr "Uzulonomo" msgctxt "#30005" msgid "Password" msgstr "pasvorto" msgctxt "#30352" msgid "High" msgstr "Nobla" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Malnobla" msgctxt "#30368" msgid "Default" msgstr "Default" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.es_ar/000077500000000000000000000000001355512543200257645ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.es_ar/strings.po000066400000000000000000000032671355512543200300250ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend nombre o dirección IP" msgctxt "#30002" msgid "HTTP port" msgstr "Puerto HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Puerto HTSP" msgctxt "#30004" msgid "Username" msgstr "Usuario" msgctxt "#30005" msgid "Password" msgstr "Contraseña" msgctxt "#30010" msgid "Timer settings" msgstr "Programar eventos" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Transferencia de EPG asíncrona" msgctxt "#30200" msgid "Debugging" msgstr "Depuración" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Traza (detallada)" msgctxt "#30352" msgid "High" msgstr "Alta" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Baja" msgctxt "#30356" msgid "Record all episodes" msgstr "Grabar todos los episodios" msgctxt "#30368" msgid "Default" msgstr "Por defecto" msgctxt "#30373" msgid "Until space needed" msgstr "Hasta que se necesite el espacio" msgctxt "#30510" msgid "Recordings" msgstr "Grabaciones" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.es_es/000077500000000000000000000000001355512543200257715ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.es_es/strings.po000066400000000000000000000173511355512543200300310ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Ajustes de Conexión" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend nombre o dirección IP" msgctxt "#30002" msgid "HTTP port" msgstr "Puerto HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Puerto HTSP" msgctxt "#30004" msgid "Username" msgstr "Usuario" msgctxt "#30005" msgid "Password" msgstr "Contraseña" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Tiempo de espera para conexión (segundos)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Tiempo de espera de respuesta (en segundos)" msgctxt "#30008" msgid "Advanced settings" msgstr "Ajustes avanzados" msgctxt "#30009" msgid "Streaming settings" msgstr "Ajustes de streaming" msgctxt "#30010" msgid "Timer settings" msgstr "Ajustes de grabación" msgctxt "#30050" msgid "Auto recordings" msgstr "Grabaciones automáticas" msgctxt "#30051" msgid "Start time window calculation" msgstr "Iniciar cálculo de tiempo" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Estricto (tiempo inicial + tiempo final)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Relajado (tiempo inicial +/- márgen)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Márgen máximo de tiempo inicial (en minutos)" msgctxt "#30055" msgid "Default priority" msgstr "Prioridad por defecto" msgctxt "#30056" msgid "Default lifetime" msgstr "Tiempo de vida por defecto" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Detección de duplicados por defecto" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Por defecto para nuevos temporizadores" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Grabaciones programadas" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Ignorar duplicados (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Transferencia de datos" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Transferencia asíncrona de EPG" msgctxt "#30200" msgid "Debugging" msgstr "Depuración" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Traza (detallada)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "La versión de HTSP no coincide (soportada: v%d, requerida v%d). Por favor, actualice tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Una Vez (Programado por regla)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Importante (más alto)" msgctxt "#30352" msgid "High" msgstr "Alta" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Baja" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "No importante (más bajo)" msgctxt "#30356" msgid "Record all episodes" msgstr "Grabar todos los episodios" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Grabar si el número de episodio es diferente" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Grabar si el nombre del episodio es diferente" msgctxt "#30359" msgid "Record if description differs" msgstr "Grabar si la descipción es diferente" msgctxt "#30360" msgid "Record max once per week" msgstr "Grabar máximo una vez por semana" msgctxt "#30361" msgid "Record max once per day" msgstr "Grabar máximo una vez al día" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Solo esta regla: Grabar si el número de episodio difiere" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Solo esta regla: Grabar si el nombre de episodio difiere" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Solo esta regla: Grabar si el título difiere" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Solo esta regla: Grabar si la descripción difiere" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Solo esta regla: Grabar una vez por semana máximo" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Solo esta regla: Grabar una vez al día máximo" msgctxt "#30368" msgid "Default" msgstr "Por defecto" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Regla Programación (enlace series)" msgctxt "#30370" msgid "Record max once per month" msgstr "Grabar una vez al mes máx" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Solo esta regla: Grabar una vez al mes máx" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Grabar si es episodio único según EPG/XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Hasta que necesite espacio" msgctxt "#30374" msgid "Forever" msgstr "Siempre" msgctxt "#30375" msgid "1 day" msgstr "1 día" msgctxt "#30376" msgid "3 days" msgstr "3 días" msgctxt "#30377" msgid "5 days" msgstr "5 días" msgctxt "#30378" msgid "1 week" msgstr "1 semana" msgctxt "#30379" msgid "2 weeks" msgstr "2 semanas" msgctxt "#30380" msgid "3 weeks" msgstr "3 semanas" msgctxt "#30381" msgid "1 month" msgstr "1 mes" msgctxt "#30382" msgid "2 months" msgstr "2 meses" msgctxt "#30383" msgid "3 months" msgstr "3 meses" msgctxt "#30384" msgid "6 months" msgstr "6 meses" msgctxt "#30385" msgid "1 year" msgstr "1 año" msgctxt "#30386" msgid "2 years" msgstr "2 años" msgctxt "#30387" msgid "3 years" msgstr "3 años" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Hasta que se necesite espacio (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Para siempre (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Sintonización predictiva" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Número de suscripciones a usar" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Demora al cerrar suscripción sin usar (segundos)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Usar sintonización predictiva para acelerar cambio de canales" msgctxt "#30450" msgid "No free adapter available" msgstr "Sin adaptador libre disponible" msgctxt "#30451" msgid "Scrambled channel" msgstr "Canal codificado" msgctxt "#30452" msgid "No signal" msgstr "Sin señal" msgctxt "#30453" msgid "Tuning failed" msgstr "Fallo en la sintonía" msgctxt "#30454" msgid "User limit reached" msgstr "Alcanzado número máximo de usuarios" msgctxt "#30455" msgid "No access" msgstr "Sin acceso" msgctxt "#30456" msgid "Subscription error" msgstr "Error de suscripción" msgctxt "#30500" msgid "Streaming profile" msgstr "Perfil de streaming" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Perfil a usar (vacío = por defecto)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "El perfil de streaming %s no está disponible" msgctxt "#30503" msgid "Data transfer" msgstr "Transferencia de datos" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Tamaño del pedacito de lectura para las grabaciones (KB)" msgctxt "#30510" msgid "Recordings" msgstr "Grabaciones" msgctxt "#30511" msgid "Server based play status" msgstr "Estado de reproducción basado en servidor" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.es_mx/000077500000000000000000000000001355512543200260065ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.es_mx/strings.po000066400000000000000000000165771355512543200300570ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Configuración de la conexión" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Nombre de host o dirección IP de Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "Puerto HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Puerto HTSP" msgctxt "#30004" msgid "Username" msgstr "Usuario" msgctxt "#30005" msgid "Password" msgstr "Contraseña" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Tiempo de espera de la conexión (segundos)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Tiempo de espera de respuesta (segundos)" msgctxt "#30008" msgid "Advanced settings" msgstr "Ajustes avanzados" msgctxt "#30009" msgid "Streaming settings" msgstr "Configuración de transmisión" msgctxt "#30010" msgid "Timer settings" msgstr "Configuración del temporizador" msgctxt "#30050" msgid "Auto recordings" msgstr "Grabaciones automáticas" msgctxt "#30051" msgid "Start time window calculation" msgstr "Ventana de cálculo de tiempo de inicio" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Estricto (hora de inicio + hora de finalización)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Relajado (tiempo de inicio +/- margen)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Margen máximo de tiempo de inicio (minutos)" msgctxt "#30055" msgid "Default priority" msgstr "Prioridad predeterminada" msgctxt "#30056" msgid "Default lifetime" msgstr "Vida predeterminada" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Detección de duplicados predeterminada" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Predeterminados para nuevos temporizadores" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Grabaciones programadas" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Ignora duplicados (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Transferencia de datos" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Transferencia asíncrona de EPG" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Traza (detallado)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Versión distinta de HTSP (soportado: v%d, requerido: v%d). Por favor, actualice tvheadend." msgctxt "#30351" msgid "Important (Highest)" msgstr "Importante (más alto)" msgctxt "#30352" msgid "High" msgstr "Alto" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Bajo" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Sin importancia (Menor)" msgctxt "#30356" msgid "Record all episodes" msgstr "Grabar todos los episodios" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Grabar si el número de episodio es diferente" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Grabar si el nombre del episodio difiere" msgctxt "#30359" msgid "Record if description differs" msgstr "Grabar si la descripción difiere" msgctxt "#30360" msgid "Record max once per week" msgstr "Registro máximo una vez por semana" msgctxt "#30361" msgid "Record max once per day" msgstr "Registro máximo una vez por semana" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Esta regla sólo: Graba si el número de episodio es diferente" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Esta regla sólo: Graba si el nombre de episodio es diferente" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Esta regla sólo: Graba si el título es diferente" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Esta regla sólo: Graba si la descripción es diferente" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Esta regla sólo: Graba máximo una vez por semana" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Esta regla sólo: Graba máximo una vez por día" msgctxt "#30368" msgid "Default" msgstr "Por defecto" msgctxt "#30370" msgid "Record max once per month" msgstr "Graba máximo una vez por mes" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Esta regla solo: Graba máximo una ver por mes" msgctxt "#30373" msgid "Until space needed" msgstr "Hasta que se necesite espacio" msgctxt "#30374" msgid "Forever" msgstr "Por sienpre" msgctxt "#30375" msgid "1 day" msgstr "1 día" msgctxt "#30376" msgid "3 days" msgstr "3 días" msgctxt "#30377" msgid "5 days" msgstr "5 días" msgctxt "#30378" msgid "1 week" msgstr "1 semana" msgctxt "#30379" msgid "2 weeks" msgstr "2 semanas" msgctxt "#30380" msgid "3 weeks" msgstr "3 semanas" msgctxt "#30381" msgid "1 month" msgstr "1 mes" msgctxt "#30382" msgid "2 months" msgstr "2 meses" msgctxt "#30383" msgid "3 months" msgstr "3 meses" msgctxt "#30384" msgid "6 months" msgstr "6 meses" msgctxt "#30385" msgid "1 year" msgstr "1 año" msgctxt "#30386" msgid "2 years" msgstr "2 años" msgctxt "#30387" msgid "3 years" msgstr "3 años" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Hasta el espacio necesario (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Siempre (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Sintonización predictiva" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Número de suscripciones a usar" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Duración de cierre de la suscripción no utilizada (segundos)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Use la sintonía predictiva para acelerar los conmutadores de canal" msgctxt "#30450" msgid "No free adapter available" msgstr "No hay adaptador disponible" msgctxt "#30451" msgid "Scrambled channel" msgstr "Canal codificado" msgctxt "#30452" msgid "No signal" msgstr "Sin señal" msgctxt "#30453" msgid "Tuning failed" msgstr "El ajuste falló" msgctxt "#30454" msgid "User limit reached" msgstr "Se ha alcanzado el límite de usuario" msgctxt "#30455" msgid "No access" msgstr "Sin acceso" msgctxt "#30456" msgid "Subscription error" msgstr "Error de suscripción" msgctxt "#30500" msgid "Streaming profile" msgstr "Perfil de transmisión" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Perfil a usar (vacío = predeterminado)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "El perfil de streaming %s no está disponible" msgctxt "#30503" msgid "Data transfer" msgstr "Transferencia de datos" msgctxt "#30510" msgid "Recordings" msgstr "Grabaciones" msgctxt "#30511" msgid "Server based play status" msgstr "Servidor basado en el estado de reproducción" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.et_ee/000077500000000000000000000000001355512543200257545ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.et_ee/strings.po000066400000000000000000000026731355512543200300150ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend hosti nimi või IP aadress" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP port" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP port" msgctxt "#30004" msgid "Username" msgstr "Kasutajanimi" msgctxt "#30005" msgid "Password" msgstr "Salasõna" msgctxt "#30010" msgid "Timer settings" msgstr "Taimeri seaded" msgctxt "#30200" msgid "Debugging" msgstr "Silumine" msgctxt "#30352" msgid "High" msgstr "Kõrge" msgctxt "#30353" msgid "Normal" msgstr "Normaalne" msgctxt "#30354" msgid "Low" msgstr "Madal" msgctxt "#30356" msgid "Record all episodes" msgstr "Salvesta kõik episoodid" msgctxt "#30368" msgid "Default" msgstr "Vaikimisi" msgctxt "#30510" msgid "Recordings" msgstr "Salvestused" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.eu_es/000077500000000000000000000000001355512543200257735ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.eu_es/strings.po000066400000000000000000000030501355512543200300220ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30000" msgid "Connection settings" msgstr "Konexio-ezarpenak" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP ataka" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP ataka" msgctxt "#30004" msgid "Username" msgstr "Erabiltzailea" msgctxt "#30005" msgid "Password" msgstr "Pasahitza" msgctxt "#30008" msgid "Advanced settings" msgstr "Ezarpen aurreratuak" msgctxt "#30010" msgid "Timer settings" msgstr "Programazio ezarpenak" msgctxt "#30050" msgid "Auto recordings" msgstr "Audio grabazioak" msgctxt "#30200" msgid "Debugging" msgstr "Arazketa" msgctxt "#30352" msgid "High" msgstr "Handia" msgctxt "#30353" msgid "Normal" msgstr "Arrunta" msgctxt "#30354" msgid "Low" msgstr "Baxua" msgctxt "#30356" msgid "Record all episodes" msgstr "Grabatu atal guztiak" msgctxt "#30368" msgid "Default" msgstr "Lehenetsia" msgctxt "#30510" msgid "Recordings" msgstr "Grabazioak" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.fa_af/000077500000000000000000000000001355512543200257275ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.fa_af/strings.po000066400000000000000000000016311355512543200277610ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30004" msgid "Username" msgstr "نام کاربری" msgctxt "#30005" msgid "Password" msgstr "کلمه عبور" msgctxt "#30353" msgid "Normal" msgstr "نورمال" msgctxt "#30368" msgid "Default" msgstr "پیش فرض" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.fa_ir/000077500000000000000000000000001355512543200257535ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.fa_ir/strings.po000066400000000000000000000024711355512543200300100ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30002" msgid "HTTP port" msgstr "پورت HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "پورت HTSP" msgctxt "#30004" msgid "Username" msgstr "نام کاربری" msgctxt "#30005" msgid "Password" msgstr "رمز عبور" msgctxt "#30200" msgid "Debugging" msgstr "دیباگ" msgctxt "#30352" msgid "High" msgstr "زیاد" msgctxt "#30353" msgid "Normal" msgstr "نرمال" msgctxt "#30354" msgid "Low" msgstr "کم" msgctxt "#30356" msgid "Record all episodes" msgstr "همه قسمت‌ها را ضبط کن" msgctxt "#30368" msgid "Default" msgstr "پیش فرض" msgctxt "#30510" msgid "Recordings" msgstr "ضبط شده ها" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.fi_fi/000077500000000000000000000000001355512543200257475ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.fi_fi/strings.po000066400000000000000000000172561355512543200300130ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Yhteysasetukset" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend-palvelimen nimi tai IP-osoite" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP-portti" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP-portti" msgctxt "#30004" msgid "Username" msgstr "Käyttäjänimi" msgctxt "#30005" msgid "Password" msgstr "Salasana" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Yhteyden aikakatkaisu (sekuntia)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Vastauksen aikakatkaisu (sekuntia)" msgctxt "#30008" msgid "Advanced settings" msgstr "Lisäasetukset" msgctxt "#30009" msgid "Streaming settings" msgstr "Suoratoistoasetukset" msgctxt "#30010" msgid "Timer settings" msgstr "Ajastuksen asetukset" msgctxt "#30050" msgid "Auto recordings" msgstr "Automaattiset tallennukset" msgctxt "#30051" msgid "Start time window calculation" msgstr "Aloitusajan määrittely" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Tarkka (aloitusaika + lopetusaika)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Joustava (aloitusaika +/- marginaali)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Aloitusajan enimmäismarginaali (minuuttia)" msgctxt "#30055" msgid "Default priority" msgstr "Tärkeys" msgctxt "#30056" msgid "Default lifetime" msgstr "Elinikä" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Kaksoiskappaleiden tunnistus" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Ajastusten oletusasetukset" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Ajastukset" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Älä huomioi tuplia (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Tiedonsiirto" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Epäsynkroninen ohjelmaoppaan lataus" msgctxt "#30200" msgid "Debugging" msgstr "Virheenkorjaus" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Tallenna yksityiskohtaiset virheenkorjaustiedot" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP-versio on yhteensopimaton (tuettu: v%d, vaadittu: v%d). Ole hyvä ja päivitä tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Kerran (luotu ajastussäännöllä)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Tärkeä (korkein)" msgctxt "#30352" msgid "High" msgstr "Korkea" msgctxt "#30353" msgid "Normal" msgstr "Normaali" msgctxt "#30354" msgid "Low" msgstr "Matala" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Ei tärkeä (matalin)" msgctxt "#30356" msgid "Record all episodes" msgstr "Tallenna kaikki jaksot" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Tallenna, jos on eri jaksonumero" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Tallenna, jos on eri jaksonimi" msgctxt "#30359" msgid "Record if description differs" msgstr "Tallenna, jos on eri kuvaus" msgctxt "#30360" msgid "Record max once per week" msgstr "Tallenna enintään kerran viikossa" msgctxt "#30361" msgid "Record max once per day" msgstr "Tallenna enintään kerran päivässä" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Vain tämä sääntö: tallenna, jos on eri jaksonumero" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Vain tämä sääntö: tallenna, jos on eri jaksonimi" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Vain tämä sääntö: tallenna, jos on eri nimi" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Vain tämä sääntö: tallenna, jos on eri kuvaus" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Vain tämä sääntö: tallenna enintään kerran viikossa" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Vain tämä sääntö: tallenna enintään kerran päivässä" msgctxt "#30368" msgid "Default" msgstr "Oletus" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Ajastussääntö (sarjalinkki)" msgctxt "#30370" msgid "Record max once per month" msgstr "Tallenna enintään kerran kuukaudessa" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Vain tämä sääntö: tallenna enintään kerran kuukaudessa" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Tallenna, jos on uniikki jakso EPG:n/XMLTV:n mukaan" msgctxt "#30373" msgid "Until space needed" msgstr "Kunnes tarvetta lisätilalle" msgctxt "#30374" msgid "Forever" msgstr "Ikuisesti" msgctxt "#30375" msgid "1 day" msgstr "1 päivä" msgctxt "#30376" msgid "3 days" msgstr "3 päivää" msgctxt "#30377" msgid "5 days" msgstr "5 päivää" msgctxt "#30378" msgid "1 week" msgstr "1 viikko" msgctxt "#30379" msgid "2 weeks" msgstr "2 viikkoa" msgctxt "#30380" msgid "3 weeks" msgstr "3 viikkoa" msgctxt "#30381" msgid "1 month" msgstr "1 kuukausi" msgctxt "#30382" msgid "2 months" msgstr "2 kuukautta" msgctxt "#30383" msgid "3 months" msgstr "3 kuukautta" msgctxt "#30384" msgid "6 months" msgstr "6 kuukautta" msgctxt "#30385" msgid "1 year" msgstr "1 vuosi" msgctxt "#30386" msgid "2 years" msgstr "2 vuotta" msgctxt "#30387" msgid "3 years" msgstr "3 vuotta" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Kunnes tarvitaan lisätilaa (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Ikuisesti (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Ennakoiva viritys" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Viritettävien kanavien määrä" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Viive virityksen poistamiselle (sekuntia)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Nopeuta kanavanvaihtoa ennakoivalla virityksellä" msgctxt "#30450" msgid "No free adapter available" msgstr "Yhtään viritintä ei ole vapaana" msgctxt "#30451" msgid "Scrambled channel" msgstr "Salattu kanava" msgctxt "#30452" msgid "No signal" msgstr "Ei signaalia" msgctxt "#30453" msgid "Tuning failed" msgstr "Viritys epäonnistui" msgctxt "#30454" msgid "User limit reached" msgstr "Käyttäjäraja saavutettu" msgctxt "#30455" msgid "No access" msgstr "Ei pääsyä" msgctxt "#30456" msgid "Subscription error" msgstr "Tilausvirhe" msgctxt "#30500" msgid "Streaming profile" msgstr "Suoratoistoprofiili" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Käytettävä profiili (tyhjä = oletus)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Suoratoistoprofiili %s ei ole saatavilla" msgctxt "#30503" msgid "Data transfer" msgstr "Tiedonsiirto" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Tallenteita toistettaessa käytettävä pakettikoko (kt)" msgctxt "#30510" msgid "Recordings" msgstr "Tallenteet" msgctxt "#30511" msgid "Server based play status" msgstr "Palvelinpohjainen katsottujen tallenteiden merkintä" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.fo_fo/000077500000000000000000000000001355512543200257635ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.fo_fo/strings.po000066400000000000000000000020331355512543200300120ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30004" msgid "Username" msgstr "Brúkaranavn" msgctxt "#30005" msgid "Password" msgstr "Loyniorð" msgctxt "#30352" msgid "High" msgstr "Høgt" msgctxt "#30353" msgid "Normal" msgstr "Vanligt" msgctxt "#30354" msgid "Low" msgstr "Lágt" msgctxt "#30368" msgid "Default" msgstr "Vanligt" msgctxt "#30510" msgid "Recordings" msgstr "Upptøkur" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.fr_ca/000077500000000000000000000000001355512543200257455ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.fr_ca/strings.po000066400000000000000000000201521355512543200277760ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Paramètres de connexion" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Nom d’hôte ou adresse IP de Tvheadend " msgctxt "#30002" msgid "HTTP port" msgstr "Port HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Port HTSP" msgctxt "#30004" msgid "Username" msgstr "Nom d’utilisateur" msgctxt "#30005" msgid "Password" msgstr "Mot de passe" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Temporisation de connexion (secondes)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Temporisation de réponse (secondes)" msgctxt "#30008" msgid "Advanced settings" msgstr "Paramètres avancés" msgctxt "#30009" msgid "Streaming settings" msgstr "Paramètres de diffusion en continu" msgctxt "#30010" msgid "Timer settings" msgstr "Paramètres de minuterie" msgctxt "#30050" msgid "Auto recordings" msgstr "Enregistrements automatiques" msgctxt "#30051" msgid "Start time window calculation" msgstr "Calcul de la fenêtre d’heure de début" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Stricte (heure de début + heure de fin)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Tolérant (heure de début +/- marge)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Marge maximale d’heure de début (minutes)" msgctxt "#30055" msgid "Default priority" msgstr "Priorité par défaut" msgctxt "#30056" msgid "Default lifetime" msgstr "Durée de vie par défaut" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Détection des doublons par défaut" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Valeurs par défaut des nouvelles minuteries" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Enregistrements planifiés" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Ignorer les doublons (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Transfert de données" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Transfert asynchrone de l’ÉGP" msgctxt "#30200" msgid "Debugging" msgstr "Débogage" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Trace (détaillée)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Mauvaise version HTSP (prise en charge : v%d, exigée : v%d). Veuillez mettre tvheadend à jour." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Une fois (planifiée par une règle de minuterie)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Importante (la plus élevée)" msgctxt "#30352" msgid "High" msgstr "Élevée" msgctxt "#30353" msgid "Normal" msgstr "Normale" msgctxt "#30354" msgid "Low" msgstr "Basse" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Sans importance (la moins élevée)" msgctxt "#30356" msgid "Record all episodes" msgstr "Enregistrer tous les épisodes" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Enregistrer si le numéro d’épisode diffère" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Enregistrer si le nom de l’épisode diffère" msgctxt "#30359" msgid "Record if description differs" msgstr "Enregistrer si la description diffère" msgctxt "#30360" msgid "Record max once per week" msgstr "Enregistrer au plus une fois par semaine" msgctxt "#30361" msgid "Record max once per day" msgstr "Enregistrer au plus une fois par jour" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Cette règle seulement : enregistrer si le numéro d’épisode diffère" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Cette règle seulement : enregistrer si le nom de l’épisode diffère" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Cette règle seulement : enregistrer si le titre diffère" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Cette règle seulement : enregistrer si la description diffère" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Cette règle seulement : enregistrer au plus une fois par semaine" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Cette règle seulement : enregistrer au plus une fois par jour" msgctxt "#30368" msgid "Default" msgstr "Valeur par défaut" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Règle de minuterie (lien de série)" msgctxt "#30370" msgid "Record max once per month" msgstr "Enregistrer au plus une fois par mois" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Cette règle seulement : enregistrer au plus une fois par mois" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Enregistrer si l’épisode est unique d’après le GÉP ou XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Jusqu’à ce que l’espace soit requis" msgctxt "#30374" msgid "Forever" msgstr "Permanent" msgctxt "#30375" msgid "1 day" msgstr "1 jour" msgctxt "#30376" msgid "3 days" msgstr "3 jours" msgctxt "#30377" msgid "5 days" msgstr "5 jours" msgctxt "#30378" msgid "1 week" msgstr "1 semaine" msgctxt "#30379" msgid "2 weeks" msgstr "2 semaines" msgctxt "#30380" msgid "3 weeks" msgstr "3 semaines" msgctxt "#30381" msgid "1 month" msgstr "1 mois" msgctxt "#30382" msgid "2 months" msgstr "2 mois" msgctxt "#30383" msgid "3 months" msgstr "3 mois" msgctxt "#30384" msgid "6 months" msgstr "6 mois" msgctxt "#30385" msgid "1 year" msgstr "1 an" msgctxt "#30386" msgid "2 years" msgstr "2 ans" msgctxt "#30387" msgid "3 years" msgstr "3 ans" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Jusqu’à ce que l’espace soit requis (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Indéfiniment (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Syntonisation prévisionnelle" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Nombre d’abonnements à utiliser" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Délai de fermeture d’un abonnement non utilisé (secondes)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Utiliser la syntonisation prévisionnelle pour accélérer les changements de chaînes" msgctxt "#30450" msgid "No free adapter available" msgstr "Aucun adaptateur gratuit proposé" msgctxt "#30451" msgid "Scrambled channel" msgstr "Chaîne brouillée" msgctxt "#30452" msgid "No signal" msgstr "Aucun signal" msgctxt "#30453" msgid "Tuning failed" msgstr "Échec de syntonisation" msgctxt "#30454" msgid "User limit reached" msgstr "Limite de l’utilisateur atteinte" msgctxt "#30455" msgid "No access" msgstr "Aucun accès" msgctxt "#30456" msgid "Subscription error" msgstr "Erreur d’abonnement" msgctxt "#30500" msgid "Streaming profile" msgstr "Profil de diffusion en continu" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profil à utiliser (vide = valeur par défaut)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Le profil de diffusion en continu %s n’est pas disponible" msgctxt "#30503" msgid "Data transfer" msgstr "Transfert de données" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Taille des fragments de lecture du flux pour les enregistrements (ko)" msgctxt "#30510" msgid "Recordings" msgstr "Enregistrements" msgctxt "#30511" msgid "Server based play status" msgstr "État de lecture d’après le serveur" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.fr_fr/000077500000000000000000000000001355512543200257715ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.fr_fr/strings.po000066400000000000000000000177411355512543200300340ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Paramètres de connexion" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Nom d'hôte ou adresse IP Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "Port HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Port HTSP" msgctxt "#30004" msgid "Username" msgstr "Nom d'utilisateur" msgctxt "#30005" msgid "Password" msgstr "Mot de passe" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Temporisation de connexion (secondes)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Temporisation de réponse (sec.)" msgctxt "#30008" msgid "Advanced settings" msgstr "Paramètres avancés" msgctxt "#30009" msgid "Streaming settings" msgstr "Paramètres de diffusion" msgctxt "#30010" msgid "Timer settings" msgstr "Paramètres de la programmation" msgctxt "#30050" msgid "Auto recordings" msgstr "Enregistrements auto." msgctxt "#30051" msgid "Start time window calculation" msgstr "Calcul de la fenêtre du temps de début" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Stricte (temps de début + temps de fin)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Approximative (temps de début +/- marge)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Marge max. de temps de début (min.)" msgctxt "#30055" msgid "Default priority" msgstr "Priorité par défaut" msgctxt "#30056" msgid "Default lifetime" msgstr "Durée de vie par défaut" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Détection de duplication par défaut" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Préréglages des nouvelles programmations" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Enregistrements planifiés" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Ignorer les doublons (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Transfert de données" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Transfert asynchrone du guide des programmes" msgctxt "#30200" msgid "Debugging" msgstr "Débogage" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Trace (détaillée)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Version HTSP différente (reconnue : v%d, requise : v%d). Merci de mettre à jour tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Une fois (planifiée par une règle de programmation)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Important (le plus élevé)" msgctxt "#30352" msgid "High" msgstr "Haute" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Basse" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Important (le moins élevé)" msgctxt "#30356" msgid "Record all episodes" msgstr "Enregistrer tous les épisodes" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Enregistrer si le nombre d'épisodes est différent" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Enregistrer si le nom de l'épisode est différent" msgctxt "#30359" msgid "Record if description differs" msgstr "Enregistrer si la description est différente" msgctxt "#30360" msgid "Record max once per week" msgstr "Enregistrer max. une fois pas semaine" msgctxt "#30361" msgid "Record max once per day" msgstr "Enregistrer max. une fois pas jour" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Cette règle seulement : enregistrer si le n° d'épisode diffère" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Cette règle seulement : enregistrer si le nom d'épisode diffère" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Cette règle seulement : enregistrer si le titre diffère" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Cette règle seulement : enregistrer si la description diffère" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Cette règle seulement : enregistrer 1x max. par semaine" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Cette règle seulement : enregistrer 1x max. par jour" msgctxt "#30368" msgid "Default" msgstr "Prédéfini" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Règle de programmation" msgctxt "#30370" msgid "Record max once per month" msgstr "Enregistrer une fois max. par mois" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Cette règle seulement : enregistrer une fois max. par mois" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Enregistrer si épisode unique selon le guide/XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Jusqu'à ce qu'il y ait besoin d'espace" msgctxt "#30374" msgid "Forever" msgstr "Indéfiniment" msgctxt "#30375" msgid "1 day" msgstr "1 jour" msgctxt "#30376" msgid "3 days" msgstr "3 jours" msgctxt "#30377" msgid "5 days" msgstr "5 jours" msgctxt "#30378" msgid "1 week" msgstr "1 semaine" msgctxt "#30379" msgid "2 weeks" msgstr "2 semaines" msgctxt "#30380" msgid "3 weeks" msgstr "3 semaines" msgctxt "#30381" msgid "1 month" msgstr "1 mois" msgctxt "#30382" msgid "2 months" msgstr "2 mois" msgctxt "#30383" msgid "3 months" msgstr "3 mois" msgctxt "#30384" msgid "6 months" msgstr "6 mois" msgctxt "#30385" msgid "1 year" msgstr "1 an" msgctxt "#30386" msgid "2 years" msgstr "2 ans" msgctxt "#30387" msgid "3 years" msgstr "3 ans" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Jusqu'à ce qu'il y ait besoin d'espace (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Indéfiniment (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Syntonisation prédictive" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Nombre de souscriptions à utiliser" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Délai avant péremption de la souscription inutilisée (sec.)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Utiliser la syntonisation prédictive pour accélérer les changements de chaînes" msgctxt "#30450" msgid "No free adapter available" msgstr "Aucun adaptateur libre" msgctxt "#30451" msgid "Scrambled channel" msgstr "Chaîne cryptée" msgctxt "#30452" msgid "No signal" msgstr "Aucun signal" msgctxt "#30453" msgid "Tuning failed" msgstr "Échec de la syntonisation" msgctxt "#30454" msgid "User limit reached" msgstr "Limite utilisateur atteinte" msgctxt "#30455" msgid "No access" msgstr "Aucun accès" msgctxt "#30456" msgid "Subscription error" msgstr "Erreur à la souscription" msgctxt "#30500" msgid "Streaming profile" msgstr "Profil de diffusion" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profil à utiliser (vide = prédéfini)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Le profil %s de diffusion par flux n'est pas disponible." msgctxt "#30503" msgid "Data transfer" msgstr "Transfert de données" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Taille des blocs de flux de lecture des enregistrements (ko)" msgctxt "#30510" msgid "Recordings" msgstr "Enregistrements" msgctxt "#30511" msgid "Server based play status" msgstr "État de lecture basé sur le serveur" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.gl_es/000077500000000000000000000000001355512543200257645ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.gl_es/strings.po000066400000000000000000000152061355512543200300210ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Configuración da Conexión" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Nome do host ou enderezo IP" msgctxt "#30002" msgid "HTTP port" msgstr "Porto HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Porto HTSP" msgctxt "#30004" msgid "Username" msgstr "Nome de usuario" msgctxt "#30005" msgid "Password" msgstr "Contrasinal" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Tempo de espera da conexión (segundos)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Tempo de espera da resposta (segundos)" msgctxt "#30008" msgid "Advanced settings" msgstr "Axustes avanzados" msgctxt "#30009" msgid "Streaming settings" msgstr "Axustes da transmisión" msgctxt "#30010" msgid "Timer settings" msgstr "Axuste do temporizador" msgctxt "#30050" msgid "Auto recordings" msgstr "Gravacións auto." msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Estrito (hora de inicio + hora de fin)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Relaxado (hora de inicio +/- marxe)" msgctxt "#30055" msgid "Default priority" msgstr "Prioridade predefinida" msgctxt "#30056" msgid "Default lifetime" msgstr "Tempo de vida predefinido" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Detección de duplicados predefinida" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Predefinicións para novos temporizadores" msgctxt "#30100" msgid "Data transfer" msgstr "Transferencia de datos" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Transferencia asíncrona da Guía" msgctxt "#30200" msgid "Debugging" msgstr "Depuración" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Rexistro (detallado)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "A versión do HTSP non coincide (soportado: v%d, requirido: v%d). Por favor actualice o tvheadend." msgctxt "#30351" msgid "Important (Highest)" msgstr "Importante (Maior)" msgctxt "#30352" msgid "High" msgstr "Alta" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Baixa" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Sen importancia (máis baixo)" msgctxt "#30356" msgid "Record all episodes" msgstr "Gravar todos os episodios" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Gravar se o número do episodio é diferente" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Gravar se o nome do episodio é diferente" msgctxt "#30359" msgid "Record if description differs" msgstr "Gravar se a descrición é diferente" msgctxt "#30360" msgid "Record max once per week" msgstr "Gravar unha vez por semana como máximo" msgctxt "#30361" msgid "Record max once per day" msgstr "Gravar unha vez ao día como máximo" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Só esta regra: Gravar se o número do capítulo é diferente" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Só esta regra: Gravar se o nome do episodio é diferente" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Só esta regra: Gravar se o título é diferente" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Só esta regra: Gravar se a descrición é diferente" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Só esta regra: Gravar unha vez por semana como máximo" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Só esta regra: Gravar unha vez ao día como máximo" msgctxt "#30368" msgid "Default" msgstr "Predefinida" msgctxt "#30373" msgid "Until space needed" msgstr "Até que precise de espazo" msgctxt "#30374" msgid "Forever" msgstr "Sempre" msgctxt "#30375" msgid "1 day" msgstr "1 día" msgctxt "#30376" msgid "3 days" msgstr "3 días" msgctxt "#30377" msgid "5 days" msgstr "5 días" msgctxt "#30378" msgid "1 week" msgstr "1 semana" msgctxt "#30379" msgid "2 weeks" msgstr "2 semanas" msgctxt "#30380" msgid "3 weeks" msgstr "3 semanas" msgctxt "#30381" msgid "1 month" msgstr "1 mes" msgctxt "#30382" msgid "2 months" msgstr "2 meses" msgctxt "#30383" msgid "3 months" msgstr "3 meses" msgctxt "#30384" msgid "6 months" msgstr "6 meses" msgctxt "#30385" msgid "1 year" msgstr "1 ano" msgctxt "#30386" msgid "2 years" msgstr "2 anos" msgctxt "#30387" msgid "3 years" msgstr "3 anos" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Até que precise de espazo (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Sempre (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Sintonización preditiva" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Número de subscricións a empregar" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Atraso para pechar subscrición sen uso (segundos)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Empregar sintonización predictiva para mellorar o troco de canles" msgctxt "#30450" msgid "No free adapter available" msgstr "Sen adaptador libre dispoñíbel" msgctxt "#30451" msgid "Scrambled channel" msgstr "Canles codificadas" msgctxt "#30452" msgid "No signal" msgstr "Sen sinal" msgctxt "#30453" msgid "Tuning failed" msgstr "Fallou a sintonización" msgctxt "#30454" msgid "User limit reached" msgstr "Acadado o límite do usuario" msgctxt "#30455" msgid "No access" msgstr "Sen acceso" msgctxt "#30456" msgid "Subscription error" msgstr "Erro na subscrición" msgctxt "#30500" msgid "Streaming profile" msgstr "Perfil da transmisión" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Perfil a empregar (baleiro = predefinido)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "O perfil de transmisión %s non está dispoñible" msgctxt "#30503" msgid "Data transfer" msgstr "Transferencia de datos" msgctxt "#30510" msgid "Recordings" msgstr "Gravacións" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.he_il/000077500000000000000000000000001355512543200257535ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.he_il/strings.po000066400000000000000000000172671355512543200300210ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "הגדרות חיבור" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "שם מארח או כתובת IP" msgctxt "#30002" msgid "HTTP port" msgstr "פורט HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "פורט HTSP" msgctxt "#30004" msgid "Username" msgstr "שם משתמש" msgctxt "#30005" msgid "Password" msgstr "סיסמה" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "זמן מירבי לניסיון חיבור (שנ')" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "זמן מירבי לתגובה משרת (שנ')" msgctxt "#30008" msgid "Advanced settings" msgstr "הגדרות מתקדמות" msgctxt "#30009" msgid "Streaming settings" msgstr "הגדרות הזרמה" msgctxt "#30010" msgid "Timer settings" msgstr "הגדרות תזמון" msgctxt "#30050" msgid "Auto recordings" msgstr "הקלטות אוטומטיות" msgctxt "#30051" msgid "Start time window calculation" msgstr "חלון התחל חישוב זמן" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "קפדני (שעת התחלה + שעת סיום)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "רגוע (שעת ההתחלה +/- מרווח)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "מרווח מקסימלי שעת התחלה (דקות)" msgctxt "#30055" msgid "Default priority" msgstr "קדימות ברירת מחדל" msgctxt "#30056" msgid "Default lifetime" msgstr "אורך חיים ברירת מחדל" msgctxt "#30057" msgid "Default duplicate detection" msgstr "ברירת מחדל לזיהוי כפילויות" msgctxt "#30058" msgid "Defaults for new timers" msgstr "ברירות מחדל לתזמון חדש" msgctxt "#30100" msgid "Data transfer" msgstr "העברת נתונים" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "העברת מדריך שידורים אסינכרונית" msgctxt "#30200" msgid "Debugging" msgstr "ניפוי שגיאות" msgctxt "#30201" msgid "Trace (detailed)" msgstr "מעקב תקשורת (מפורט)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "חוסר תאימות גרסת HTSP (נתמכת v%d, נדרשת: v%d). יש לעדכן את שרת Tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "חד פעמי (מתוזמן על ידי כלל של שעון העצר)" msgctxt "#30351" msgid "Important (Highest)" msgstr "חשובה (גבוהה ביותר)" msgctxt "#30352" msgid "High" msgstr "גבוהה" msgctxt "#30353" msgid "Normal" msgstr "רגילה" msgctxt "#30354" msgid "Low" msgstr "נמוכה" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "לא חשובה (נמוכה ביותר)" msgctxt "#30356" msgid "Record all episodes" msgstr "הקלט כל הפרקים" msgctxt "#30357" msgid "Record if episode number differs" msgstr "הקלט כאשר מספר הפרק שונה" msgctxt "#30358" msgid "Record if episode name differs" msgstr "הקלט כאשר שם הפרק שונה" msgctxt "#30359" msgid "Record if description differs" msgstr "הקלט כאשר תיאור הפרק שונה" msgctxt "#30360" msgid "Record max once per week" msgstr "הקלטה מקסימלית פעם בשבוע" msgctxt "#30361" msgid "Record max once per day" msgstr "הקלטה מקסימלית פעם ביום" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "כלל זה בלבד: יש להקליט אם מספר הפרק שונה" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "כלל זה בלבד: יש להקליט אם שם הפרק שונה" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "כלל זה בלבד: יש להקליט אם הכותרת שונה" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "כלל זה בלבד: יש להקליט אם התיאור שונה" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "כלל זה בלבד: יש להקליט פעם אחת בשבוע" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "כלל זה בלבד: יש להקליט פעם אחת ביום" msgctxt "#30368" msgid "Default" msgstr "ברירת מחדל" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "כלל שעון העצר (קישור בסדרה)" msgctxt "#30373" msgid "Until space needed" msgstr "עד שנפח האחסון נדרש" msgctxt "#30374" msgid "Forever" msgstr "לעד" msgctxt "#30375" msgid "1 day" msgstr "יום יחיד" msgctxt "#30376" msgid "3 days" msgstr "3 ימים" msgctxt "#30377" msgid "5 days" msgstr "5 ימים" msgctxt "#30378" msgid "1 week" msgstr "שבוע יחיד" msgctxt "#30379" msgid "2 weeks" msgstr "שבועיים" msgctxt "#30380" msgid "3 weeks" msgstr "3 שבועות" msgctxt "#30381" msgid "1 month" msgstr "חודש יחיד" msgctxt "#30382" msgid "2 months" msgstr "חודשיים" msgctxt "#30383" msgid "3 months" msgstr "3 חודשים" msgctxt "#30384" msgid "6 months" msgstr "6 חודשים" msgctxt "#30385" msgid "1 year" msgstr "שנה אחת" msgctxt "#30386" msgid "2 years" msgstr "שנתיים" msgctxt "#30387" msgid "3 years" msgstr "3 שנים" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "עד שנפח האיחסון הנדרש (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "לתמיד (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "כוונון חזוי" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "מספר המנויים המוגדר לשימוש" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "סגירת השהיה מנויים בשימוש (שניות)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "השתמש בכוונון חזוי בכדי להאיץ החלפת ערוצים" msgctxt "#30450" msgid "No free adapter available" msgstr "אין מקלט זמין" msgctxt "#30451" msgid "Scrambled channel" msgstr "ערוץ מוצפן" msgctxt "#30452" msgid "No signal" msgstr "אין קליטה" msgctxt "#30453" msgid "Tuning failed" msgstr "כוונון נכשל" msgctxt "#30454" msgid "User limit reached" msgstr "המערכת הגיעה למגבלת המשתמש" msgctxt "#30455" msgid "No access" msgstr "אין גישה" msgctxt "#30456" msgid "Subscription error" msgstr "שגיאה במנויים" msgctxt "#30500" msgid "Streaming profile" msgstr "פרופיל הזרמה" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "פרופיל לשימוש (ריק = ברירת מחדל)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "פרופיל הזרמה %s אינו זמין" msgctxt "#30503" msgid "Data transfer" msgstr "העברת נתונים" msgctxt "#30510" msgid "Recordings" msgstr "הקלטות" msgctxt "#30511" msgid "Server based play status" msgstr "שרת מבוסס סטטוס משחק" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.hi_in/000077500000000000000000000000001355512543200257615ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.hi_in/strings.po000066400000000000000000000020511355512543200300100ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30004" msgid "Username" msgstr "उपयोगकर्ता नाम" msgctxt "#30200" msgid "Debugging" msgstr "डिबगिंग" msgctxt "#30352" msgid "High" msgstr "उच्च" msgctxt "#30353" msgid "Normal" msgstr "सामान्य" msgctxt "#30354" msgid "Low" msgstr "लो" msgctxt "#30368" msgid "Default" msgstr "डिफ़ॉल्ट" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.hr_hr/000077500000000000000000000000001355512543200257755ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.hr_hr/strings.po000066400000000000000000000173311355512543200300330ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Postavke povezivanja" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend naziv računala ili IP adresa" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP ulaz" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP ulaz" msgctxt "#30004" msgid "Username" msgstr "Korisničko ime" msgctxt "#30005" msgid "Password" msgstr "Lozinka" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Istek povezivanja (sekunde)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Vrijeme odaziva (sekunde)" msgctxt "#30008" msgid "Advanced settings" msgstr "Napredne postavke" msgctxt "#30009" msgid "Streaming settings" msgstr "Postavke stremanja" msgctxt "#30010" msgid "Timer settings" msgstr "Zakazana snimanja" msgctxt "#30050" msgid "Auto recordings" msgstr "Automatska snimanja" msgctxt "#30051" msgid "Start time window calculation" msgstr "Izračun početnog vremena" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Točno (početno vrijeme + završno vrijeme)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Prilagođeno (početno vrijeme +/- vrijednost)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Najveća vrijednost početnog vremena (minute)" msgctxt "#30055" msgid "Default priority" msgstr "Zadani prioritet" msgctxt "#30056" msgid "Default lifetime" msgstr "Zadano trajanje snimanja" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Zadano otkrivanje duplikata" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Zadano za nova zakazana snimanja" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Raspored snimanja" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Zanemari duplikate (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Prijenos podataka" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Neusklađeni EPG prijenos" msgctxt "#30200" msgid "Debugging" msgstr "Otklanjanje grešaka" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Praćenje (opširnije)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP inačica se ne podudara (podržana: v%d, potrebna: v%d). Nadogradite tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Jednom (Zakazano zadanim rasporedom)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Značajan (Najviši)" msgctxt "#30352" msgid "High" msgstr "Visok" msgctxt "#30353" msgid "Normal" msgstr "Normalan" msgctxt "#30354" msgid "Low" msgstr "Nizak" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Beznačajan (Najniži)" msgctxt "#30356" msgid "Record all episodes" msgstr "Snimi sve epizode" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Snimi ako se broj epizode razlikuje" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Snimi ako se naslov epizode razlikuje" msgctxt "#30359" msgid "Record if description differs" msgstr "Snimi ako se opis razlikuje" msgctxt "#30360" msgid "Record max once per week" msgstr "Snimi najviše jednom tjedno" msgctxt "#30361" msgid "Record max once per day" msgstr "Snimi najviše jednom dnevno" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Samo ovo pravilo: Snimi ako se broj epizode razlikuje" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Samo ovo pravilo: Snimi ako se naslov epizode razlikuje" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Samo ovo pravilo: Snimi ako se naslov razlikuje" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Samo ovo pravilo: Snimi ako se opis razlikuje" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Samo ovo pravilo: Snimi najviše jednom tjedno" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Samo ovo pravilo: Snimi najviše jednom dnevno" msgctxt "#30368" msgid "Default" msgstr "Zadano" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Pravilo zakazanih snimanja (serijska poveznica)" msgctxt "#30370" msgid "Record max once per month" msgstr "Snimi najviše jednom mjesečno" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Samo za ovo pravilo: Snimi najviše jednom mjesečno" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Snimi ako je epizoda jedinstvena prema EPG/XMLTV vodiču" msgctxt "#30373" msgid "Until space needed" msgstr "Dok ima slobodnog prostora" msgctxt "#30374" msgid "Forever" msgstr "Zauvijek" msgctxt "#30375" msgid "1 day" msgstr "1 dan" msgctxt "#30376" msgid "3 days" msgstr "3 dana" msgctxt "#30377" msgid "5 days" msgstr "5 dana" msgctxt "#30378" msgid "1 week" msgstr "1 tjedan" msgctxt "#30379" msgid "2 weeks" msgstr "2 tjedna" msgctxt "#30380" msgid "3 weeks" msgstr "3 tjedna" msgctxt "#30381" msgid "1 month" msgstr "1 mjesec" msgctxt "#30382" msgid "2 months" msgstr "2 mjeseca" msgctxt "#30383" msgid "3 months" msgstr "3 mjeseca" msgctxt "#30384" msgid "6 months" msgstr "6 mjeseca" msgctxt "#30385" msgid "1 year" msgstr "1 godina" msgctxt "#30386" msgid "2 years" msgstr "2 godine" msgctxt "#30387" msgid "3 years" msgstr "3 godine" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Dok ima slobodnog prostora (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Zauvijek (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Predvidljivo podešavanje" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Broj pretplata za korištenje" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Odgoda zatvaranja neiskorištenih pretplata (sekunde)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Koristi predvidljivo podešavanje za ubrzavanje prebacivanja programa" msgctxt "#30450" msgid "No free adapter available" msgstr "Nema slobodnih dostupnih uređaja" msgctxt "#30451" msgid "Scrambled channel" msgstr "Kôdirani programi" msgctxt "#30452" msgid "No signal" msgstr "Nema signala" msgctxt "#30453" msgid "Tuning failed" msgstr "Podešavanje neuspjelo" msgctxt "#30454" msgid "User limit reached" msgstr "Ograničenje korisnika dostignuto" msgctxt "#30455" msgid "No access" msgstr "Nema pristupa" msgctxt "#30456" msgid "Subscription error" msgstr "Greška pretplate" msgctxt "#30500" msgid "Streaming profile" msgstr "Profil streamanja" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profil za korištenje (prazno = zadano)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Streaming profil %s nije dostupan" msgctxt "#30503" msgid "Data transfer" msgstr "Prijenos podataka" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Veličina čitanja dijela strujanja za snimanja (KB)" msgctxt "#30510" msgid "Recordings" msgstr "Snimke" msgctxt "#30511" msgid "Server based play status" msgstr "Status reprodukcije temeljen poslužiteljem" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.hu_hu/000077500000000000000000000000001355512543200260035ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.hu_hu/strings.po000066400000000000000000000176331355512543200300460ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Kapcsolódási beállítások" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "TVHeadend kiszolgálónév vagy IP cím" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP Port" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP port" msgctxt "#30004" msgid "Username" msgstr "Felhasználónév" msgctxt "#30005" msgid "Password" msgstr "Jelszó" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Kapcsolódási időtúllépés (mp.)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Válasz időkorlát (másodpercben)" msgctxt "#30008" msgid "Advanced settings" msgstr "Speciális beállítások" msgctxt "#30009" msgid "Streaming settings" msgstr "Adatfolyam beállítások" msgctxt "#30010" msgid "Timer settings" msgstr "Időzítő beállítások" msgctxt "#30050" msgid "Auto recordings" msgstr "Automatikus felvételek" msgctxt "#30051" msgid "Start time window calculation" msgstr "Kezdési időablak kiszámítása" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Szigorú (kezdési idő + záró idő)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Laza (kezdési idő +/- margó)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Maximális kezdési idő margó (percben)" msgctxt "#30055" msgid "Default priority" msgstr "Alapértelmezett fontosság" msgctxt "#30056" msgid "Default lifetime" msgstr "Alapértelmezett élettartam" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Alapértelmezett duplikáció érzékelés" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Alapértelmezések az új időzítőkhöz" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Ütemezett felvételek" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "A másolatok figyelmen kívül hagyása (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Adatátvitel" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asszinkron EPG átvitel" msgctxt "#30200" msgid "Debugging" msgstr "Hibakeresés" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Nyomkövetés (részletes)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP verzió eltérés (támogatott: v%d, szükséges: v%d). Kérlek frissítsd a TVHeadend-et." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Egyszeri (az időzítő szabály ütemezése szerint)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Fontos (legmagasabb)" msgctxt "#30352" msgid "High" msgstr "Magas" msgctxt "#30353" msgid "Normal" msgstr "Normál" msgctxt "#30354" msgid "Low" msgstr "Alacsony" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Nem fontos (legalacsonyabb)" msgctxt "#30356" msgid "Record all episodes" msgstr "Minden epizód felvétele" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Rögzítse ha az epizódszám különböző" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Rögzítse, ha az epizódnév különböző" msgctxt "#30359" msgid "Record if description differs" msgstr "Rögzítse, ha a leírás különbözik" msgctxt "#30360" msgid "Record max once per week" msgstr "Rögzítés legfeljebb hetente egyszer" msgctxt "#30361" msgid "Record max once per day" msgstr "Rögzítés legfeljebb naponta egyszer" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Csak ez a szabály: Rögzítse, ha az epizódszám különböző" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Csak ez a szabály: Rögzítse, ha az epizódnév különböző" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Csak ez a szabály: Rögzítse, ha a cím különböző" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Csak ez a szabály: Rögzítse, ha a leírás különböző" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Csak ez a szabály: Hetente legfeljebb egyszer rögzítse" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Csak ez a szabály: Naponta legfeljebb egyszer rögzítse" msgctxt "#30368" msgid "Default" msgstr "Alapértelmezett" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Időzítési szabály (sorozat hivatkozás)" msgctxt "#30370" msgid "Record max once per month" msgstr "Rögzítés legfeljebb havonta egyszer" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Csak ez a szabály: Havonta legfeljebb egyszer rögzítse" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Rögzítés akkor, ha az EPG/XMLTC szerint egyedi epizód" msgctxt "#30373" msgid "Until space needed" msgstr "Amíg van szabad hely" msgctxt "#30374" msgid "Forever" msgstr "Örökké" msgctxt "#30375" msgid "1 day" msgstr "1 nap" msgctxt "#30376" msgid "3 days" msgstr "3 nap" msgctxt "#30377" msgid "5 days" msgstr "5 nap" msgctxt "#30378" msgid "1 week" msgstr "1 hét" msgctxt "#30379" msgid "2 weeks" msgstr "2 hét" msgctxt "#30380" msgid "3 weeks" msgstr "3 hét" msgctxt "#30381" msgid "1 month" msgstr "1 hónap" msgctxt "#30382" msgid "2 months" msgstr "2 hónap" msgctxt "#30383" msgid "3 months" msgstr "3 hónap" msgctxt "#30384" msgid "6 months" msgstr "6 hónap" msgctxt "#30385" msgid "1 year" msgstr "1 év" msgctxt "#30386" msgid "2 years" msgstr "2 év" msgctxt "#30387" msgid "3 years" msgstr "3 év" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Ameddig hely szükséges (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Örökké (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Prediktív hangolás" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Használni kívánt feliratkozások száma" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Nem használt feliratkozások lezárási késleltetése (másodpercben)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Prediktív hangolás használata a csatornaváltások felgyorsítására" msgctxt "#30450" msgid "No free adapter available" msgstr "Nincs elérhető szabad adapter" msgctxt "#30451" msgid "Scrambled channel" msgstr "Kódolt csatorna" msgctxt "#30452" msgid "No signal" msgstr "Nincs jel" msgctxt "#30453" msgid "Tuning failed" msgstr "Hangolás sikertelen" msgctxt "#30454" msgid "User limit reached" msgstr "Felhasználó korlát elérve" msgctxt "#30455" msgid "No access" msgstr "Nincs hozzáférés" msgctxt "#30456" msgid "Subscription error" msgstr "Feliratkozási hiba" msgctxt "#30500" msgid "Streaming profile" msgstr "Adatfolyam profil" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Használandó profil (üres = alapértelmezett)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "%s adatfolyam profil nem elérhető" msgctxt "#30503" msgid "Data transfer" msgstr "Adatátvitel" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Stream olvasott darabméret felvételekhez (KB)" msgctxt "#30510" msgid "Recordings" msgstr "Felvételek" msgctxt "#30511" msgid "Server based play status" msgstr "Kiszolgáló alapú lejátszási állapot" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.hy_am/000077500000000000000000000000001355512543200257705ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.hy_am/strings.po000066400000000000000000000017041355512543200300230ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30005" msgid "Password" msgstr "Գաղտնաբառ" msgctxt "#30352" msgid "High" msgstr "Բարձր" msgctxt "#30353" msgid "Normal" msgstr "Նորմալ" msgctxt "#30354" msgid "Low" msgstr "Ցածր" msgctxt "#30368" msgid "Default" msgstr "Նախնական" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.id_id/000077500000000000000000000000001355512543200257435ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.id_id/strings.po000066400000000000000000000036541355512543200300040ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Hostname atau alamat IP Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "Port HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Port HTSP" msgctxt "#30004" msgid "Username" msgstr "Nama Pengguna" msgctxt "#30005" msgid "Password" msgstr "Sandi" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Koneksi timeout (detik)" msgctxt "#30010" msgid "Timer settings" msgstr "Setelan Timer" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Transfer EPG Asinkron" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Jejak (rinci)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP versi mismatch (didukung: v% d, dibutuhkan: v% d). Mohon perbarui tvheadend." msgctxt "#30352" msgid "High" msgstr "Tinggi" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Rendah" msgctxt "#30356" msgid "Record all episodes" msgstr "Rekam semua episode" msgctxt "#30368" msgid "Default" msgstr "Standar" msgctxt "#30373" msgid "Until space needed" msgstr "Sampai ruang yang dibutuhkan" msgctxt "#30510" msgid "Recordings" msgstr "Perekaman" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.is_is/000077500000000000000000000000001355512543200260015ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.is_is/strings.po000066400000000000000000000174241355512543200300420ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Stillingar tengingar" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Nafn eða IP-vistfang Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP gátt" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP gátt" msgctxt "#30004" msgid "Username" msgstr "Notandanafn" msgctxt "#30005" msgid "Password" msgstr "Lykilorð" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Tengitími rennur út (sekúndur)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Tímatakmörk svartíma (sekúndur)" msgctxt "#30008" msgid "Advanced settings" msgstr "Ítarlegar stillingar" msgctxt "#30009" msgid "Streaming settings" msgstr "Stillingar á streymingu" msgctxt "#30010" msgid "Timer settings" msgstr "Stillingar tímatöku" msgctxt "#30050" msgid "Auto recordings" msgstr "Sjálfvirkar upptökur" msgctxt "#30051" msgid "Start time window calculation" msgstr "Útreikningur á mörkum upphafstíma" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Strangt (upphafstími + lokatími)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Vítt (upphafstími +/- vikmörk)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Hámarksvikmörk upphafstíma (mínútur)" msgctxt "#30055" msgid "Default priority" msgstr "Sjálfgefinn forgangur" msgctxt "#30056" msgid "Default lifetime" msgstr "Sjálfgefinn líftími" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Sjálfgefin leit að tvítökum" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Sjálfgefið fyrir nýjar tímatökur" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Áætlaðar upptökur" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Hunsa tvítekningar (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Gagnaflutningur" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Ósamstilltur flutningur stafrænna dagskrárvísa" msgctxt "#30200" msgid "Debugging" msgstr "Kembing" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Trace (nákvæmt)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP útgáfa ósamhæfð (samhæfð: v%d, þarfnast: v%d). Uppfærðu tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Eins-skiptis (sett á með tímatökureglu)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Mikilvægt (hæst)" msgctxt "#30352" msgid "High" msgstr "Hæst" msgctxt "#30353" msgid "Normal" msgstr "Venjulegt" msgctxt "#30354" msgid "Low" msgstr "Lægst" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Ekki mikilvægt (lægst)" msgctxt "#30356" msgid "Record all episodes" msgstr "Taka upp allar þáttaraðir" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Taka upp ef mismunur er á númerum þátta" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Taka upp ef mismunur er á nöfnum þátta" msgctxt "#30359" msgid "Record if description differs" msgstr "Taka upp ef mismunur er á lýsingum þátta" msgctxt "#30360" msgid "Record max once per week" msgstr "Taka upp mest einu sinni í viku" msgctxt "#30361" msgid "Record max once per day" msgstr "Taka upp mest einu sinni á dag" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Einungis þessi regla: Taka upp ef mismunur er á númerum þátta" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Einungis þessi regla: Taka upp ef mismunur er á nöfnum þátta" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Einungis þessi regla: Taka upp ef mismunur er á titli" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Einungis þessi regla: Taka upp ef mismunur er á lýsingum þátta" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Einungis þessi regla: Taka upp mest einu sinni í viku" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Einungis þessi regla: Taka upp mest einu sinni á dag" msgctxt "#30368" msgid "Default" msgstr "Sjálfgefið" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Tímatökuregla (tengt við raðir)" msgctxt "#30370" msgid "Record max once per month" msgstr "Taka upp mest einu sinni á mánuði" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Einungis þessi regla: Taka upp mest einu sinni á mánuði" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Taka upp ef er einstakur þáttur miðað við EPG/XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Þangað til vantar pláss" msgctxt "#30374" msgid "Forever" msgstr "Að eilífu" msgctxt "#30375" msgid "1 day" msgstr "1 dag" msgctxt "#30376" msgid "3 days" msgstr "3 dagar" msgctxt "#30377" msgid "5 days" msgstr "5 dagar" msgctxt "#30378" msgid "1 week" msgstr "1 vika" msgctxt "#30379" msgid "2 weeks" msgstr "2 vikur" msgctxt "#30380" msgid "3 weeks" msgstr "3 vikur" msgctxt "#30381" msgid "1 month" msgstr "1 mánuður" msgctxt "#30382" msgid "2 months" msgstr "2 mánuðir" msgctxt "#30383" msgid "3 months" msgstr "3 mánuðir" msgctxt "#30384" msgid "6 months" msgstr "6 mánuðir" msgctxt "#30385" msgid "1 year" msgstr "1 ár" msgctxt "#30386" msgid "2 years" msgstr "2 ár" msgctxt "#30387" msgid "3 years" msgstr "3 ár" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Þangað til vantar pláss (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Að eilífu (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Forspárinnstilling" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Fjöldi áskrifta sem á að nota" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Bið áður en ónotaðri áskrift er lokað (sekúndur)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Nota forspárinnstillingu til að hraða skiptingu á milli rása" msgctxt "#30450" msgid "No free adapter available" msgstr "Ekkert laust tengi tiltækt" msgctxt "#30451" msgid "Scrambled channel" msgstr "Rugluð rás" msgctxt "#30452" msgid "No signal" msgstr "Ekkert merki" msgctxt "#30453" msgid "Tuning failed" msgstr "Innstilling mistókst" msgctxt "#30454" msgid "User limit reached" msgstr "Hámarksfjölda notenda er náð" msgctxt "#30455" msgid "No access" msgstr "Enginn aðgangur" msgctxt "#30456" msgid "Subscription error" msgstr "Áskriftarvilla" msgctxt "#30500" msgid "Streaming profile" msgstr "Snið streymis" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Snið sem á að nota (autt = sjálfgefið)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Streymissniðið %s er ekki tiltækt" msgctxt "#30503" msgid "Data transfer" msgstr "Gagnaflutningur" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Stærð lesbúts streymis í upptökum (KB)" msgctxt "#30510" msgid "Recordings" msgstr "Upptökur" msgctxt "#30511" msgid "Server based play status" msgstr "Staða spilunar frá þjóni" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.it_it/000077500000000000000000000000001355512543200260035ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.it_it/strings.po000066400000000000000000000170441355512543200300420ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Impostazioni di connessione" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend hostname o indirizzo IP" msgctxt "#30002" msgid "HTTP port" msgstr "Porta HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Porta HTSP" msgctxt "#30004" msgid "Username" msgstr "Nome utente" msgctxt "#30005" msgid "Password" msgstr "Password" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Timeout Connessione (secondi)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Timeout risposta (secondi)" msgctxt "#30008" msgid "Advanced settings" msgstr "Impostazioni avanzate" msgctxt "#30009" msgid "Streaming settings" msgstr "Impostazioni Streaming" msgctxt "#30010" msgid "Timer settings" msgstr "Impostazioni Timer" msgctxt "#30050" msgid "Auto recordings" msgstr "Registrazioni Automatiche" msgctxt "#30051" msgid "Start time window calculation" msgstr "Avvia calcolo della finestra temporale" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Stretto necessario (ora inizio + ora fine)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Rilassato (ora inizio +/- margine)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Massimo margine di tempo (minuti)" msgctxt "#30055" msgid "Default priority" msgstr "Priorità predefinita" msgctxt "#30056" msgid "Default lifetime" msgstr "Durata di vita predefinita" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Rilevamento dei duplicati predefinito" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Preimpostazione per nuovi timer" msgctxt "#30100" msgid "Data transfer" msgstr "Trasferimento dati" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Trasferimento EPG asincrono" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Traccia (dettagliata)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "La versione di HTSP non corrisponde (supportata: v%d, necessaria: v&d). Aggiorna tvheadend, per favore." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Una volta (Pianificato da timer)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Importante (Maggiore)" msgctxt "#30352" msgid "High" msgstr "Alta" msgctxt "#30353" msgid "Normal" msgstr "Normale" msgctxt "#30354" msgid "Low" msgstr "Bassa" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Meno importante (Minore)" msgctxt "#30356" msgid "Record all episodes" msgstr "Registra tutti gli episodi" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Registra se il numero dell'episodio è differente" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Registra se il nome dell'episodio è differente" msgctxt "#30359" msgid "Record if description differs" msgstr "Registra se la descrizione è differente" msgctxt "#30360" msgid "Record max once per week" msgstr "Registra al massimo una volta a settimana" msgctxt "#30361" msgid "Record max once per day" msgstr "Registra al massimo una volta al giorno" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Solo questa regola: Registra se il numero dell'episodio è differente" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Solo questa regola: Registra se il nome dell'episodio è differente" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Solo questa regola: Registra se il titolo è differente" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Solo questa regola: Registra se la descrizione è differente" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Solo questa regola: Registra al massimo una volta a settimana" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Solo questa regola: Registra al massimo una volta al giorno" msgctxt "#30368" msgid "Default" msgstr "Predefinito" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Regola timer (serie collegate)" msgctxt "#30370" msgid "Record max once per month" msgstr "Registra al massimo una volta al mese" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Solo questa regola: Registra al massimo una volta al mese" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Registra se unico episodio in base a EPG/XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Fino a spazio necessario" msgctxt "#30374" msgid "Forever" msgstr "Per sempre" msgctxt "#30375" msgid "1 day" msgstr "1 giorno" msgctxt "#30376" msgid "3 days" msgstr "3 giorni" msgctxt "#30377" msgid "5 days" msgstr "5 giorni" msgctxt "#30378" msgid "1 week" msgstr "una settimana" msgctxt "#30379" msgid "2 weeks" msgstr "2 settimane" msgctxt "#30380" msgid "3 weeks" msgstr "3 settimane" msgctxt "#30381" msgid "1 month" msgstr "un mese" msgctxt "#30382" msgid "2 months" msgstr "2 mesi" msgctxt "#30383" msgid "3 months" msgstr "3 mesi" msgctxt "#30384" msgid "6 months" msgstr "6 mesi" msgctxt "#30385" msgid "1 year" msgstr "un anno" msgctxt "#30386" msgid "2 years" msgstr "2 anni" msgctxt "#30387" msgid "3 years" msgstr "3 anni" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Fino a richiesta di spazio (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Per sempre (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Sintonizzazione predittiva" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Numero di sottoscrizioni da usare" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Ritardo nella chiusura della sottoscrizioni inutilizzate (secondi)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Usa sintonizzazione predittiva per accelerare il cambio canale" msgctxt "#30450" msgid "No free adapter available" msgstr "Nessun adattatore libero disponibile" msgctxt "#30451" msgid "Scrambled channel" msgstr "Canale codificato" msgctxt "#30452" msgid "No signal" msgstr "Nessun segnale" msgctxt "#30453" msgid "Tuning failed" msgstr "Sintonizzazione fallita" msgctxt "#30454" msgid "User limit reached" msgstr "Raggiunto limite utente" msgctxt "#30455" msgid "No access" msgstr "Nessun accesso" msgctxt "#30456" msgid "Subscription error" msgstr "Errore di sottoscrizione" msgctxt "#30500" msgid "Streaming profile" msgstr "Profilo di streaming" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profilo da usare (vuoto = predefinito)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Profilo di streaming %s non disponibile" msgctxt "#30503" msgid "Data transfer" msgstr "Trasferimento dati" msgctxt "#30510" msgid "Recordings" msgstr "Registrazioni" msgctxt "#30511" msgid "Server based play status" msgstr "Stato di riproduzione basato su server" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ja_jp/000077500000000000000000000000001355512543200257565ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ja_jp/strings.po000066400000000000000000000031661355512543200300150ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "接続設定" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "TVheadend ホスト名または IP アドレス" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP ポート" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP ポート" msgctxt "#30004" msgid "Username" msgstr "ユーザー名" msgctxt "#30005" msgid "Password" msgstr "パスワード" msgctxt "#30010" msgid "Timer settings" msgstr "タイマーの設定" msgctxt "#30200" msgid "Debugging" msgstr "デバッグ" msgctxt "#30352" msgid "High" msgstr "高" msgctxt "#30353" msgid "Normal" msgstr "中" msgctxt "#30354" msgid "Low" msgstr "低" msgctxt "#30356" msgid "Record all episodes" msgstr "すべての回を録画する" msgctxt "#30368" msgid "Default" msgstr "デフォルト" msgctxt "#30373" msgid "Until space needed" msgstr "容量がいっぱいになるまで" msgctxt "#30510" msgid "Recordings" msgstr "録音" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ko_kr/000077500000000000000000000000001355512543200260005ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ko_kr/strings.po000066400000000000000000000167421355512543200300430ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "연결 설정" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend 호스트네임 또는 IP 주소" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP 포트" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP 포트" msgctxt "#30004" msgid "Username" msgstr "사용자명" msgctxt "#30005" msgid "Password" msgstr "비밀번호" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "연결 시간 제한 (초)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "응답 제한시간 (초)" msgctxt "#30008" msgid "Advanced settings" msgstr "고급 설정" msgctxt "#30009" msgid "Streaming settings" msgstr "스트리밍 설정" msgctxt "#30010" msgid "Timer settings" msgstr "타이머 설정" msgctxt "#30050" msgid "Auto recordings" msgstr "자동 녹화" msgctxt "#30051" msgid "Start time window calculation" msgstr "시작 시각 창 계산" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "고정(시작 시각 + 종료 시각)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "여유(시작 시각 +/- 여백)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "최대 시작 시각 여백 (분)" msgctxt "#30055" msgid "Default priority" msgstr "기본 우선순위" msgctxt "#30056" msgid "Default lifetime" msgstr "기본 보존기간" msgctxt "#30057" msgid "Default duplicate detection" msgstr "기본 중복 확인" msgctxt "#30058" msgid "Defaults for new timers" msgstr "새 타이머의 기본 설정" msgctxt "#30059" msgid "Scheduled recordings" msgstr "예약된 녹화" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "중복 무시 (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "데이터 전송" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "비동기 EPG 전송" msgctxt "#30200" msgid "Debugging" msgstr "디버깅" msgctxt "#30201" msgid "Trace (detailed)" msgstr "추적 (상세)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP 버전 불일치 (지원: v%d, 필요: v%d). tvheadend를 업데이트해 주십시요." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "한 번 (타이머 규정으로 예약)" msgctxt "#30351" msgid "Important (Highest)" msgstr "중요 (높은 순)" msgctxt "#30352" msgid "High" msgstr "높음" msgctxt "#30353" msgid "Normal" msgstr "보통" msgctxt "#30354" msgid "Low" msgstr "낮음" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "중요하지 않음 (낮은 순)" msgctxt "#30356" msgid "Record all episodes" msgstr "모든 에피소드 녹화" msgctxt "#30357" msgid "Record if episode number differs" msgstr "에피소드 숫자가 다를 시 녹화" msgctxt "#30358" msgid "Record if episode name differs" msgstr "에피소드 이름이 다를 시 녹화" msgctxt "#30359" msgid "Record if description differs" msgstr "설명이 다를 시 녹화" msgctxt "#30360" msgid "Record max once per week" msgstr "일주일 최대 한번 녹화" msgctxt "#30361" msgid "Record max once per day" msgstr "하루 최대 한 번 녹화" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "이 규정만: 에피소드 번호가 다르면 녹화" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "이 규정만: 에피소드 이름이 다르면 녹화" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "이 규정만: 제목이 다르면 녹화" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "이 규정만: 설명이 다르면 녹화" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "이 규정만: 최대 주별 한 번만 녹화" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "이 규정만: 최대 하루에 한 번만 녹화" msgctxt "#30368" msgid "Default" msgstr "보통" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "타이머 규정 (시리즈 링크)" msgctxt "#30370" msgid "Record max once per month" msgstr "최대 월별 한 번만 녹화" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "이 규정만: 최대 월별 한 번만 녹화" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "EPG/XMLTV에 따라 유일한 에피소드라면 녹화" msgctxt "#30373" msgid "Until space needed" msgstr "저장공간이 더 필요할 때까지" msgctxt "#30374" msgid "Forever" msgstr "영원히" msgctxt "#30375" msgid "1 day" msgstr "1일" msgctxt "#30376" msgid "3 days" msgstr "3일" msgctxt "#30377" msgid "5 days" msgstr "5일" msgctxt "#30378" msgid "1 week" msgstr "1주" msgctxt "#30379" msgid "2 weeks" msgstr "2주" msgctxt "#30380" msgid "3 weeks" msgstr "3주" msgctxt "#30381" msgid "1 month" msgstr "1개월" msgctxt "#30382" msgid "2 months" msgstr "2개월" msgctxt "#30383" msgid "3 months" msgstr "3개월" msgctxt "#30384" msgid "6 months" msgstr "6개월" msgctxt "#30385" msgid "1 year" msgstr "1년" msgctxt "#30386" msgid "2 years" msgstr "2년" msgctxt "#30387" msgid "3 years" msgstr "3년" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "저장공간이 더 필요할 때까지 (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "영원히 (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "예측 튜닝" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "사용할 구독 수" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "미사용 구독 닫기까지 지연 (초)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "빠른 채널 전환을 위해 예측 튜닝 사용" msgctxt "#30450" msgid "No free adapter available" msgstr "사용 가능 어댑터 없음" msgctxt "#30451" msgid "Scrambled channel" msgstr "암호화 채널" msgctxt "#30452" msgid "No signal" msgstr "신호 없음" msgctxt "#30453" msgid "Tuning failed" msgstr "튜닝 실패" msgctxt "#30454" msgid "User limit reached" msgstr "설정 한도 도달함" msgctxt "#30455" msgid "No access" msgstr "권한 없음" msgctxt "#30456" msgid "Subscription error" msgstr "구독 오류" msgctxt "#30500" msgid "Streaming profile" msgstr "스트리밍 프로필" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "사용할 프로필 (빈 창 = 기본)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "스트리밍 프로필 %s 사용 불가능" msgctxt "#30503" msgid "Data transfer" msgstr "데이터 전송" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "녹화의 스트림 읽기 청크 사이즈 (KB)" msgctxt "#30510" msgid "Recordings" msgstr "녹화" msgctxt "#30511" msgid "Server based play status" msgstr "서버 기반의 재생 상태" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.lt_lt/000077500000000000000000000000001355512543200260115ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.lt_lt/strings.po000066400000000000000000000177441355512543200300570ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Prisijungimo nustatymai" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend serverio vardas arba IP adresas" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP prievadas" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP prievadas" msgctxt "#30004" msgid "Username" msgstr "Vartotojo vardas" msgctxt "#30005" msgid "Password" msgstr "Slaptažodis" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Prisijungimo laukimo laikas (sekundėmis)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Atsakymo laukimo laikas (sekundėmis)" msgctxt "#30008" msgid "Advanced settings" msgstr "Išplėstiniai nustatymai" msgctxt "#30009" msgid "Streaming settings" msgstr "Transliacijos nustatymai" msgctxt "#30010" msgid "Timer settings" msgstr "Laikmačio nustatymai" msgctxt "#30050" msgid "Auto recordings" msgstr "Automatinis įrašymas" msgctxt "#30051" msgid "Start time window calculation" msgstr "Pradžios laiko lango apskaičiavimas" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Tikslus (pradžios laikas + pabaigos laikas)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Laisvas (pradžios laikas +/- paklaida)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Maksimali pradžios laiko paklaida (minutėmis)" msgctxt "#30055" msgid "Default priority" msgstr "Numatytasis prioritetas" msgctxt "#30056" msgid "Default lifetime" msgstr "Numatytasis saugojimo laikas" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Numatytasis dublikatų aptikimas" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Numatytieji parametrai naujiems laikmačiams" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Suplanuoti įrašymai" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Ignoruoti dublikatus (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Duomenų perkėlimas" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asinchroninis EPG perdavimas" msgctxt "#30200" msgid "Debugging" msgstr "Derinimas" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Sekti (išsamiai)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTPS versija neatitinka (palaikoma: v%d, reikalinga: v%d). Atnaujinkite tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Vieną kartą (suplanuota laikmačio taisyklės)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Svarbus (aukščiausias)" msgctxt "#30352" msgid "High" msgstr "Aukštas" msgctxt "#30353" msgid "Normal" msgstr "Normalus" msgctxt "#30354" msgid "Low" msgstr "Žemas" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Nesvarbus (žemiausias)" msgctxt "#30356" msgid "Record all episodes" msgstr "Įrašyti visus epizodus" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Įrašyti, jei skiriasi epizodo numeris" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Įrašyti, jei skiriasi epizodo pavadinimas" msgctxt "#30359" msgid "Record if description differs" msgstr "Įrašyti, jei skiriasi aprašymas" msgctxt "#30360" msgid "Record max once per week" msgstr "Įrašyti daugiausiai vieną kartą per savaitę" msgctxt "#30361" msgid "Record max once per day" msgstr "Įrašyti daugiausiai vieną kartą per dieną" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Tik šiai taisyklei: įrašyti, jei epizodo numeris skiriasi" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Tik šiai taisyklei: įrašyti, jei epizodo pavadinimas skiriasi" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Tik šiai taisyklei: įrašyti, jei pavadinimas skiriasi" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Tik šiai taisyklei: įrašyti, jei aprašymas skiriasi" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Tik šiai taisyklei: įrašyti ne daugiau nei kartą per savaitę" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Tik šiai taisyklei: įrašyti ne daugiau nei kartą per dieną" msgctxt "#30368" msgid "Default" msgstr "Numatytas" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Laikmačio taisyklė (serialo nuoroda)" msgctxt "#30370" msgid "Record max once per month" msgstr "Įrašyti daugiausiai vieną kartą per mėnesį" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Tik šiai taisyklei: įrašyti ne daugiau nei kartą per mėnesį" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Įrašyti, jei unikalus epizodas pagal EPG/XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Kol reikalinga vieta" msgctxt "#30374" msgid "Forever" msgstr "Visam laiką" msgctxt "#30375" msgid "1 day" msgstr "1 diena" msgctxt "#30376" msgid "3 days" msgstr "3 dienos" msgctxt "#30377" msgid "5 days" msgstr "5 dienos" msgctxt "#30378" msgid "1 week" msgstr "1 savaitė" msgctxt "#30379" msgid "2 weeks" msgstr "2 savaitės" msgctxt "#30380" msgid "3 weeks" msgstr "3 savaitės" msgctxt "#30381" msgid "1 month" msgstr "1 mėnuo" msgctxt "#30382" msgid "2 months" msgstr "2 mėnesiai" msgctxt "#30383" msgid "3 months" msgstr "3 mėnesiai" msgctxt "#30384" msgid "6 months" msgstr "6 mėnesiai" msgctxt "#30385" msgid "1 year" msgstr "1 metai" msgctxt "#30386" msgid "2 years" msgstr "2 metai" msgctxt "#30387" msgid "3 years" msgstr "3 metai" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Kol prireiks vietos (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Visada (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Nuspėjamas derinimas" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Naudojamų prenumeratų skaičius" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Nenaudojamos prenumeratos uždarymo uždelsimas (sekundėmis)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "naudoti nuspėjamą derinimą, kad pagreitinti kanalų perjungimą" msgctxt "#30450" msgid "No free adapter available" msgstr "Nėra prieinamo laisvo adapterio" msgctxt "#30451" msgid "Scrambled channel" msgstr "Koduoti kanalai" msgctxt "#30452" msgid "No signal" msgstr "Nėra signalo" msgctxt "#30453" msgid "Tuning failed" msgstr "Derinimas nepavyko" msgctxt "#30454" msgid "User limit reached" msgstr "Pasiektas vartotojo limitas" msgctxt "#30455" msgid "No access" msgstr "Nėra prieigos" msgctxt "#30456" msgid "Subscription error" msgstr "Prenumeratos klaida" msgctxt "#30500" msgid "Streaming profile" msgstr "Transliacijos profilis" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profilis, kurį naudoti (tuščia = numatytasis)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Transliacijos profilis %s neprieinamas" msgctxt "#30503" msgid "Data transfer" msgstr "Duomenų perkėlimas" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Srauto skaitymo dalies dydis įrašams (KB)" msgctxt "#30510" msgid "Recordings" msgstr "Įrašai" msgctxt "#30511" msgid "Server based play status" msgstr "Serveris paremtas atkūrimo būsena" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.lv_lv/000077500000000000000000000000001355512543200260155ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.lv_lv/strings.po000066400000000000000000000035071355512543200300530ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Pieslēguma iestatījumi" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend saimniekvārds vai IP adrese" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP ports" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP ports" msgctxt "#30004" msgid "Username" msgstr "LIetotājs" msgctxt "#30005" msgid "Password" msgstr "Parole" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Pieslēguma noilgums (sekundes)" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asinhronā EPG pārsūtīšana" msgctxt "#30200" msgid "Debugging" msgstr "Atkļūdošana" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Pieraksts (detalizēts)" msgctxt "#30352" msgid "High" msgstr "Augsts" msgctxt "#30353" msgid "Normal" msgstr "Normāls" msgctxt "#30354" msgid "Low" msgstr "Zems" msgctxt "#30356" msgid "Record all episodes" msgstr "Ierakstīt visas sērijas" msgctxt "#30368" msgid "Default" msgstr "Noklusējums" msgctxt "#30373" msgid "Until space needed" msgstr "Līdz nepieciešama vieta" msgctxt "#30510" msgid "Recordings" msgstr "Ieraksti" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.mi/000077500000000000000000000000001355512543200253005ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.mi/strings.po000066400000000000000000000021011355512543200273230ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30004" msgid "Username" msgstr "Ingoa kaiwhakamahi" msgctxt "#30005" msgid "Password" msgstr "Kupuhipa" msgctxt "#30200" msgid "Debugging" msgstr "Patuiro" msgctxt "#30352" msgid "High" msgstr "Teitei" msgctxt "#30353" msgid "Normal" msgstr "Pūnoa" msgctxt "#30354" msgid "Low" msgstr "Hakahaka" msgctxt "#30368" msgid "Default" msgstr "Taunoa" msgctxt "#30510" msgid "Recordings" msgstr "Ngā pūhopu" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.mk_mk/000077500000000000000000000000001355512543200257715ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.mk_mk/strings.po000066400000000000000000000034461355512543200300310ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend хост или IP адреса" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP порта" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP порта" msgctxt "#30004" msgid "Username" msgstr "Корисничко име" msgctxt "#30005" msgid "Password" msgstr "Лозинка" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Асинхрон EPG трансфер" msgctxt "#30200" msgid "Debugging" msgstr "Барање грешки" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Следи (детално)" msgctxt "#30352" msgid "High" msgstr "висок" msgctxt "#30353" msgid "Normal" msgstr "Нормално" msgctxt "#30354" msgid "Low" msgstr "низок" msgctxt "#30356" msgid "Record all episodes" msgstr "Сними ги сите епизоди" msgctxt "#30368" msgid "Default" msgstr "Подразбирачко" msgctxt "#30373" msgid "Until space needed" msgstr "Се додека не е потребен простор" msgctxt "#30510" msgid "Recordings" msgstr "Снимки" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.mn_mn/000077500000000000000000000000001355512543200257775ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.mn_mn/strings.po000066400000000000000000000036501355512543200300340ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend нэр эсвэл IP хаяг" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP порт" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP порт" msgctxt "#30004" msgid "Username" msgstr "Хэрэглэгчийн нэр" msgctxt "#30005" msgid "Password" msgstr "Нууц үг" msgctxt "#30010" msgid "Timer settings" msgstr "Цагалбарын тохиргоо" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Асинхрон EPG дамжуулалт" msgctxt "#30200" msgid "Debugging" msgstr "Програм хяналт, засвар" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Мөр (дэлгэрэнгүй)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP ийн хувилбар таарахгүй байна (боломжтой: v%d, шаардлагатай: v%d). tvheadend-ийг шинэчилнэ үү." msgctxt "#30352" msgid "High" msgstr "Өндөр" msgctxt "#30353" msgid "Normal" msgstr "Энгийн" msgctxt "#30354" msgid "Low" msgstr "Бага" msgctxt "#30368" msgid "Default" msgstr "Үндсэн" msgctxt "#30510" msgid "Recordings" msgstr "Бичлэгүүд" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ms_my/000077500000000000000000000000001355512543200260175ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ms_my/strings.po000066400000000000000000000170041355512543200300520ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Tetapan sambungan" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Nama hos atau alamat IP Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "Port HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Port HTSP" msgctxt "#30004" msgid "Username" msgstr "Nama Pengguna" msgctxt "#30005" msgid "Password" msgstr "Kata Laluan" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Had masa tamat sambungan (saat)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Had masa tamat respons (saat)" msgctxt "#30008" msgid "Advanced settings" msgstr "Tetapan lanjutan" msgctxt "#30009" msgid "Streaming settings" msgstr "Tetapan penstriman" msgctxt "#30010" msgid "Timer settings" msgstr "Tetapan pemasa" msgctxt "#30050" msgid "Auto recordings" msgstr "Auto-rakaman" msgctxt "#30051" msgid "Start time window calculation" msgstr "Pengiraan tetingkap masa mula" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Ketat (masa mula + masa tamat)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Santai (masa mula +/1 margin)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Margin masa mula maksimum (minit)" msgctxt "#30055" msgid "Default priority" msgstr "Keutamaan lalai" msgctxt "#30056" msgid "Default lifetime" msgstr "Masa hayat lalai" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Pengesanan pendua lalai" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Lalai untuk pemasa baharu" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Rakaman berjadual" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Abai pendua (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Pemindahan data" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Penambahan EPG segerak" msgctxt "#30200" msgid "Debugging" msgstr "Penyahpepijatan" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Surih (terperinci)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Versi HTSP tidak sepadan (disokong: v%d, diperlukan: v%d). Sila kemaskini tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Satu Kali (Dijadual mengikut peraturan pemasa)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Penting (Paling Tinggi)" msgctxt "#30352" msgid "High" msgstr "Tinggi" msgctxt "#30353" msgid "Normal" msgstr "Biasa" msgctxt "#30354" msgid "Low" msgstr "Rendah" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Tidak Penting (Paling Rendah)" msgctxt "#30356" msgid "Record all episodes" msgstr "Rakam semua episod" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Rakam jika nombor episod berbeza" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Rakam jika nama episod berbeza" msgctxt "#30359" msgid "Record if description differs" msgstr "Rakam jika keterangan berbeza" msgctxt "#30360" msgid "Record max once per week" msgstr "Rakam maksimum sekali dalam seminggu" msgctxt "#30361" msgid "Record max once per day" msgstr "Rakam maksimum sekali dalam sehari" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Peraturan ini sahaja: Rakam jika nombor episod berbeza" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Peraturan ini sahaja: Rakam jika nama episod berbeza" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Peraturan ini sahaja: Rakam jika tajuk berbeza" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Peraturan ini sahaja: Rakam jika keterangan berbeza" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Peraturan ini sahaja: Rakam maksimum sekali dalam seminggu" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Peraturan ini sahaja: Rakam maksimum sekali dalam sehari" msgctxt "#30368" msgid "Default" msgstr "Lalai" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Peraturan pemasa (pautan siri)" msgctxt "#30370" msgid "Record max once per month" msgstr "Rakam maksimum sekali dalam sebulan" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Peraturan ini sahaja: Rakam maksimum sekali dalam sebulan" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Rakam jika episod unik berdasarkan EPG/XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Sehingga ruang diperlukan" msgctxt "#30374" msgid "Forever" msgstr "Selama-lamanya" msgctxt "#30375" msgid "1 day" msgstr "1 hari" msgctxt "#30376" msgid "3 days" msgstr "3 hari" msgctxt "#30377" msgid "5 days" msgstr "5 hari" msgctxt "#30378" msgid "1 week" msgstr "1 minggu" msgctxt "#30379" msgid "2 weeks" msgstr "2 minggu" msgctxt "#30380" msgid "3 weeks" msgstr "3 minggu" msgctxt "#30381" msgid "1 month" msgstr "1 bulan" msgctxt "#30382" msgid "2 months" msgstr "2 bulan" msgctxt "#30383" msgid "3 months" msgstr "3 bulan" msgctxt "#30384" msgid "6 months" msgstr "6 bulan" msgctxt "#30385" msgid "1 year" msgstr "1 tahun" msgctxt "#30386" msgid "2 years" msgstr "2 tahun" msgctxt "#30387" msgid "3 years" msgstr "3 tahun" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Sehingga ruang diperlukan (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Selamanya (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Penalaan jangkaan" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Bilangan langganan yang digunakan" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Lengahan tutup langganan yang tidak digunakan (saat)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Guna penalaan jangkaan untuk lajukan pertukaran saluran" msgctxt "#30450" msgid "No free adapter available" msgstr "Tiada penyesuai bebas tersedia" msgctxt "#30451" msgid "Scrambled channel" msgstr "Saluran terkarau" msgctxt "#30452" msgid "No signal" msgstr "Tiada isyarat" msgctxt "#30453" msgid "Tuning failed" msgstr "Penalaan gagal" msgctxt "#30454" msgid "User limit reached" msgstr "Had pengguna dicapai" msgctxt "#30455" msgid "No access" msgstr "Tiada capaian" msgctxt "#30456" msgid "Subscription error" msgstr "Ralat langganan" msgctxt "#30500" msgid "Streaming profile" msgstr "Profil penstriman" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profil yang digunakan (kosong = lalai)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Profil penstriman %s tidak tersedia" msgctxt "#30503" msgid "Data transfer" msgstr "Pemindahan data" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Strimkan saiz cebisan baca untuk rakaman (KB)" msgctxt "#30510" msgid "Recordings" msgstr "Rakaman" msgctxt "#30511" msgid "Server based play status" msgstr "Pelayar berdasarkan status main" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.mt_mt/000077500000000000000000000000001355512543200260135ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.mt_mt/strings.po000066400000000000000000000036511355512543200300510ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Hostname u indirizz IP tat- TVheadend" msgctxt "#30002" msgid "HTTP port" msgstr "port tal- HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "port tal- HTSP" msgctxt "#30004" msgid "Username" msgstr "Username" msgctxt "#30005" msgid "Password" msgstr "Sigriet" msgctxt "#30010" msgid "Timer settings" msgstr "Settings tal-arloġġ" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Transferiment asinkroniku tal- EPG" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Traċċi (dettaljat)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Il-Verżjoni tal-HTSP ma taqbilx (jiflaħ għal: v%d, hemm bżonn: v%d). Jekk jogħġbok aġġorna t-tvheadend." msgctxt "#30352" msgid "High" msgstr "Filmati/Atturi" msgctxt "#30353" msgid "Normal" msgstr "Normali" msgctxt "#30354" msgid "Low" msgstr "Filmati/Generi" msgctxt "#30356" msgid "Record all episodes" msgstr "Irrekordja l-episodji kollha" msgctxt "#30368" msgid "Default" msgstr "Difolt" msgctxt "#30510" msgid "Recordings" msgstr "Recordings" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.my_mm/000077500000000000000000000000001355512543200260115ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.my_mm/strings.po000066400000000000000000000022521355512543200300430ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30004" msgid "Username" msgstr "အသုံးပြုသူအမည်" msgctxt "#30005" msgid "Password" msgstr "စကားဝှက်" msgctxt "#30352" msgid "High" msgstr "အမြင့်စား" msgctxt "#30353" msgid "Normal" msgstr "ပုံမှန်" msgctxt "#30354" msgid "Low" msgstr "အနိမ့်စား" msgctxt "#30368" msgid "Default" msgstr "မူလအတိုင်း" msgctxt "#30510" msgid "Recordings" msgstr "အသံသွင်းခြင်း" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.nb_no/000077500000000000000000000000001355512543200257665ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.nb_no/strings.po000066400000000000000000000170721355512543200300260ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Tilkoblingsinnstillinger" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend vertsnavn eller IP-adresse" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP-port" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP-port" msgctxt "#30004" msgid "Username" msgstr "Brukernavn" msgctxt "#30005" msgid "Password" msgstr "Passord" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Tidsavbrudd for tilkobling (sekunder)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Responstidsavbrudd (sekunder)" msgctxt "#30008" msgid "Advanced settings" msgstr "Avanserte innstillinger" msgctxt "#30009" msgid "Streaming settings" msgstr "Strømmeinnstillinger" msgctxt "#30010" msgid "Timer settings" msgstr "Instillinger for tidsur" msgctxt "#30050" msgid "Auto recordings" msgstr "Autoopptak" msgctxt "#30051" msgid "Start time window calculation" msgstr "Starttid for vinduskalkuleringer" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Streng (start tid + slutt tid)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Avslappet (start tid +/- margin)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Maksimal starttidsmargin (minutter)" msgctxt "#30055" msgid "Default priority" msgstr "Forvalgt prioritet" msgctxt "#30056" msgid "Default lifetime" msgstr "Forvalgt levetid" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Forvalgt duplikatgjenkjennelse" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Forvalg for nytt tidsur" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Planlagte opptak" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Ignorer duplikater (tvh 4,3 +)" msgctxt "#30100" msgid "Data transfer" msgstr "Dataoverføring" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asynkron EPG-overføring" msgctxt "#30200" msgid "Debugging" msgstr "Feilsøking" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Spor (detaljert)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP versjon stemmer ikke (supported: v%d, required: v%d). Venligst oppdater tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Én gang (opprettet av tidsursregel)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Viktig (høyeste)" msgctxt "#30352" msgid "High" msgstr "Høy" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Lav" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Uviktig (laveste)" msgctxt "#30356" msgid "Record all episodes" msgstr "Ta opp alle episoder" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Ta opp dersom episodenummer er forskjellig" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Ta opp dersom episodenavn er forskjellig" msgctxt "#30359" msgid "Record if description differs" msgstr "Ta opp dersom beskrivelsen er forskjellig" msgctxt "#30360" msgid "Record max once per week" msgstr "Ta opp maks en gang i uken" msgctxt "#30361" msgid "Record max once per day" msgstr "Ta opp maks en gang om dagen" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Kun denne regelen: Ta opp dersom episodenummer er forskjellig" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Kun denne regelen: Ta opp dersom episodenavn er forskjellig" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Kun denne regelen: Ta opp dersom tittelen er forskjellig" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Kun denne regelen: Ta opp dersom beskrivelsen er forskjellig" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Kun denne regelen: Ta opp maks én gang i uken" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Kun denne regelen: Ta opp maks én gang per dag" msgctxt "#30368" msgid "Default" msgstr "Standard" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Tidsbasert regel (serielenke)" msgctxt "#30370" msgid "Record max once per month" msgstr "Ta opp maks en gang pr måned" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Kun denne regelen: Ta opp maks en gang pr måned" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Ta opp dersom unik episode i henhold til EPG/XLMTV" msgctxt "#30373" msgid "Until space needed" msgstr "Frem til plass trengs" msgctxt "#30374" msgid "Forever" msgstr "Alltid" msgctxt "#30375" msgid "1 day" msgstr "Én dag" msgctxt "#30376" msgid "3 days" msgstr "3 dager" msgctxt "#30377" msgid "5 days" msgstr "5 dager" msgctxt "#30378" msgid "1 week" msgstr "Én uke" msgctxt "#30379" msgid "2 weeks" msgstr "To uker" msgctxt "#30380" msgid "3 weeks" msgstr "Tre uker" msgctxt "#30381" msgid "1 month" msgstr "Én måned" msgctxt "#30382" msgid "2 months" msgstr "To måneder" msgctxt "#30383" msgid "3 months" msgstr "Tre måneder" msgctxt "#30384" msgid "6 months" msgstr "Seks måneder" msgctxt "#30385" msgid "1 year" msgstr "Ett år" msgctxt "#30386" msgid "2 years" msgstr "To år" msgctxt "#30387" msgid "3 years" msgstr "Tre år" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Frem til plass trengs (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "For alltid (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Forutsigbar søking" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Antall abbonement å bruke" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Forsinkelse for stenging av ubrukt abonnement (sekunder)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Bruk forutsigbar søking for å gjøre kanalbytte hurtigere" msgctxt "#30450" msgid "No free adapter available" msgstr "Ingen ledige tilkoblinger" msgctxt "#30451" msgid "Scrambled channel" msgstr "Kryptert kanal" msgctxt "#30452" msgid "No signal" msgstr "Intet signal" msgctxt "#30453" msgid "Tuning failed" msgstr "Søking feilet" msgctxt "#30454" msgid "User limit reached" msgstr "Maks antall brukere oppnådd" msgctxt "#30455" msgid "No access" msgstr "Ingen tilgang" msgctxt "#30456" msgid "Subscription error" msgstr "Abonnementfeil" msgctxt "#30500" msgid "Streaming profile" msgstr "Strømningsprofil" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profil som brukes (tom = forvalg)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Strømningsprofilen %s er ikke tilgjengelig" msgctxt "#30503" msgid "Data transfer" msgstr "Dataoverføring" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Bitstørrelse for strømmeopptak (KB)" msgctxt "#30510" msgid "Recordings" msgstr "Opptak" msgctxt "#30511" msgid "Server based play status" msgstr "Tjenerbasert avspillingsstatus" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.nl_nl/000077500000000000000000000000001355512543200257755ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.nl_nl/strings.po000066400000000000000000000171061355512543200300330ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Verbindingsinstellingen" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend servernaam of IP-adres" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP-poort" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP-poort" msgctxt "#30004" msgid "Username" msgstr "Gebruikersnaam" msgctxt "#30005" msgid "Password" msgstr "Wachtwoord" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Verbindingstime-out (seconden)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Antwoordtimeout (seconden)" msgctxt "#30008" msgid "Advanced settings" msgstr "Geavanceerde instellingen" msgctxt "#30009" msgid "Streaming settings" msgstr "Streaminginstellingen" msgctxt "#30010" msgid "Timer settings" msgstr "Timer-instellingen" msgctxt "#30050" msgid "Auto recordings" msgstr "Automatische opnamen" msgctxt "#30051" msgid "Start time window calculation" msgstr "Starttijd schermcalculatie" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Strikt (starttijd + eindtijd)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Ontspannen (starttijd +/- marge)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Maximale starttijdmarge (minuten)" msgctxt "#30055" msgid "Default priority" msgstr "Standaardprioriteit" msgctxt "#30056" msgid "Default lifetime" msgstr "Standaardlevensduur" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Standaard dubbelendetectie" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Standaard voor nieuwe opnames" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Geplande opnamen" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Negeer duplicaten (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Data-overdracht" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asynchrone EPG-overdracht" msgctxt "#30200" msgid "Debugging" msgstr "Foutregistratie" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Loggen (in detail)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP-versieverschil (ondersteund: v%d, vereist: v%d). Update A.U.B. tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Eén tijd (geschematiseerd door timer regel)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Belangrijk (Hoogste)" msgctxt "#30352" msgid "High" msgstr "Hoog" msgctxt "#30353" msgid "Normal" msgstr "Normaal" msgctxt "#30354" msgid "Low" msgstr "Laag" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Onbelangrijk (Laagste)" msgctxt "#30356" msgid "Record all episodes" msgstr "Alle afleveringen opnemen" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Opnemen als afleveringnummer afwijkt" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Opnemen als afleveringsnaam afwijkt" msgctxt "#30359" msgid "Record if description differs" msgstr "Opnemen als omschrijving afwijkt" msgctxt "#30360" msgid "Record max once per week" msgstr "Maximaal één keer per week opnemen" msgctxt "#30361" msgid "Record max once per day" msgstr "Maximaal één keer per dag opnemen" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Alleen deze regel: Alleen opname bij afwijkende afleveringnummers" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Alleen deze regel: Alleen opname bij afwijkende afleveringsnaam" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Alleen deze regel: Alleen opname bij afwijkende titel" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Alleen deze regel: Alleen opname bij afwijkende omschrijving" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Alleen deze regel: Alleen opname 1x per week" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Alleen deze regel: Alleen opname bij 1x per dag" msgctxt "#30368" msgid "Default" msgstr "Standaard" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Timer regel (serie`s link)" msgctxt "#30370" msgid "Record max once per month" msgstr "Maximaal één keer per maand opnemen" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Alleen deze regel: Alleen opname eenmaal per maand" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Neem op wanneer unieke aflevering volgens EPG/XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Tot benodigde ruimte" msgctxt "#30374" msgid "Forever" msgstr "Altijd" msgctxt "#30375" msgid "1 day" msgstr "1 dag" msgctxt "#30376" msgid "3 days" msgstr "3 dagen" msgctxt "#30377" msgid "5 days" msgstr "5 dagen" msgctxt "#30378" msgid "1 week" msgstr "1 week" msgctxt "#30379" msgid "2 weeks" msgstr "2 weken" msgctxt "#30380" msgid "3 weeks" msgstr "3 weken" msgctxt "#30381" msgid "1 month" msgstr "1 maand" msgctxt "#30382" msgid "2 months" msgstr "2 maanden" msgctxt "#30383" msgid "3 months" msgstr "3 maanden" msgctxt "#30384" msgid "6 months" msgstr "6 maanden" msgctxt "#30385" msgid "1 year" msgstr "1 jaar" msgctxt "#30386" msgid "2 years" msgstr "2 jaar" msgctxt "#30387" msgid "3 years" msgstr "3 jaar" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Tot benodigde ruimte (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Altijd (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Voorspellende tuning" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Aantal te gebruiken inschrijvingen" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Ongebruikte inschrijvingssluitvertraging (seconden)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Gebruik voorspellende tuning om kanaalwissels te versnellen" msgctxt "#30450" msgid "No free adapter available" msgstr "Geen vrije adapter beschikbaar" msgctxt "#30451" msgid "Scrambled channel" msgstr "Gecodeerde kanalen" msgctxt "#30452" msgid "No signal" msgstr "Geen signaal" msgctxt "#30453" msgid "Tuning failed" msgstr "Tuning mislukt" msgctxt "#30454" msgid "User limit reached" msgstr "Gebruikerslimiet bereikt" msgctxt "#30455" msgid "No access" msgstr "Geen toegang" msgctxt "#30456" msgid "Subscription error" msgstr "Inschrijvingsfout" msgctxt "#30500" msgid "Streaming profile" msgstr "Streamingprofiel" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Te gebruiken profiel (leeg = standaard)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Streamingprofiel %s is niet beschikbaar" msgctxt "#30503" msgid "Data transfer" msgstr "Data-overdracht" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Leesgrootte datablokken voor opnames (KB)" msgctxt "#30510" msgid "Recordings" msgstr "Opnames" msgctxt "#30511" msgid "Server based play status" msgstr "Servergebaseerde afspeelstatus" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.pl_pl/000077500000000000000000000000001355512543200260015ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.pl_pl/strings.po000066400000000000000000000164011355512543200300340ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Ustawienia połączenia" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Nazwa lub adres serwera" msgctxt "#30002" msgid "HTTP port" msgstr "Port HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Port HTSP" msgctxt "#30004" msgid "Username" msgstr "Użytkownik" msgctxt "#30005" msgid "Password" msgstr "Hasło" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Limit czasu połączenia (sekundy)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Limit czasu odpowiedzi (sekundy)" msgctxt "#30008" msgid "Advanced settings" msgstr "Ustawienia zaawansowane" msgctxt "#30009" msgid "Streaming settings" msgstr "Ustawienia transmisji" msgctxt "#30010" msgid "Timer settings" msgstr "Ustawienia zadania" msgctxt "#30050" msgid "Auto recordings" msgstr "Nagrywanie automatyczne" msgctxt "#30051" msgid "Start time window calculation" msgstr "Wyliczanie okna czasu rozpoczęcia" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Ścisłe (czas początku + czas końca)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Luźny (czas początku +/- zapasowy czas)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Nagrywaj przed zaplanowanym czasem początku (minuty)" msgctxt "#30055" msgid "Default priority" msgstr "Domyślny priorytet" msgctxt "#30056" msgid "Default lifetime" msgstr "Domyślny czas życia" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Domyślna detekcja duplikatów" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Domyślne dla nowych zadań" msgctxt "#30100" msgid "Data transfer" msgstr "Transfer danych" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asynchroniczny transfer danych przewodnika" msgctxt "#30200" msgid "Debugging" msgstr "Diagnostyka" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Śledzenie (szczegółowe)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Nieprawidłowa wersja HTSP (obsługiwana: v%d, wymagana: v%d). Proszę zaktualizować program tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Jednorazowo (reguła harmonogramu)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Ważna (Najwyższa)" msgctxt "#30352" msgid "High" msgstr "Wysoka" msgctxt "#30353" msgid "Normal" msgstr "Normalny" msgctxt "#30354" msgid "Low" msgstr "Niska" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Nieważna (Najniższa)" msgctxt "#30356" msgid "Record all episodes" msgstr "Nagrywaj wszystkie odcinki" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Nagrywaj jeśli numer odcinka się różni" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Nagrywaj jeśli nazwa odcinka się różni" msgctxt "#30359" msgid "Record if description differs" msgstr "Nagrywaj jeśli opis się różni" msgctxt "#30360" msgid "Record max once per week" msgstr "Nagrywaj maksymalnie raz na tydzień" msgctxt "#30361" msgid "Record max once per day" msgstr "Nagrywaj maksymalnie raz na dzień" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Tylko ta reguła: Nagrywaj, gdy różnią się numery odcinków" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Tylko ta reguła: Nagrywaj, gdy różnią się nazwy odcinków" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Tylko ta reguła: Nagrywaj, gdy różnią się tytuły" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Tylko ta reguła: Nagrywaj, gdy różnią się opisy" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Tylko ta reguła: Nagrywaj maksymalnie raz na tydzień" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Tylko ta reguła: Nagrywaj maksymalnie raz na dzień" msgctxt "#30368" msgid "Default" msgstr "Domyślnie" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Reguła harmonogramu (wiązanie seryjne)" msgctxt "#30370" msgid "Record max once per month" msgstr "Nagrywaj maksimum raz na miesiąc" msgctxt "#30373" msgid "Until space needed" msgstr "Do zakończenia programu" msgctxt "#30374" msgid "Forever" msgstr "Zawsze" msgctxt "#30375" msgid "1 day" msgstr "1 dzień" msgctxt "#30376" msgid "3 days" msgstr "3 dni" msgctxt "#30377" msgid "5 days" msgstr "5 dni" msgctxt "#30378" msgid "1 week" msgstr "1 tydzień" msgctxt "#30379" msgid "2 weeks" msgstr "2 tygodnie" msgctxt "#30380" msgid "3 weeks" msgstr "3 tygodnie" msgctxt "#30381" msgid "1 month" msgstr "1 miesiąc" msgctxt "#30382" msgid "2 months" msgstr "2 miesiące" msgctxt "#30383" msgid "3 months" msgstr "3 miesiące" msgctxt "#30384" msgid "6 months" msgstr "6 miesiący" msgctxt "#30385" msgid "1 year" msgstr "1 rok" msgctxt "#30386" msgid "2 years" msgstr "2 lata" msgctxt "#30387" msgid "3 years" msgstr "3 lata" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Do momentu, gdy braknie przestrzeni (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Bez końca (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Wstępne dostrajanie" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Liczba subskrypcji w użyciu" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Opóźnienie zamykania nieużywanych subskrypcji (sekundy)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Używaj wstępnego dostrajania w celu przyśpieszenia przełączania kanałów" msgctxt "#30450" msgid "No free adapter available" msgstr "Brak wolnych adapterów" msgctxt "#30451" msgid "Scrambled channel" msgstr "Kanał zakodowany" msgctxt "#30452" msgid "No signal" msgstr "Brak sygnału" msgctxt "#30453" msgid "Tuning failed" msgstr "Nieudane dostrajanie" msgctxt "#30454" msgid "User limit reached" msgstr "Przekroczono limit użytkowników" msgctxt "#30455" msgid "No access" msgstr "Brak dostępu" msgctxt "#30456" msgid "Subscription error" msgstr "Błąd subskrypcji" msgctxt "#30500" msgid "Streaming profile" msgstr "Profil transmisji" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Używany profil (pusty = domyślny)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Brak profilu transmisji %s" msgctxt "#30503" msgid "Data transfer" msgstr "Transfer danych" msgctxt "#30510" msgid "Recordings" msgstr "Nagrania" msgctxt "#30511" msgid "Server based play status" msgstr "Stan odtwarzania na serwerze" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.pt_br/000077500000000000000000000000001355512543200260015ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.pt_br/strings.po000066400000000000000000000166551355512543200300470ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Ajustes de Conexão" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend: Hostname ou endereço IP" msgctxt "#30002" msgid "HTTP port" msgstr "Porta HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Porta HTSP" msgctxt "#30004" msgid "Username" msgstr "Nome de utilizador" msgctxt "#30005" msgid "Password" msgstr "Senha" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Tempo limite para conexão (segundos)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Tempo limite para resposta (segundos)" msgctxt "#30008" msgid "Advanced settings" msgstr "Ajustes avançados" msgctxt "#30009" msgid "Streaming settings" msgstr "Ajustes Streaming" msgctxt "#30010" msgid "Timer settings" msgstr "Ajustes de Gravação" msgctxt "#30050" msgid "Auto recordings" msgstr "Auto gravar" msgctxt "#30051" msgid "Start time window calculation" msgstr "Iniciar o cálculo na janela de tempo" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Estrito (hora início + hora final)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Relaxado (hora início +/- margem)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Margem máxima de tempo de início (minutos)" msgctxt "#30055" msgid "Default priority" msgstr "Prioridade padrão" msgctxt "#30056" msgid "Default lifetime" msgstr "Tempo de vida útil padrão" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Detecção de padrão para itens duplicados" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Padrão para novos agendamentos" msgctxt "#30100" msgid "Data transfer" msgstr "Transferência de Dados" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Transferência de EPG Assincrônica" msgctxt "#30200" msgid "Debugging" msgstr "Depurando" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Trace (detalhado)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Incompatibilidade de versão HTSP (suportado: v%d, requerido: v%d). Por favor atualize o tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Uma vez (agendado pelo regra do agendador)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Importante (mais alto)" msgctxt "#30352" msgid "High" msgstr "Máxima" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Mínima" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Sem importância (mais baixa)" msgctxt "#30356" msgid "Record all episodes" msgstr "Gravar todos os episódios" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Gravar se o número do episódio difira" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Gravar se o nome do episódio difira" msgctxt "#30359" msgid "Record if description differs" msgstr "Gravar se a descrição difira" msgctxt "#30360" msgid "Record max once per week" msgstr "Máximo gravações na semana" msgctxt "#30361" msgid "Record max once per day" msgstr "Máximo de gravações por dia" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Esta regra somente: Gravar se o número do episódio difira" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Esta regra somente: Gravar se o nome do episódio difira" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Esta regra somente: Gravar se o título diferir" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Esta regra somente: Gravar se a descrição difira" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Esta regra somente: Gravar máximo uma vez por semana" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Esta regra somente: Gravar máximo uma vez por dia" msgctxt "#30368" msgid "Default" msgstr "Padrão" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Regra do Agendador (link series)" msgctxt "#30370" msgid "Record max once per month" msgstr "Gravar máximo uma vez por mês" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Esta regra apenas: gravar uma vez por mês" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Gravar se o episódio for único de acordo com o EPG/XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Até existir espaço necessário" msgctxt "#30374" msgid "Forever" msgstr "Para sempre" msgctxt "#30375" msgid "1 day" msgstr "1 dia" msgctxt "#30376" msgid "3 days" msgstr "3 dias" msgctxt "#30377" msgid "5 days" msgstr "5 dias" msgctxt "#30378" msgid "1 week" msgstr "1 semana" msgctxt "#30379" msgid "2 weeks" msgstr "2 semanas" msgctxt "#30380" msgid "3 weeks" msgstr "3 semanas" msgctxt "#30381" msgid "1 month" msgstr "1 mês" msgctxt "#30382" msgid "2 months" msgstr "2 meses" msgctxt "#30383" msgid "3 months" msgstr "3 meses" msgctxt "#30384" msgid "6 months" msgstr "6 meses" msgctxt "#30385" msgid "1 year" msgstr "1 ano" msgctxt "#30386" msgid "2 years" msgstr "2 anos" msgctxt "#30387" msgid "3 years" msgstr "3 anos" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Enquanto tiver espaço (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Para sempre (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Sintonização preditiva" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Número de subscrições para uso" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Subscrição não utilizada encerre o atraso (segundos)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Usar sintonização preditiva para acelerar a troca entre canais" msgctxt "#30450" msgid "No free adapter available" msgstr "Nenhum adaptador livre disponível" msgctxt "#30451" msgid "Scrambled channel" msgstr "Canal codificado" msgctxt "#30452" msgid "No signal" msgstr "Sem sinal" msgctxt "#30453" msgid "Tuning failed" msgstr "Sintonização falhou" msgctxt "#30454" msgid "User limit reached" msgstr "Limite de usuário atingido" msgctxt "#30455" msgid "No access" msgstr "Sem acesso" msgctxt "#30456" msgid "Subscription error" msgstr "Erro de subscrição" msgctxt "#30500" msgid "Streaming profile" msgstr "Perfil streaming" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Perfil para uso (vazio = padrão)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Perfil streaming %s não está disponível" msgctxt "#30503" msgid "Data transfer" msgstr "Transferência de Dados" msgctxt "#30510" msgid "Recordings" msgstr "Gravações" msgctxt "#30511" msgid "Server based play status" msgstr "Servidor baseado no estatus de reprodução" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.pt_pt/000077500000000000000000000000001355512543200260215ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.pt_pt/strings.po000066400000000000000000000141171355512543200300560ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Definições da ligação" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Nome do servidor Tvheadend ou endereço IP" msgctxt "#30002" msgid "HTTP port" msgstr "Porto de HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Porto de HTSP" msgctxt "#30004" msgid "Username" msgstr "Nome de utilizador" msgctxt "#30005" msgid "Password" msgstr "Palavra-passe" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Tempo-limite de ligação (segundos)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Tempo-limite da resposta (segundos)" msgctxt "#30008" msgid "Advanced settings" msgstr "Definições avançadas" msgctxt "#30009" msgid "Streaming settings" msgstr "Definições da emissão" msgctxt "#30010" msgid "Timer settings" msgstr "Definições do temporizador" msgctxt "#30050" msgid "Auto recordings" msgstr "Gravações automáticas" msgctxt "#30051" msgid "Start time window calculation" msgstr "Cálculo do intervalo da hora de início" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Restrito (hora inicial e hora final)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Tolerante (hora inicial +/- margem)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Margem máxima da hora inicial (minutos)" msgctxt "#30055" msgid "Default priority" msgstr "Prioridade padrão" msgctxt "#30056" msgid "Default lifetime" msgstr "Ciclo de vida" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Deteção de duplicados" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Padrão para novos temporizadores" msgctxt "#30100" msgid "Data transfer" msgstr "Transferência de dados" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Transferência EPG assíncrona" msgctxt "#30200" msgid "Debugging" msgstr "Depuração" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Rastreio (detalhado)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Incompatibilidade na versão do HTSP (suportado: v%d, necessário: v%d). Atualize o tvheadend." msgctxt "#30351" msgid "Important (Highest)" msgstr "Importante (mais alta)" msgctxt "#30352" msgid "High" msgstr "Alta" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Baixa" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Não importante (mais baixa)" msgctxt "#30356" msgid "Record all episodes" msgstr "Gravar todos os episódios" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Gravar se o número do episódio for diferente" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Gravar se o nome do episódio for diferente" msgctxt "#30359" msgid "Record if description differs" msgstr "Gravar se a descrição do episódio for diferente" msgctxt "#30360" msgid "Record max once per week" msgstr "Gravar, no máximo, uma vez por semana" msgctxt "#30361" msgid "Record max once per day" msgstr "Gravar, no máximo, uma vez por dia" msgctxt "#30368" msgid "Default" msgstr "Normal" msgctxt "#30373" msgid "Until space needed" msgstr "Até ser necessário espaço" msgctxt "#30374" msgid "Forever" msgstr "Para sempre" msgctxt "#30375" msgid "1 day" msgstr "1 dia" msgctxt "#30376" msgid "3 days" msgstr "3 dias" msgctxt "#30377" msgid "5 days" msgstr "5 dias" msgctxt "#30378" msgid "1 week" msgstr "1 semana" msgctxt "#30379" msgid "2 weeks" msgstr "2 semanas" msgctxt "#30380" msgid "3 weeks" msgstr "3 semanas" msgctxt "#30381" msgid "1 month" msgstr "1 mês" msgctxt "#30382" msgid "2 months" msgstr "2 meses" msgctxt "#30383" msgid "3 months" msgstr "3 meses" msgctxt "#30384" msgid "6 months" msgstr "6 meses" msgctxt "#30385" msgid "1 year" msgstr "1 ano" msgctxt "#30386" msgid "2 years" msgstr "2 anos" msgctxt "#30387" msgid "3 years" msgstr "3 anos" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Até ser necessário espaço (TVH 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Para sempre (TVH 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Sintonização preditiva" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Número de subscrições a utilizar" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Atraso para fechar subscrições inativas (segundos)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Usar a sintonização preditiva para melhorar a troca de canais" msgctxt "#30450" msgid "No free adapter available" msgstr "Nenhum adaptador livre disponível" msgctxt "#30451" msgid "Scrambled channel" msgstr "Canal codificado" msgctxt "#30452" msgid "No signal" msgstr "Sem sinal" msgctxt "#30453" msgid "Tuning failed" msgstr "Falha de sintonização" msgctxt "#30454" msgid "User limit reached" msgstr "Limite de utilizadores atingido" msgctxt "#30455" msgid "No access" msgstr "Sem acesso" msgctxt "#30456" msgid "Subscription error" msgstr "Erro de subscrição" msgctxt "#30500" msgid "Streaming profile" msgstr "Perfil de transmissão" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Perfil a usar (vazio = padrão)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "O perfil de transmissão %s não está disponível" msgctxt "#30503" msgid "Data transfer" msgstr "Transferência de dados" msgctxt "#30510" msgid "Recordings" msgstr "Gravações" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ro_ro/000077500000000000000000000000001355512543200260135ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ro_ro/strings.po000066400000000000000000000157651355512543200300620ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Stabiliri conexiune" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Nume gazdă sau adresă IP pentru Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "Port HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Port HTSP" msgctxt "#30004" msgid "Username" msgstr "Utilizator" msgctxt "#30005" msgid "Password" msgstr "Parolă" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Expirare timp conexiune (secunde)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Limită de timp răspuns (secunde)" msgctxt "#30008" msgid "Advanced settings" msgstr "Stabiliri avansate" msgctxt "#30009" msgid "Streaming settings" msgstr "Stabiliri difuzare în flux" msgctxt "#30010" msgid "Timer settings" msgstr "Stabiliri cronometru" msgctxt "#30050" msgid "Auto recordings" msgstr "Înregistrări automate" msgctxt "#30051" msgid "Start time window calculation" msgstr "Calculare fereastră timp de pornire" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Strict (timp de începere + timp de încheiere)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Relaxat (timp de începere +/- margine)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Margine maximă timp de începere (minute)" msgctxt "#30055" msgid "Default priority" msgstr "Prioritate implicită" msgctxt "#30056" msgid "Default lifetime" msgstr "Durată de viață implicită" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Detactare uplicată implicită" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Implicite pentru cronometrele noi" msgctxt "#30100" msgid "Data transfer" msgstr "Transfer de date" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Transfer ghid tv asincron" msgctxt "#30200" msgid "Debugging" msgstr "Depanare" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Urmărire (detaliată)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Nepotrivire versiune HTSP (compatibilă: v%d, necesară: v%d). Actualizați tvheadend." msgctxt "#30351" msgid "Important (Highest)" msgstr "Importantă (Cea mai mare)" msgctxt "#30352" msgid "High" msgstr "Mare" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Mică" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Importantă (Cea mai mică)" msgctxt "#30356" msgid "Record all episodes" msgstr "Înregistrează toate episoadele" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Înregistrează dacă numărul episodului diferă" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Înregistrează dacă numele episodului diferă" msgctxt "#30359" msgid "Record if description differs" msgstr "Înregistrează dacă descrierea diferă" msgctxt "#30360" msgid "Record max once per week" msgstr "Înregistrează maxim o dată pe săptămână" msgctxt "#30361" msgid "Record max once per day" msgstr "Înregistrează maxim o dată pe zi" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Doar această regulă: Înregistrează dacă numărul episodului diferă" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Doar această regulă: Înregistrează dacă numele episodului diferă" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Doar această regulă: Înregistrează dacă titlul diferă" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Doar această regulă: Înregistrează dacă descrierea diferă" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Doar această regulă: Înregistrează maxim o dată pe săptămână" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Doar această regulă: Înregistrează maxim o dată pe zi" msgctxt "#30368" msgid "Default" msgstr "Standard" msgctxt "#30373" msgid "Until space needed" msgstr "Până este nevoie de spațiu" msgctxt "#30374" msgid "Forever" msgstr "Pentru totdeauna" msgctxt "#30375" msgid "1 day" msgstr "1 zi" msgctxt "#30376" msgid "3 days" msgstr "3 zile" msgctxt "#30377" msgid "5 days" msgstr "5 zile" msgctxt "#30378" msgid "1 week" msgstr "1 săptămână" msgctxt "#30379" msgid "2 weeks" msgstr "2 săptămâni" msgctxt "#30380" msgid "3 weeks" msgstr "3 săptămâni" msgctxt "#30381" msgid "1 month" msgstr "1 lună" msgctxt "#30382" msgid "2 months" msgstr "2 luni" msgctxt "#30383" msgid "3 months" msgstr "3 luni" msgctxt "#30384" msgid "6 months" msgstr "6 luni" msgctxt "#30385" msgid "1 year" msgstr "1 an" msgctxt "#30386" msgid "2 years" msgstr "2 ani" msgctxt "#30387" msgid "3 years" msgstr "3 ani" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Până când e nevoie de spațiu (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Totdeauna (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Prindere prezicătoare" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Număr de abonamente de folosit" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Întârziere închidere abonament nefolosit (secunde)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Folosește prinderea prezicătoare pentru a face mai rapidă schimbarea canalelor" msgctxt "#30450" msgid "No free adapter available" msgstr "Nu este disponibil niciun adaptor liber" msgctxt "#30451" msgid "Scrambled channel" msgstr "Canal codat" msgctxt "#30452" msgid "No signal" msgstr "Fără semnal" msgctxt "#30453" msgid "Tuning failed" msgstr "Prindere eșuată" msgctxt "#30454" msgid "User limit reached" msgstr "Limită de utilizatori atinsă" msgctxt "#30455" msgid "No access" msgstr "Fără acces" msgctxt "#30456" msgid "Subscription error" msgstr "Eroare abonament" msgctxt "#30500" msgid "Streaming profile" msgstr "Profil difuzare în flux" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profil de folosit (gol = implicit)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Profilul pentru difuzarea în flux %s nu este disponibil" msgctxt "#30503" msgid "Data transfer" msgstr "Transfer de date" msgctxt "#30510" msgid "Recordings" msgstr "Înregistrări" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ru_ru/000077500000000000000000000000001355512543200260275ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ru_ru/strings.po000066400000000000000000000230331355512543200300610ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Настройки подключения" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Имя пользователя или IP-адрес Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "Порт HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Порт HTSP" msgctxt "#30004" msgid "Username" msgstr "Имя пользователя" msgctxt "#30005" msgid "Password" msgstr "Пароль" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Таймаут подключения (секунд)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Ожидание ответа (секунд)" msgctxt "#30008" msgid "Advanced settings" msgstr "Дополнительные настройки" msgctxt "#30009" msgid "Streaming settings" msgstr "Настройки потока" msgctxt "#30010" msgid "Timer settings" msgstr "Установки таймера" msgctxt "#30050" msgid "Auto recordings" msgstr "Аудио записи" msgctxt "#30051" msgid "Start time window calculation" msgstr "Расчёт стартового времени" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Строгий (время начала + время конца)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Мягкий (время начала +/- отступы)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Максимальный отступ начального времени (минуты)" msgctxt "#30055" msgid "Default priority" msgstr "Приоритет по-умолчанию" msgctxt "#30056" msgid "Default lifetime" msgstr "Хранение по-умолчанию" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Определение повторов по-умолчанию" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Настройки по-умолчанию для новых таймеров" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Запланированные записи" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Игнорировать дубликаты (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Передача данных" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Асинхронная получение EPG" msgctxt "#30200" msgid "Debugging" msgstr "Отладка" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Трассировка (подробнее)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Не соответствие версий HTSP (поддерживаемая: v%d, требуемая: v%d). Пожалуйста, обновите tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Один раз (запланированное правило таймера)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Важный (Наивысший)" msgctxt "#30352" msgid "High" msgstr "Высокое" msgctxt "#30353" msgid "Normal" msgstr "Нормальное" msgctxt "#30354" msgid "Low" msgstr "Низкое" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Не важный (наименьший)" msgctxt "#30356" msgid "Record all episodes" msgstr "Запись всех эпизодов" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Записывать если номер серии отличается" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Записывать если имя серии отличается" msgctxt "#30359" msgid "Record if description differs" msgstr "Записывать если описание отличается" msgctxt "#30360" msgid "Record max once per week" msgstr "Записывать максимум раз в неделю" msgctxt "#30361" msgid "Record max once per day" msgstr "Записывать максимум раз в день" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Это правило только: запись, если номер эпизода отличается" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Это правило только: запись, если имя эпизода отличается" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Это правило только: запись, если название отличается" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Это правило только: запись, если описание отличается" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Это правило только: запись максимальной раз в неделю" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Это правило только: запись макс один раз в день" msgctxt "#30368" msgid "Default" msgstr "По-умолчанию" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Правило таймера (серия ссылок)" msgctxt "#30370" msgid "Record max once per month" msgstr "Максимальное количество записей в месяц" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Это правило только: запись максимальной раз в месяц" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Запись, если уникальный эпизод согласно EPG / XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Пока не будет нужно свободное место" msgctxt "#30374" msgid "Forever" msgstr "Всегда" msgctxt "#30375" msgid "1 day" msgstr "1 день" msgctxt "#30376" msgid "3 days" msgstr "3 дня" msgctxt "#30377" msgid "5 days" msgstr "5 дней" msgctxt "#30378" msgid "1 week" msgstr "1 неделя" msgctxt "#30379" msgid "2 weeks" msgstr "2 недели" msgctxt "#30380" msgid "3 weeks" msgstr "3 недели" msgctxt "#30381" msgid "1 month" msgstr "1 месяц" msgctxt "#30382" msgid "2 months" msgstr "2 месяца" msgctxt "#30383" msgid "3 months" msgstr "3 месяца" msgctxt "#30384" msgid "6 months" msgstr "6 месяцев" msgctxt "#30385" msgid "1 year" msgstr "1 год" msgctxt "#30386" msgid "2 years" msgstr "2 года" msgctxt "#30387" msgid "3 years" msgstr "3 года" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Пока не будет нужно свободное место (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Бесконечно (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Интеллектуальная регулировка" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Количество используемых подписок" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Задержка закрытия неиспользуемой подписки (секунд)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Использовать интеллектуальную регулировку для ускорения переключений каналов" msgctxt "#30450" msgid "No free adapter available" msgstr "Нет доступных адаптеров" msgctxt "#30451" msgid "Scrambled channel" msgstr "Кодированный канал" msgctxt "#30452" msgid "No signal" msgstr "Нет сигнала" msgctxt "#30453" msgid "Tuning failed" msgstr "Не удалось настроить" msgctxt "#30454" msgid "User limit reached" msgstr "Исчерпан лимит пользователей" msgctxt "#30455" msgid "No access" msgstr "Нет доступа" msgctxt "#30456" msgid "Subscription error" msgstr "Ошибка подписки" msgctxt "#30500" msgid "Streaming profile" msgstr "Профиль потока" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Использовать профиль (пустой = по-умолчанию)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Профиль потока %s не доступен" msgctxt "#30503" msgid "Data transfer" msgstr "Передача данных" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Поток читает размер блока для записей (KB)" msgctxt "#30510" msgid "Recordings" msgstr "Записи" msgctxt "#30511" msgid "Server based play status" msgstr "Состояние воспроизведения на основе сервера" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.si_lk/000077500000000000000000000000001355512543200257745ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.si_lk/strings.po000066400000000000000000000025051355512543200300270ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30002" msgid "HTTP port" msgstr "HTTP තිර්ථය" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP තිර්ථය" msgctxt "#30004" msgid "Username" msgstr "පරිශීලක නම" msgctxt "#30005" msgid "Password" msgstr "මුරපදය" msgctxt "#30200" msgid "Debugging" msgstr "නිදොස්කරමින් " msgctxt "#30352" msgid "High" msgstr "ඉහළ" msgctxt "#30353" msgid "Normal" msgstr "සාමාන්‍ය " msgctxt "#30354" msgid "Low" msgstr "අඩු" msgctxt "#30368" msgid "Default" msgstr "නියත " msgctxt "#30510" msgid "Recordings" msgstr "පටිගතකිරීම්" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.sk_sk/000077500000000000000000000000001355512543200260055ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.sk_sk/strings.po000066400000000000000000000175421355512543200300470ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Nastavenia pripojenia" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Názov hostiteľa Tvheadend alebo IP adresa" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP port" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP port" msgctxt "#30004" msgid "Username" msgstr "Používateľské meno" msgctxt "#30005" msgid "Password" msgstr "Heslo" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Časový limit spojenia (v sekundách)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Časový limit pre odpoveď (sekundy)" msgctxt "#30008" msgid "Advanced settings" msgstr "Pokročilé nastavenia" msgctxt "#30009" msgid "Streaming settings" msgstr "Nastavenia streamovania" msgctxt "#30010" msgid "Timer settings" msgstr "Nastavenia časovača" msgctxt "#30050" msgid "Auto recordings" msgstr "Automatické nahrávania" msgctxt "#30051" msgid "Start time window calculation" msgstr "Výpočet okna pre čas začiatku" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Striktné (čas začiatku + čas konca)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Zmiernené (čas začiatku +/- okraj)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Maximálny okraj pre čas začiatku (minúty)" msgctxt "#30055" msgid "Default priority" msgstr "Predvolená priorita" msgctxt "#30056" msgid "Default lifetime" msgstr "Predvolená životnosť" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Predvolená detekcia duplikátov" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Predvolené pre nové časovače" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Naplánované nahrávania" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Ignorovať duplikáty (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Prenos údajov" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asynchrónny prenos EPG" msgctxt "#30200" msgid "Debugging" msgstr "Ladenie / Debug" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Sledovanie (detailné)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Nezhoda verzie HTSP (podporované: v%d, požadované: v%d). Aktualizujte tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "Jednorazovo (naplánované pravidlom časovača)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Dôležité (najvyššia)" msgctxt "#30352" msgid "High" msgstr "Vysoká" msgctxt "#30353" msgid "Normal" msgstr "Normálny" msgctxt "#30354" msgid "Low" msgstr "Nízka" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Nedôležité (najnižšia)" msgctxt "#30356" msgid "Record all episodes" msgstr "Nahrať všetky epizódy" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Nahrávať, ak sa číslo epizódy líši" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Nahrávať, ak sa názov epizódy líši" msgctxt "#30359" msgid "Record if description differs" msgstr "Nahrávať, ak sa popis líši" msgctxt "#30360" msgid "Record max once per week" msgstr "Nahrávať najviac raz za týždeň" msgctxt "#30361" msgid "Record max once per day" msgstr "Nahrávať najviac raz za deň" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Iba toto pravidlo: Nahrávať iba ak sa líši číslo epizódy" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Iba toto pravidlo: Nahrávať iba ak sa líši názov epizódy" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Iba toto pravidlo: Nahrávať iba ak sa líši titul" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Iba toto pravidlo: Nahrávať iba ak sa líši popis" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Iba toto pravidlo: Nahrávať max. raz týždenne" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Iba toto pravidlo: Nahrávať max. raz denne" msgctxt "#30368" msgid "Default" msgstr "Štandardná" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Pravidlo časovača (odkaz na seriál)" msgctxt "#30370" msgid "Record max once per month" msgstr "Nahrávať najviac raz za mesiac" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Iba toto pravidlo: Nahrávať najviac raz za mesiac" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Nahrávať, ak je to podľa EPG/XMLTV unikátna epizóda" msgctxt "#30373" msgid "Until space needed" msgstr "Dokiaľ nebude potrebné miesto" msgctxt "#30374" msgid "Forever" msgstr "Navždy" msgctxt "#30375" msgid "1 day" msgstr "1 deň" msgctxt "#30376" msgid "3 days" msgstr "3 dni" msgctxt "#30377" msgid "5 days" msgstr "5 dní" msgctxt "#30378" msgid "1 week" msgstr "1 týždeň" msgctxt "#30379" msgid "2 weeks" msgstr "2 týždne" msgctxt "#30380" msgid "3 weeks" msgstr "3 týždne" msgctxt "#30381" msgid "1 month" msgstr "1 mesiac" msgctxt "#30382" msgid "2 months" msgstr "2 mesiace" msgctxt "#30383" msgid "3 months" msgstr "3 mesiace" msgctxt "#30384" msgid "6 months" msgstr "6 mesiacov" msgctxt "#30385" msgid "1 year" msgstr "1 rok" msgctxt "#30386" msgid "2 years" msgstr "2 roky" msgctxt "#30387" msgid "3 years" msgstr "3 roky" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Dokým nebude potrebné miesto (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Navždy (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Prediktívne ladenie" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Počet odberov, ktoré sa majú použiť" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Oneskorenie pre uzavretie nepoužitého odberu (sekundy)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Použiť prediktívne ladenie na urýchlenie prepínania kanálov" msgctxt "#30450" msgid "No free adapter available" msgstr "K dispozícii nie je žiadny voľný adaptér" msgctxt "#30451" msgid "Scrambled channel" msgstr "Kódovaný kanál" msgctxt "#30452" msgid "No signal" msgstr "Žiadny signál" msgctxt "#30453" msgid "Tuning failed" msgstr "Ladenie zlyhalo" msgctxt "#30454" msgid "User limit reached" msgstr "Bol dosiahnutý používateľský limit" msgctxt "#30455" msgid "No access" msgstr "Žiadny prístup" msgctxt "#30456" msgid "Subscription error" msgstr "Chyba odberu" msgctxt "#30500" msgid "Streaming profile" msgstr "Profil streamovania" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profil, ktorý sa má použiť (prázdny = predvolené)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Profil streamovania %s nie je k dispozícii" msgctxt "#30503" msgid "Data transfer" msgstr "Prenos údajov" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Veľkosť chunku pre čítanie streamu u nahrávok (KB)" msgctxt "#30510" msgid "Recordings" msgstr "Nahrávky" msgctxt "#30511" msgid "Server based play status" msgstr "Stav prehrávania založený na serveri" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.sl_si/000077500000000000000000000000001355512543200260045ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.sl_si/strings.po000066400000000000000000000065261355512543200300460ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Nastavitve povezave" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Ime gostitelja ali IP strežnika Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "Vrata HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Vrata HTSP" msgctxt "#30004" msgid "Username" msgstr "Uporabniško ime" msgctxt "#30005" msgid "Password" msgstr "Geslo" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Prekinitev povezave (sekunde)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Časovni rok odgovora (v sekundah)" msgctxt "#30008" msgid "Advanced settings" msgstr "Napredne nastavitve" msgctxt "#30009" msgid "Streaming settings" msgstr "Nastavitve pretakanja" msgctxt "#30010" msgid "Timer settings" msgstr "Nastavitve časovnika" msgctxt "#30050" msgid "Auto recordings" msgstr "Samodejno snemanje" msgctxt "#30055" msgid "Default priority" msgstr "Privzeta prioriteta" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asinhroni prenos EPG" msgctxt "#30200" msgid "Debugging" msgstr "Razhroščevanje" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Sledi (podrobno)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Neujemanje različice HTSP (podprta: v%d, obvezna: v%d). Posodobite tvheadend." msgctxt "#30352" msgid "High" msgstr "Visoka" msgctxt "#30353" msgid "Normal" msgstr "Običajno" msgctxt "#30354" msgid "Low" msgstr "Nizka" msgctxt "#30356" msgid "Record all episodes" msgstr "Posnemi vse epizode" msgctxt "#30368" msgid "Default" msgstr "Privzeto" msgctxt "#30373" msgid "Until space needed" msgstr "Dokler se ne potrebuje prostora" msgctxt "#30374" msgid "Forever" msgstr "za vedno" msgctxt "#30375" msgid "1 day" msgstr "1 dan" msgctxt "#30376" msgid "3 days" msgstr "3 dni" msgctxt "#30377" msgid "5 days" msgstr "5 dni" msgctxt "#30378" msgid "1 week" msgstr "1 teden" msgctxt "#30379" msgid "2 weeks" msgstr "2 tedna" msgctxt "#30380" msgid "3 weeks" msgstr "3 tedne" msgctxt "#30381" msgid "1 month" msgstr "1 mesec" msgctxt "#30382" msgid "2 months" msgstr "2 meseca" msgctxt "#30383" msgid "3 months" msgstr "3 mesece" msgctxt "#30384" msgid "6 months" msgstr "6 mesecev" msgctxt "#30385" msgid "1 year" msgstr "1 leto" msgctxt "#30386" msgid "2 years" msgstr "2 leti" msgctxt "#30387" msgid "3 years" msgstr "3 leta" msgctxt "#30452" msgid "No signal" msgstr "Ni signala" msgctxt "#30455" msgid "No access" msgstr "Ni dostopa" msgctxt "#30456" msgid "Subscription error" msgstr "Napaka naročnine" msgctxt "#30510" msgid "Recordings" msgstr "Posnetki" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.sq_al/000077500000000000000000000000001355512543200257725ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.sq_al/strings.po000066400000000000000000000024541355512543200300300ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend hostname ose adresa IP" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP porti" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP porti" msgctxt "#30004" msgid "Username" msgstr "Emër-kalues" msgctxt "#30005" msgid "Password" msgstr "Fjalkalim" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" msgctxt "#30352" msgid "High" msgstr "Lartë" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Poshtë" msgctxt "#30368" msgid "Default" msgstr "Prezgjedhuar" msgctxt "#30510" msgid "Recordings" msgstr "Rregjistrime" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.sr_rs/000077500000000000000000000000001355512543200260235ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.sr_rs/strings.po000066400000000000000000000201741355512543200300600ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Подешавања повезивања" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend hostname или IP адреса" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP порт" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP порт" msgctxt "#30004" msgid "Username" msgstr "Корисничко име" msgctxt "#30005" msgid "Password" msgstr "Лозинка" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Истек времена за повезивање (секунде)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Истек времена за одзив (секунде)" msgctxt "#30008" msgid "Advanced settings" msgstr "Напредна подешавања" msgctxt "#30009" msgid "Streaming settings" msgstr "Подешавања стримовања" msgctxt "#30010" msgid "Timer settings" msgstr "Подешавања тајмера" msgctxt "#30050" msgid "Auto recordings" msgstr "Аутоматска снимања" msgctxt "#30051" msgid "Start time window calculation" msgstr "Започни прорачун временског прозора" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Строг (време почетка + време краја)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Лежеран (време почетка +/- маргина)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Максимална маргина времена почетка (минути)" msgctxt "#30055" msgid "Default priority" msgstr "Подразумеван приоритет" msgctxt "#30056" msgid "Default lifetime" msgstr "Подразумеван животни век" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Подразумевано откривање дупликата" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Подразумевано за нове тајмере" msgctxt "#30100" msgid "Data transfer" msgstr "Пренос података" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Асинхрони EPG пренос" msgctxt "#30200" msgid "Debugging" msgstr "Тражење грешака" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Прати (детаљно)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Непоклапање HTSP верзије (подржане: v%d, потребне: v%d). Молимо, ажурирајте tvheadend." msgctxt "#30351" msgid "Important (Highest)" msgstr "Важно (Највише)" msgctxt "#30352" msgid "High" msgstr "Високо" msgctxt "#30353" msgid "Normal" msgstr "Нормално" msgctxt "#30354" msgid "Low" msgstr "Ниско" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Неважно (Најниже)" msgctxt "#30356" msgid "Record all episodes" msgstr "Сними све епизоде" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Сними ако је број епизоде различит" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Сними ако је име епизоде различито" msgctxt "#30359" msgid "Record if description differs" msgstr "Сними ако је опис различит" msgctxt "#30360" msgid "Record max once per week" msgstr "Сними максимално једном недељно" msgctxt "#30361" msgid "Record max once per day" msgstr "Сними максимално једном дневно" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Само ово правило: Снимај ако је различит број епизоде" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Само ово правило: Снимај ако је различито име епизоде" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Само ово правило: Снимај ако је наслов различит" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Само ово правило: Снимај ако је опис различит" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Само ово правило: Снимај максимално једном недељно" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Само ово правило: Снимај максимално једном дневно" msgctxt "#30368" msgid "Default" msgstr "Подразумевана" msgctxt "#30373" msgid "Until space needed" msgstr "Док простор није потребан" msgctxt "#30374" msgid "Forever" msgstr "Заувек" msgctxt "#30375" msgid "1 day" msgstr "1 дан" msgctxt "#30376" msgid "3 days" msgstr "3 дана" msgctxt "#30377" msgid "5 days" msgstr "5 дана" msgctxt "#30378" msgid "1 week" msgstr "1 недеља" msgctxt "#30379" msgid "2 weeks" msgstr "2 недеље" msgctxt "#30380" msgid "3 weeks" msgstr "3 недеље" msgctxt "#30381" msgid "1 month" msgstr "1 месец" msgctxt "#30382" msgid "2 months" msgstr "2 месеца" msgctxt "#30383" msgid "3 months" msgstr "3 месеца" msgctxt "#30384" msgid "6 months" msgstr "6 месеци" msgctxt "#30385" msgid "1 year" msgstr "1 година" msgctxt "#30386" msgid "2 years" msgstr "2 године" msgctxt "#30387" msgid "3 years" msgstr "3 године" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Док простор није потребан (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Заувек (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Предиктивни пријем" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Број претплата за коришћење" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Одлагање затварања некоришћених претплата (секунде)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Користи предиктиван пријем за убрзање промене канала" msgctxt "#30450" msgid "No free adapter available" msgstr "Ниједан слободан адаптер није доступан" msgctxt "#30451" msgid "Scrambled channel" msgstr "Кодиран канал" msgctxt "#30452" msgid "No signal" msgstr "Нема сигнала" msgctxt "#30453" msgid "Tuning failed" msgstr "Пријем није успео" msgctxt "#30454" msgid "User limit reached" msgstr "Достигнут лимит корисника" msgctxt "#30455" msgid "No access" msgstr "Нема приступа" msgctxt "#30456" msgid "Subscription error" msgstr "Грешка претплате" msgctxt "#30500" msgid "Streaming profile" msgstr "Профил стримовања" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Профил за коришћење (празно = подразумевано)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Профил стримовања %s није доступан" msgctxt "#30503" msgid "Data transfer" msgstr "Пренос података" msgctxt "#30510" msgid "Recordings" msgstr "Снимци" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.sr_rs@latin/000077500000000000000000000000001355512543200271535ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.sr_rs@latin/strings.po000066400000000000000000000154341355512543200312130ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Podešavanja povezivanja" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend hostname ili IP adresa" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP port" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP port" msgctxt "#30004" msgid "Username" msgstr "Korisničko ime" msgctxt "#30005" msgid "Password" msgstr "Lozinka" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Istek vremena za povezivanje (sekunde)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Istek vremena za odziv (sekunde)" msgctxt "#30008" msgid "Advanced settings" msgstr "Napredna podešavanja" msgctxt "#30009" msgid "Streaming settings" msgstr "Podešavanja strimovanja" msgctxt "#30010" msgid "Timer settings" msgstr "Podešavanja tajmera" msgctxt "#30050" msgid "Auto recordings" msgstr "Automatska snimanja" msgctxt "#30051" msgid "Start time window calculation" msgstr "Započni proračun vremenskog prozora" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Strog (vreme početka + vreme kraja)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Ležeran (vreme početka +/- margina)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Maksimalna margina vremena početka (minuti)" msgctxt "#30055" msgid "Default priority" msgstr "Podrazumevan prioritet" msgctxt "#30056" msgid "Default lifetime" msgstr "Podrazumevan životni vek" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Podrazumevano otkrivanje duplikata" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Podrazumevano za nove tajmere" msgctxt "#30100" msgid "Data transfer" msgstr "Prenos podataka" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asinhroni EPG prenos" msgctxt "#30200" msgid "Debugging" msgstr "Traženje grešaka" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Prati (detaljno)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Nepoklapanje HTSP verzije (podržane: v%d, potrebne: v%d). Molimo, ažurirajte tvheadend." msgctxt "#30351" msgid "Important (Highest)" msgstr "Važno (Najviše)" msgctxt "#30352" msgid "High" msgstr "Jak" msgctxt "#30353" msgid "Normal" msgstr "Normalno" msgctxt "#30354" msgid "Low" msgstr "Slab" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Nevažno (Najniže)" msgctxt "#30356" msgid "Record all episodes" msgstr "Snimi sve epizode" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Snimi ako je broj epizode različit" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Snimi ako je ime epizode različito" msgctxt "#30359" msgid "Record if description differs" msgstr "Snimi ako je opis različit" msgctxt "#30360" msgid "Record max once per week" msgstr "Snimi maksimalno jednom nedeljno" msgctxt "#30361" msgid "Record max once per day" msgstr "Snimi maksimalno jednom dnevno" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Samo ovo pravilo: Snimaj ako je različit broj epizode" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Samo ovo pravilo: Snimaj ako je različito ime epizode" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Samo ovo pravilo: Snimaj ako je naslov različit" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Samo ovo pravilo: Snimaj ako je opis različit" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Samo ovo pravilo: Snimaj maksimalno jednom nedeljno" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Samo ovo pravilo: Snimaj maksimalno jednom dnevno" msgctxt "#30368" msgid "Default" msgstr "Podrazumevana" msgctxt "#30373" msgid "Until space needed" msgstr "Dok prostor nije potreban" msgctxt "#30374" msgid "Forever" msgstr "Zauvek" msgctxt "#30375" msgid "1 day" msgstr "1 dan" msgctxt "#30376" msgid "3 days" msgstr "3 dana" msgctxt "#30377" msgid "5 days" msgstr "5 dana" msgctxt "#30378" msgid "1 week" msgstr "1 nedelja" msgctxt "#30379" msgid "2 weeks" msgstr "2 nedelje" msgctxt "#30380" msgid "3 weeks" msgstr "3 nedelje" msgctxt "#30381" msgid "1 month" msgstr "1 mesec" msgctxt "#30382" msgid "2 months" msgstr "2 meseca" msgctxt "#30383" msgid "3 months" msgstr "3 meseca" msgctxt "#30384" msgid "6 months" msgstr "6 meseci" msgctxt "#30385" msgid "1 year" msgstr "1 godina" msgctxt "#30386" msgid "2 years" msgstr "2 godine" msgctxt "#30387" msgid "3 years" msgstr "3 godine" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Dok prostor nije potreban (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Zauvek (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Prediktivni prijem" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Broj pretplata za korišćenje" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Odlaganje zatvaranja nekorišćenih pretplata (sekunde)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Koristi prediktivan prijem za ubrzanje promene kanala" msgctxt "#30450" msgid "No free adapter available" msgstr "Nijedan slobodan adapter nije dostupan" msgctxt "#30451" msgid "Scrambled channel" msgstr "Kodiran kanal" msgctxt "#30452" msgid "No signal" msgstr "Nema signala" msgctxt "#30453" msgid "Tuning failed" msgstr "Prijem nije uspeo" msgctxt "#30454" msgid "User limit reached" msgstr "Dostignut limit korisnika" msgctxt "#30455" msgid "No access" msgstr "Nema pristupa" msgctxt "#30456" msgid "Subscription error" msgstr "Greška pretplate" msgctxt "#30500" msgid "Streaming profile" msgstr "Profil strimovanja" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profil za korišćenje (prazno = podrazumevano)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Profil strimovanja %s nije dostupan" msgctxt "#30503" msgid "Data transfer" msgstr "Prenos podataka" msgctxt "#30510" msgid "Recordings" msgstr "Snimci" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.sv_se/000077500000000000000000000000001355512543200260125ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.sv_se/strings.po000066400000000000000000000171251355512543200300510ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Anslutningsinställningar" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend värdnamn eller IP-adress" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP-port" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP-port" msgctxt "#30004" msgid "Username" msgstr "Användarnamn" msgctxt "#30005" msgid "Password" msgstr "Lösenord" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Anslutningstimeout (sekunder)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Responstimeout (sekunder)" msgctxt "#30008" msgid "Advanced settings" msgstr "Avancerade inställningar" msgctxt "#30009" msgid "Streaming settings" msgstr "Ströminställningar" msgctxt "#30010" msgid "Timer settings" msgstr "TimerInställningar" msgctxt "#30050" msgid "Auto recordings" msgstr "Autoinspelningar" msgctxt "#30051" msgid "Start time window calculation" msgstr "Starta beräkning av tidsfönster" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Strikt (starttid + sluttid)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Avslappnad (starttid +/- marginal)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Maximal marginal för starttid (minuter)" msgctxt "#30055" msgid "Default priority" msgstr "Standardprioritet" msgctxt "#30056" msgid "Default lifetime" msgstr "Standardlivstid" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Standard dubblett detektering" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Standard för nya timers" msgctxt "#30059" msgid "Scheduled recordings" msgstr "Schemalagda inspelningar" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "Ignorera dubbletter (tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "Dataöverföring" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asynkron EPG-överföring" msgctxt "#30200" msgid "Debugging" msgstr "Debuggning" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Spåra (detaljerad)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP-versionen överensstämmer inte (stöds: v%d, krävs: v%d). Vänligen uppdatera tvheadend." msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "En gång (Schemalagd enligt timerregeln)" msgctxt "#30351" msgid "Important (Highest)" msgstr "Viktigt (Högsta)" msgctxt "#30352" msgid "High" msgstr "Hög" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Låg" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Oviktigt (Lägsta)" msgctxt "#30356" msgid "Record all episodes" msgstr "Spela in alla avsnitt" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Spela in om avsnittsnumret skiljer sig" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Spela in om avsnittsnamnet skiljer sig" msgctxt "#30359" msgid "Record if description differs" msgstr "Spela in om beskrivning skiljer sig" msgctxt "#30360" msgid "Record max once per week" msgstr "Spela in max en gång per vecka" msgctxt "#30361" msgid "Record max once per day" msgstr "Spela in max en gång per dag" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "Endast denna ragel: Spela in om avsnittsnumret skiljer sig" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "Endast denna ragel: Spela in om avsnittsnamnet skiljer sig" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "Endast denna ragel: Spela in om titel skiljer sig" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "Endast denna ragel: Spela in om beskrivning skiljer sig" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "Endast denna ragel: Spela in max en gång per vecka" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "Endast denna ragel: Spela in max en gång per dag" msgctxt "#30368" msgid "Default" msgstr "Standard" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "Timerregel (serie länk)" msgctxt "#30370" msgid "Record max once per month" msgstr "Spela in max en gång per månad" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "Endast denna regel: Spela in max en gång per månad" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "Spela in om unik episod enligt EPG/XMLTV" msgctxt "#30373" msgid "Until space needed" msgstr "Tills utrymme krävs" msgctxt "#30374" msgid "Forever" msgstr "För alltid" msgctxt "#30375" msgid "1 day" msgstr "1 dag" msgctxt "#30376" msgid "3 days" msgstr "3 dagar" msgctxt "#30377" msgid "5 days" msgstr "5 dagar" msgctxt "#30378" msgid "1 week" msgstr "1 vecka" msgctxt "#30379" msgid "2 weeks" msgstr "2 veckor" msgctxt "#30380" msgid "3 weeks" msgstr "3 veckor" msgctxt "#30381" msgid "1 month" msgstr "1 månad" msgctxt "#30382" msgid "2 months" msgstr "2 månader" msgctxt "#30383" msgid "3 months" msgstr "3 månader" msgctxt "#30384" msgid "6 months" msgstr "6 månader" msgctxt "#30385" msgid "1 year" msgstr "1 år" msgctxt "#30386" msgid "2 years" msgstr "2 år" msgctxt "#30387" msgid "3 years" msgstr "3 år" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Tills utrymme behövs (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "För alltid (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Förutspå förinställning" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Antal abonnemang att använda" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Oanvänd abonnemang stängningsfördröjning (sekunder)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Använd automatisk avstämning för att påskynda kanalbyte" msgctxt "#30450" msgid "No free adapter available" msgstr "Ingen fri adapter tillgänglig" msgctxt "#30451" msgid "Scrambled channel" msgstr "Kodad kanal" msgctxt "#30452" msgid "No signal" msgstr "Ingen signal" msgctxt "#30453" msgid "Tuning failed" msgstr "Förinställning misslyckades" msgctxt "#30454" msgid "User limit reached" msgstr "Användargräns nådd" msgctxt "#30455" msgid "No access" msgstr "Ingen tillgång" msgctxt "#30456" msgid "Subscription error" msgstr "Prenumerationsfel" msgctxt "#30500" msgid "Streaming profile" msgstr "Streamingprofil" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Profil att använda (tom = standard)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Streamingprofil %s är inte tillänglig" msgctxt "#30503" msgid "Data transfer" msgstr "Dataöverföring" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "Segmentstorlek på strömläsningar vid inspelningar (KB)" msgctxt "#30510" msgid "Recordings" msgstr "Inspelningar" msgctxt "#30511" msgid "Server based play status" msgstr "Serverbaserad spelstatus" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.szl/000077500000000000000000000000001355512543200255035ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.szl/strings.po000066400000000000000000000141441355512543200275400ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Sztelōnki skuplowaniŏ" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Miano ôd hosta Tvheadend abo ôd niygo adresa IP" msgctxt "#30002" msgid "HTTP port" msgstr "Port HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Port HTSP" msgctxt "#30004" msgid "Username" msgstr "Miano ôd używŏcza" msgctxt "#30005" msgid "Password" msgstr "Hasło" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Czŏs na kuplowanie (sekōndy)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "Limit czŏsu ôdpowiydzi (sekundy)" msgctxt "#30008" msgid "Advanced settings" msgstr "Sztelōnki ekszperta" msgctxt "#30009" msgid "Streaming settings" msgstr "Sztelōnki szpricowaniŏ" msgctxt "#30010" msgid "Timer settings" msgstr "Sztelōnki minutnika" msgctxt "#30050" msgid "Auto recordings" msgstr "Nagrowanie autōmatyczne" msgctxt "#30051" msgid "Start time window calculation" msgstr "Rachowanie ôkna czŏsu napoczyńciŏ" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Sztram (czŏs zaczōntku + czŏs kōńca)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Frajny (czŏs zaczōntku +/- margines)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "Nagrowej przed ôbcyrklowanym czŏsym zaczōntku (minuty)" msgctxt "#30055" msgid "Default priority" msgstr "Wychodny priorytet" msgctxt "#30056" msgid "Default lifetime" msgstr "Wychodny czŏs życiŏ" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Wychodnŏ detekcyjŏ tuplikatōw" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Wychodne dlŏ nowych auftragōw" msgctxt "#30100" msgid "Data transfer" msgstr "Transfer danych" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Niysynchrōniczny przekŏz EPG" msgctxt "#30200" msgid "Debugging" msgstr "Debugowaniy" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Szlakować (akuratne)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Niynŏleżnŏ wersyjŏ HTSP (ôbsugowanŏ: v%d, fołdrowanŏ: v%d). Zaktualizuj program tvheadend." msgctxt "#30351" msgid "Important (Highest)" msgstr "Wŏżnŏ (Nŏjzwielgszŏ)" msgctxt "#30352" msgid "High" msgstr "Wysokŏ" msgctxt "#30353" msgid "Normal" msgstr "Ôbyczajny" msgctxt "#30354" msgid "Low" msgstr "min." msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Niywŏżnŏ (Nŏjniższŏ)" msgctxt "#30356" msgid "Record all episodes" msgstr "Nagrowej wszyjske party" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Nagrowej jeźli numer partu je inkszy" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Nagrowej jeźli miano partu je inksze" msgctxt "#30359" msgid "Record if description differs" msgstr "Nagrowej jeźli ôpis je inkszy" msgctxt "#30360" msgid "Record max once per week" msgstr "Nagrowej maksymalnie rŏz na tydziyń" msgctxt "#30361" msgid "Record max once per day" msgstr "Nagrowej maksymalnie rŏz na dziyń" msgctxt "#30368" msgid "Default" msgstr "Wychodne" msgctxt "#30373" msgid "Until space needed" msgstr "Aż braknie placu" msgctxt "#30374" msgid "Forever" msgstr "Dycki" msgctxt "#30375" msgid "1 day" msgstr "1 dziyń" msgctxt "#30376" msgid "3 days" msgstr "3 dni" msgctxt "#30377" msgid "5 days" msgstr "5 dni" msgctxt "#30378" msgid "1 week" msgstr "1 tydziyń" msgctxt "#30379" msgid "2 weeks" msgstr "2 tydni" msgctxt "#30380" msgid "3 weeks" msgstr "3 tydni" msgctxt "#30381" msgid "1 month" msgstr "1 miesiōnc" msgctxt "#30382" msgid "2 months" msgstr "2 miesiōnce" msgctxt "#30383" msgid "3 months" msgstr "3 miesiōnce" msgctxt "#30384" msgid "6 months" msgstr "6 miesiyncy" msgctxt "#30385" msgid "1 year" msgstr "1 rok" msgctxt "#30386" msgid "2 years" msgstr "2 lata" msgctxt "#30387" msgid "3 years" msgstr "3 lata" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Aż braknie przestrzyństwa (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Bez kōńca (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Stympne dostrajanie" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Numer subskrypcyje we użyciu" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Zniyskorzynie zawiyraniŏ niyużywanych subskrypcyji (sekundy)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Używej wstympnygo dostrãjaniŏ, coby zrychlić szaltrowanie kanałōw" msgctxt "#30450" msgid "No free adapter available" msgstr "Niy ma swobodnych adapterów" msgctxt "#30451" msgid "Scrambled channel" msgstr "Kanał zakodowany" msgctxt "#30452" msgid "No signal" msgstr "Niy ma sygnału" msgctxt "#30453" msgid "Tuning failed" msgstr "Niypodarzōne dostrŏjanie" msgctxt "#30454" msgid "User limit reached" msgstr "Przestōmpiōny limit używŏczōw" msgctxt "#30455" msgid "No access" msgstr "Niy ma dostympu" msgctxt "#30456" msgid "Subscription error" msgstr "Feler subskrypcyje" msgctxt "#30500" msgid "Streaming profile" msgstr "Profil szpricowaniŏ" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Używany profil (prōżny = wychodny)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Profil szpricowaniŏ %s niydostympny" msgctxt "#30503" msgid "Data transfer" msgstr "Transfer danych" msgctxt "#30510" msgid "Recordings" msgstr "Spamiyntania" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ta_in/000077500000000000000000000000001355512543200257655ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.ta_in/strings.po000066400000000000000000000031231355512543200300150ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend பின்தள புரவலன் பெயர் அல்லது ஐபி" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP துறை" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP துறை" msgctxt "#30004" msgid "Username" msgstr "பயனர்பெயர்" msgctxt "#30005" msgid "Password" msgstr "அடையாளச் சொல்" msgctxt "#30010" msgid "Timer settings" msgstr "நேர அமைப்புகள்" msgctxt "#30200" msgid "Debugging" msgstr "வழுநீக்கு" msgctxt "#30352" msgid "High" msgstr "அதிகம்" msgctxt "#30353" msgid "Normal" msgstr "வழக்கமான" msgctxt "#30354" msgid "Low" msgstr "குறைவு" msgctxt "#30368" msgid "Default" msgstr "இயல்புநிலை" msgctxt "#30510" msgid "Recordings" msgstr "பதிவகள்" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.te_in/000077500000000000000000000000001355512543200257715ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.te_in/strings.po000066400000000000000000000026121355512543200300230ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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: Telugu (India) (http://www.transifex.com/projects/p/kodi-main/language/te_IN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: te_IN\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend హోస్ట్ పేరు లేదా IP చిరునామా" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP పోర్ట్" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP పోర్ట్" msgctxt "#30004" msgid "Username" msgstr "వాడుకరి పేరు" msgctxt "#30005" msgid "Password" msgstr "సంకేతపదం" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "ఎసిన్క్రోనస్ EPG బదిలీ" msgctxt "#30200" msgid "Debugging" msgstr "డీబగ్గింగ్" msgctxt "#30201" msgid "Trace (detailed)" msgstr "ట్రేస్ (వివరణాత్మక)" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.tg_tj/000077500000000000000000000000001355512543200260025ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.tg_tj/strings.po000066400000000000000000000025631355512543200300410ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Суроғаи IP ва номи мизбони Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "Порти HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Порти HTSP" msgctxt "#30004" msgid "Username" msgstr "Номи корбар" msgctxt "#30005" msgid "Password" msgstr "Парол" msgctxt "#30200" msgid "Debugging" msgstr "Ислоҳи хатоҳо" msgctxt "#30352" msgid "High" msgstr "Баланд" msgctxt "#30353" msgid "Normal" msgstr "Оддӣ" msgctxt "#30354" msgid "Low" msgstr "Паст" msgctxt "#30368" msgid "Default" msgstr "Пешфарз" msgctxt "#30510" msgid "Recordings" msgstr "Сабтҳо" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.th_th/000077500000000000000000000000001355512543200260015ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.th_th/strings.po000066400000000000000000000026111355512543200300320ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30004" msgid "Username" msgstr "ชื่อผู้ใช้" msgctxt "#30005" msgid "Password" msgstr "รหัสผ่าน" msgctxt "#30010" msgid "Timer settings" msgstr "การตั้งค่าตัวจับเวลา" msgctxt "#30200" msgid "Debugging" msgstr "แก้จุดบกพร่อง" msgctxt "#30352" msgid "High" msgstr "สูง" msgctxt "#30353" msgid "Normal" msgstr "ปกติ" msgctxt "#30354" msgid "Low" msgstr "ต่ำ" msgctxt "#30356" msgid "Record all episodes" msgstr "บันทึกทุกตอน" msgctxt "#30368" msgid "Default" msgstr "ค่าพื้นฐาน" msgctxt "#30510" msgid "Recordings" msgstr "กำลังบันทึก" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.tr_tr/000077500000000000000000000000001355512543200260255ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.tr_tr/strings.po000066400000000000000000000137601355512543200300650ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "Bağlantı Ayarları" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend ana bilgisayar adı veya IP adresi" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP bağlantı noktası" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP bağlantı noktası" msgctxt "#30004" msgid "Username" msgstr "Kullanıcı adı" msgctxt "#30005" msgid "Password" msgstr "Parola" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Bağlantı zaman aşımı (saniye)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "yanıt zaman aşımı (saniye)" msgctxt "#30008" msgid "Advanced settings" msgstr "Gelişmiş Ayarlar" msgctxt "#30009" msgid "Streaming settings" msgstr "Akış ayarları" msgctxt "#30010" msgid "Timer settings" msgstr "Zamanlayıcı ayarları" msgctxt "#30050" msgid "Auto recordings" msgstr "Otomatik Kayıtlar" msgctxt "#30051" msgid "Start time window calculation" msgstr "Başlangıç zamanı pencere hesaplaması" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "Kesin (başlangıç zamanı + bitiş zamanı)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "Gevşek (başlangıç zamanı +/- ihtiyat payı)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "En fazla başlangıç zamanı ihtiyat payı (dakika)" msgctxt "#30055" msgid "Default priority" msgstr "Varsayılan öncelik" msgctxt "#30056" msgid "Default lifetime" msgstr "Varsayılan ömür" msgctxt "#30057" msgid "Default duplicate detection" msgstr "Varsayılan kopya tespiti" msgctxt "#30058" msgid "Defaults for new timers" msgstr "Yeni zamanlayıcılar için varsayılanlar" msgctxt "#30100" msgid "Data transfer" msgstr "Bilgi Transferi" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Eşzamanlı olmayan EPG aktarımı" msgctxt "#30200" msgid "Debugging" msgstr "Hata ayıklama" msgctxt "#30201" msgid "Trace (detailed)" msgstr "İz (ayrıntılı)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP sürümü uyuşmadı (desteklenen: v%d, gereken: v%d). Lütfen tvheadend'i güncelleyin." msgctxt "#30351" msgid "Important (Highest)" msgstr "Önemli (En Yüksek)" msgctxt "#30352" msgid "High" msgstr "Yüksek" msgctxt "#30353" msgid "Normal" msgstr "Normal" msgctxt "#30354" msgid "Low" msgstr "Düşük" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "Önemsiz (En düşük)" msgctxt "#30356" msgid "Record all episodes" msgstr "Tüm bölümleri kaydet" msgctxt "#30357" msgid "Record if episode number differs" msgstr "Bölüm Numarası Farklıysa Kaydet" msgctxt "#30358" msgid "Record if episode name differs" msgstr "Bölüm Adı Farklıysa Kaydet" msgctxt "#30359" msgid "Record if description differs" msgstr "Açıklama Farklıysa kaydet" msgctxt "#30360" msgid "Record max once per week" msgstr "Haftada Bir Kez Kaydet" msgctxt "#30361" msgid "Record max once per day" msgstr "Günde Bir Kez Kaydet" msgctxt "#30368" msgid "Default" msgstr "Varsayılan" msgctxt "#30373" msgid "Until space needed" msgstr "Boşluk gerekene kadar" msgctxt "#30374" msgid "Forever" msgstr "Sonsuza dek" msgctxt "#30375" msgid "1 day" msgstr "1 gün" msgctxt "#30376" msgid "3 days" msgstr "3 gün" msgctxt "#30377" msgid "5 days" msgstr "5 gün" msgctxt "#30378" msgid "1 week" msgstr "Bir hafta" msgctxt "#30379" msgid "2 weeks" msgstr "2 hafta" msgctxt "#30380" msgid "3 weeks" msgstr "3 hafta" msgctxt "#30381" msgid "1 month" msgstr "Bir ay" msgctxt "#30382" msgid "2 months" msgstr "2 ay" msgctxt "#30383" msgid "3 months" msgstr "3 ay" msgctxt "#30384" msgid "6 months" msgstr "6 ay" msgctxt "#30385" msgid "1 year" msgstr "Bir yıl" msgctxt "#30386" msgid "2 years" msgstr "2 yıl" msgctxt "#30387" msgid "3 years" msgstr "3 yıl" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "Boş alan gerekene kadar (tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "Sonsuza dek (tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "Öngörüsel ayarlama" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "Kullanılacak abonelik sayısı" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "Kullanılmayan aboneliğin sonlandırılma mühleti (saniye)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "Kanal geçişlerini hızlandırmak için öngörüsel ayarlama kullan" msgctxt "#30450" msgid "No free adapter available" msgstr "Boşta adaptör yok" msgctxt "#30451" msgid "Scrambled channel" msgstr "Şifreli kanal" msgctxt "#30452" msgid "No signal" msgstr "Sinyal Yok" msgctxt "#30453" msgid "Tuning failed" msgstr "İstasyon ayarlama başarısız oldu" msgctxt "#30454" msgid "User limit reached" msgstr "Kullanıcı Sayısı Limitine Erişildi" msgctxt "#30455" msgid "No access" msgstr "Yetkiniz Yok" msgctxt "#30456" msgid "Subscription error" msgstr "Abonelik hatası" msgctxt "#30500" msgid "Streaming profile" msgstr "Akış profili" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "Kullanılacak profil (boş = varsayılan)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "Akış profili %s mevcut değil" msgctxt "#30503" msgid "Data transfer" msgstr "Bilgi Transferi" msgctxt "#30510" msgid "Recordings" msgstr "Kayıtlar" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.uk_ua/000077500000000000000000000000001355512543200257775ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.uk_ua/strings.po000066400000000000000000000035411355512543200300330ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Ім'я серверу Tvheadend або його IP адреса" msgctxt "#30002" msgid "HTTP port" msgstr "Порт HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Порт HTSP" msgctxt "#30004" msgid "Username" msgstr "Ім'я користувача" msgctxt "#30005" msgid "Password" msgstr "Пароль" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "Тайм-аут з'єднання (секунди)" msgctxt "#30008" msgid "Advanced settings" msgstr "Розширені налаштування" msgctxt "#30010" msgid "Timer settings" msgstr "Налаштування таймера" msgctxt "#30200" msgid "Debugging" msgstr "Налагодження" msgctxt "#30352" msgid "High" msgstr "Макс." msgctxt "#30353" msgid "Normal" msgstr "Нормальне" msgctxt "#30354" msgid "Low" msgstr "Мін." msgctxt "#30356" msgid "Record all episodes" msgstr "Записати усі серії" msgctxt "#30368" msgid "Default" msgstr "Як усталено" msgctxt "#30510" msgid "Recordings" msgstr "Записи" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.uz_uz/000077500000000000000000000000001355512543200260475ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.uz_uz/strings.po000066400000000000000000000016541355512543200301060ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30004" msgid "Username" msgstr "Foydalanuvchi nomi" msgctxt "#30005" msgid "Password" msgstr "Maxfiy so'z" msgctxt "#30352" msgid "High" msgstr "Yuqori" msgctxt "#30354" msgid "Low" msgstr "Past" msgctxt "#30368" msgid "Default" msgstr "Andoza" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.vi_vn/000077500000000000000000000000001355512543200260145ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.vi_vn/strings.po000066400000000000000000000025221355512543200300460ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tên miền hoặc địa chỉ IP của Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "Cổng HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Cổng HTSP" msgctxt "#30004" msgid "Username" msgstr "Tên truy nhập" msgctxt "#30005" msgid "Password" msgstr "Mật khẩu" msgctxt "#30200" msgid "Debugging" msgstr "Tìm sửa lỗi" msgctxt "#30352" msgid "High" msgstr "Cao" msgctxt "#30353" msgid "Normal" msgstr "Bình thường" msgctxt "#30354" msgid "Low" msgstr "Thấp" msgctxt "#30368" msgid "Default" msgstr "Mặc định" msgctxt "#30510" msgid "Recordings" msgstr "Các bản ghi" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.zh_cn/000077500000000000000000000000001355512543200257745ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.zh_cn/strings.po000066400000000000000000000162221355512543200300300ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "连接设置" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend 主机名或 IP 地址" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP 端口" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP 端口" msgctxt "#30004" msgid "Username" msgstr "用户名" msgctxt "#30005" msgid "Password" msgstr "密码" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "连接超时(秒)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "响应超时(秒)" msgctxt "#30008" msgid "Advanced settings" msgstr "高级设置" msgctxt "#30009" msgid "Streaming settings" msgstr "流设置" msgctxt "#30010" msgid "Timer settings" msgstr "定时器设置" msgctxt "#30050" msgid "Auto recordings" msgstr "自动录像" msgctxt "#30051" msgid "Start time window calculation" msgstr "开始时间窗口计算" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "严格(开始时间+结束时间)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "宽松(开始时间+/-余量)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "最大开始时间余量(分钟)" msgctxt "#30055" msgid "Default priority" msgstr "默认优先级" msgctxt "#30056" msgid "Default lifetime" msgstr "默认生命期" msgctxt "#30057" msgid "Default duplicate detection" msgstr "默认重复检测" msgctxt "#30058" msgid "Defaults for new timers" msgstr "新定时器默认值" msgctxt "#30059" msgid "Scheduled recordings" msgstr "预约录像" msgctxt "#30060" msgid "Ignore duplicates (tvh 4.3+)" msgstr "忽略重复(tvh 4.3+)" msgctxt "#30100" msgid "Data transfer" msgstr "数据传输" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "异步电子节目单传输" msgctxt "#30200" msgid "Debugging" msgstr "调试" msgctxt "#30201" msgid "Trace (detailed)" msgstr "跟踪(细节)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP 版本不匹配(支持:v%d,需要:v%d)。请升级 tvheadend。" msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "单次(由定时器规则计划)" msgctxt "#30351" msgid "Important (Highest)" msgstr "重要(最高)" msgctxt "#30352" msgid "High" msgstr "高" msgctxt "#30353" msgid "Normal" msgstr "正常" msgctxt "#30354" msgid "Low" msgstr "低" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "不重要(最低)" msgctxt "#30356" msgid "Record all episodes" msgstr "录制所有分集" msgctxt "#30357" msgid "Record if episode number differs" msgstr "录制集号不同的" msgctxt "#30358" msgid "Record if episode name differs" msgstr "录制集名不同的" msgctxt "#30359" msgid "Record if description differs" msgstr "录制描述不同的" msgctxt "#30360" msgid "Record max once per week" msgstr "每周最多录制一次" msgctxt "#30361" msgid "Record max once per day" msgstr "每天最多录制一次" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "仅此规则:如果剧集号不同则录制" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "仅此规则:如果剧集名不同则录制" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "仅此规则:如果标题不同则录制" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "仅此规则:如果描述不同则录制" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "仅此规则:每周最多录制一次" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "仅此规则:每天最多录制一次" msgctxt "#30368" msgid "Default" msgstr "默认" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "定时器规则(系列链接)" msgctxt "#30370" msgid "Record max once per month" msgstr "每月最多录制一次" msgctxt "#30371" msgid "This rule only: Record max once per month" msgstr "仅此规则:每月最多录制一次" msgctxt "#30372" msgid "Record if unique episode according EPG/XMLTV" msgstr "如果根据 EPG/XMLTV 为唯一的剧集则录制" msgctxt "#30373" msgid "Until space needed" msgstr "直到需要空间" msgctxt "#30374" msgid "Forever" msgstr "永远" msgctxt "#30375" msgid "1 day" msgstr "1 天" msgctxt "#30376" msgid "3 days" msgstr "3 天" msgctxt "#30377" msgid "5 days" msgstr "5 天" msgctxt "#30378" msgid "1 week" msgstr "1 周" msgctxt "#30379" msgid "2 weeks" msgstr "2 周" msgctxt "#30380" msgid "3 weeks" msgstr "3 周" msgctxt "#30381" msgid "1 month" msgstr "1 月" msgctxt "#30382" msgid "2 months" msgstr "2 月" msgctxt "#30383" msgid "3 months" msgstr "3 月" msgctxt "#30384" msgid "6 months" msgstr "6 月" msgctxt "#30385" msgid "1 year" msgstr "1 年" msgctxt "#30386" msgid "2 years" msgstr "2 年" msgctxt "#30387" msgid "3 years" msgstr "3 年" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "直到需要空间(tvh 4.1+)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "永远(tvh 4.1+)" msgctxt "#30400" msgid "Predictive tuning" msgstr "预测调台" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "使用订阅数" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "未使用的订阅关闭延时(秒)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "使用预测调台加快频道切换" msgctxt "#30450" msgid "No free adapter available" msgstr "无可用适配器" msgctxt "#30451" msgid "Scrambled channel" msgstr "加密频道" msgctxt "#30452" msgid "No signal" msgstr "无信号" msgctxt "#30453" msgid "Tuning failed" msgstr "调台失败" msgctxt "#30454" msgid "User limit reached" msgstr "达到用户限制" msgctxt "#30455" msgid "No access" msgstr "无访问" msgctxt "#30456" msgid "Subscription error" msgstr "订阅错误" msgctxt "#30500" msgid "Streaming profile" msgstr "流媒体配置" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "使用配置(空 =默认)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "流媒体配置 %s 不可用" msgctxt "#30503" msgid "Data transfer" msgstr "数据传输" msgctxt "#30504" msgid "Stream read chunk size for recordings (KB)" msgstr "录制过程中媒体流读取块大小(KB)" msgctxt "#30510" msgid "Recordings" msgstr "录像" msgctxt "#30511" msgid "Server based play status" msgstr "基于服务器的播放状态" pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.zh_tw/000077500000000000000000000000001355512543200260265ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/pvr.hts/resources/language/resource.language.zh_tw/strings.po000066400000000000000000000152251355512543200300640ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Tvheadend HTSP Client # Addon id: pvr.hts # Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp, Kai Sommerfeld 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 "Connection settings" msgstr "連接設定" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Tvheadend主機名稱或IP位址" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP連接埠" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP連接埠" msgctxt "#30004" msgid "Username" msgstr "帳號" msgctxt "#30005" msgid "Password" msgstr "密碼" msgctxt "#30006" msgid "Connection timeout (seconds)" msgstr "連接逾時 (秒)" msgctxt "#30007" msgid "Response timeout (seconds)" msgstr "回應逾時 (秒)" msgctxt "#30008" msgid "Advanced settings" msgstr "進階設定" msgctxt "#30009" msgid "Streaming settings" msgstr "串流設定" msgctxt "#30010" msgid "Timer settings" msgstr "計時器設定" msgctxt "#30050" msgid "Auto recordings" msgstr "自動錄影" msgctxt "#30051" msgid "Start time window calculation" msgstr "開始時間計算視窗" msgctxt "#30052" msgid "Strict (start time + end time)" msgstr "精確 (開始時間 + 結束時間)" msgctxt "#30053" msgid "Relaxed (start time +/- margin)" msgstr "粗略 (開始時間 +/- 緩衝空間)" msgctxt "#30054" msgid "Maximum start time margin (minutes)" msgstr "最大的開始時間緩衝值 (分)" msgctxt "#30055" msgid "Default priority" msgstr "預設優先權" msgctxt "#30056" msgid "Default lifetime" msgstr "預設的生命週期" msgctxt "#30057" msgid "Default duplicate detection" msgstr "預設的重複偵測" msgctxt "#30058" msgid "Defaults for new timers" msgstr "新設計時器的預設值" msgctxt "#30100" msgid "Data transfer" msgstr "資料傳輸" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "非同步的電子節目表傳輸" msgctxt "#30200" msgid "Debugging" msgstr "除錯" msgctxt "#30201" msgid "Trace (detailed)" msgstr "追蹤 (詳細)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "HTSP版本不匹配 (支援:v%d, 最低:v%d)。請更新電視端程式。" msgctxt "#30350" msgid "One Time (Scheduled by timer rule)" msgstr "單次 (由定時器規則排程)" msgctxt "#30351" msgid "Important (Highest)" msgstr "重要 (最高)" msgctxt "#30352" msgid "High" msgstr "高" msgctxt "#30353" msgid "Normal" msgstr "一般" msgctxt "#30354" msgid "Low" msgstr "低" msgctxt "#30355" msgid "Unimportant (Lowest)" msgstr "不重要 (最低)" msgctxt "#30356" msgid "Record all episodes" msgstr "錄製全集" msgctxt "#30357" msgid "Record if episode number differs" msgstr "若影集編號不同則進行錄影" msgctxt "#30358" msgid "Record if episode name differs" msgstr "若影集名稱不同則進行錄影" msgctxt "#30359" msgid "Record if description differs" msgstr "若描述不同即進行錄影" msgctxt "#30360" msgid "Record max once per week" msgstr "每週單次錄影的最大值" msgctxt "#30361" msgid "Record max once per day" msgstr "每日單次錄影的最大值" msgctxt "#30362" msgid "This rule only: Record if episode number differs" msgstr "僅限本規則:集數不同即進行錄影" msgctxt "#30363" msgid "This rule only: Record if episode name differs" msgstr "僅限本規則:單集名稱不同即進行錄影" msgctxt "#30364" msgid "This rule only: Record if title differs" msgstr "僅限本規則:標題不同即進行錄影" msgctxt "#30365" msgid "This rule only: Record if description differs" msgstr "僅限本規則:敘述不同即進行錄影" msgctxt "#30366" msgid "This rule only: Record max once per week" msgstr "僅限本規則:每週最多錄一次" msgctxt "#30367" msgid "This rule only: Record max once per day" msgstr "僅限本規則:每天最多錄一次" msgctxt "#30368" msgid "Default" msgstr "預設" msgctxt "#30369" msgid "Timer rule (series link)" msgstr "定時器規則 (同系列的聯結)" msgctxt "#30373" msgid "Until space needed" msgstr "直到空間不足" msgctxt "#30374" msgid "Forever" msgstr "無限" msgctxt "#30375" msgid "1 day" msgstr "1天" msgctxt "#30376" msgid "3 days" msgstr "3天" msgctxt "#30377" msgid "5 days" msgstr "5天" msgctxt "#30378" msgid "1 week" msgstr "1週" msgctxt "#30379" msgid "2 weeks" msgstr "2週" msgctxt "#30380" msgid "3 weeks" msgstr "3週" msgctxt "#30381" msgid "1 month" msgstr "1個月" msgctxt "#30382" msgid "2 months" msgstr "2個月" msgctxt "#30383" msgid "3 months" msgstr "3個月" msgctxt "#30384" msgid "6 months" msgstr "6個月" msgctxt "#30385" msgid "1 year" msgstr "1年" msgctxt "#30386" msgid "2 years" msgstr "2年" msgctxt "#30387" msgid "3 years" msgstr "3年" msgctxt "#30388" msgid "Until space needed (tvh 4.1+)" msgstr "直到空間不足 (tvh 4.1以上)" msgctxt "#30389" msgid "Forever (tvh 4.1+)" msgstr "無限 (tvh 4.1以上)" msgctxt "#30400" msgid "Predictive tuning" msgstr "預知式轉台" msgctxt "#30401" msgid "Number of subscriptions to use" msgstr "使用的訂閱數量" msgctxt "#30402" msgid "Unused subscription close delay (seconds)" msgstr "未使用的訂閱內容關閉延遲 (秒)" msgctxt "#30403" msgid "Use predictive tuning to speedup channel switches" msgstr "使用預知式轉台來加速頻道轉換" msgctxt "#30450" msgid "No free adapter available" msgstr "沒有可用的連接介面" msgctxt "#30451" msgid "Scrambled channel" msgstr "加密頻道" msgctxt "#30452" msgid "No signal" msgstr "沒有訊號" msgctxt "#30453" msgid "Tuning failed" msgstr "轉台失敗" msgctxt "#30454" msgid "User limit reached" msgstr "已達使用者限量" msgctxt "#30455" msgid "No access" msgstr "不可存取" msgctxt "#30456" msgid "Subscription error" msgstr "訂閱錯誤" msgctxt "#30500" msgid "Streaming profile" msgstr "串流設定檔" msgctxt "#30501" msgid "Profile to use (empty = default)" msgstr "欲使用的設定檔 (瘤空 = 預設值)" msgctxt "#30502" msgid "Streaming profile %s is not available" msgstr "串流設定檔 %s 不可用" msgctxt "#30503" msgid "Data transfer" msgstr "資料傳輸" msgctxt "#30510" msgid "Recordings" msgstr "錄影檔" msgctxt "#30511" msgid "Server based play status" msgstr "伺服器端的播放狀態" pvr.hts-4.4.20-Leia/pvr.hts/resources/settings.xml000066400000000000000000000052031355512543200220620ustar00rootroot00000000000000 pvr.hts-4.4.20-Leia/src/000077500000000000000000000000001355512543200146515ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/src/Tvheadend.cpp000066400000000000000000002556051355512543200172740ustar00rootroot00000000000000/* * Copyright (C) 2005-2014 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 "Tvheadend.h" #include #include #include #include "tvheadend/HTSPConnection.h" #include "tvheadend/HTSPDemuxer.h" #include "tvheadend/HTSPMessage.h" #include "tvheadend/HTSPVFS.h" #include "tvheadend/Settings.h" #include "tvheadend/utilities/LifetimeMapper.h" #include "tvheadend/utilities/LocalizedString.h" #include "tvheadend/utilities/Logger.h" #include "tvheadend/utilities/Utilities.h" using namespace ADDON; using namespace P8PLATFORM; using namespace tvheadend; using namespace tvheadend::entity; using namespace tvheadend::utilities; CTvheadend::CTvheadend(PVR_PROPERTIES *pvrProps) : m_conn(new HTSPConnection(*this)), m_streamchange(false), m_vfs(new HTSPVFS(*m_conn)), m_queue((size_t)-1), m_asyncState(Settings::GetInstance().GetResponseTimeout()), m_timeRecordings(*m_conn), m_autoRecordings(*m_conn), m_epgMaxDays(pvrProps->iEpgMaxDays), m_playingLiveStream(false), m_playingRecording(nullptr) { for (int i = 0; i < 1 || i < Settings::GetInstance().GetTotalTuners(); i++) { m_dmx.emplace_back(new HTSPDemuxer(*m_conn)); } m_dmx_active = m_dmx[0]; } CTvheadend::~CTvheadend() { for (auto *dmx : m_dmx) delete dmx; delete m_conn; delete m_vfs; } void CTvheadend::Start ( void ) { CreateThread(); m_conn->Start(); } void CTvheadend::Stop ( void ) { for (auto *dmx : m_dmx) dmx->Close(); m_conn->Stop(); StopThread(0); } /* ************************************************************************** * Miscellaneous * *************************************************************************/ PVR_ERROR CTvheadend::GetDriveSpace ( long long *total, long long *used ) { int64_t s64; CLockObject lock(m_conn->Mutex()); htsmsg_t *m = htsmsg_create_map(); m = m_conn->SendAndWait("getDiskSpace", m); if (m == NULL) return PVR_ERROR_SERVER_ERROR; if (htsmsg_get_s64(m, "totaldiskspace", &s64)) goto error; *total = s64 / 1024; if (htsmsg_get_s64(m, "freediskspace", &s64)) goto error; *used = *total - (s64 / 1024); htsmsg_destroy(m); return PVR_ERROR_NO_ERROR; error: htsmsg_destroy(m); Logger::Log(LogLevel::LEVEL_ERROR, "malformed getDiskSpace response: 'totaldiskspace'/'freediskspace' missing"); return PVR_ERROR_SERVER_ERROR; } std::string CTvheadend::GetImageURL ( const char *str ) { if (*str != '/') { if (strncmp(str, "imagecache/", 11) == 0) return m_conn->GetWebURL("/%s", str); return str; } else { return m_conn->GetWebURL("%s", str); } } void CTvheadend::QueryAvailableProfiles() { /* Build message */ htsmsg_t *m = htsmsg_create_map(); /* Send */ { CLockObject lock(m_conn->Mutex()); m = m_conn->SendAndWait("getProfiles", m); } /* Validate */ if (m == nullptr) return; htsmsg_t *l; htsmsg_field_t *f; if ((l = htsmsg_get_list(m, "profiles")) == NULL) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed getProfiles: 'profiles' missing"); htsmsg_destroy(m); return; } /* Process */ HTSMSG_FOREACH(f, l) { const char *str; Profile profile; if ((str = htsmsg_get_str(&f->hmf_msg, "uuid")) != NULL) profile.SetUuid(str); if ((str = htsmsg_get_str(&f->hmf_msg, "name")) != NULL) profile.SetName(str); if ((str = htsmsg_get_str(&f->hmf_msg, "comment")) != NULL) profile.SetComment(str); Logger::Log(LogLevel::LEVEL_DEBUG, "profile name: %s, comment: %s added", profile.GetName().c_str(), profile.GetComment().c_str()); m_profiles.emplace_back(profile); } htsmsg_destroy(m); } bool CTvheadend::HasStreamingProfile(const std::string &streamingProfile) const { return std::find_if( m_profiles.cbegin(), m_profiles.cend(), [&streamingProfile](const Profile &profile) { return profile.GetName() == streamingProfile; } ) != m_profiles.cend(); } /* ************************************************************************** * Tags * *************************************************************************/ int CTvheadend::GetTagCount ( void ) { if (!m_asyncState.WaitForState(ASYNC_DVR)) return 0; CLockObject lock(m_mutex); return m_tags.size(); } PVR_ERROR CTvheadend::GetTags ( ADDON_HANDLE handle, bool bRadio ) { if (!m_asyncState.WaitForState(ASYNC_DVR)) return PVR_ERROR_FAILED; std::vector tags; { CLockObject lock(m_mutex); for (const auto &entry : m_tags) { /* Does group contain channels of the requested type? */ /* Note: tvheadend groups can contain both radio and tv channels. */ /* Thus, one tvheadend group can 'map' to two Kodi groups. */ if (!entry.second.ContainsChannelType(bRadio ? CHANNEL_TYPE_RADIO : CHANNEL_TYPE_TV, GetChannels())) continue; PVR_CHANNEL_GROUP tag = { 0 }; strncpy(tag.strGroupName, entry.second.GetName().c_str(), sizeof(tag.strGroupName) - 1); tag.bIsRadio = bRadio; tag.iPosition = entry.second.GetIndex(); tags.emplace_back(tag); } } std::vector::const_iterator it; for (it = tags.begin(); it != tags.end(); ++it) { /* Callback. */ PVR->TransferChannelGroup(handle, &(*it)); } return PVR_ERROR_NO_ERROR; } PVR_ERROR CTvheadend::GetTagMembers ( ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group ) { if (!m_asyncState.WaitForState(ASYNC_DVR)) return PVR_ERROR_FAILED; std::vector gms; { CLockObject lock(m_mutex); // Find the tag const auto it = std::find_if( m_tags.cbegin(), m_tags.cend(), [group](const TagMapEntry &tag) { return tag.second.GetName() == group.strGroupName; }); if (it != m_tags.cend()) { // Find all channels in this group that are of the correct type for (const auto &channelId : it->second.GetChannels()) { auto cit = m_channels.find(channelId); if (cit != m_channels.cend() && cit->second.GetType() == (group.bIsRadio ? CHANNEL_TYPE_RADIO : CHANNEL_TYPE_TV)) { PVR_CHANNEL_GROUP_MEMBER gm = { 0 }; strncpy( gm.strGroupName, group.strGroupName, sizeof(gm.strGroupName) - 1); gm.iChannelUniqueId = cit->second.GetId(); gm.iChannelNumber = cit->second.GetNum(); gm.iSubChannelNumber = cit->second.GetNumMinor(); gms.emplace_back(gm); } } } } std::vector::const_iterator it; for (it = gms.begin(); it != gms.end(); ++it) { /* Callback. */ PVR->TransferChannelGroupMember(handle, &(*it)); } return PVR_ERROR_NO_ERROR; } /* ************************************************************************** * Channels * *************************************************************************/ int CTvheadend::GetChannelCount ( void ) { if (!m_asyncState.WaitForState(ASYNC_DVR)) return 0; CLockObject lock(m_mutex); return m_channels.size(); } PVR_ERROR CTvheadend::GetChannels ( ADDON_HANDLE handle, bool radio ) { if (!m_asyncState.WaitForState(ASYNC_DVR)) return PVR_ERROR_FAILED; std::vector channels; { CLockObject lock(m_mutex); for (const auto &entry : m_channels) { const auto &channel = entry.second; if (channel.GetType() != (radio ? CHANNEL_TYPE_RADIO : CHANNEL_TYPE_TV)) continue; PVR_CHANNEL chn = { 0 }; chn.iUniqueId = channel.GetId(); chn.bIsRadio = radio; chn.iChannelNumber = channel.GetNum(); chn.iSubChannelNumber = channel.GetNumMinor(); chn.iEncryptionSystem = channel.GetCaid(); chn.bIsHidden = false; strncpy(chn.strChannelName, channel.GetName().c_str(), sizeof(chn.strChannelName) - 1); strncpy(chn.strIconPath, channel.GetIcon().c_str(), sizeof(chn.strIconPath) - 1); channels.emplace_back(chn); } } std::vector::const_iterator it; for (it = channels.begin(); it != channels.end(); ++it) { /* Callback. */ PVR->TransferChannelEntry(handle, &(*it)); } return PVR_ERROR_NO_ERROR; } /* ************************************************************************** * Recordings * *************************************************************************/ PVR_ERROR CTvheadend::SendDvrDelete ( uint32_t id, const char *method ) { uint32_t u32; CLockObject lock(m_conn->Mutex()); /* Build message */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "id", id); /* Send and wait a bit longer than usual */ if ((m = m_conn->SendAndWait(method, m, std::max(30000, Settings::GetInstance().GetResponseTimeout()))) == NULL) return PVR_ERROR_SERVER_ERROR; /* Check for error */ if (htsmsg_get_u32(m, "success", &u32)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed deleteDvrEntry/cancelDvrEntry response: 'success' missing"); u32 = PVR_ERROR_FAILED; } htsmsg_destroy(m); return u32 > 0 ? PVR_ERROR_NO_ERROR : PVR_ERROR_FAILED; } PVR_ERROR CTvheadend::SendDvrUpdate( htsmsg_t* m ) { uint32_t u32; /* Send and Wait */ { CLockObject lock(m_conn->Mutex()); m = m_conn->SendAndWait("updateDvrEntry", m); } if (m == NULL) return PVR_ERROR_SERVER_ERROR; /* Check for error */ if (htsmsg_get_u32(m, "success", &u32)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed updateDvrEntry response: 'success' missing"); u32 = PVR_ERROR_FAILED; } htsmsg_destroy(m); return u32 > 0 ? PVR_ERROR_NO_ERROR : PVR_ERROR_FAILED; } int CTvheadend::GetRecordingCount ( void ) { if (!m_asyncState.WaitForState(ASYNC_EPG)) return 0; CLockObject lock(m_mutex); return std::count_if( m_recordings.cbegin(), m_recordings.cend(), [](const RecordingMapEntry &entry) { return entry.second.IsRecording(); }); } PVR_ERROR CTvheadend::GetRecordings ( ADDON_HANDLE handle ) { if (!m_asyncState.WaitForState(ASYNC_EPG)) return PVR_ERROR_FAILED; std::vector recs; { CLockObject lock(m_mutex); Channels::const_iterator cit; char buf[128]; for (const auto &entry : m_recordings) { const auto &recording = entry.second; if (!recording.IsRecording()) continue; /* Setup entry */ PVR_RECORDING rec = { 0 }; /* Channel icon */ if ((cit = m_channels.find(recording.GetChannel())) != m_channels.end()) { strncpy(rec.strIconPath, cit->second.GetIcon().c_str(), sizeof(rec.strIconPath) - 1); } /* Channel name */ strncpy(rec.strChannelName, recording.GetChannelName().c_str(), sizeof(rec.strChannelName) - 1); /* Thumbnail image */ strncpy(rec.strThumbnailPath, recording.GetImage().c_str(), sizeof(rec.strThumbnailPath) - 1); /* Fanart image */ strncpy(rec.strFanartPath, recording.GetFanartImage().c_str(), sizeof(rec.strFanartPath) - 1); /* ID */ snprintf(buf, sizeof(buf), "%i", recording.GetId()); strncpy(rec.strRecordingId, buf, sizeof(rec.strRecordingId) - 1); /* Title */ strncpy(rec.strTitle, recording.GetTitle().c_str(), sizeof(rec.strTitle) - 1); /* Subtitle */ strncpy(rec.strEpisodeName, recording.GetSubtitle().c_str(), sizeof(rec.strEpisodeName) - 1); /* season/episode (tvh 4.3+) */ rec.iSeriesNumber = recording.GetSeason(); rec.iEpisodeNumber = recording.GetEpisode(); /* Description */ strncpy(rec.strPlot, recording.GetDescription().c_str(), sizeof(rec.strPlot) - 1); /* Genre */ rec.iGenreType = recording.GetGenreType(); rec.iGenreSubType = recording.GetGenreSubType(); /* Time/Duration (prefer real start/stop time over scheduled start/stop time if possible.) */ int64_t start; int64_t stop; if (recording.GetFilesStart() > 0) { start = recording.GetFilesStart(); if (recording.GetFilesStop() > 0) // finished / in progress? stop = recording.GetFilesStop(); else stop = recording.GetStop() + recording.GetStopExtra() * 60; } else { start = recording.GetStart() - recording.GetStartExtra() * 60; stop = recording.GetStop() + recording.GetStopExtra() * 60; } rec.recordingTime = static_cast(start); rec.iDuration = static_cast(stop - start); /* Priority */ rec.iPriority = recording.GetPriority(); /* Lifetime (based on retention or removal) */ rec.iLifetime = recording.GetLifetime(); /* Play status */ rec.iPlayCount = recording.GetPlayCount(); rec.iLastPlayedPosition = recording.GetPlayPosition(); /* Directory */ // TODO: Move this logic to GetPath(), alternatively GetMangledPath() if (recording.GetPath() != "") { size_t idx = recording.GetPath().rfind("/"); if (idx == 0 || idx == std::string::npos) strncpy(rec.strDirectory, "/", sizeof(rec.strDirectory) - 1); else { std::string d = recording.GetPath().substr(0, idx); if (d[0] != '/') d = "/" + d; strncpy(rec.strDirectory, d.c_str(), sizeof(rec.strDirectory) - 1); } } /* EPG event id */ rec.iEpgEventId = recording.GetEventId(); /* channel id */ rec.iChannelUid = recording.GetChannel() > 0 ? recording.GetChannel() : PVR_CHANNEL_INVALID_UID; /* channel type */ switch (recording.GetChannelType()) { case CHANNEL_TYPE_TV: rec.channelType = PVR_RECORDING_CHANNEL_TYPE_TV; break; case CHANNEL_TYPE_RADIO: rec.channelType = PVR_RECORDING_CHANNEL_TYPE_RADIO; break; case CHANNEL_TYPE_OTHER: default: rec.channelType = PVR_RECORDING_CHANNEL_TYPE_UNKNOWN; break; } recs.emplace_back(rec); } } std::vector::const_iterator it; for (it = recs.begin(); it != recs.end(); ++it) { /* Callback. */ PVR->TransferRecordingEntry(handle, &(*it)); } return PVR_ERROR_NO_ERROR; } PVR_ERROR CTvheadend::GetRecordingEdl ( const PVR_RECORDING &rec, PVR_EDL_ENTRY edl[], int *num ) { htsmsg_t *list; htsmsg_field_t *f; int idx; /* Build request */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "id", atoi(rec.strRecordingId)); Logger::Log(LogLevel::LEVEL_DEBUG, "dvr get cutpoints id=%s", rec.strRecordingId); /* Send and Wait */ { CLockObject lock(m_conn->Mutex()); if ((m = m_conn->SendAndWait("getDvrCutpoints", m)) == NULL) return PVR_ERROR_SERVER_ERROR; } /* Check for optional "cutpoints" reply message field */ if (!(list = htsmsg_get_list(m, "cutpoints"))) { *num = 0; htsmsg_destroy(m); return PVR_ERROR_NO_ERROR; } /* Process */ idx = 0; HTSMSG_FOREACH(f, list) { uint32_t start, end, type; if (f->hmf_type != HMF_MAP) continue; /* Full */ if (idx >= *num) break; /* Get fields */ if (htsmsg_get_u32(&f->hmf_msg, "start", &start) || htsmsg_get_u32(&f->hmf_msg, "end", &end) || htsmsg_get_u32(&f->hmf_msg, "type", &type)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed getDvrCutpoints response: invalid EDL entry, will ignore"); continue; } /* Build entry */ edl[idx].start = start; edl[idx].end = end; switch (type) { case DVR_ACTION_TYPE_CUT: edl[idx].type = PVR_EDL_TYPE_CUT; break; case DVR_ACTION_TYPE_MUTE: edl[idx].type = PVR_EDL_TYPE_MUTE; break; case DVR_ACTION_TYPE_SCENE: edl[idx].type = PVR_EDL_TYPE_SCENE; break; case DVR_ACTION_TYPE_COMBREAK: default: edl[idx].type = PVR_EDL_TYPE_COMBREAK; break; } idx++; Logger::Log(LogLevel::LEVEL_DEBUG, "edl start:%d end:%d action:%d", start, end, type); } *num = idx; htsmsg_destroy(m); return PVR_ERROR_NO_ERROR; } PVR_ERROR CTvheadend::DeleteRecording ( const PVR_RECORDING &rec ) { return SendDvrDelete(atoi(rec.strRecordingId), "deleteDvrEntry"); } PVR_ERROR CTvheadend::RenameRecording ( const PVR_RECORDING &rec ) { if (m_conn->GetProtocol() < 28) return PVR_ERROR_NOT_IMPLEMENTED; /* Build message */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "id", atoi(rec.strRecordingId)); htsmsg_add_str(m, "title", rec.strTitle); return SendDvrUpdate(m); } PVR_ERROR CTvheadend::SetLifetime ( const PVR_RECORDING &rec ) { if (m_conn->GetProtocol() < 28) return PVR_ERROR_NOT_IMPLEMENTED; Logger::Log(LogLevel::LEVEL_DEBUG, "Setting lifetime to %i for recording %s", rec.iLifetime, rec.strRecordingId); /* Build message */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "id", atoi(rec.strRecordingId)); if (m_conn->GetProtocol() >= 25) htsmsg_add_u32(m, "removal", LifetimeMapper::KodiToTvh(rec.iLifetime)); // remove from disk else htsmsg_add_u32(m, "retention", LifetimeMapper::KodiToTvh(rec.iLifetime)); // remove from tvh database return SendDvrUpdate(m); } PVR_ERROR CTvheadend::SetPlayCount ( const PVR_RECORDING &rec, int playCount ) { if (m_conn->GetProtocol() < 27 || !Settings::GetInstance().GetDvrPlayStatus()) return PVR_ERROR_NOT_IMPLEMENTED; Logger::Log(LogLevel::LEVEL_DEBUG, "Setting play count to %i for recording %s", playCount, rec.strRecordingId); /* Build message */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "id", atoi(rec.strRecordingId)); htsmsg_add_u32(m, "playcount", playCount); return SendDvrUpdate(m); } PVR_ERROR CTvheadend::SetPlayPosition ( const PVR_RECORDING &rec, int playPosition ) { if (m_conn->GetProtocol() < 27 || !Settings::GetInstance().GetDvrPlayStatus()) return PVR_ERROR_NOT_IMPLEMENTED; Logger::Log(LogLevel::LEVEL_DEBUG, "Setting play position to %i for recording %s", playPosition, rec.strRecordingId); /* Build message */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "id", atoi(rec.strRecordingId)); htsmsg_add_u32(m, "playposition", playPosition >= 0 ? playPosition : 0); // Kodi uses -1 when fully watched return SendDvrUpdate(m); } int CTvheadend::GetPlayPosition ( const PVR_RECORDING &rec ) { if (m_conn->GetProtocol() < 27 || !Settings::GetInstance().GetDvrPlayStatus()) return -1; CLockObject lock(m_mutex); const auto &it = m_recordings.find(atoi(rec.strRecordingId)); if (it != m_recordings.end() && it->second.IsRecording()) { Logger::Log(LogLevel::LEVEL_DEBUG, "Getting play position %i for recording %s", it->second.GetPlayPosition(), rec.strTitle); return it->second.GetPlayPosition(); } return -1; } namespace { struct TimerType : PVR_TIMER_TYPE { TimerType(unsigned int id, unsigned int attributes, const std::string &description, const std::vector< std::pair > &priorityValues = std::vector< std::pair >(), const std::vector< std::pair > &lifetimeValues = std::vector< std::pair >(), const std::vector< std::pair > &dupEpisodesValues = std::vector< std::pair >()) { memset(this, 0, sizeof(PVR_TIMER_TYPE)); iId = id; iAttributes = attributes; iPrioritiesSize = priorityValues.size(); iPrioritiesDefault = Settings::GetInstance().GetDvrPriority(); iPreventDuplicateEpisodesSize = dupEpisodesValues.size(); iPreventDuplicateEpisodesDefault = Settings::GetInstance().GetDvrDupdetect(); iLifetimesSize = lifetimeValues.size(); iLifetimesDefault = LifetimeMapper::TvhToKodi(Settings::GetInstance().GetDvrLifetime()); strncpy(strDescription, description.c_str(), sizeof(strDescription) - 1); int i = 0; for (auto it = priorityValues.begin(); it != priorityValues.end(); ++it, ++i) { priorities[i].iValue = it->first; strncpy(priorities[i].strDescription, it->second.c_str(), sizeof(priorities[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 = lifetimeValues.begin(); it != lifetimeValues.end(); ++it, ++i) { lifetimes[i].iValue = it->first; strncpy(lifetimes[i].strDescription, it->second.c_str(), sizeof(lifetimes[i].strDescription) - 1); } } }; } // unnamed namespace void CTvheadend::GetLivetimeValues(std::vector>& lifetimeValues) const { lifetimeValues = { { LifetimeMapper::TvhToKodi(DVR_RET_1DAY), LocalizedString(30375).Get() }, { LifetimeMapper::TvhToKodi(DVR_RET_3DAY), LocalizedString(30376).Get() }, { LifetimeMapper::TvhToKodi(DVR_RET_5DAY), LocalizedString(30377).Get() }, { LifetimeMapper::TvhToKodi(DVR_RET_1WEEK), LocalizedString(30378).Get() }, { LifetimeMapper::TvhToKodi(DVR_RET_2WEEK), LocalizedString(30379).Get() }, { LifetimeMapper::TvhToKodi(DVR_RET_3WEEK), LocalizedString(30380).Get() }, { LifetimeMapper::TvhToKodi(DVR_RET_1MONTH), LocalizedString(30381).Get() }, { LifetimeMapper::TvhToKodi(DVR_RET_2MONTH), LocalizedString(30382).Get() }, { LifetimeMapper::TvhToKodi(DVR_RET_3MONTH), LocalizedString(30383).Get() }, { LifetimeMapper::TvhToKodi(DVR_RET_6MONTH), LocalizedString(30384).Get() }, { LifetimeMapper::TvhToKodi(DVR_RET_1YEAR), LocalizedString(30385).Get() }, { LifetimeMapper::TvhToKodi(DVR_RET_2YEARS), LocalizedString(30386).Get() }, { LifetimeMapper::TvhToKodi(DVR_RET_3YEARS), LocalizedString(30387).Get() }, }; if (m_conn->GetProtocol() >= 25) { lifetimeValues.emplace_back(std::make_pair(LifetimeMapper::TvhToKodi(DVR_RET_SPACE), LocalizedString(30373).Get())); lifetimeValues.emplace_back(std::make_pair(LifetimeMapper::TvhToKodi(DVR_RET_FOREVER), LocalizedString(30374).Get())); } } PVR_ERROR CTvheadend::GetTimerTypes ( PVR_TIMER_TYPE types[], int *size ) { /* PVR_Timer.iPriority values and presentation.*/ static std::vector< std::pair > priorityValues; if (priorityValues.size() == 0) { priorityValues = { { DVR_PRIO_DEFAULT, LocalizedString(30368).Get() }, { DVR_PRIO_UNIMPORTANT, LocalizedString(30355).Get() }, { DVR_PRIO_LOW, LocalizedString(30354).Get() }, { DVR_PRIO_NORMAL, LocalizedString(30353).Get() }, { DVR_PRIO_HIGH, LocalizedString(30352).Get() }, { DVR_PRIO_IMPORTANT, LocalizedString(30351).Get() }, }; } /* PVR_Timer.iPreventDuplicateEpisodes values and presentation.*/ std::vector< std::pair > deDupValues = { { DVR_AUTOREC_RECORD_ALL, LocalizedString(30356).Get() }, { DVR_AUTOREC_RECORD_DIFFERENT_EPISODE_NUMBER, LocalizedString(30357).Get() }, { DVR_AUTOREC_RECORD_DIFFERENT_SUBTITLE, LocalizedString(30358).Get() }, { DVR_AUTOREC_RECORD_DIFFERENT_DESCRIPTION, LocalizedString(30359).Get() }, }; if (m_conn->GetProtocol() >= 27) deDupValues.emplace_back(std::make_pair(DVR_AUTOREC_RECORD_ONCE_PER_MONTH, LocalizedString(30370).Get())); deDupValues.emplace_back(std::make_pair(DVR_AUTOREC_RECORD_ONCE_PER_WEEK, LocalizedString(30360).Get())); deDupValues.emplace_back(std::make_pair(DVR_AUTOREC_RECORD_ONCE_PER_DAY, LocalizedString(30361).Get())); if (m_conn->GetProtocol() >= 26) { deDupValues.emplace_back(std::make_pair(DVR_AUTOREC_LRECORD_DIFFERENT_EPISODE_NUMBER, LocalizedString(30362).Get())); deDupValues.emplace_back(std::make_pair(DVR_AUTOREC_LRECORD_DIFFERENT_SUBTITLE, LocalizedString(30363).Get())); deDupValues.emplace_back(std::make_pair(DVR_AUTOREC_LRECORD_DIFFERENT_TITLE, LocalizedString(30364).Get())); deDupValues.emplace_back(std::make_pair(DVR_AUTOREC_LRECORD_DIFFERENT_DESCRIPTION, LocalizedString(30365).Get())); } if (m_conn->GetProtocol() >= 27) deDupValues.emplace_back(std::make_pair(DVR_AUTOREC_LRECORD_ONCE_PER_MONTH, LocalizedString(30371).Get())); if (m_conn->GetProtocol() >= 26) { deDupValues.emplace_back(std::make_pair(DVR_AUTOREC_LRECORD_ONCE_PER_WEEK, LocalizedString(30366).Get())); deDupValues.emplace_back(std::make_pair(DVR_AUTOREC_LRECORD_ONCE_PER_DAY, LocalizedString(30367).Get())); } if (m_conn->GetProtocol() >= 31) deDupValues.emplace_back(std::make_pair(DVR_AUTOREC_RECORD_UNIQUE, LocalizedString(30372).Get())); /* PVR_Timer.iLifetime values and presentation.*/ std::vector< std::pair > lifetimeValues; GetLivetimeValues(lifetimeValues); unsigned int TIMER_ONCE_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_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME; unsigned int TIMER_ONCE_EPG_ATTRIBS = PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_START_TIME | PVR_TIMER_TYPE_SUPPORTS_END_TIME | PVR_TIMER_TYPE_REQUIRES_EPG_TAG_ON_CREATE | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME; if (m_conn->GetProtocol() >= 23) { TIMER_ONCE_MANUAL_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE; TIMER_ONCE_EPG_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE; } /* Timer types definition. */ std::vector< std::unique_ptr > timerTypes; timerTypes.emplace_back( /* One-shot manual (time and channel based) */ std::unique_ptr(new TimerType( /* Type id. */ TIMER_ONCE_MANUAL, /* Attributes. */ TIMER_ONCE_MANUAL_ATTRIBS, /* Let Kodi generate the description. */ "", /* Values definitions for priorities. */ priorityValues, /* Values definitions for lifetime. */ lifetimeValues))); timerTypes.emplace_back( /* One-shot epg based */ std::unique_ptr(new TimerType( /* Type id. */ TIMER_ONCE_EPG, /* Attributes. */ TIMER_ONCE_EPG_ATTRIBS, /* Let Kodi generate the description. */ "", /* Values definitions for priorities. */ priorityValues, /* Values definitions for lifetime. */ lifetimeValues))); timerTypes.emplace_back( /* Read-only one-shot for timers generated by timerec */ std::unique_ptr(new TimerType( /* Type id. */ TIMER_ONCE_CREATED_BY_TIMEREC, /* Attributes. */ TIMER_ONCE_MANUAL_ATTRIBS | PVR_TIMER_TYPE_IS_READONLY | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES, /* Description. */ LocalizedString(30350).Get(), // "One Time (Scheduled by timer rule)" /* Values definitions for priorities. */ priorityValues, /* Values definitions for lifetime. */ lifetimeValues))); timerTypes.emplace_back( /* Read-only one-shot for timers generated by autorec */ std::unique_ptr(new TimerType( /* Type id. */ TIMER_ONCE_CREATED_BY_AUTOREC, /* Attributes. */ TIMER_ONCE_EPG_ATTRIBS | PVR_TIMER_TYPE_IS_READONLY | PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES, /* Description. */ LocalizedString(30350).Get(), // "One Time (Scheduled by timer rule)" /* Values definitions for priorities. */ priorityValues, /* Values definitions for lifetime. */ lifetimeValues))); timerTypes.emplace_back( /* Repeating manual (time and channel based) - timerec */ std::unique_ptr(new TimerType( /* Type id. */ TIMER_REPEATING_MANUAL, /* Attributes. */ PVR_TIMER_TYPE_IS_MANUAL | PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_START_TIME | PVR_TIMER_TYPE_SUPPORTS_END_TIME | PVR_TIMER_TYPE_SUPPORTS_WEEKDAYS | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_FOLDERS, /* Let Kodi generate the description. */ "", /* Values definitions for priorities. */ priorityValues, /* Values definitions for lifetime. */ lifetimeValues))); if (m_conn->GetProtocol() >= 29) { unsigned int TIMER_REPEATING_SERIESLINK_ATTRIBS = PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_START_TIME | PVR_TIMER_TYPE_SUPPORTS_START_ANYTIME | PVR_TIMER_TYPE_SUPPORTS_WEEKDAYS | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_FOLDERS | PVR_TIMER_TYPE_SUPPORTS_ANY_CHANNEL | PVR_TIMER_TYPE_REQUIRES_EPG_SERIESLINK_ON_CREATE; if (!Settings::GetInstance().GetAutorecApproxTime()) { /* We need the end time to represent the end of the tvh starting window */ TIMER_REPEATING_SERIESLINK_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_END_TIME; TIMER_REPEATING_SERIESLINK_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_END_ANYTIME; } timerTypes.emplace_back( /* Repeating epg based - series link autorec */ std::unique_ptr(new TimerType( /* Type id. */ TIMER_REPEATING_SERIESLINK, /* Attributes. */ TIMER_REPEATING_SERIESLINK_ATTRIBS, /* Description. */ LocalizedString(30369).Get(), // "Timer rule (series link)" /* Values definitions for priorities. */ priorityValues, /* Values definitions for lifetime. */ lifetimeValues))); } unsigned int TIMER_REPEATING_EPG_ATTRIBS = PVR_TIMER_TYPE_IS_REPEATING | PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | PVR_TIMER_TYPE_SUPPORTS_TITLE_EPG_MATCH | PVR_TIMER_TYPE_SUPPORTS_CHANNELS | PVR_TIMER_TYPE_SUPPORTS_START_TIME | PVR_TIMER_TYPE_SUPPORTS_START_ANYTIME | PVR_TIMER_TYPE_SUPPORTS_WEEKDAYS | PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | PVR_TIMER_TYPE_SUPPORTS_PRIORITY | PVR_TIMER_TYPE_SUPPORTS_LIFETIME | PVR_TIMER_TYPE_SUPPORTS_RECORDING_FOLDERS | PVR_TIMER_TYPE_SUPPORTS_ANY_CHANNEL; if (m_conn->GetProtocol() >= 20) { TIMER_REPEATING_EPG_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_FULLTEXT_EPG_MATCH; TIMER_REPEATING_EPG_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_RECORD_ONLY_NEW_EPISODES; } if (!Settings::GetInstance().GetAutorecApproxTime()) { /* We need the end time to represent the end of the tvh starting window */ TIMER_REPEATING_EPG_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_END_TIME; TIMER_REPEATING_EPG_ATTRIBS |= PVR_TIMER_TYPE_SUPPORTS_END_ANYTIME; } timerTypes.emplace_back( /* Repeating epg based - autorec */ std::unique_ptr(new TimerType( /* Type id. */ TIMER_REPEATING_EPG, /* Attributes. */ TIMER_REPEATING_EPG_ATTRIBS, /* Let Kodi generate the description. */ "", /* Values definitions for priorities. */ priorityValues, /* Values definitions for lifetime. */ lifetimeValues, /* Values definitions for prevent duplicate episodes. */ deDupValues))); /* Copy data to target array. */ int i = 0; for (auto it = timerTypes.begin(); it != timerTypes.end(); ++it, ++i) types[i] = **it; *size = timerTypes.size(); return PVR_ERROR_NO_ERROR; } int CTvheadend::GetTimerCount ( void ) { if (!m_asyncState.WaitForState(ASYNC_EPG)) return 0; CLockObject lock(m_mutex); // Normal timers int timerCount = std::count_if( m_recordings.cbegin(), m_recordings.cend(), [](const RecordingMapEntry &entry) { return entry.second.IsTimer(); }); // Repeating timers timerCount += m_timeRecordings.GetTimerecTimerCount(); timerCount += m_autoRecordings.GetAutorecTimerCount(); return timerCount; } bool CTvheadend::CreateTimer ( const Recording &tvhTmr, PVR_TIMER &tmr ) { tmr = { 0 }; tmr.iClientIndex = tvhTmr.GetId(); tmr.iClientChannelUid = (tvhTmr.GetChannel() > 0) ? tvhTmr.GetChannel() : PVR_CHANNEL_INVALID_UID; tmr.startTime = static_cast(tvhTmr.GetStart()); tmr.endTime = static_cast(tvhTmr.GetStop()); strncpy(tmr.strTitle, tvhTmr.GetTitle().c_str(), sizeof(tmr.strTitle) - 1); strncpy(tmr.strEpgSearchString, "", sizeof(tmr.strEpgSearchString) - 1); // n/a for one-shot timers strncpy(tmr.strDirectory, "", sizeof(tmr.strDirectory) - 1); // n/a for one-shot timers strncpy(tmr.strSummary, tvhTmr.GetDescription().c_str(), sizeof(tmr.strSummary) - 1); if (m_conn->GetProtocol() >= 23) tmr.state = !tvhTmr.IsEnabled() ? PVR_TIMER_STATE_DISABLED : tvhTmr.GetState(); else tmr.state = tvhTmr.GetState(); tmr.iPriority = tvhTmr.GetPriority(); tmr.iLifetime = tvhTmr.GetLifetime(); tmr.iTimerType = tvhTmr.GetTimerType(); tmr.iMaxRecordings = 0; // not supported by tvh tmr.iRecordingGroup = 0; // not supported by tvh tmr.iPreventDuplicateEpisodes = 0; // n/a for one-shot timers tmr.firstDay = 0; // not supported by tvh tmr.iWeekdays = PVR_WEEKDAY_NONE; // n/a for one-shot timers tmr.iEpgUid = (tvhTmr.GetEventId() > 0) ? tvhTmr.GetEventId() : PVR_TIMER_NO_EPG_UID; tmr.iMarginStart = static_cast(tvhTmr.GetStartExtra()); tmr.iMarginEnd = static_cast(tvhTmr.GetStopExtra()); tmr.iGenreType = 0; // not supported by tvh? tmr.iGenreSubType = 0; // not supported by tvh? tmr.bFullTextEpgSearch = false; // n/a for one-shot timers tmr.iParentClientIndex = tmr.iTimerType == TIMER_ONCE_CREATED_BY_TIMEREC ? m_timeRecordings.GetTimerIntIdFromStringId(tvhTmr.GetTimerecId()) : tmr.iTimerType == TIMER_ONCE_CREATED_BY_AUTOREC ? m_autoRecordings.GetTimerIntIdFromStringId(tvhTmr.GetAutorecId()) : 0; return true; } PVR_ERROR CTvheadend::GetTimers ( ADDON_HANDLE handle ) { if (!m_asyncState.WaitForState(ASYNC_EPG)) return PVR_ERROR_FAILED; std::vector timers; { CLockObject lock(m_mutex); /* One-shot timers */ for (const auto &entry : m_recordings) { const auto &recording = entry.second; if (!recording.IsTimer()) continue; /* Setup entry */ PVR_TIMER tmr; if (CreateTimer(recording, tmr)) timers.emplace_back(tmr); } /* Time-based repeating timers */ m_timeRecordings.GetTimerecTimers(timers); /* EPG-query-based repeating timers */ m_autoRecordings.GetAutorecTimers(timers); } std::vector::const_iterator it; for (it = timers.begin(); it != timers.end(); ++it) { /* Callback. */ PVR->TransferTimerEntry(handle, &(*it)); } return PVR_ERROR_NO_ERROR; } PVR_ERROR CTvheadend::AddTimer ( const PVR_TIMER &timer ) { if ((timer.iTimerType == TIMER_ONCE_MANUAL) || (timer.iTimerType == TIMER_ONCE_EPG)) { /* one shot timer */ uint32_t u32; /* Build message */ htsmsg_t *m = htsmsg_create_map(); int64_t start = timer.startTime; if (timer.iEpgUid > PVR_TIMER_NO_EPG_UID && timer.iTimerType == TIMER_ONCE_EPG && start != 0) { /* EPG-based timer */ htsmsg_add_u32(m, "eventId", timer.iEpgUid); } else { /* manual timer */ htsmsg_add_str(m, "title", timer.strTitle); if (start == 0) { /* Instant timer. Adjust start time to 'now'. */ start = time(NULL); } htsmsg_add_s64(m, "start", start); htsmsg_add_s64(m, "stop", timer.endTime); htsmsg_add_u32(m, "channelId", timer.iClientChannelUid); htsmsg_add_str(m, "description", timer.strSummary); } if (m_conn->GetProtocol() >= 23) htsmsg_add_u32(m, "enabled", timer.state == PVR_TIMER_STATE_DISABLED ? 0 : 1); htsmsg_add_s64(m, "startExtra", timer.iMarginStart); htsmsg_add_s64(m, "stopExtra", timer.iMarginEnd); if (m_conn->GetProtocol() >= 25) htsmsg_add_u32(m, "removal", LifetimeMapper::KodiToTvh(timer.iLifetime)); // remove from disk else htsmsg_add_u32(m, "retention", LifetimeMapper::KodiToTvh(timer.iLifetime)); // remove from tvh database htsmsg_add_u32(m, "priority", timer.iPriority); /* Send and Wait */ { CLockObject lock(m_conn->Mutex()); m = m_conn->SendAndWait("addDvrEntry", m); } if (m == NULL) return PVR_ERROR_SERVER_ERROR; /* Check for error */ if (htsmsg_get_u32(m, "success", &u32)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed addDvrEntry response: 'success' missing"); u32 = PVR_ERROR_FAILED; } htsmsg_destroy(m); return u32 > 0 ? PVR_ERROR_NO_ERROR : PVR_ERROR_FAILED; } else if (timer.iTimerType == TIMER_REPEATING_MANUAL) { /* time-based repeating timer */ return m_timeRecordings.SendTimerecAdd(timer); } else if (timer.iTimerType == TIMER_REPEATING_EPG || timer.iTimerType == TIMER_REPEATING_SERIESLINK) { /* EPG-query-based repeating timers */ return m_autoRecordings.SendAutorecAdd(timer); } else { /* unknown timer */ Logger::Log(LogLevel::LEVEL_ERROR, "unknown timer type"); return PVR_ERROR_INVALID_PARAMETERS; } } PVR_ERROR CTvheadend::DeleteTimer(const PVR_TIMER &timer, bool) { { CLockObject lock(m_mutex); const auto& it = m_recordings.find(timer.iClientIndex); if (it != m_recordings.end() && it->second.IsRecording()) { // This is a request to stop an active recording. if (m_conn->GetProtocol() >= 26) { // gracefully stop the recording (mark as success in tvh) return SendDvrDelete(timer.iClientIndex, "stopDvrEntry"); } else { // abort the recording (mark as failure in tvh) - no other choice, // because graceful stop HTSP method was not available before HTSP v26. return SendDvrDelete(timer.iClientIndex, "cancelDvrEntry"); } } } if ((timer.iTimerType == TIMER_ONCE_MANUAL) || (timer.iTimerType == TIMER_ONCE_EPG)) { /* one shot timer */ return SendDvrDelete(timer.iClientIndex, "cancelDvrEntry"); } else if (timer.iTimerType == TIMER_REPEATING_MANUAL) { /* time-based repeating timer */ return m_timeRecordings.SendTimerecDelete(timer); } else if (timer.iTimerType == TIMER_REPEATING_EPG || timer.iTimerType == TIMER_REPEATING_SERIESLINK) { /* EPG-query-based repeating timer */ return m_autoRecordings.SendAutorecDelete(timer); } else if ((timer.iTimerType == TIMER_ONCE_CREATED_BY_TIMEREC) || (timer.iTimerType == TIMER_ONCE_CREATED_BY_AUTOREC)) { /* Read-only timer created by autorec or timerec */ Logger::Log(LogLevel::LEVEL_ERROR, "timer is read-only"); return PVR_ERROR_INVALID_PARAMETERS; } else { /* unknown timer */ Logger::Log(LogLevel::LEVEL_ERROR, "unknown timer type"); return PVR_ERROR_INVALID_PARAMETERS; } } PVR_ERROR CTvheadend::UpdateTimer ( const PVR_TIMER &timer ) { if ((timer.iTimerType == TIMER_ONCE_MANUAL) || (timer.iTimerType == TIMER_ONCE_EPG)) { /* one shot timer */ /* Build message */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "id", timer.iClientIndex); if (m_conn->GetProtocol() >= 22) { /* support for updating the channel was added very late to the htsp protocol. */ htsmsg_add_u32(m, "channelId", timer.iClientChannelUid); } else { CLockObject lock(m_mutex); const auto &it = m_recordings.find(timer.iClientIndex); if (it == m_recordings.end()) { Logger::Log(LogLevel::LEVEL_ERROR, "cannot find the timer to update"); return PVR_ERROR_INVALID_PARAMETERS; } if (it->second.GetChannel() != static_cast(timer.iClientChannelUid)) { Logger::Log(LogLevel::LEVEL_ERROR, "updating channels of one-shot timers not supported by HTSP v%d", m_conn->GetProtocol()); return PVR_ERROR_NOT_IMPLEMENTED; } } htsmsg_add_str(m, "title", timer.strTitle); if (m_conn->GetProtocol() >= 23) htsmsg_add_u32(m, "enabled", timer.state == PVR_TIMER_STATE_DISABLED ? 0 : 1); int64_t start = timer.startTime; if (start == 0) { /* Instant timer. Adjust start time to 'now'. */ start = time(NULL); } htsmsg_add_s64(m, "start", start); htsmsg_add_s64(m, "stop", timer.endTime); htsmsg_add_str(m, "description", timer.strSummary); htsmsg_add_s64(m, "startExtra", timer.iMarginStart); htsmsg_add_s64(m, "stopExtra", timer.iMarginEnd); if (m_conn->GetProtocol() >= 25) htsmsg_add_u32(m, "removal", LifetimeMapper::KodiToTvh(timer.iLifetime)); // remove from disk else htsmsg_add_u32(m, "retention", LifetimeMapper::KodiToTvh(timer.iLifetime)); // remove from tvh database htsmsg_add_u32(m, "priority", timer.iPriority); return SendDvrUpdate(m); } else if (timer.iTimerType == TIMER_REPEATING_MANUAL) { /* time-based repeating timer */ return m_timeRecordings.SendTimerecUpdate(timer); } else if (timer.iTimerType == TIMER_REPEATING_EPG || timer.iTimerType == TIMER_REPEATING_SERIESLINK) { /* EPG-query-based repeating timers */ return m_autoRecordings.SendAutorecUpdate(timer); } else if ((timer.iTimerType == TIMER_ONCE_CREATED_BY_TIMEREC) || (timer.iTimerType == TIMER_ONCE_CREATED_BY_AUTOREC)) { if (m_conn->GetProtocol() >= 23) { /* Read-only timer created by autorec or timerec */ CLockObject lock(m_mutex); const auto &it = m_recordings.find(timer.iClientIndex); if (it != m_recordings.end() && (it->second.IsEnabled() == (timer.state == PVR_TIMER_STATE_DISABLED))) { /* This is actually a request to enable/disable a timer. */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "id", timer.iClientIndex); htsmsg_add_u32(m, "enabled", timer.state == PVR_TIMER_STATE_DISABLED ? 0 : 1); return SendDvrUpdate(m); } } Logger::Log(LogLevel::LEVEL_ERROR, "timer is read-only"); return PVR_ERROR_INVALID_PARAMETERS; } else { /* unknown timer */ Logger::Log(LogLevel::LEVEL_ERROR, "unknown timer type"); return PVR_ERROR_INVALID_PARAMETERS; } } /* ************************************************************************** * EPG * *************************************************************************/ void CTvheadend::CreateEvent ( const Event &event, EPG_TAG &epg ) { epg = { 0 }; epg.iUniqueBroadcastId = event.GetId(); epg.iUniqueChannelId = event.GetChannel(); epg.strTitle = event.GetTitle().c_str(); epg.startTime = event.GetStart(); epg.endTime = event.GetStop(); epg.strPlotOutline = event.GetSummary().c_str(); epg.strPlot = event.GetDesc().c_str(); epg.strOriginalTitle = NULL; /* not supported by tvh */ epg.strCast = event.GetCast().c_str(); epg.strDirector = event.GetDirectors().c_str(); epg.strWriter = event.GetWriters().c_str(); epg.iYear = event.GetYear(); epg.strIMDBNumber = NULL; /* not supported by tvh */ epg.strIconPath = event.GetImage().c_str(); epg.iGenreType = event.GetGenreType(); epg.iGenreSubType = event.GetGenreSubType(); if (epg.iGenreType == 0) { const std::string& categories = event.GetCategories(); if (!categories.empty()) { epg.iGenreType = EPG_GENRE_USE_STRING; epg.strGenreDescription = categories.c_str(); } } epg.firstAired = event.GetAired(); epg.iParentalRating = event.GetAge(); epg.iStarRating = event.GetStars(); epg.bNotify = false; /* not supported by tvh */ epg.iSeriesNumber = event.GetSeason(); epg.iEpisodeNumber = event.GetEpisode(); epg.iEpisodePartNumber = event.GetPart(); epg.strEpisodeName = event.GetSubtitle().c_str(); epg.iFlags = EPG_TAG_FLAG_UNDEFINED; epg.strSeriesLink = event.GetSeriesLink().c_str(); } void CTvheadend::TransferEvent ( const Event &event, EPG_EVENT_STATE state ) { /* Build */ EPG_TAG tag; CreateEvent(event, tag); /* Transfer event to Kodi */ PVR->EpgEventStateChange(&tag, state); } void CTvheadend::TransferEvent ( ADDON_HANDLE handle, const Event &event ) { /* Build */ EPG_TAG tag; CreateEvent(event, tag); /* Transfer event to Kodi */ PVR->TransferEpgEntry(handle, &tag); } PVR_ERROR CTvheadend::GetEPGForChannel ( ADDON_HANDLE handle, const PVR_CHANNEL &chn, time_t start, time_t end ) { htsmsg_field_t *f; Logger::Log(LogLevel::LEVEL_DEBUG, "get epg channel %d start %ld stop %ld", chn.iUniqueId, (long long)start, (long long)end); /* Build message */ htsmsg_t *msg = htsmsg_create_map(); htsmsg_add_u32(msg, "channelId", chn.iUniqueId); htsmsg_add_s64(msg, "maxTime", end); /* Send and Wait */ { CLockObject lock(m_conn->Mutex()); if ((msg = m_conn->SendAndWait0("getEvents", msg)) == NULL) return PVR_ERROR_SERVER_ERROR; } /* Process */ htsmsg_t *l; if (!(l = htsmsg_get_list(msg, "events"))) { htsmsg_destroy(msg); Logger::Log(LogLevel::LEVEL_ERROR, "malformed getEvents response: 'events' missing"); return PVR_ERROR_SERVER_ERROR; } int n = 0; HTSMSG_FOREACH(f, l) { Event event; if (f->hmf_type == HMF_MAP) { if (ParseEvent(&f->hmf_msg, true, event)) { /* Callback. */ TransferEvent(handle, event); ++n; } } } htsmsg_destroy(msg); Logger::Log(LogLevel::LEVEL_DEBUG, "get epg channel %d events %d", chn.iUniqueId, n); return PVR_ERROR_NO_ERROR; } PVR_ERROR CTvheadend::SetEPGTimeFrame(int iDays) { if (m_epgMaxDays != iDays) { m_epgMaxDays = iDays; if (Settings::GetInstance().GetAsyncEpg()) { Logger::Log(LogLevel::LEVEL_TRACE, "reconnecting to synchronize epg data. epg max time: old = %d, new = %d", m_epgMaxDays, iDays); m_conn->Disconnect(); // reconnect to synchronize epg data } } return PVR_ERROR_NO_ERROR; } /* ************************************************************************** * Connection * *************************************************************************/ void CTvheadend::Disconnected ( void ) { m_asyncState.SetState(ASYNC_NONE); } bool CTvheadend::Connected ( void ) { htsmsg_t *msg; /* Rebuild state */ for (auto *dmx : m_dmx) { dmx->Connected(); } m_vfs->Connected(); m_timeRecordings.Connected(); m_autoRecordings.Connected(); /* Flag all async fields in case they've been deleted */ for (auto &entry : m_channels) entry.second.SetDirty(true); for (auto &entry : m_tags) entry.second.SetDirty(true); for (auto &entry : m_schedules) entry.second.SetDirty(true); { CLockObject lock(m_mutex); for (auto &entry : m_recordings) entry.second.SetDirty(true); } /* Request Async data, first is channels */ m_asyncState.SetState(ASYNC_CHN); msg = htsmsg_create_map(); if (Settings::GetInstance().GetAsyncEpg()) { Logger::Log(LogLevel::LEVEL_INFO, "request async EPG (%ld)", (long)m_epgMaxDays); htsmsg_add_u32(msg, "epg", 1); if (m_epgMaxDays > EPG_TIMEFRAME_UNLIMITED) htsmsg_add_s64(msg, "epgMaxTime", static_cast(time(NULL) + m_epgMaxDays * int64_t(24 * 60 *60))); } else htsmsg_add_u32(msg, "epg", 0); if ((msg = m_conn->SendAndWait0("enableAsyncMetadata", msg)) == NULL) { m_asyncState.SetState(ASYNC_NONE); return false; } htsmsg_destroy(msg); Logger::Log(LogLevel::LEVEL_INFO, "async updates requested"); return true; } std::string CTvheadend::GetServerName() const { return m_conn->GetServerName(); } std::string CTvheadend::GetServerVersion() const { return m_conn->GetServerVersion(); } std::string CTvheadend::GetServerString() const { return m_conn->GetServerString(); } int CTvheadend::GetProtocol() const { return m_conn->GetProtocol(); } bool CTvheadend::HasCapability(const std::string &capability) const { return m_conn->HasCapability(capability); } void CTvheadend::OnSleep() { m_conn->OnSleep(); } void CTvheadend::OnWake() { m_conn->OnWake(); } /* ************************************************************************** * VFS * *************************************************************************/ bool CTvheadend::VfsOpen(const PVR_RECORDING &rec) { bool ret = m_vfs->Open(rec); if (ret) { CLockObject lock(m_mutex); const auto &it = m_recordings.find(atoi(rec.strRecordingId)); if (it != m_recordings.end()) { m_playingRecording = &(it->second); } } return ret; } void CTvheadend::VfsClose() { m_vfs->Close(); CLockObject lock(m_mutex); m_playingRecording = nullptr; } ssize_t CTvheadend::VfsRead(unsigned char *buf, unsigned int len) { return m_vfs->Read(buf, len, VfsIsActiveRecording()); } long long CTvheadend::VfsSeek(long long position, int whence) { return m_vfs->Seek(position, whence, VfsIsActiveRecording()); } long long CTvheadend::VfsSize() { return m_vfs->Size(); } void CTvheadend::VfsPauseStream(bool paused) { if (VfsIsActiveRecording()) m_vfs->PauseStream(paused); } bool CTvheadend::VfsIsRealTimeStream() { if (VfsIsActiveRecording()) return m_vfs->IsRealTimeStream(); else return false; } /* ************************************************************************** * Message handling * *************************************************************************/ bool CTvheadend::ProcessMessage ( const char *method, htsmsg_t *msg ) { uint32_t subId; if (!htsmsg_get_u32(msg, "subscriptionId", &subId)) { /* subscriptionId found - for a Demuxer */ for (auto *dmx : m_dmx) { if (dmx->GetSubscriptionId() == subId) return dmx->ProcessMessage(method, msg); } return true; } /* Store */ m_queue.Push(HTSPMessage(method, msg)); return false; } void CTvheadend::CloseExpiredSubscriptions() { // predictive tuning active? if (m_dmx.size() > 1) { int closeDelay = Settings::GetInstance().GetPreTunerCloseDelay(); if (closeDelay > 0) { for (auto *dmx : m_dmx) { // do not close the running subscription if it is currently paused if (m_playingLiveStream && dmx == m_dmx_active && dmx->IsPaused()) continue; time_t lastUse = dmx->GetLastUse(); if (lastUse > 0 && lastUse + closeDelay < std::time(nullptr)) { Logger::Log(LogLevel::LEVEL_TRACE, "closing expired subscription %u", dmx->GetSubscriptionId()); dmx->Close(); } } } } } void* CTvheadend::Process ( void ) { HTSPMessage msg; const char *method; while (!IsStopped()) { /* Check Q */ // this is a bit horrible, but meh bool bSuccess = m_queue.Pop(msg, 2000); if (IsStopped()) continue; // check for expired predictive tuning subscriptions and close those CloseExpiredSubscriptions(); if (!bSuccess || !msg.GetMessage()) continue; method = msg.GetMethod().c_str(); SHTSPEventList eventsCopy; /* Scope lock for processing */ { CLockObject lock(m_mutex); /* Channels */ if (!strcmp("channelAdd", method)) ParseChannelAddOrUpdate(msg.GetMessage(), true); else if (!strcmp("channelUpdate", method)) ParseChannelAddOrUpdate(msg.GetMessage(), false); else if (!strcmp("channelDelete", method)) ParseChannelDelete(msg.GetMessage()); /* Channel Tags (aka channel groups)*/ else if (!strcmp("tagAdd", method)) ParseTagAddOrUpdate(msg.GetMessage(), true); else if (!strcmp("tagUpdate", method)) ParseTagAddOrUpdate(msg.GetMessage(), false); else if (!strcmp("tagDelete", method)) ParseTagDelete(msg.GetMessage()); /* Recordings */ else if (!strcmp("dvrEntryAdd", method)) ParseRecordingAddOrUpdate(msg.GetMessage(), true); else if (!strcmp("dvrEntryUpdate", method)) ParseRecordingAddOrUpdate(msg.GetMessage(), false); else if (!strcmp("dvrEntryDelete", method)) ParseRecordingDelete(msg.GetMessage()); /* Timerec */ else if (!strcmp("timerecEntryAdd", method)) { if (m_timeRecordings.ParseTimerecAddOrUpdate(msg.GetMessage(), true)) TriggerTimerUpdate(); } else if (!strcmp("timerecEntryUpdate", method)) { if (m_timeRecordings.ParseTimerecAddOrUpdate(msg.GetMessage(), false)) TriggerTimerUpdate(); } else if (!strcmp("timerecEntryDelete", method)) { if (m_timeRecordings.ParseTimerecDelete(msg.GetMessage())) TriggerTimerUpdate(); } /* Autorec */ else if (!strcmp("autorecEntryAdd", method)) { if (m_autoRecordings.ParseAutorecAddOrUpdate(msg.GetMessage(), true)) TriggerTimerUpdate(); } else if (!strcmp("autorecEntryUpdate", method)) { if (m_autoRecordings.ParseAutorecAddOrUpdate(msg.GetMessage(), false)) TriggerTimerUpdate(); } else if (!strcmp("autorecEntryDelete", method)) { if (m_autoRecordings.ParseAutorecDelete(msg.GetMessage())) TriggerTimerUpdate(); } /* EPG */ else if (!strcmp("eventAdd", method)) ParseEventAddOrUpdate(msg.GetMessage(), true); else if (!strcmp("eventUpdate", method)) ParseEventAddOrUpdate(msg.GetMessage(), false); else if (!strcmp("eventDelete", method)) ParseEventDelete(msg.GetMessage()); /* ASync complete */ else if (!strcmp("initialSyncCompleted", method)) SyncCompleted(); /* Unknown */ else Logger::Log(LogLevel::LEVEL_DEBUG, "unhandled message [%s]", method); /* make a copy of events list to process it without lock. */ eventsCopy = m_events; m_events.clear(); } /* Manual delete rather than waiting */ msg.ClearMessage(); if (IsStopped()) continue; /* Process events * Note: due to potential deadly embrace this must be done without the * m_mutex held! */ SHTSPEventList::const_iterator it; for (it = eventsCopy.begin(); it != eventsCopy.end(); ++it) { switch (it->m_type) { case HTSP_EVENT_TAG_UPDATE: PVR->TriggerChannelGroupsUpdate(); break; case HTSP_EVENT_CHN_UPDATE: PVR->TriggerChannelUpdate(); break; case HTSP_EVENT_REC_UPDATE: PVR->TriggerTimerUpdate(); PVR->TriggerRecordingUpdate(); break; case HTSP_EVENT_EPG_UPDATE: TransferEvent(it->m_epg, it->m_state); break; case HTSP_EVENT_NONE: break; } } } return nullptr; } void CTvheadend::TriggerChannelGroupsUpdate() { m_events.emplace_back(SHTSPEvent(HTSP_EVENT_TAG_UPDATE)); } void CTvheadend::TriggerChannelUpdate() { m_events.emplace_back(SHTSPEvent(HTSP_EVENT_CHN_UPDATE)); } void CTvheadend::TriggerRecordingUpdate() { m_events.emplace_back(SHTSPEvent(HTSP_EVENT_REC_UPDATE)); } void CTvheadend::TriggerTimerUpdate() { m_events.emplace_back(SHTSPEvent(HTSP_EVENT_REC_UPDATE)); } void CTvheadend::PushEpgEventUpdate(const Event &epg, EPG_EVENT_STATE state) { SHTSPEvent event = SHTSPEvent(HTSP_EVENT_EPG_UPDATE, epg, state); if (std::find(m_events.begin(), m_events.end(), event) == m_events.end()) m_events.emplace_back(event); } void CTvheadend::SyncCompleted ( void ) { Logger::Log(LogLevel::LEVEL_INFO, "async updates initialised"); /* The complete calls are probably redundant, but its a safety feature */ SyncChannelsCompleted(); SyncDvrCompleted(); SyncEpgCompleted(); m_asyncState.SetState(ASYNC_DONE); /* Query the server for available streaming profiles */ QueryAvailableProfiles(); /* Show a notification if the profile is not available */ std::string streamingProfile = Settings::GetInstance().GetStreamingProfile(); if (!streamingProfile.empty() && !HasStreamingProfile(streamingProfile)) { XBMC->QueueNotification( QUEUE_ERROR, LocalizedString(30502).Get().c_str(), streamingProfile.c_str()); } else { /* Tell each demuxer to use this profile from now on */ for (auto *dmx : m_dmx) dmx->SetStreamingProfile(streamingProfile); } } void CTvheadend::SyncChannelsCompleted ( void ) { /* check state engine */ if (m_asyncState.GetState() != ASYNC_CHN) return; /* Tags */ utilities::erase_if(m_tags, [](const TagMapEntry &entry) { return entry.second.IsDirty(); }); TriggerChannelGroupsUpdate(); /* Channels */ utilities::erase_if(m_channels, [](const ChannelMapEntry &entry) { return entry.second.IsDirty(); }); TriggerChannelUpdate(); /* Next */ m_asyncState.SetState(ASYNC_DVR); } void CTvheadend::SyncDvrCompleted ( void ) { /* check state engine */ if (m_asyncState.GetState() != ASYNC_DVR) return; /* Recordings */ { CLockObject lock(m_mutex); // save id of currently playing recording, if any uint32_t id = m_playingRecording ? m_playingRecording->GetId() : 0; utilities::erase_if(m_recordings, [](const RecordingMapEntry &entry) { return entry.second.IsDirty(); }); if (m_playingRecording) { const auto &it = m_recordings.find(id); if (it == m_recordings.end()) m_playingRecording = nullptr; } } /* Time-based repeating timers */ m_timeRecordings.SyncDvrCompleted(); /* EPG-query-based repeating timers */ m_autoRecordings.SyncDvrCompleted(); TriggerRecordingUpdate(); TriggerTimerUpdate(); /* Next */ m_asyncState.SetState(ASYNC_EPG); } void CTvheadend::SyncEpgCompleted ( void ) { /* check state engine */ if (!Settings::GetInstance().GetAsyncEpg()) { m_asyncState.SetState(ASYNC_DONE); return; } /* check state engine */ if (m_asyncState.GetState() != ASYNC_EPG) return; /* Schedules */ std::vector > deletedEvents; utilities::erase_if(m_schedules, [&](const ScheduleMapEntry &entry) { if (entry.second.IsDirty()) { // all events are dirty too! for (auto &evt : entry.second.GetEvents()) deletedEvents.emplace_back( std::make_pair(evt.second.GetId() /* event uid */, entry.second.GetId() /* channel uid */)); return true; } return false; }); /* Events */ for (auto &entry : m_schedules) { utilities::erase_if(entry.second.GetEvents(), [&](const EventUidsMapEntry &mapEntry) { if (mapEntry.second.IsDirty()) { deletedEvents.emplace_back( std::make_pair(mapEntry.second.GetId() /* event uid */, entry.second.GetId() /* channel uid */)); return true; } return false; }); } Event evt; for (auto &entry : deletedEvents) { /* Transfer event to Kodi (callback) */ evt.SetId(entry.first); evt.SetChannel(entry.second); PushEpgEventUpdate(evt, EPG_EVENT_DELETED); } /* Next */ m_asyncState.SetState(ASYNC_DONE); } void CTvheadend::ParseTagAddOrUpdate ( htsmsg_t *msg, bool bAdd ) { uint32_t u32; const char *str; htsmsg_t *list; /* Validate */ if (htsmsg_get_u32(msg, "tagId", &u32)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed tagAdd/tagUpdate: 'tagId' missing"); return; } /* Locate object */ auto &existingTag = m_tags[u32]; existingTag.SetDirty(false); /* Create new object */ Tag tag; tag.SetId(u32); /* Index */ if (!htsmsg_get_u32(msg, "tagIndex", &u32)) tag.SetIndex(u32); /* Name */ if ((str = htsmsg_get_str(msg, "tagName")) != NULL) tag.SetName(str); else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed tagAdd: 'tagName' missing"); return; } /* Icon */ if ((str = htsmsg_get_str(msg, "tagIcon")) != NULL) tag.SetIcon(GetImageURL(str)); /* Members */ if ((list = htsmsg_get_list(msg, "members")) != NULL) { htsmsg_field_t *f; HTSMSG_FOREACH(f, list) { if (f->hmf_type != HMF_S64) continue; tag.GetChannels().emplace_back((int)f->hmf_s64); } } /* Update */ if (existingTag != tag) { existingTag = tag; Logger::Log(LogLevel::LEVEL_DEBUG, "tag updated id:%u, name:%s", existingTag.GetId(), existingTag.GetName().c_str()); if (m_asyncState.GetState() > ASYNC_CHN) TriggerChannelGroupsUpdate(); } } void CTvheadend::ParseTagDelete ( htsmsg_t *msg ) { uint32_t u32; /* Validate */ if (htsmsg_get_u32(msg, "tagId", &u32)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed tagDelete: 'tagId' missing"); return; } Logger::Log(LogLevel::LEVEL_DEBUG, "delete tag %u", u32); /* Erase */ m_tags.erase(u32); TriggerChannelGroupsUpdate(); } void CTvheadend::ParseChannelAddOrUpdate ( htsmsg_t *msg, bool bAdd ) { uint32_t u32; const char *str; htsmsg_t *list; /* Validate */ if (htsmsg_get_u32(msg, "channelId", &u32)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed channelAdd/channelUpdate: 'channelId' missing"); return; } /* Locate channel object */ Channel &channel = m_channels[u32]; Channel comparison = channel; channel.SetId(u32); channel.SetDirty(false); /* Channel name */ if ((str = htsmsg_get_str(msg, "channelName")) != NULL) channel.SetName(str); else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed channelAdd: 'channelName' missing"); return; } /* Channel number */ if (!htsmsg_get_u32(msg, "channelNumber", &u32)) { if (!u32) u32 = GetNextUnnumberedChannelNumber(); channel.SetNum(u32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed channelAdd: 'channelNumber' missing"); return; } else if (!channel.GetNum()) channel.SetNum(GetNextUnnumberedChannelNumber()); /* ATSC subchannel number */ if (!htsmsg_get_u32(msg, "channelNumberMinor", &u32)) channel.SetNumMinor(u32); /* Channel icon */ if ((str = htsmsg_get_str(msg, "channelIcon")) != NULL) channel.SetIcon(GetImageURL(str)); /* Services */ if ((list = htsmsg_get_list(msg, "services")) != NULL) { htsmsg_field_t *f; uint32_t caid = 0; HTSMSG_FOREACH(f, list) { if (f->hmf_type != HMF_MAP) continue; /* Channel type */ if (m_conn->GetProtocol() >= 26) { if (!htsmsg_get_u32(&f->hmf_msg, "content", &u32)) channel.SetType(u32); } else { if ((str = htsmsg_get_str(&f->hmf_msg, "type")) != NULL) { if (!strcmp(str, "Radio")) channel.SetType(CHANNEL_TYPE_RADIO); else if (!strcmp(str, "SDTV") || !strcmp(str, "HDTV")) channel.SetType(CHANNEL_TYPE_TV); } } /* CAID */ if (caid == 0) htsmsg_get_u32(&f->hmf_msg, "caid", &caid); } channel.SetCaid(caid); } /* Update Kodi */ if (channel != comparison) { Logger::Log(LogLevel::LEVEL_DEBUG, "channel %s id:%u, name:%s", (bAdd ? "added" : "updated"), channel.GetId(), channel.GetName().c_str()); if (bAdd) m_channelTuningPredictor.AddChannel(channel); else m_channelTuningPredictor.UpdateChannel(comparison, channel); if (m_asyncState.GetState() > ASYNC_CHN) TriggerChannelUpdate(); } } void CTvheadend::ParseChannelDelete ( htsmsg_t *msg ) { uint32_t u32; /* Validate */ if (htsmsg_get_u32(msg, "channelId", &u32)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed channelDelete: 'channelId' missing"); return; } Logger::Log(LogLevel::LEVEL_DEBUG, "delete channel %u", u32); /* Erase */ m_channels.erase(u32); m_channelTuningPredictor.RemoveChannel(u32); TriggerChannelUpdate(); } void CTvheadend::ParseRecordingAddOrUpdate ( htsmsg_t *msg, bool bAdd ) { const char *state, *str; uint32_t id, channel, eventId, retention, removal, priority, enabled, contentType, playCount, playPosition, season, episode, part; int64_t start, stop, startExtra, stopExtra; /* Channels must be complete */ SyncChannelsCompleted(); /* Validate */ if (htsmsg_get_u32(msg, "id", &id)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed dvrEntryAdd/dvrEntryUpdate: 'id' missing"); return; } /* Ignore duplicates */ uint32_t dup = 0; if (Settings::GetInstance().GetIgnoreDuplicateSchedules() && !htsmsg_get_u32(msg, "duplicate", &dup) && dup == 1) return; /* Get/create entry */ Recording &rec = m_recordings[id]; Recording comparison = rec; rec.SetId(id); rec.SetDirty(false); { CLockObject lock(m_mutex); if (m_playingRecording && m_playingRecording->GetId() == id) m_playingRecording = &rec; } // Set the time the recording was scheduled to start. This may differ from the actual start. if (!htsmsg_get_s64(msg, "start", &start)) rec.SetStart(start); else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed dvrEntryAdd: 'start' missing"); return; } // Set the time the recording was scheduled to stop. This may differ from the actual stop. if (!htsmsg_get_s64(msg, "stop", &stop)) rec.SetStop(stop); else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed dvrEntryAdd: 'stop' missing"); return; } /* Channel is optional, it may not exist anymore */ if (!htsmsg_get_u32(msg, "channel", &channel)) { /* Channel Id */ rec.SetChannel(channel); auto cit = m_channels.find(rec.GetChannel()); if (cit != m_channels.cend()) { /* Channel type */ rec.SetChannelType(cit->second.GetType()); /* Channel name */ rec.SetChannelName(cit->second.GetName()); } } htsmsg_t *files, *streams; if ((files = htsmsg_get_list(msg, "files")) != NULL) { htsmsg_field_t *file, *stream; uint32_t u32; int64_t s64; bool needChannelType = !rec.GetChannelType() && m_conn->GetProtocol() >= 25; bool hasAudio = false; bool hasVideo = false; start = 0; stop = 0; HTSMSG_FOREACH(file, files) // Loop through all files { if (file->hmf_type != HMF_MAP) continue; if (needChannelType && !(hasAudio && hasVideo)) { if ((streams = htsmsg_get_list(&file->hmf_msg, "info")) != NULL) { HTSMSG_FOREACH(stream, streams) // Loop through all streams { if (stream->hmf_type != HMF_MAP) continue; if (!htsmsg_get_u32(&stream->hmf_msg, "audio_type", &u32)) // Only present for audio streams hasAudio = true; if (!htsmsg_get_u32(&stream->hmf_msg, "aspect_num", &u32)) // Only present for video streams hasVideo = true; } } } if (!htsmsg_get_s64(&file->hmf_msg, "start", &s64) && (start == 0 || start > s64)) start = s64; if (!htsmsg_get_s64(&file->hmf_msg, "stop", &s64) && stop < s64) stop = s64; } // Set the times the recording actually started/stopped. They may differ from the scheduled start/stop. rec.SetFilesStart(start); rec.SetFilesStop(stop); /* Channel type fallback (in case channel was deleted) */ if (needChannelType) rec.SetChannelType(hasVideo ? CHANNEL_TYPE_TV : (hasAudio ? CHANNEL_TYPE_RADIO : CHANNEL_TYPE_OTHER)); } /* Channel name fallback (in case channel was deleted) */ if (rec.GetChannelName().empty() && m_conn->GetProtocol() >= 25) { if ((str = htsmsg_get_str(msg, "channelName")) != NULL) rec.SetChannelName(str); } if (!htsmsg_get_s64(msg, "startExtra", &startExtra)) rec.SetStartExtra(startExtra); else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed dvrEntryAdd: 'startExtra' missing"); return; } if (!htsmsg_get_s64(msg, "stopExtra", &stopExtra)) rec.SetStopExtra(stopExtra); else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed dvrEntryAdd: 'stopExtra' missing"); return; } if (m_conn->GetProtocol() >= 25) { if (!htsmsg_get_u32(msg, "removal", &removal)) rec.SetLifetime(removal); else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed dvrEntryAdd: 'removal' missing"); return; } } else { if (!htsmsg_get_u32(msg, "retention", &retention)) rec.SetLifetime(retention); else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed dvrEntryAdd: 'retention' missing"); return; } } if (!htsmsg_get_u32(msg, "priority", &priority)) { switch (priority) { case DVR_PRIO_IMPORTANT: case DVR_PRIO_HIGH: case DVR_PRIO_NORMAL: case DVR_PRIO_LOW: case DVR_PRIO_UNIMPORTANT: case DVR_PRIO_DEFAULT: rec.SetPriority(priority); break; default: Logger::Log(LogLevel::LEVEL_ERROR, "malformed dvrEntryAdd/dvrEntryUpdate: unknown priority value %d", priority); return; } } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed dvrEntryAdd: 'priority' missing"); return; } /* Parse state */ if ((state = htsmsg_get_str(msg, "state")) != NULL) { if (strstr(state, "scheduled") != NULL) rec.SetState(PVR_TIMER_STATE_SCHEDULED); else if (strstr(state, "recording") != NULL) rec.SetState(PVR_TIMER_STATE_RECORDING); else if (strstr(state, "completed") != NULL) rec.SetState(PVR_TIMER_STATE_COMPLETED); else if (strstr(state, "missed") != NULL) rec.SetState(PVR_TIMER_STATE_ERROR); else if (strstr(state, "invalid") != NULL) rec.SetState(PVR_TIMER_STATE_ERROR); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed dvrEntryAdd: 'state' missing"); return; } /* Add optional fields */ if (!htsmsg_get_u32(msg, "eventId", &eventId)) rec.SetEventId(eventId); if (!htsmsg_get_u32(msg, "enabled", &enabled)) rec.SetEnabled(enabled); if ((str = htsmsg_get_str(msg, "title")) != NULL) rec.SetTitle(str); if ((str = htsmsg_get_str(msg, "subtitle")) != NULL) rec.SetSubtitle(str); if ((str = htsmsg_get_str(msg, "path")) != NULL) rec.SetPath(str); if ((str = htsmsg_get_str(msg, "description")) != NULL) rec.SetDescription(str); else if ((str = htsmsg_get_str(msg, "summary")) != NULL) rec.SetDescription(str); if (!htsmsg_get_u32(msg, "contentType", &contentType)) rec.SetContentType(contentType); if ((str = htsmsg_get_str(msg, "timerecId")) != NULL) rec.SetTimerecId(str); if ((str = htsmsg_get_str(msg, "autorecId")) != NULL) rec.SetAutorecId(str); if ((str = htsmsg_get_str(msg, "image")) != NULL) rec.SetImage(GetImageURL(str)); if ((str = htsmsg_get_str(msg, "fanartImage")) != NULL) rec.SetFanartImage(GetImageURL(str)); if (m_conn->GetProtocol() >= 32) { if (rec.GetDescription().empty() && !rec.GetSubtitle().empty()) { /* Due to changes in HTSP v32, if the description is empty, try to use the subtitle as the description. Clear the subtitle afterwards to avoid duplicate information being displayed. This was done by TVHeadend prior to HTSP v32. */ rec.SetDescription(rec.GetSubtitle()); rec.SetSubtitle(""); } } /* Error */ if ((str = htsmsg_get_str(msg, "error")) != NULL) { if (!strcmp(str, "300")) rec.SetState(PVR_TIMER_STATE_ABORTED); else if (strstr(str, "missing") != NULL) rec.SetState(PVR_TIMER_STATE_ERROR); else rec.SetError(str); } /* A running recording will have an active subscription assigned to it */ if (rec.GetState() == PVR_TIMER_STATE_RECORDING) { /* Parse subscription error */ /* This field is absent when everything is fine or when htsp version < 20 */ if ((str = htsmsg_get_str(msg, "subscriptionError")) != NULL) { /* No free adapter, AKA subscription conflict */ if (!strcmp("noFreeAdapter", str)) rec.SetState(PVR_TIMER_STATE_CONFLICT_NOK); } } /* Play status (optional) */ if (m_conn->GetProtocol() >= 27) { if (!htsmsg_get_u32(msg, "playcount", &playCount)) rec.SetPlayCount(playCount); if (!htsmsg_get_u32(msg, "playposition", &playPosition)) rec.SetPlayPosition(playPosition); } /* season/episode/part */ if (!htsmsg_get_u32(msg, "seasonNumber", &season)) rec.SetSeason(season); if (!htsmsg_get_u32(msg, "episodeNumber", &episode)) rec.SetEpisode(episode); if (!htsmsg_get_u32(msg, "partNumber", &part)) rec.SetPart(part); /* Update */ if (rec != comparison) { std::string error = rec.GetError().empty() ? "none" : rec.GetError(); Logger::Log(LogLevel::LEVEL_DEBUG, "recording id:%d, state:%s, title:%s, desc:%s, error:%s", rec.GetId(), state, rec.GetTitle().c_str(), rec.GetDescription().c_str(), error.c_str()); if (m_asyncState.GetState() > ASYNC_DVR) { TriggerTimerUpdate(); TriggerRecordingUpdate(); } } } void CTvheadend::ParseRecordingDelete ( htsmsg_t *msg ) { uint32_t u32; /* Validate */ if (htsmsg_get_u32(msg, "id", &u32)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed dvrEntryDelete: 'id' missing"); return; } Logger::Log(LogLevel::LEVEL_DEBUG, "delete recording %u", u32); /* Erase */ { CLockObject lock(m_mutex); if (m_playingRecording && m_playingRecording->GetId() == u32) m_playingRecording = nullptr; m_recordings.erase(u32); } /* Update */ TriggerTimerUpdate(); TriggerRecordingUpdate(); } bool CTvheadend::ParseEvent ( htsmsg_t *msg, bool bAdd, Event &evt ) { const char *str; uint32_t u32, id, channel; int64_t s64, start, stop; /* Recordings complete */ SyncDvrCompleted(); /* Validate */ if (htsmsg_get_u32(msg, "eventId", &id)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed eventAdd/eventUpdate: 'eventId' missing"); return false; } if (htsmsg_get_u32(msg, "channelId", &channel) && bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed eventAdd: 'channelId' missing"); return false; } if (htsmsg_get_s64(msg, "start", &start) && bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed eventAdd: 'start' missing"); return false; } if (htsmsg_get_s64(msg, "stop", &stop) && bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed eventAdd: 'stop' missing"); return false; } evt.SetId(id); evt.SetChannel(channel); evt.SetStart((time_t)start); evt.SetStop((time_t)stop); /* Add optional fields */ if ((str = htsmsg_get_str(msg, "title")) != NULL) evt.SetTitle(str); if ((str = htsmsg_get_str(msg, "subtitle")) != NULL) evt.SetSubtitle(str); if ((str = htsmsg_get_str(msg, "summary")) != NULL) evt.SetSummary(str); if ((str = htsmsg_get_str(msg, "description")) != NULL) evt.SetDesc(str); if ((str = htsmsg_get_str(msg, "image")) != NULL) evt.SetImage(GetImageURL(str)); if (!htsmsg_get_u32(msg, "nextEventId", &u32)) evt.SetNext(u32); if (!htsmsg_get_u32(msg, "contentType", &u32)) evt.SetContent(u32); if (!htsmsg_get_u32(msg, "starRating", &u32)) evt.SetStars(u32); if (!htsmsg_get_u32(msg, "ageRating", &u32)) evt.SetAge(u32); if (!htsmsg_get_s64(msg, "firstAired", &s64)) evt.SetAired((time_t)s64); if (!htsmsg_get_u32(msg, "seasonNumber", &u32)) evt.SetSeason(u32); if (!htsmsg_get_u32(msg, "episodeNumber", &u32)) evt.SetEpisode(u32); if (!htsmsg_get_u32(msg, "partNumber", &u32)) evt.SetPart(u32); if ((str = htsmsg_get_str(msg, "serieslinkUri")) != NULL) evt.SetSeriesLink(str); if (!htsmsg_get_u32(msg, "copyrightYear", &u32)) evt.SetYear(u32); if (!htsmsg_get_u32(msg, "dvrId", &u32)) evt.SetRecordingId(u32); if (m_conn->GetProtocol() >= 32) { if (evt.GetDesc().empty()) { /* Due to changes in HTSP v32, if the description is empty, try to use the summary as the description. If the summary is empty, try to use the subtitle as the description. Also clear the respective entries to avoid duplicate information being displayed. This was done by TVHeadend prior to HTSP v32. */ if (!evt.GetSummary().empty()) { evt.SetDesc(evt.GetSummary()); evt.SetSummary(""); } else if (!evt.GetSubtitle().empty()) { evt.SetDesc(evt.GetSubtitle()); evt.SetSubtitle(""); } } } htsmsg_t *l; if ((l = htsmsg_get_map(msg, "credits")) != nullptr) { std::vector writers; std::vector directors; std::vector cast; htsmsg_field_t *f; HTSMSG_FOREACH(f, l) { if (f->hmf_name == nullptr) continue; const char *str = htsmsg_field_get_string(f); if (str == nullptr) continue; if (!strcmp(str, "writer")) writers.emplace_back(f->hmf_name); else if (!strcmp(str, "director")) directors.emplace_back(f->hmf_name); else if (!strcmp(str, "actor") || !strcmp(str, "guest") || !strcmp(str, "presenter")) cast.emplace_back(f->hmf_name); } evt.SetWriters(writers); evt.SetDirectors(directors); evt.SetCast(cast); } if ((l = htsmsg_get_list(msg, "category")) != nullptr) { std::vector categories; htsmsg_field_t *f; HTSMSG_FOREACH(f, l) { const char *str = f->hmf_str; if (str != nullptr) categories.emplace_back(str); } evt.SetCategories(categories); } return true; } void CTvheadend::ParseEventAddOrUpdate ( htsmsg_t *msg, bool bAdd ) { Event evt; /* Parse */ if (!ParseEvent(msg, bAdd, evt)) return; /* create/update schedule */ Schedule &sched = m_schedules[evt.GetChannel()]; sched.SetId(evt.GetChannel()); sched.SetDirty(false); /* create/update event */ EventUids &events = sched.GetEvents(); bool bUpdated(false); if (bAdd && m_asyncState.GetState() < ASYNC_DONE) { // After a reconnect, during processing of "enableAsyncMetadata" htsp // method, tvheadend sends all events as "added". Check whether we // announced the event already and in case send it as "updated" to Kodi. auto it = events.find(evt.GetId()); if (it != events.end()) { bUpdated = true; Entity &ent = it->second; ent.SetId(evt.GetId()); ent.SetDirty(false); } } if (!bUpdated) { Entity &ent = events[evt.GetId()]; ent.SetId(evt.GetId()); ent.SetDirty(false); } Logger::Log(LogLevel::LEVEL_TRACE, "event id:%d channel:%d start:%d stop:%d title:%s desc:%s", evt.GetId(), evt.GetChannel(), (int)evt.GetStart(), (int)evt.GetStop(), evt.GetTitle().c_str(), evt.GetDesc().c_str()); /* Transfer event to Kodi (callback) */ PushEpgEventUpdate(evt, (!bAdd || bUpdated) ? EPG_EVENT_UPDATED : EPG_EVENT_CREATED); } void CTvheadend::ParseEventDelete ( htsmsg_t *msg ) { uint32_t u32; /* Validate */ if (htsmsg_get_u32(msg, "eventId", &u32)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed eventDelete: 'eventId' missing"); return; } Logger::Log(LogLevel::LEVEL_TRACE, "delete event %u", u32); /* Erase */ for (auto &entry : m_schedules) { Schedule &schedule = entry.second; EventUids &events = schedule.GetEvents(); // Find the event so we can get the channel number auto eit = events.find(u32); if (eit != events.end()) { Logger::Log(LogLevel::LEVEL_TRACE, "deleted event %d from channel %d", u32, schedule.GetId()); events.erase(eit); /* Transfer event to Kodi (callback) */ Event evt; evt.SetId(u32); evt.SetChannel(schedule.GetId()); PushEpgEventUpdate(evt, EPG_EVENT_DELETED); return; } } } uint32_t CTvheadend::GetNextUnnumberedChannelNumber() { static uint32_t number = UNNUMBERED_CHANNEL; return number++; } void CTvheadend::TuneOnOldest( uint32_t channelId ) { HTSPDemuxer* oldest = NULL; for (auto *dmx : m_dmx) { if (dmx->GetChannelId() == channelId) { dmx->Weight(SUBSCRIPTION_WEIGHT_PRETUNING); return; } if (dmx == m_dmx_active) continue; if (oldest == NULL || dmx->GetLastUse() <= oldest->GetLastUse()) oldest = dmx; } if (oldest) { Logger::Log(LogLevel::LEVEL_TRACE, "pretuning channel %u on subscription %u", m_channels[channelId].GetNum(), oldest->GetSubscriptionId()); oldest->Open(channelId, SUBSCRIPTION_WEIGHT_PRETUNING); } } void CTvheadend::PredictiveTune( uint32_t fromChannelId, uint32_t toChannelId ) { CLockObject lock(m_mutex); /* Consult the predictive tuning helper for which channel * should be predictably tuned next */ uint32_t predictedChannelId = m_channelTuningPredictor.PredictNextChannelId(fromChannelId, toChannelId); if (predictedChannelId != predictivetune::CHANNEL_ID_NONE) TuneOnOldest(predictedChannelId); } bool CTvheadend::DemuxOpen( const PVR_CHANNEL &chn ) { HTSPDemuxer *oldest; uint32_t prevId; oldest = m_dmx[0]; if (m_dmx.size() == 1) { /* speedup things if we don't use predictive tuning */ m_playingLiveStream = oldest->Open(chn.iUniqueId, SUBSCRIPTION_WEIGHT_SERVERCONF); m_dmx_active = oldest; return m_playingLiveStream; } /* If we have a lingering subscription for the target channel * we reuse that subscription */ for (auto *dmx : m_dmx) { if (dmx->GetChannelId() == chn.iUniqueId) { Logger::Log(LogLevel::LEVEL_TRACE, "retuning channel %u on subscription %u", m_channels[chn.iUniqueId].GetNum(), dmx->GetSubscriptionId()); if (dmx != m_dmx_active) { /* Lower the priority on the current subscrption */ m_dmx_active->Weight(SUBSCRIPTION_WEIGHT_POSTTUNING); prevId = m_dmx_active->GetChannelId(); /* Promote the lingering subscription to the active one */ dmx->Weight(SUBSCRIPTION_WEIGHT_NORMAL); m_dmx_active = dmx; PredictiveTune(prevId, chn.iUniqueId); m_streamchange = true; } m_playingLiveStream = true; return true; } if (dmx->GetLastUse() < oldest->GetLastUse()) oldest = dmx; } /* If we don't have an existing subscription for the channel we create one * on the oldest demuxer */ Logger::Log(LogLevel::LEVEL_TRACE, "tuning channel %u on subscription %u", m_channels[chn.iUniqueId].GetNum(), oldest->GetSubscriptionId()); prevId = m_dmx_active->GetChannelId(); m_dmx_active->Weight(SUBSCRIPTION_WEIGHT_POSTTUNING); m_playingLiveStream = oldest->Open(chn.iUniqueId, SUBSCRIPTION_WEIGHT_NORMAL); m_dmx_active = oldest; if (m_playingLiveStream) PredictiveTune(prevId, chn.iUniqueId); return m_playingLiveStream; } DemuxPacket* CTvheadend::DemuxRead ( void ) { DemuxPacket *pkt = NULL; if (m_streamchange) { /* when switching to a previously used channel, we have to trigger a stream * change update through kodi. We don't queue that through the dmx packet * buffer, as we really want to use the currently queued packets for * immediate playback. */ pkt = PVR->AllocateDemuxPacket(0); pkt->iStreamId = DMX_SPECIALID_STREAMCHANGE; m_streamchange = false; return pkt; } for (auto *dmx : m_dmx) { if (dmx == m_dmx_active) pkt = dmx->Read(); else dmx->Trim(); } return pkt; } void CTvheadend::DemuxClose ( void ) { // If predictive tuning is active, demuxers will be closed automatically once they are expired. if (m_dmx.size() == 1) m_dmx_active->Close(); m_playingLiveStream = false; } void CTvheadend::DemuxFlush ( void ) { m_dmx_active->Flush(); } void CTvheadend::DemuxAbort ( void ) { // If predictive tuning is active, demuxers will be closed/aborted automatically once they are expired. if (m_dmx.size() == 1) m_dmx_active->Abort(); } bool CTvheadend::DemuxSeek ( double time, bool backward, double *startpts ) { return m_dmx_active->Seek(time, backward, startpts); } void CTvheadend::DemuxSpeed ( int speed ) { m_dmx_active->Speed(speed); } PVR_ERROR CTvheadend::DemuxCurrentStreams ( PVR_STREAM_PROPERTIES *streams ) { return m_dmx_active->CurrentStreams(streams); } PVR_ERROR CTvheadend::DemuxCurrentSignal ( PVR_SIGNAL_STATUS &sig ) { return m_dmx_active->CurrentSignal(sig); } PVR_ERROR CTvheadend::DemuxCurrentDescramble( PVR_DESCRAMBLE_INFO *info) { return m_dmx_active->CurrentDescrambleInfo(info); } bool CTvheadend::DemuxIsTimeShifting() const { return m_dmx_active->IsTimeShifting(); } bool CTvheadend::DemuxIsRealTimeStream() const { return m_dmx_active->IsRealTimeStream(); } PVR_ERROR CTvheadend::GetStreamTimes(PVR_STREAM_TIMES *times) { if (m_playingLiveStream) { return m_dmx_active->GetStreamTimes(times); } CLockObject lock(m_mutex); if (m_playingRecording) { *times = {0}; if (m_playingRecording->GetState() == PVR_TIMER_STATE_RECORDING) { if (m_playingRecording->GetFilesStart() > 0) { times->ptsEnd = (std::time(nullptr) - m_playingRecording->GetFilesStart()) * DVD_TIME_BASE; } else { // Older tvh versions do not expose real recording start/stop time. // Remark: Following calculation does not always work. Returned end time might be to large, as the // recording might actually have started later than scheduled start time (server came up too late etc). times->ptsEnd = (m_playingRecording->GetStartExtra() * 60 + std::time(nullptr) - m_playingRecording->GetStart()) * DVD_TIME_BASE; } } else { if (m_playingRecording->GetFilesStart() > 0 && m_playingRecording->GetFilesStop() > 0) { times->ptsEnd = (m_playingRecording->GetFilesStop() - m_playingRecording->GetFilesStart()) * DVD_TIME_BASE; } else { // Older tvh versions do not expose real recording start/stop time. // Remark: Kodi is handling finished recording's times very well on its own - in difference to // in-progress recording's times. Returning not implemented will make Kodi handle the stream times. return PVR_ERROR_NOT_IMPLEMENTED; } } return PVR_ERROR_NO_ERROR; } return PVR_ERROR_INVALID_PARAMETERS; } pvr.hts-4.4.20-Leia/src/Tvheadend.h000066400000000000000000000206301355512543200167250ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2014 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 * */ extern "C" { #include #include "libhts/htsmsg.h" } #include #include #include #include "p8-platform/util/buffer.h" #include "p8-platform/threads/threads.h" #include "tvheadend/AutoRecordings.h" #include "tvheadend/ChannelTuningPredictor.h" #include "tvheadend/HTSPMessage.h" #include "tvheadend/IHTSPConnectionListener.h" #include "tvheadend/Profile.h" #include "tvheadend/TimeRecordings.h" #include "tvheadend/entity/Channel.h" #include "tvheadend/entity/Recording.h" #include "tvheadend/entity/Schedule.h" #include "tvheadend/entity/Tag.h" #include "tvheadend/utilities/AsyncState.h" #include "client.h" #define UNNUMBERED_CHANNEL (10000) /* * Forward decleration of classes */ namespace tvheadend { class HTSPConnection; class HTSPDemuxer; class HTSPVFS; } /* Typedefs */ typedef P8PLATFORM::SyncedBuffer HTSPMessageQueue; /* * Root object for Tvheadend connection */ class CTvheadend : public P8PLATFORM::CThread, public tvheadend::IHTSPConnectionListener { public: CTvheadend(PVR_PROPERTIES *pvrProps); ~CTvheadend() override; void Start ( void ); void Stop ( void ); // IHTSPConnectionListener implementation void Disconnected() override; bool Connected() override; bool ProcessMessage(const char *method, htsmsg_t *msg) override; const tvheadend::entity::Channels& GetChannels () const { return m_channels; } PVR_ERROR GetDriveSpace ( long long *total, long long *used ); int GetTagCount ( void ); PVR_ERROR GetTags ( ADDON_HANDLE handle, bool bRadio ); PVR_ERROR GetTagMembers ( ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group ); int GetChannelCount ( void ); PVR_ERROR GetChannels ( ADDON_HANDLE handle, bool radio ); int GetRecordingCount ( void ); PVR_ERROR GetRecordings ( ADDON_HANDLE handle ); PVR_ERROR GetRecordingEdl ( const PVR_RECORDING &rec, PVR_EDL_ENTRY edl[], int *num ); PVR_ERROR DeleteRecording ( const PVR_RECORDING &rec ); PVR_ERROR RenameRecording ( const PVR_RECORDING &rec ); PVR_ERROR SetLifetime (const PVR_RECORDING &rec); PVR_ERROR SetPlayCount ( const PVR_RECORDING &rec, int playcount ); PVR_ERROR SetPlayPosition ( const PVR_RECORDING &rec, int playposition ); int GetPlayPosition ( const PVR_RECORDING &rec ); PVR_ERROR GetTimerTypes ( PVR_TIMER_TYPE types[], int *size ); int GetTimerCount ( void ); PVR_ERROR GetTimers ( ADDON_HANDLE handle ); PVR_ERROR AddTimer ( const PVR_TIMER &tmr ); PVR_ERROR DeleteTimer ( const PVR_TIMER &tmr, bool force ); PVR_ERROR UpdateTimer ( const PVR_TIMER &tmr ); PVR_ERROR GetEPGForChannel ( ADDON_HANDLE handle, const PVR_CHANNEL &chn, time_t start, time_t end ); PVR_ERROR SetEPGTimeFrame ( int iDays ); void GetLivetimeValues(std::vector>& lifetimeValues) const; private: bool CreateTimer ( const tvheadend::entity::Recording &tvhTmr, PVR_TIMER &tmr ); uint32_t GetNextUnnumberedChannelNumber (); std::string GetImageURL ( const char *str ); /** * Queries the server for available streaming profiles and populates * m_profiles */ void QueryAvailableProfiles(); /** * @param streamingProfile the streaming profile to check for * @return whether the server supports the specified streaming profile */ bool HasStreamingProfile(const std::string &streamingProfile) const; /* * Predictive tuning */ void PredictiveTune ( uint32_t fromChannelId, uint32_t toChannelId ); void TuneOnOldest ( uint32_t channelId ); /* * Message processing (CThread implementation) */ void *Process() override; /* * Event handling */ void TriggerChannelGroupsUpdate(); void TriggerChannelUpdate(); void TriggerRecordingUpdate(); void TriggerTimerUpdate(); void PushEpgEventUpdate(const tvheadend::entity::Event &epg, EPG_EVENT_STATE state); /* * Epg Handling */ void CreateEvent ( const tvheadend::entity::Event &event, EPG_TAG &epg ); void TransferEvent ( const tvheadend::entity::Event &event, EPG_EVENT_STATE state ); void TransferEvent ( ADDON_HANDLE handle, const tvheadend::entity::Event &event ); /* * Message sending */ PVR_ERROR SendDvrDelete ( uint32_t id, const char *method ); PVR_ERROR SendDvrUpdate ( htsmsg_t *m ); /* * Channel/Tags/Recordings/Events */ void SyncChannelsCompleted ( void ); void SyncDvrCompleted ( void ); void SyncEpgCompleted ( void ); void SyncCompleted ( void ); void ParseTagAddOrUpdate ( htsmsg_t *m, bool bAdd ); void ParseTagDelete ( htsmsg_t *m ); void ParseChannelAddOrUpdate ( htsmsg_t *m, bool bAdd ); void ParseChannelDelete ( htsmsg_t *m ); void ParseRecordingAddOrUpdate ( htsmsg_t *m, bool bAdd ); void ParseRecordingDelete ( htsmsg_t *m ); void ParseEventAddOrUpdate ( htsmsg_t *m, bool bAdd ); void ParseEventDelete ( htsmsg_t *m ); bool ParseEvent ( htsmsg_t *msg, bool bAdd, tvheadend::entity::Event &evt ); /* * VFS */ bool VfsIsActiveRecording() const { return m_playingRecording && m_playingRecording->GetState() == PVR_TIMER_STATE_RECORDING; } public: /* * Connection (pass-thru) */ std::string GetServerName() const; std::string GetServerVersion() const; std::string GetServerString() const; int GetProtocol() const; bool HasCapability(const std::string &capability) const; void OnSleep(); void OnWake(); /* * Demuxer */ bool DemuxOpen ( const PVR_CHANNEL &chn ); void DemuxClose ( void ); DemuxPacket *DemuxRead ( void ); void DemuxFlush ( void ); void DemuxAbort ( void ); bool DemuxSeek ( double time, bool backward, double *startpts ); void DemuxSpeed ( int speed ); PVR_ERROR DemuxCurrentStreams ( PVR_STREAM_PROPERTIES *streams ); PVR_ERROR DemuxCurrentSignal ( PVR_SIGNAL_STATUS &sig ); PVR_ERROR DemuxCurrentDescramble( PVR_DESCRAMBLE_INFO *info); bool DemuxIsTimeShifting() const; bool DemuxIsRealTimeStream() const; void CloseExpiredSubscriptions(); /* * VFS (pass-thru) */ bool VfsOpen(const PVR_RECORDING &rec); void VfsClose(); ssize_t VfsRead(unsigned char *buf, unsigned int len); long long VfsSeek(long long position, int whence); long long VfsSize(); void VfsPauseStream(bool paused); bool VfsIsRealTimeStream(); /* * stream times (live streams and recordings) */ PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES *times); /** * The streaming profiles available on the server */ tvheadend::Profiles m_profiles; P8PLATFORM::CMutex m_mutex; tvheadend::HTSPConnection* m_conn; std::vector m_dmx; tvheadend::HTSPDemuxer* m_dmx_active; bool m_streamchange; tvheadend::HTSPVFS* m_vfs; HTSPMessageQueue m_queue; tvheadend::entity::Channels m_channels; tvheadend::entity::Tags m_tags; tvheadend::entity::Recordings m_recordings; tvheadend::entity::Schedules m_schedules; tvheadend::ChannelTuningPredictor m_channelTuningPredictor; tvheadend::SHTSPEventList m_events; tvheadend::utilities::AsyncState m_asyncState; tvheadend::TimeRecordings m_timeRecordings; tvheadend::AutoRecordings m_autoRecordings; int m_epgMaxDays; bool m_playingLiveStream; tvheadend::entity::Recording* m_playingRecording; }; pvr.hts-4.4.20-Leia/src/client.cpp000066400000000000000000000331341355512543200166370ustar00rootroot00000000000000/* * Copyright (C) 2005-2011 Team XBMC * http://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 "client.h" #include "kodi/xbmc_pvr_dll.h" #include "kodi/libKODI_guilib.h" #include "p8-platform/util/util.h" #include "Tvheadend.h" #include "tvheadend/Settings.h" #include "tvheadend/utilities/Logger.h" using namespace ADDON; using namespace P8PLATFORM; using namespace tvheadend; using namespace tvheadend::utilities; /* ************************************************************************** * Global variables * *************************************************************************/ /* * Client state */ ADDON_STATUS m_CurStatus = ADDON_STATUS_UNKNOWN; /* * Globals */ CMutex g_mutex; CHelper_libXBMC_addon *XBMC = NULL; CHelper_libXBMC_pvr *PVR = NULL; PVR_MENUHOOK *menuHook = NULL; CTvheadend *tvh = NULL; /* ************************************************************************** * ADDON setup * *************************************************************************/ extern "C" { void ADDON_ReadSettings(void) { Settings::GetInstance().ReadSettings(); } ADDON_STATUS ADDON_Create(void* hdl, void* props) { if (!hdl || !props) return m_CurStatus; /* Instantiate helpers */ XBMC = new CHelper_libXBMC_addon; PVR = new CHelper_libXBMC_pvr; if (!XBMC->RegisterMe(hdl) || !PVR->RegisterMe(hdl)) { SAFE_DELETE(PVR); SAFE_DELETE(XBMC); m_CurStatus = ADDON_STATUS_PERMANENT_FAILURE; return m_CurStatus; } /* Configure the logger */ Logger::GetInstance().SetImplementation([](LogLevel level, const char *message) { /* Convert the log level */ addon_log_t addonLevel; switch (level) { case LogLevel::LEVEL_ERROR: addonLevel = addon_log_t::LOG_ERROR; break; case LogLevel::LEVEL_INFO: addonLevel = addon_log_t::LOG_INFO; break; default: addonLevel = addon_log_t::LOG_DEBUG; } /* Don't log trace messages unless told so */ if (level == LogLevel::LEVEL_TRACE && !Settings::GetInstance().GetTraceDebug()) return; XBMC->Log(addonLevel, "%s", message); }); Logger::GetInstance().SetPrefix("pvr.hts"); Logger::Log(LogLevel::LEVEL_INFO, "starting PVR client"); ADDON_ReadSettings(); tvh = new CTvheadend(reinterpret_cast(props)); tvh->Start(); m_CurStatus = ADDON_STATUS_OK; return m_CurStatus; } ADDON_STATUS ADDON_GetStatus() { CLockObject lock(g_mutex); return m_CurStatus; } void ADDON_Destroy() { CLockObject lock(g_mutex); tvh->Stop(); SAFE_DELETE(tvh); SAFE_DELETE(PVR); SAFE_DELETE(XBMC); SAFE_DELETE(menuHook); m_CurStatus = ADDON_STATUS_UNKNOWN; } ADDON_STATUS ADDON_SetSetting (const char *settingName, const void *settingValue) { CLockObject lock(g_mutex); m_CurStatus = Settings::GetInstance().SetSetting(settingName, settingValue); return m_CurStatus; } void OnSystemSleep() { tvh->OnSleep(); } void OnSystemWake() { tvh->OnWake(); } void OnPowerSavingActivated() { } void OnPowerSavingDeactivated() { } /* ************************************************************************** * Capabilities / Info * *************************************************************************/ PVR_ERROR GetAddonCapabilities(PVR_ADDON_CAPABILITIES* pCapabilities) { pCapabilities->bSupportsEPG = true; pCapabilities->bSupportsTV = true; pCapabilities->bSupportsRadio = true; pCapabilities->bSupportsRecordings = true; pCapabilities->bSupportsRecordingsUndelete = false; pCapabilities->bSupportsTimers = true; pCapabilities->bSupportsChannelGroups = true; pCapabilities->bHandlesInputStream = true; pCapabilities->bHandlesDemuxing = true; pCapabilities->bSupportsRecordingEdl = true; pCapabilities->bSupportsRecordingPlayCount = (tvh->GetProtocol() >= 27 && Settings::GetInstance().GetDvrPlayStatus()); pCapabilities->bSupportsLastPlayedPosition = (tvh->GetProtocol() >= 27 && Settings::GetInstance().GetDvrPlayStatus()); pCapabilities->bSupportsDescrambleInfo = true; pCapabilities->bSupportsAsyncEPGTransfer = Settings::GetInstance().GetAsyncEpg(); if (tvh->GetProtocol() >= 28) { pCapabilities->bSupportsRecordingsRename = true; pCapabilities->bSupportsRecordingsLifetimeChange = true; /* PVR_RECORDING.iLifetime values and presentation.*/ std::vector> lifetimeValues; tvh->GetLivetimeValues(lifetimeValues); pCapabilities->iRecordingsLifetimesSize = lifetimeValues.size(); int i = 0; for (auto it = lifetimeValues.cbegin(); it != lifetimeValues.cend(); ++it, ++i) { pCapabilities->recordingsLifetimeValues[i].iValue = it->first; strncpy(pCapabilities->recordingsLifetimeValues[i].strDescription, it->second.c_str(), sizeof(pCapabilities->recordingsLifetimeValues[i].strDescription) - 1); } } return PVR_ERROR_NO_ERROR; } const char *GetBackendName(void) { static std::string serverName; serverName = tvh->GetServerName(); return serverName.c_str(); } const char *GetBackendVersion(void) { static std::string serverVersion; serverVersion = tvh->GetServerVersion(); return serverVersion.c_str(); } const char *GetConnectionString(void) { static std::string serverString; serverString = tvh->GetServerString(); return serverString.c_str(); } const char *GetBackendHostname(void) { return Settings::GetInstance().GetConstCharHostname(); } PVR_ERROR GetDriveSpace(long long *iTotal, long long *iUsed) { return tvh->GetDriveSpace(iTotal, iUsed); } /* ************************************************************************** * GUI hooks * *************************************************************************/ PVR_ERROR CallMenuHook(const PVR_MENUHOOK&, const PVR_MENUHOOK_DATA&) { return PVR_ERROR_NO_ERROR; } /* ************************************************************************** * Demuxer * *************************************************************************/ PVR_ERROR GetStreamReadChunkSize(int* chunksize) { if (!chunksize) return PVR_ERROR_INVALID_PARAMETERS; *chunksize = Settings::GetInstance().GetStreamReadChunkSize() * 1024; return PVR_ERROR_NO_ERROR; } bool CanPauseStream(void) { return tvh->HasCapability("timeshift"); } bool CanSeekStream(void) { return tvh->HasCapability("timeshift"); } PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES *times) { if (!times) return PVR_ERROR_INVALID_PARAMETERS; return tvh->GetStreamTimes(times); } bool IsTimeshifting(void) { return tvh->DemuxIsTimeShifting(); } bool IsRealTimeStream() { if (tvh->m_playingRecording) return tvh->VfsIsRealTimeStream(); else return tvh->DemuxIsRealTimeStream(); } bool OpenLiveStream(const PVR_CHANNEL &channel) { return tvh->DemuxOpen(channel); } void CloseLiveStream(void) { tvh->DemuxClose(); } bool SeekTime(double time,bool backward,double *startpts) { return tvh->DemuxSeek(time, backward, startpts); } void SetSpeed(int speed) { tvh->DemuxSpeed(speed); } void PauseStream(bool paused) { if (tvh->m_playingRecording) tvh->VfsPauseStream(paused); } PVR_ERROR GetStreamProperties(PVR_STREAM_PROPERTIES* pProperties) { return tvh->DemuxCurrentStreams(pProperties); } PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS &signalStatus) { return tvh->DemuxCurrentSignal(signalStatus); } PVR_ERROR GetDescrambleInfo(PVR_DESCRAMBLE_INFO* descrambleInfo) { if (!descrambleInfo) return PVR_ERROR_INVALID_PARAMETERS; return tvh->DemuxCurrentDescramble(descrambleInfo); } DemuxPacket* DemuxRead(void) { return tvh->DemuxRead(); } void DemuxAbort(void) { tvh->DemuxAbort(); } void DemuxReset(void) { } void DemuxFlush(void) { tvh->DemuxFlush(); } /* ************************************************************************** * Channel Management * *************************************************************************/ int GetChannelGroupsAmount(void) { return tvh->GetTagCount(); } PVR_ERROR GetChannelGroups(ADDON_HANDLE handle, bool bRadio) { return tvh->GetTags(handle, bRadio); } PVR_ERROR GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group) { return tvh->GetTagMembers(handle, group); } int GetChannelsAmount(void) { return tvh->GetChannelCount(); } PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio) { return tvh->GetChannels(handle, bRadio); } /* ************************************************************************** * EPG * *************************************************************************/ PVR_ERROR GetEPGForChannel (ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd) { return tvh->GetEPGForChannel(handle, channel, iStart, iEnd); } PVR_ERROR SetEPGTimeFrame(int iDays) { return tvh->SetEPGTimeFrame(iDays); } /* ************************************************************************** * Recording Management * *************************************************************************/ int GetRecordingsAmount(bool deleted) { return tvh->GetRecordingCount(); } PVR_ERROR GetRecordings(ADDON_HANDLE handle, bool deleted) { return tvh->GetRecordings(handle); } PVR_ERROR GetRecordingEdl (const PVR_RECORDING &rec, PVR_EDL_ENTRY edl[], int *num) { return tvh->GetRecordingEdl(rec, edl, num); } PVR_ERROR DeleteRecording(const PVR_RECORDING &rec) { return tvh->DeleteRecording(rec); } PVR_ERROR RenameRecording(const PVR_RECORDING &rec) { return tvh->RenameRecording(rec); } PVR_ERROR UndeleteRecording(const PVR_RECORDING& recording) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR DeleteAllRecordingsFromTrash() { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR SetRecordingLifetime(const PVR_RECORDING *recording) { if (!recording) { Logger::Log(LogLevel::LEVEL_ERROR, "recording must not be nullptr"); return PVR_ERROR_INVALID_PARAMETERS; } return tvh->SetLifetime(*recording); } PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING &recording, int count) { return tvh->SetPlayCount(recording, count); } PVR_ERROR SetRecordingLastPlayedPosition(const PVR_RECORDING &recording, int lastplayedposition) { return tvh->SetPlayPosition(recording, lastplayedposition); } int GetRecordingLastPlayedPosition(const PVR_RECORDING &recording) { return tvh->GetPlayPosition(recording); } PVR_ERROR GetTimerTypes(PVR_TIMER_TYPE types[], int *size) { return tvh->GetTimerTypes(types, size); } int GetTimersAmount(void) { return tvh->GetTimerCount(); } PVR_ERROR GetTimers(ADDON_HANDLE handle) { return tvh->GetTimers(handle); } PVR_ERROR AddTimer(const PVR_TIMER &timer) { return tvh->AddTimer(timer); } PVR_ERROR DeleteTimer(const PVR_TIMER &timer, bool bForceDelete) { return tvh->DeleteTimer(timer, bForceDelete); } PVR_ERROR UpdateTimer(const PVR_TIMER &timer) { return tvh->UpdateTimer(timer); } /* ************************************************************************** * Recording VFS * *************************************************************************/ bool OpenRecordedStream(const PVR_RECORDING &recording) { return tvh->VfsOpen(recording); } void CloseRecordedStream(void) { tvh->VfsClose(); } int ReadRecordedStream(unsigned char *pBuffer, unsigned int iBufferSize) { return static_cast(tvh->VfsRead(pBuffer, iBufferSize)); } long long SeekRecordedStream(long long iPosition, int iWhence /* = SEEK_SET */) { return tvh->VfsSeek(iPosition, iWhence); } long long LengthRecordedStream(void) { return tvh->VfsSize(); } /* ************************************************************************** * Unused Functions * *************************************************************************/ PVR_ERROR OpenDialogChannelScan(void) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR DeleteChannel(const PVR_CHANNEL&) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR RenameChannel(const PVR_CHANNEL&) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR OpenDialogChannelSettings(const PVR_CHANNEL&) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR OpenDialogChannelAdd(const PVR_CHANNEL&) { return PVR_ERROR_NOT_IMPLEMENTED; } int ReadLiveStream(unsigned char *, unsigned int) { return 0; } long long SeekLiveStream(long long, int) { return -1; } long long LengthLiveStream(void) { return -1; } PVR_ERROR GetChannelStreamProperties(const PVR_CHANNEL*, PVR_NAMED_VALUE*, unsigned int*) { 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; } } /* extern "C" */ pvr.hts-4.4.20-Leia/src/client.h000066400000000000000000000017721355512543200163070ustar00rootroot00000000000000#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 * */ #include "p8-platform/os.h" #include "kodi/libXBMC_addon.h" #include "kodi/libXBMC_pvr.h" extern ADDON::CHelper_libXBMC_addon* XBMC; extern CHelper_libXBMC_pvr* PVR; pvr.hts-4.4.20-Leia/src/tvheadend/000077500000000000000000000000001355512543200166135ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/src/tvheadend/AutoRecordings.cpp000066400000000000000000000376171355512543200222650ustar00rootroot00000000000000/* * Copyright (C) 2005-2015 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Kodi; 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 "AutoRecordings.h" #include "HTSPConnection.h" #include "Settings.h" #include "entity/Recording.h" #include "utilities/Utilities.h" #include "utilities/Logger.h" #include "utilities/LifetimeMapper.h" using namespace P8PLATFORM; using namespace tvheadend; using namespace tvheadend::entity; using namespace tvheadend::utilities; AutoRecordings::AutoRecordings(HTSPConnection &conn) : m_conn(conn) { } AutoRecordings::~AutoRecordings() { } void AutoRecordings::Connected() { /* Flag all async fields in case they've been deleted */ for (auto it = m_autoRecordings.begin(); it != m_autoRecordings.end(); ++it) it->second.SetDirty(true); } void AutoRecordings::SyncDvrCompleted() { utilities::erase_if(m_autoRecordings, [](const AutoRecordingMapEntry &entry) { return entry.second.IsDirty(); }); } int AutoRecordings::GetAutorecTimerCount() const { return m_autoRecordings.size(); } void AutoRecordings::GetAutorecTimers(std::vector &timers) { for (auto tit = m_autoRecordings.begin(); tit != m_autoRecordings.end(); ++tit) { /* Setup entry */ PVR_TIMER tmr = { 0 }; tmr.iClientIndex = tit->second.GetId(); tmr.iClientChannelUid = (tit->second.GetChannel() > 0) ? tit->second.GetChannel() : PVR_TIMER_ANY_CHANNEL; tmr.startTime = tit->second.GetStart(); tmr.endTime = tit->second.GetStop(); if (tmr.startTime == 0) tmr.bStartAnyTime = true; if (tmr.endTime == 0) tmr.bEndAnyTime = true; if (!tmr.bStartAnyTime && tmr.bEndAnyTime) tmr.endTime = tmr.startTime + 60 * 60; // Nominal 1 hour duration if (tmr.bStartAnyTime && !tmr.bEndAnyTime) tmr.startTime = tmr.endTime - 60 * 60; // Nominal 1 hour duration if (tmr.bStartAnyTime && tmr.bEndAnyTime) { tmr.startTime = time(NULL); // now tmr.endTime = tmr.startTime + 60 * 60; // Nominal 1 hour duration } if (tit->second.GetName().empty()) // timers created on backend may not contain a name strncpy(tmr.strTitle, tit->second.GetTitle().c_str(), sizeof(tmr.strTitle) - 1); else strncpy(tmr.strTitle, tit->second.GetName().c_str(), sizeof(tmr.strTitle) - 1); strncpy(tmr.strEpgSearchString, tit->second.GetTitle().c_str(), sizeof(tmr.strEpgSearchString) - 1); strncpy(tmr.strDirectory, tit->second.GetDirectory().c_str(), sizeof(tmr.strDirectory) - 1); strncpy(tmr.strSummary, "", sizeof(tmr.strSummary) - 1); // n/a for repeating timers strncpy(tmr.strSeriesLink, tit->second.GetSeriesLink().c_str(), sizeof(tmr.strSeriesLink) - 1); tmr.state = tit->second.IsEnabled() ? PVR_TIMER_STATE_SCHEDULED : PVR_TIMER_STATE_DISABLED; tmr.iTimerType = tit->second.GetSeriesLink().empty() ? TIMER_REPEATING_EPG : TIMER_REPEATING_SERIESLINK; tmr.iPriority = tit->second.GetPriority(); tmr.iLifetime = tit->second.GetLifetime(); tmr.iMaxRecordings = 0; // not supported by tvh tmr.iRecordingGroup = 0; // not supported by tvh if (m_conn.GetProtocol() >= 20) tmr.iPreventDuplicateEpisodes = tit->second.GetDupDetect(); else tmr.iPreventDuplicateEpisodes = 0; // not supported by tvh tmr.firstDay = 0; // not supported by tvh tmr.iWeekdays = tit->second.GetDaysOfWeek(); tmr.iEpgUid = PVR_TIMER_NO_EPG_UID; // n/a for repeating timers tmr.iMarginStart = static_cast(tit->second.GetMarginStart()); tmr.iMarginEnd = static_cast(tit->second.GetMarginEnd()); tmr.iGenreType = 0; // not supported by tvh? tmr.iGenreSubType = 0; // not supported by tvh? tmr.bFullTextEpgSearch = tit->second.GetFulltext(); tmr.iParentClientIndex = 0; timers.emplace_back(tmr); } } const unsigned int AutoRecordings::GetTimerIntIdFromStringId(const std::string &strId) const { for (auto tit = m_autoRecordings.begin(); tit != m_autoRecordings.end(); ++tit) { if (tit->second.GetStringId() == strId) return tit->second.GetId(); } Logger::Log(LogLevel::LEVEL_ERROR, "Autorec: Unable to obtain int id for string id %s", strId.c_str()); return 0; } const std::string AutoRecordings::GetTimerStringIdFromIntId(unsigned int intId) const { for (auto tit = m_autoRecordings.begin(); tit != m_autoRecordings.end(); ++tit) { if (tit->second.GetId() == intId) return tit->second.GetStringId(); } Logger::Log(LogLevel::LEVEL_ERROR, "Autorec: Unable to obtain string id for int id %s", intId); return ""; } PVR_ERROR AutoRecordings::SendAutorecAdd(const PVR_TIMER &timer) { return SendAutorecAddOrUpdate(timer, false); } PVR_ERROR AutoRecordings::SendAutorecUpdate(const PVR_TIMER &timer) { if (m_conn.GetProtocol() >= 25) return SendAutorecAddOrUpdate(timer, true); /* Note: there is no "updateAutorec" htsp method for htsp version < 25, thus delete + add. */ PVR_ERROR error = SendAutorecDelete(timer); if (error == PVR_ERROR_NO_ERROR) error = SendAutorecAdd(timer); return error; } PVR_ERROR AutoRecordings::SendAutorecAddOrUpdate(const PVR_TIMER &timer, bool update) { uint32_t u32; const std::string method = update ? "updateAutorecEntry" : "addAutorecEntry"; /* Build message */ htsmsg_t *m = htsmsg_create_map(); if (update) { std::string strId = GetTimerStringIdFromIntId(timer.iClientIndex); if (strId.empty()) { htsmsg_destroy(m); return PVR_ERROR_FAILED; } htsmsg_add_str(m, "id", strId.c_str()); // Autorec DVR Entry ID (string! } htsmsg_add_str(m, "name", timer.strTitle); /* epg search data match string (regexp) */ htsmsg_add_str(m, "title", timer.strEpgSearchString); /* fulltext epg search: */ /* "title" not empty && !fulltext => match strEpgSearchString against episode title only */ /* "title" not empty && fulltext => match strEpgSearchString against episode title, episode */ /* subtitle, episode summary and episode description (HTSPv19) */ if (m_conn.GetProtocol() >= 20) htsmsg_add_u32(m, "fulltext", timer.bFullTextEpgSearch ? 1 : 0); htsmsg_add_s64(m, "startExtra", timer.iMarginStart); htsmsg_add_s64(m, "stopExtra", timer.iMarginEnd); if (m_conn.GetProtocol() >= 25) { htsmsg_add_u32(m, "removal", timer.iLifetime); // remove from disk htsmsg_add_s64(m, "channelId", timer.iClientChannelUid); // channelId is signed for >= htspv25, -1 = any } else { htsmsg_add_u32(m, "retention", LifetimeMapper::KodiToTvh(timer.iLifetime)); // remove from tvh database if (timer.iClientChannelUid >= 0) htsmsg_add_u32(m, "channelId", timer.iClientChannelUid); // channelId is unsigned for < htspv25, not sending = any } htsmsg_add_u32(m, "daysOfWeek", timer.iWeekdays); if (m_conn.GetProtocol() >= 20) htsmsg_add_u32(m, "dupDetect", timer.iPreventDuplicateEpisodes); htsmsg_add_u32(m, "priority", timer.iPriority); htsmsg_add_u32(m, "enabled", timer.state == PVR_TIMER_STATE_DISABLED ? 0 : 1); /* Note: As a result of internal filename cleanup, for "directory" == "/", */ /* tvh would put recordings into a folder named "-". Not a big issue */ /* but ugly. */ if (strcmp(timer.strDirectory, "/") != 0) htsmsg_add_str(m, "directory", timer.strDirectory); /* bAutorecApproxTime enabled: => start time in kodi = approximate start time in tvh */ /* => 'approximate' = starting window / 2 */ /* */ /* bAutorecApproxTime disabled: => start time in kodi = begin of starting window in tvh */ /* => end time in kodi = end of starting window in tvh */ const Settings &settings = Settings::GetInstance(); if (settings.GetAutorecApproxTime()) { /* Not sending causes server to set start and startWindow to any time */ if (timer.startTime > 0 && !timer.bStartAnyTime) { time_t startTime = timer.startTime; struct tm *tm_start = localtime(&startTime); int32_t startWindowBegin = tm_start->tm_hour * 60 + tm_start->tm_min - settings.GetAutorecMaxDiff(); int32_t startWindowEnd = tm_start->tm_hour * 60 + tm_start->tm_min + settings.GetAutorecMaxDiff(); /* Past midnight correction */ if (startWindowBegin < 0) startWindowBegin += (24 * 60); if (startWindowEnd > (24 * 60)) startWindowEnd -= (24 * 60); htsmsg_add_s32(m, "start", startWindowBegin); htsmsg_add_s32(m, "startWindow", startWindowEnd); } } else { if (timer.startTime > 0 && !timer.bStartAnyTime) { /* Exact start time (minutes from midnight). */ time_t startTime = timer.startTime; struct tm *tm_start = localtime(&startTime); htsmsg_add_s32(m, "start", tm_start->tm_hour * 60 + tm_start->tm_min); } else htsmsg_add_s32(m, "start", 25 * 60); // -1 or not sending causes server to set start and startWindow to any time if (timer.endTime > 0 && !timer.bEndAnyTime) { /* Exact stop time (minutes from midnight). */ time_t endTime = timer.endTime; struct tm *tm_stop = localtime(&endTime); htsmsg_add_s32(m, "startWindow", tm_stop->tm_hour * 60 + tm_stop->tm_min); } else htsmsg_add_s32(m, "startWindow", 25 * 60); // -1 or not sending causes server to set start and startWindow to any time } /* series link */ if (timer.iTimerType == TIMER_REPEATING_SERIESLINK) htsmsg_add_str(m, "serieslinkUri", timer.strSeriesLink); /* Send and Wait */ { CLockObject lock(m_conn.Mutex()); m = m_conn.SendAndWait(method.c_str(), m); } if (m == NULL) return PVR_ERROR_SERVER_ERROR; /* Check for error */ if (htsmsg_get_u32(m, "success", &u32)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed %s response: 'success' missing", method.c_str()); u32 = PVR_ERROR_FAILED; } htsmsg_destroy(m); return u32 == 1 ? PVR_ERROR_NO_ERROR : PVR_ERROR_FAILED; } PVR_ERROR AutoRecordings::SendAutorecDelete(const PVR_TIMER &timer) { uint32_t u32; std::string strId = GetTimerStringIdFromIntId(timer.iClientIndex); if (strId.empty()) return PVR_ERROR_FAILED; htsmsg_t *m = htsmsg_create_map(); htsmsg_add_str(m, "id", strId.c_str()); // Autorec DVR Entry ID (string!) /* Send and Wait */ { CLockObject lock(m_conn.Mutex()); m = m_conn.SendAndWait("deleteAutorecEntry", m); } if (m == NULL) return PVR_ERROR_SERVER_ERROR; /* Check for error */ if (htsmsg_get_u32(m, "success", &u32)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed deleteAutorecEntry response: 'success' missing"); } htsmsg_destroy(m); return u32 == 1 ? PVR_ERROR_NO_ERROR : PVR_ERROR_FAILED; } bool AutoRecordings::ParseAutorecAddOrUpdate(htsmsg_t *msg, bool bAdd) { const char *str; uint32_t u32; int32_t s32; int64_t s64; /* Validate/set mandatory fields */ if ((str = htsmsg_get_str(msg, "id")) == NULL) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd/autorecEntryUpdate: 'id' missing"); return false; } /* Locate/create entry */ AutoRecording &rec = m_autoRecordings[std::string(str)]; rec.SetStringId(std::string(str)); rec.SetDirty(false); /* Validate/set fields mandatory for autorecEntryAdd */ if (!htsmsg_get_u32(msg, "enabled", &u32)) { rec.SetEnabled(u32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd: 'enabled' missing"); return false; } if (m_conn.GetProtocol() >= 25) { if (!htsmsg_get_u32(msg, "removal", &u32)) { rec.SetLifetime(u32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd: 'removal' missing"); return false; } } else { if (!htsmsg_get_u32(msg, "retention", &u32)) { rec.SetLifetime(u32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd: 'retention' missing"); return false; } } if (!htsmsg_get_u32(msg, "daysOfWeek", &u32)) { rec.SetDaysOfWeek(u32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd: 'daysOfWeek' missing"); return false; } if (!htsmsg_get_u32(msg, "priority", &u32)) { rec.SetPriority(u32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd: 'priority' missing"); return false; } if (!htsmsg_get_s32(msg, "start", &s32)) { rec.SetStartWindowBegin(s32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd: 'start' missing"); return false; } if (!htsmsg_get_s32(msg, "startWindow", &s32)) { rec.SetStartWindowEnd(s32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd: 'startWindow' missing"); return false; } if (!htsmsg_get_s64(msg, "startExtra", &s64)) { rec.SetMarginStart(s64); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd: 'startExtra' missing"); return false; } if (!htsmsg_get_s64(msg, "stopExtra", &s64)) { rec.SetMarginEnd(s64); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd: 'stopExtra' missing"); return false; } if (!htsmsg_get_u32(msg, "dupDetect", &u32)) { rec.SetDupDetect(u32); } else if (bAdd && (m_conn.GetProtocol() >= 20)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryAdd: 'dupDetect' missing"); return false; } /* Add optional fields */ if ((str = htsmsg_get_str(msg, "title")) != NULL) { rec.SetTitle(str); } if ((str = htsmsg_get_str(msg, "name")) != NULL) { rec.SetName(str); } if ((str = htsmsg_get_str(msg, "directory")) != NULL) { rec.SetDirectory(str); } if ((str = htsmsg_get_str(msg, "owner")) != NULL) { rec.SetOwner(str); } if ((str = htsmsg_get_str(msg, "creator")) != NULL) { rec.SetCreator(str); } if (!htsmsg_get_u32(msg, "channel", &u32)) { rec.SetChannel(u32); } else rec.SetChannel(PVR_TIMER_ANY_CHANNEL); // an empty channel field = any channel if (!htsmsg_get_u32(msg, "fulltext", &u32)) { rec.SetFulltext(u32); } if ((str = htsmsg_get_str(msg, "serieslinkUri")) != NULL) { rec.SetSeriesLink(str); } return true; } bool AutoRecordings::ParseAutorecDelete(htsmsg_t *msg) { const char *id; /* Validate/set mandatory fields */ if ((id = htsmsg_get_str(msg, "id")) == NULL) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed autorecEntryDelete: 'id' missing"); return false; } Logger::Log(LogLevel::LEVEL_TRACE, "delete autorec entry %s", id); /* Erase */ m_autoRecordings.erase(std::string(id)); return true; } pvr.hts-4.4.20-Leia/src/tvheadend/AutoRecordings.h000066400000000000000000000037361355512543200217250ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Kodi; 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 extern "C" { #include #include "libhts/htsmsg.h" } #include "kodi/libXBMC_pvr.h" #include "entity/AutoRecording.h" namespace tvheadend { class HTSPConnection; class AutoRecordings { public: AutoRecordings(HTSPConnection &conn); ~AutoRecordings(); /* state updates */ void Connected(); void SyncDvrCompleted(); /* data access */ int GetAutorecTimerCount() const; void GetAutorecTimers(std::vector &timers); const unsigned int GetTimerIntIdFromStringId(const std::string &strId) const; /* client to server messages */ PVR_ERROR SendAutorecAdd (const PVR_TIMER &timer); PVR_ERROR SendAutorecUpdate(const PVR_TIMER &timer); PVR_ERROR SendAutorecDelete(const PVR_TIMER &timer); /* server to client messages */ bool ParseAutorecAddOrUpdate(htsmsg_t *msg, bool bAdd); bool ParseAutorecDelete(htsmsg_t *msg); private: const std::string GetTimerStringIdFromIntId(unsigned int intId) const; PVR_ERROR SendAutorecAddOrUpdate(const PVR_TIMER &timer, bool update); HTSPConnection &m_conn; tvheadend::entity::AutoRecordingsMap m_autoRecordings; }; } // namespace tvheadend pvr.hts-4.4.20-Leia/src/tvheadend/ChannelTuningPredictor.cpp000066400000000000000000000054211355512543200237320ustar00rootroot00000000000000/* * 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 * */ #include "ChannelTuningPredictor.h" #include using namespace tvheadend; using namespace tvheadend::entity; using namespace tvheadend::predictivetune; void ChannelTuningPredictor::AddChannel(const Channel &channel) { m_channels.insert(MakeChannelPair(channel)); } void ChannelTuningPredictor::UpdateChannel(const Channel &oldChannel, const Channel &newChannel) { m_channels.erase(MakeChannelPair(oldChannel)); m_channels.insert(MakeChannelPair(newChannel)); } void ChannelTuningPredictor::RemoveChannel(uint32_t channelId) { auto it = GetIterator(channelId); if (it != m_channels.end()) m_channels.erase(it); } ChannelPair ChannelTuningPredictor::MakeChannelPair(const entity::Channel &channel) { return ChannelPair(channel.GetId(), ChannelNumber(channel.GetNum(), channel.GetNumMinor())); } ChannelPairIterator ChannelTuningPredictor::GetIterator(uint32_t channelId) const { return std::find_if( m_channels.cbegin(), m_channels.cend(), [channelId](const ChannelPair &channel) { return channel.first == channelId; } ); } uint32_t ChannelTuningPredictor::PredictNextChannelId(uint32_t tuningFrom, uint32_t tuningTo) const { auto fromIt = GetIterator(tuningFrom); auto toIt = GetIterator(tuningTo); /* Determine the respective channel numbers as well as the first channel */ const ChannelNumber& firstNum = m_channels.cbegin()->second; /* Create an iterator for the predicted channel. If prediction succeeds, * it will point at the channel we should tune to */ std::set::iterator predictedIt = m_channels.cend(); if (fromIt == m_channels.cend() || std::next(fromIt, 1) == toIt || toIt->second == firstNum) { /* Tuning up or if we're tuning the first channel */ predictedIt = ++toIt; } else if (std::prev(fromIt, 1) == toIt) { /* Tuning down */ predictedIt = --toIt; } if (predictedIt != m_channels.cend()) return predictedIt->first; else return CHANNEL_ID_NONE; } pvr.hts-4.4.20-Leia/src/tvheadend/ChannelTuningPredictor.h000066400000000000000000000107061355512543200234010ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team Kodi * 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 "entity/Channel.h" #include #include namespace tvheadend { namespace predictivetune { /** * Used to indicate that predictive tuning failed to determine which * channel to be tuned next */ const uint32_t CHANNEL_ID_NONE = -1; /** * Defines a channel number */ class ChannelNumber { public: ChannelNumber() : m_channelNumber(0), m_subchannelNumber(0) {} ChannelNumber(uint32_t channelNumber, uint32_t subchannelNumber) : m_channelNumber(channelNumber), m_subchannelNumber(subchannelNumber) {} bool operator ==(const ChannelNumber &right) const { return (m_channelNumber == right.m_channelNumber && m_subchannelNumber == right.m_subchannelNumber); } bool operator <(const ChannelNumber &right) const { if (m_channelNumber == right.m_channelNumber) return m_subchannelNumber < right.m_subchannelNumber; return m_channelNumber < right.m_channelNumber; } private: uint32_t m_channelNumber; uint32_t m_subchannelNumber; }; /** * Defines a single channel ID/number pair */ typedef std::pair ChannelPair; typedef std::set::const_iterator ChannelPairIterator; /** * Sorter for channel pairs */ struct SortChannelPair { bool operator()(const ChannelPair &left, const ChannelPair &right) const { return left.second < right.second; } }; } /** * This class holds a sorted set of channel "pairs" (ID -> number mapping) and * can be used to predict which channel ID should be tuned after a normal zap * is performed. */ class ChannelTuningPredictor { public: /** * Adds the specified channel * @param channel the channel */ void AddChannel(const entity::Channel &channel); /** * Swaps the old channel with the new channel * @param oldChannel the channel that should be updated * @param newChannel the new channel */ void UpdateChannel(const entity::Channel &oldChannel, const entity::Channel &newChannel); /** * Removes the channel with the specified channel ID * @param channelId the channel ID */ void RemoveChannel(uint32_t channelId); /** * Attempts to predict the channel ID that should be tuned * @param tuningFrom the channel number we are tuning away from * @param tuningTo the channel number we are tuning to * @return the predicted channel number that should be tuned in advance, or * CHANNEL_ID_NONE if nothing could be predicted */ uint32_t PredictNextChannelId(uint32_t tuningFrom, uint32_t tuningTo) const; private: /** * Constructs a channel pair from the specified channel number * @param channel the channel to construct a pair from */ static predictivetune::ChannelPair MakeChannelPair(const entity::Channel &channel); /** * Returns an iterator positioned at the channel pair that matches the * specified channel ID. If no match is found, an end iterator is returned * @param channelId the channel ID * @return the iterator */ predictivetune::ChannelPairIterator GetIterator(uint32_t channelId) const; /** * Set of pairs which map channel IDs to channel numbers. A custsom comparator is * used to ensure that all inserted pairs are always sorted by the channel number. * This way we can get the next/previous channel by simply adjusting iterators. */ std::set m_channels; }; } pvr.hts-4.4.20-Leia/src/tvheadend/HTSPConnection.cpp000066400000000000000000000430541355512543200221230ustar00rootroot00000000000000/* * 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 * */ #include "HTSPConnection.h" extern "C" { #include "libhts/htsmsg_binary.h" #include "libhts/sha1.h" } #include "p8-platform/os.h" #include "p8-platform/util/StringUtils.h" #include "../client.h" #include "IHTSPConnectionListener.h" #include "Settings.h" #include "utilities/Logger.h" using namespace P8PLATFORM; using namespace tvheadend; using namespace tvheadend::utilities; #define FAST_RECONNECT_ATTEMPTS (5) #define FAST_RECONNECT_INTERVAL (500) // ms #define SLOW_RECONNECT_INTERVAL (5000) // ms #define HTSP_MIN_SERVER_VERSION (19) // Server must support at least this htsp version #define HTSP_CLIENT_VERSION (34) // Client uses HTSP features up to this version. If the respective // addon feature requires htsp features introduced after // HTSP_MIN_SERVER_VERSION this feature will only be available if the // actual server HTSP version matches (runtime htsp version check). namespace tvheadend { /* * HTSP Response handler */ class HTSPResponse { public: HTSPResponse() : m_flag(false), m_msg(nullptr) { } ~HTSPResponse() { if (m_msg) htsmsg_destroy(m_msg); Set(nullptr); // ensure signal is sent } htsmsg_t *Get(P8PLATFORM::CMutex &mutex, uint32_t timeout) { m_cond.Wait(mutex, m_flag, timeout); htsmsg_t *r = m_msg; m_msg = NULL; m_flag = false; return r; } void Set(htsmsg_t *msg) { m_msg = msg; m_flag = true; m_cond.Broadcast(); } private: P8PLATFORM::CCondition m_cond; bool m_flag; htsmsg_t *m_msg; }; } // namespace tvheadend /* * HTSP Connection handler */ HTSPConnection::HTSPConnection (IHTSPConnectionListener& connListener) : m_connListener(connListener), m_socket(NULL), m_regThread(new HTSPRegister(this)), m_ready(false), m_seq(0), m_serverName(""), m_serverVersion(""), m_htspVersion(0), m_webRoot(""), m_challenge(NULL), m_challengeLen(0), m_suspended(false), m_state(PVR_CONNECTION_STATE_UNKNOWN) { } HTSPConnection::~HTSPConnection() { StopThread(-1); Disconnect(); StopThread(0); delete m_regThread; } void HTSPConnection::Start() { // Note: "connecting" must only be set one time, before the very first connection attempt, not on every reconnect. SetState(PVR_CONNECTION_STATE_CONNECTING); CreateThread(); } void HTSPConnection::Stop() { StopThread(-1); Disconnect(); } /* * Info */ std::string HTSPConnection::GetWebURL ( const char *fmt, ... ) const { va_list va; const Settings &settings = Settings::GetInstance(); // Generate the authentication string (user:pass@) std::string auth = settings.GetUsername(); if (!(auth.empty() || settings.GetPassword().empty())) auth += ":" + settings.GetPassword(); if (!auth.empty()) auth += "@"; std::string url = StringUtils::Format("http://%s%s:%d", auth.c_str(), settings.GetHostname().c_str(), settings.GetPortHTTP()); CLockObject lock(m_mutex); va_start(va, fmt); url += m_webRoot; url += StringUtils::FormatV(fmt, va); va_end(va); return url; } bool HTSPConnection::WaitForConnection ( void ) { if (!m_ready) { Logger::Log(LogLevel::LEVEL_TRACE, "waiting for registration..."); m_regCond.Wait(m_mutex, m_ready, Settings::GetInstance().GetConnectTimeout()); } return m_ready; } int HTSPConnection::GetProtocol ( void ) const { CLockObject lock(m_mutex); return m_htspVersion; } std::string HTSPConnection::GetServerName ( void ) const { CLockObject lock(m_mutex); return m_serverName; } std::string HTSPConnection::GetServerVersion ( void ) const { CLockObject lock(m_mutex); return StringUtils::Format("%s (HTSP v%d)", m_serverVersion.c_str(), m_htspVersion); } std::string HTSPConnection::GetServerString ( void ) const { const Settings &settings = Settings::GetInstance(); CLockObject lock(m_mutex); return StringUtils::Format("%s:%d", settings.GetHostname().c_str(), settings.GetPortHTSP()); } bool HTSPConnection::HasCapability(const std::string &capability) const { return std::find(m_capabilities.begin(), m_capabilities.end(), capability) != m_capabilities.end(); } void HTSPConnection::OnSleep ( void ) { CLockObject lock(m_mutex); Logger::Log(LogLevel::LEVEL_TRACE, "going to sleep (OnSleep)"); /* close connection, prevent reconnect while suspending/suspended */ m_suspended = true; } void HTSPConnection::OnWake ( void ) { CLockObject lock(m_mutex); Logger::Log(LogLevel::LEVEL_TRACE, "waking up (OnWake)"); /* recreate connection */ m_suspended = false; } void HTSPConnection::SetState ( PVR_CONNECTION_STATE state ) { PVR_CONNECTION_STATE prevState(PVR_CONNECTION_STATE_UNKNOWN); PVR_CONNECTION_STATE newState(PVR_CONNECTION_STATE_UNKNOWN); { CLockObject lock(m_mutex); /* No notification if no state change or while suspended. */ if (m_state != state && !m_suspended) { prevState = m_state; newState = state; m_state = newState; Logger::Log(LogLevel::LEVEL_DEBUG, "connection state change (%d -> %d)", prevState, newState); } } if (prevState != newState) { static std::string serverString; /* Notify connection state change (callback!) */ serverString = GetServerString(); PVR->ConnectionStateChange(serverString.c_str(), newState, NULL); } } /* * Close the connection */ void HTSPConnection::Disconnect ( void ) { CLockObject lock(m_mutex); /* Close socket */ if (m_socket) { m_socket->Shutdown(); m_socket->Close(); } /* Signal all waiters and erase messages */ m_messages.clear(); } /* * Read message from socket * * Return false if an error occurs and the connection should be terminated */ bool HTSPConnection::ReadMessage ( void ) { uint8_t *buf; uint8_t lb[4]; size_t len, cnt; ssize_t r; uint32_t seq; htsmsg_t *msg; const char *method; /* Read 4 byte len */ len = m_socket->Read(&lb, sizeof(lb)); if (len != sizeof(lb)) return false; len = (lb[0] << 24) + (lb[1] << 16) + (lb[2] << 8) + lb[3]; /* Read rest of packet */ buf = (uint8_t*)malloc(len); cnt = 0; while (cnt < len) { r = m_socket->Read((char*)buf + cnt, len - cnt, Settings::GetInstance().GetResponseTimeout()); if (r < 0) { Logger::Log(LogLevel::LEVEL_ERROR, "failed to read packet (%s)", m_socket->GetError().c_str()); free(buf); return false; } cnt += r; } /* Deserialize */ if (!(msg = htsmsg_binary_deserialize(buf, len, buf))) { /* Do not free buf here. Already done by htsmsg_binary_deserialize. */ Logger::Log(LogLevel::LEVEL_ERROR, "failed to decode message"); return false; } /* Sequence number - response */ if (htsmsg_get_u32(msg, "seq", &seq) == 0) { Logger::Log(LogLevel::LEVEL_TRACE, "received response [%d]", seq); CLockObject lock(m_mutex); HTSPResponseList::iterator it; if ((it = m_messages.find(seq)) != m_messages.end()) { it->second->Set(msg); return true; } } /* Get method */ if (!(method = htsmsg_get_str(msg, "method"))) { Logger::Log(LogLevel::LEVEL_ERROR, "message without a method"); htsmsg_destroy(msg); return true; } Logger::Log(LogLevel::LEVEL_TRACE, "receive message [%s]", method); /* Pass (if return is true, message is finished) */ if (m_connListener.ProcessMessage(method, msg)) htsmsg_destroy(msg); // TODO: maybe a copy should be made if it needs to be kept? return true; } /* * Send message to server */ bool HTSPConnection::SendMessage0 ( const char *method, htsmsg_t *msg ) { int e; void *buf; size_t len; ssize_t c; uint32_t seq; if (!htsmsg_get_u32(msg, "seq", &seq)) { Logger::Log(LogLevel::LEVEL_TRACE, "sending message [%s : %d]", method, seq); } else { Logger::Log(LogLevel::LEVEL_TRACE, "sending message [%s]", method); } htsmsg_add_str(msg, "method", method); /* Serialise */ e = htsmsg_binary_serialize(msg, &buf, &len, -1); htsmsg_destroy(msg); if (e < 0) return false; /* Send data */ c = m_socket->Write(buf, len); free(buf); if (c != (ssize_t)len) { Logger::Log(LogLevel::LEVEL_ERROR, "failed to write (%s)", m_socket->GetError().c_str()); if (!m_suspended) Disconnect(); return false; } return true; } /* * Send a message and wait for response */ htsmsg_t *HTSPConnection::SendAndWait0 ( const char *method, htsmsg_t *msg, int iResponseTimeout ) { if (iResponseTimeout == -1) iResponseTimeout = Settings::GetInstance().GetResponseTimeout(); uint32_t seq; /* Add Sequence number */ HTSPResponse resp; seq = ++m_seq; htsmsg_add_u32(msg, "seq", seq); m_messages[seq] = &resp; /* Send Message (bypass TX check) */ if (!SendMessage0(method, msg)) { m_messages.erase(seq); Logger::Log(LogLevel::LEVEL_ERROR, "failed to transmit"); return NULL; } /* Wait for response */ msg = resp.Get(m_mutex, iResponseTimeout); m_messages.erase(seq); if (!msg) { Logger::Log(LogLevel::LEVEL_ERROR, "Command %s failed: No response received", method); if (!m_suspended) Disconnect(); return NULL; } /* Check result for errors and announce. */ uint32_t noaccess; if (!htsmsg_get_u32(msg, "noaccess", &noaccess) && noaccess) { // access denied Logger::Log(LogLevel::LEVEL_ERROR, "Command %s failed: Access denied", method); htsmsg_destroy(msg); return NULL; } else { const char* strError; if((strError = htsmsg_get_str(msg, "error")) != NULL) { Logger::Log(LogLevel::LEVEL_ERROR, "Command %s failed: %s", method, strError); htsmsg_destroy(msg); return NULL; } } return msg; } /* * Send and wait for response */ htsmsg_t *HTSPConnection::SendAndWait ( const char *method, htsmsg_t *msg, int iResponseTimeout ) { if (iResponseTimeout == -1) iResponseTimeout = Settings::GetInstance().GetResponseTimeout(); if (!WaitForConnection()) return NULL; return SendAndWait0(method, msg, iResponseTimeout); } bool HTSPConnection::SendHello ( void ) { /* Build message */ htsmsg_t *msg = htsmsg_create_map(); htsmsg_add_str(msg, "clientname", "Kodi Media Center"); htsmsg_add_u32(msg, "htspversion", HTSP_CLIENT_VERSION); /* Send and Wait */ if (!(msg = SendAndWait0("hello", msg))) return false; /* Process */ const char *webroot; const void *chal; size_t chal_len; htsmsg_t *cap; /* Basic Info */ webroot = htsmsg_get_str(msg, "webroot"); m_serverName = htsmsg_get_str(msg, "servername"); m_serverVersion = htsmsg_get_str(msg, "serverversion"); m_htspVersion = htsmsg_get_u32_or_default(msg, "htspversion", 0); m_webRoot = webroot ? webroot : ""; Logger::Log(LogLevel::LEVEL_DEBUG, "connected to %s / %s (HTSPv%d)", m_serverName.c_str(), m_serverVersion.c_str(), m_htspVersion); /* Capabilities */ if ((cap = htsmsg_get_list(msg, "servercapability"))) { htsmsg_field_t *f; HTSMSG_FOREACH(f, cap) { if (f->hmf_type == HMF_STR) m_capabilities.emplace_back(f->hmf_str); } } /* Authentication */ htsmsg_get_bin(msg, "challenge", &chal, &chal_len); if (chal && chal_len) { m_challenge = malloc(chal_len); m_challengeLen = chal_len; memcpy(m_challenge, chal, chal_len); } htsmsg_destroy(msg); return true; } bool HTSPConnection::SendAuth ( const std::string &user, const std::string &pass ) { uint32_t u32; htsmsg_t *msg = htsmsg_create_map(); htsmsg_add_str(msg, "username", user.c_str()); /* Add Password */ // Note: we MUST send a digest or TVH will not evaluate the struct HTSSHA1* sha = (struct HTSSHA1*)malloc(hts_sha1_size); uint8_t d[20]; hts_sha1_init(sha); hts_sha1_update(sha, (const uint8_t*)pass.c_str(), pass.length()); if (m_challenge) hts_sha1_update(sha, (const uint8_t*)m_challenge, m_challengeLen); hts_sha1_final(sha, d); htsmsg_add_bin(msg, "digest", d, sizeof(d)); free(sha); /* Send and Wait */ msg = SendAndWait0("authenticate", msg); if (msg == NULL) return 0; if (m_htspVersion >= 26) { /* Log received permissions */ Logger::Log(LogLevel::LEVEL_INFO, " Received permissions:"); if (!htsmsg_get_u32(msg, "admin", &u32)) Logger::Log(LogLevel::LEVEL_INFO, " administrator : %i", u32); if (!htsmsg_get_u32(msg, "streaming", &u32)) Logger::Log(LogLevel::LEVEL_INFO, " HTSP streaming : %i", u32); if (!htsmsg_get_u32(msg, "dvr", &u32)) Logger::Log(LogLevel::LEVEL_INFO, " HTSP DVR : %i", u32); if (!htsmsg_get_u32(msg, "faileddvr", &u32)) Logger::Log(LogLevel::LEVEL_INFO, " Failed/aborted DVR : %i", u32); if (!htsmsg_get_u32(msg, "anonymous", &u32)) Logger::Log(LogLevel::LEVEL_INFO, " anonymous HTSP only : %i", u32); if (!htsmsg_get_u32(msg, "limitall", &u32)) Logger::Log(LogLevel::LEVEL_INFO, " global connection limit : %i", u32); if (!htsmsg_get_u32(msg, "limitdvr", &u32)) Logger::Log(LogLevel::LEVEL_INFO, " DVR connection limit : %i", u32); if (!htsmsg_get_u32(msg, "limitstreaming", &u32)) Logger::Log(LogLevel::LEVEL_INFO, " streaming connection limit : %i", u32); } htsmsg_destroy(msg); return 1; } /** * Register the connection, hello+auth */ void HTSPConnection::Register ( void ) { std::string user = Settings::GetInstance().GetUsername(); std::string pass = Settings::GetInstance().GetPassword(); { CLockObject lock(m_mutex); /* Send Greeting */ Logger::Log(LogLevel::LEVEL_DEBUG, "sending hello"); if (!SendHello()) { Logger::Log(LogLevel::LEVEL_ERROR, "failed to send hello"); SetState(PVR_CONNECTION_STATE_SERVER_MISMATCH); goto fail; } /* Check htsp server version against client minimum htsp version */ if (m_htspVersion < HTSP_MIN_SERVER_VERSION) { Logger::Log(LogLevel::LEVEL_ERROR, "server htsp version (v%d) does not match minimum htsp version required by client (v%d)", m_htspVersion, HTSP_MIN_SERVER_VERSION); SetState(PVR_CONNECTION_STATE_VERSION_MISMATCH); goto fail; } /* Send Auth */ Logger::Log(LogLevel::LEVEL_DEBUG, "sending auth"); if (!SendAuth(user, pass)) { SetState(PVR_CONNECTION_STATE_ACCESS_DENIED); goto fail; } /* Rebuild state */ Logger::Log(LogLevel::LEVEL_DEBUG, "rebuilding state"); if (!m_connListener.Connected()) goto fail; Logger::Log(LogLevel::LEVEL_DEBUG, "registered"); SetState(PVR_CONNECTION_STATE_CONNECTED); m_ready = true; m_regCond.Broadcast(); return; } fail: if (!m_suspended) { /* Don't immediately reconnect (spare server CPU cycles)*/ Sleep(SLOW_RECONNECT_INTERVAL); Disconnect(); } } /* * Main thread loop for connection and rx handling */ void* HTSPConnection::Process ( void ) { static bool log = false; static unsigned int retryAttempt = 0; const Settings &settings = Settings::GetInstance(); while (!IsStopped()) { Logger::Log(LogLevel::LEVEL_DEBUG, "new connection requested"); std::string host = settings.GetHostname(); int port, timeout; port = settings.GetPortHTSP(); timeout = settings.GetConnectTimeout(); /* Create socket (ensure mutex protection) */ { CLockObject lock(m_mutex); if (m_socket) delete m_socket; m_connListener.Disconnected(); m_socket = new CTcpSocket(host.c_str(), port); m_ready = false; m_seq = 0; if (m_challenge) { free(m_challenge); m_challenge = NULL; } } while (m_suspended) { Logger::Log(LogLevel::LEVEL_DEBUG, "suspended. Waiting for wakeup..."); /* Wait for wakeup */ Sleep(1000); } if (!log) { Logger::Log(LogLevel::LEVEL_DEBUG, "connecting to %s:%d", host.c_str(), port); log = true; } else { Logger::Log(LogLevel::LEVEL_TRACE, "connecting to %s:%d", host.c_str(), port); } /* Connect */ Logger::Log(LogLevel::LEVEL_TRACE, "waiting for connection..."); if (!m_socket->Open(timeout)) { /* Unable to connect */ Logger::Log(LogLevel::LEVEL_ERROR, "unable to connect to %s:%d", host.c_str(), port); SetState(PVR_CONNECTION_STATE_SERVER_UNREACHABLE); // Retry a few times with a short interval, after that with the default timeout if (++retryAttempt <= FAST_RECONNECT_ATTEMPTS) Sleep(FAST_RECONNECT_INTERVAL); else Sleep(timeout); continue; } Logger::Log(LogLevel::LEVEL_DEBUG, "connected"); log = false; retryAttempt = 0; /* Start connect thread */ m_regThread->CreateThread(true); /* Receive loop */ while (!IsStopped()) { if (!ReadMessage()) break; } /* Stop connect thread (if not already) */ m_regThread->StopThread(0); } return NULL; } pvr.hts-4.4.20-Leia/src/tvheadend/HTSPConnection.h000066400000000000000000000062611355512543200215670ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2017 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 #include #include extern "C" { #include "libhts/htsmsg.h" } #include "kodi/libXBMC_pvr.h" #include "p8-platform/sockets/tcp.h" #include "p8-platform/threads/mutex.h" #include "p8-platform/threads/threads.h" namespace tvheadend { class HTSPRegister; class HTSPResponse; class IHTSPConnectionListener; typedef std::map HTSPResponseList; /* * HTSP Connection */ class HTSPConnection : public P8PLATFORM::CThread { public: HTSPConnection(IHTSPConnectionListener& connListener); ~HTSPConnection() override; void Start(); void Stop(); void Disconnect(); bool SendMessage0(const char *method, htsmsg_t *m); htsmsg_t *SendAndWait0(const char *method, htsmsg_t *m, int iResponseTimeout = -1); htsmsg_t *SendAndWait(const char *method, htsmsg_t *m, int iResponseTimeout = -1); int GetProtocol() const; std::string GetWebURL(const char *fmt, ...) const; std::string GetServerName() const; std::string GetServerVersion() const; std::string GetServerString() const; bool HasCapability(const std::string &capability) const; inline P8PLATFORM::CMutex& Mutex() { return m_mutex; } void OnSleep(); void OnWake(); private: // CThread iplementation void* Process() override; void Register(); bool ReadMessage(); bool SendHello(); bool SendAuth(const std::string &u, const std::string &p); void SetState(PVR_CONNECTION_STATE state); bool WaitForConnection(); /* * HTSP Connection registration thread */ class HTSPRegister : public P8PLATFORM::CThread { public: HTSPRegister(HTSPConnection *conn) : m_conn(conn) { } ~HTSPRegister() override { StopThread(0); } private: // CThread implementation void *Process() override { m_conn->Register(); return nullptr; } HTSPConnection *m_conn; }; IHTSPConnectionListener& m_connListener; P8PLATFORM::CTcpSocket *m_socket; mutable P8PLATFORM::CMutex m_mutex; HTSPRegister* m_regThread; P8PLATFORM::CCondition m_regCond; bool m_ready; uint32_t m_seq; std::string m_serverName; std::string m_serverVersion; int m_htspVersion; std::string m_webRoot; void* m_challenge; int m_challengeLen; HTSPResponseList m_messages; std::vector m_capabilities; bool m_suspended; PVR_CONNECTION_STATE m_state; }; } // namespace tvheadend pvr.hts-4.4.20-Leia/src/tvheadend/HTSPDemuxer.cpp000066400000000000000000000633331355512543200214370ustar00rootroot00000000000000/* * Copyright (C) 2014 Adam Sutton * 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 "HTSPDemuxer.h" #include "../client.h" #include "HTSPConnection.h" #include "Settings.h" #include "utilities/Logger.h" #include "xbmc_codec_descriptor.hpp" #define TVH_TO_DVD_TIME(x) (static_cast(x) * DVD_TIME_BASE / 1000000.0f) #define INVALID_SEEKTIME (-1) #define SPEED_NORMAL (1000) // x1 playback speed // Not all streams reported to Kodi are directly from tvh, some are created by pvr.hts. // We need a unique stream index for every stream - tvh-supplied and pvr.hts-created. // Easiest way is to add a fixed offset to all stream indexes delivered by tvh and to // use numbers less than TVH_STREAM_INDEX_OFFSET for streams created by pvr.hts. static const int TVH_STREAM_INDEX_OFFSET = 1000; using namespace ADDON; using namespace P8PLATFORM; using namespace tvheadend; using namespace tvheadend::utilities; HTSPDemuxer::HTSPDemuxer ( HTSPConnection &conn ) : m_conn(conn), m_pktBuffer((size_t)-1), m_seekTime(INVALID_SEEKTIME), m_seeking(false), m_subscription(conn), m_lastUse(0), m_startTime(0), m_rdsIdx(0) { } HTSPDemuxer::~HTSPDemuxer () { } void HTSPDemuxer::Connected ( void ) { /* Re-subscribe */ if (m_subscription.IsActive()) { Logger::Log(LogLevel::LEVEL_DEBUG, "demux re-starting stream"); m_subscription.SendSubscribe(0, 0, true); m_subscription.SendSpeed(0, true); ResetStatus(false); } } /* ************************************************************************** * Demuxer API * *************************************************************************/ void HTSPDemuxer::Close0 ( void ) { /* Send unsubscribe */ if (m_subscription.IsActive()) m_subscription.SendUnsubscribe(); /* Clear */ Flush(); Abort0(); } void HTSPDemuxer::Abort0 ( void ) { CLockObject lock(m_mutex); m_streams.clear(); m_streamStat.clear(); m_rdsIdx = 0; m_seeking = false; } bool HTSPDemuxer::Open ( uint32_t channelId, enum eSubscriptionWeight weight ) { CLockObject lock(m_conn.Mutex()); Logger::Log(LogLevel::LEVEL_DEBUG, "demux open"); /* Close current stream */ Close0(); /* Open new subscription */ m_subscription.SendSubscribe(channelId, weight); /* Reset status */ ResetStatus(); /* Send unsubscribe if subscribing failed */ if (!m_subscription.IsActive()) m_subscription.SendUnsubscribe(); else m_lastUse.store(time(nullptr)); return m_subscription.IsActive(); } void HTSPDemuxer::Close ( void ) { CLockObject lock(m_conn.Mutex()); Close0(); ResetStatus(); Logger::Log(LogLevel::LEVEL_DEBUG, "demux close"); } DemuxPacket *HTSPDemuxer::Read ( void ) { DemuxPacket *pkt = NULL; m_lastUse.store(time(nullptr)); if (m_pktBuffer.Pop(pkt, 100)) { Logger::Log(LogLevel::LEVEL_TRACE, "demux read idx :%d pts %lf len %lld", pkt->iStreamId, pkt->pts, (long long)pkt->iSize); return pkt; } Logger::Log(LogLevel::LEVEL_TRACE, "demux read nothing"); return PVR->AllocateDemuxPacket(0); } void HTSPDemuxer::Flush ( void ) { DemuxPacket *pkt; Logger::Log(LogLevel::LEVEL_TRACE, "demux flush"); while (m_pktBuffer.Pop(pkt)) PVR->FreeDemuxPacket(pkt); } void HTSPDemuxer::Trim ( void ) { DemuxPacket *pkt; Logger::Log(LogLevel::LEVEL_TRACE, "demux trim"); /* reduce used buffer space to what is needed for DVDPlayer to resume * playback without buffering. This depends on the bitrate, so we don't set * this too small. */ while (m_pktBuffer.Size() > 512 && m_pktBuffer.Pop(pkt)) PVR->FreeDemuxPacket(pkt); } void HTSPDemuxer::Abort ( void ) { Logger::Log(LogLevel::LEVEL_TRACE, "demux abort"); CLockObject lock(m_conn.Mutex()); Abort0(); ResetStatus(); } bool HTSPDemuxer::Seek(double time, bool, double *startpts) { if (!m_subscription.IsActive()) return false; m_seekTime = 0; m_seeking = true; if (!m_subscription.SendSeek(time)) { m_seeking = false; return false; } /* Wait for time */ CLockObject lock(m_conn.Mutex()); if (!m_seekCond.Wait(m_conn.Mutex(), m_seekTime, Settings::GetInstance().GetResponseTimeout())) { Logger::Log(LogLevel::LEVEL_ERROR, "failed to get subscriptionSeek response"); m_seeking = false; Flush(); /* try to resync */ return false; } m_seeking = false; if (m_seekTime == INVALID_SEEKTIME) return false; /* Store */ *startpts = TVH_TO_DVD_TIME(m_seekTime - 1); Logger::Log(LogLevel::LEVEL_TRACE, "demux seek startpts = %lf", *startpts); return true; } void HTSPDemuxer::Speed ( int speed ) { CLockObject lock(m_conn.Mutex()); if (!m_subscription.IsActive()) return; if (speed != 0) speed = 1000; if (speed != m_subscription.GetSpeed()) m_subscription.SendSpeed(speed); } void HTSPDemuxer::Weight ( enum eSubscriptionWeight weight ) { if (!m_subscription.IsActive() || m_subscription.GetWeight() == static_cast(weight)) return; m_subscription.SendWeight(static_cast(weight)); } PVR_ERROR HTSPDemuxer::CurrentStreams ( PVR_STREAM_PROPERTIES *props ) { CLockObject lock(m_mutex); for (size_t i = 0; i < m_streams.size(); i++) { memcpy(&props->stream[i], &m_streams.at(i), sizeof(PVR_STREAM_PROPERTIES::PVR_STREAM)); } props->iStreamCount = static_cast(m_streams.size()); return PVR_ERROR_NO_ERROR; } PVR_ERROR HTSPDemuxer::CurrentSignal ( PVR_SIGNAL_STATUS &sig ) { CLockObject lock(m_mutex); sig = { 0 }; strncpy(sig.strAdapterName, m_sourceInfo.si_adapter.c_str(), sizeof(sig.strAdapterName) - 1); strncpy(sig.strAdapterStatus, m_signalInfo.fe_status.c_str(), sizeof(sig.strAdapterStatus) - 1); strncpy(sig.strServiceName, m_sourceInfo.si_service.c_str(), sizeof(sig.strServiceName) - 1); strncpy(sig.strProviderName, m_sourceInfo.si_provider.c_str(), sizeof(sig.strProviderName) - 1); strncpy(sig.strMuxName, m_sourceInfo.si_mux.c_str(), sizeof(sig.strMuxName) - 1); sig.iSNR = m_signalInfo.fe_snr; sig.iSignal = m_signalInfo.fe_signal; sig.iBER = m_signalInfo.fe_ber; sig.iUNC = m_signalInfo.fe_unc; return PVR_ERROR_NO_ERROR; } PVR_ERROR HTSPDemuxer::CurrentDescrambleInfo ( PVR_DESCRAMBLE_INFO *info ) { CLockObject lock(m_mutex); *info = { 0 }; info->iPid = m_descrambleInfo.GetPid(); info->iCaid = m_descrambleInfo.GetCaid(); info->iProvid = m_descrambleInfo.GetProvid(); info->iEcmTime = m_descrambleInfo.GetEcmTime(); info->iHops = m_descrambleInfo.GetHops(); strncpy(info->strCardSystem, m_descrambleInfo.GetCardSystem().c_str(), sizeof(info->strCardSystem) - 1); strncpy(info->strReader, m_descrambleInfo.GetReader().c_str(), sizeof(info->strReader) - 1); strncpy(info->strFrom, m_descrambleInfo.GetFrom().c_str(), sizeof(info->strFrom) - 1); strncpy(info->strProtocol, m_descrambleInfo.GetProtocol().c_str(), sizeof(info->strProtocol) - 1); return PVR_ERROR_NO_ERROR; } bool HTSPDemuxer::IsTimeShifting() const { if (!m_subscription.IsActive()) return false; if (m_subscription.GetSpeed() != SPEED_NORMAL) return true; CLockObject lock(m_mutex); if (m_timeshiftStatus.shift != 0) return true; return false; } bool HTSPDemuxer::IsRealTimeStream() const { return m_subscription.IsActive(); } PVR_ERROR HTSPDemuxer::GetStreamTimes(PVR_STREAM_TIMES *times) const { *times = {0}; CLockObject lock(m_mutex); times->startTime = m_startTime; times->ptsStart = 0; times->ptsBegin = TVH_TO_DVD_TIME(m_timeshiftStatus.start); times->ptsEnd = TVH_TO_DVD_TIME(m_timeshiftStatus.end); return PVR_ERROR_NO_ERROR; } uint32_t HTSPDemuxer::GetSubscriptionId() const { return m_subscription.GetId(); } uint32_t HTSPDemuxer::GetChannelId() const { if (m_subscription.IsActive()) return m_subscription.GetChannelId(); return 0; } time_t HTSPDemuxer::GetLastUse() const { if (m_subscription.IsActive()) return m_lastUse.load(); return 0; } bool HTSPDemuxer::IsPaused() const { if (m_subscription.IsActive()) return m_subscription.GetSpeed() == 0; return false; } void HTSPDemuxer::SetStreamingProfile(const std::string &profile) { m_subscription.SetProfile(profile); } void HTSPDemuxer::ResetStatus(bool resetStartTime /* = true */) { CLockObject lock(m_mutex); m_signalInfo.Clear(); m_sourceInfo.Clear(); m_descrambleInfo.Clear(); m_timeshiftStatus.Clear(); if (resetStartTime) m_startTime = 0; } /* ************************************************************************** * Parse incoming data * *************************************************************************/ bool HTSPDemuxer::ProcessMessage ( const char *method, htsmsg_t *m ) { /* Subscription messages */ if (!strcmp("muxpkt", method)) ParseMuxPacket(m); else if (!strcmp("subscriptionStatus", method)) m_subscription.ParseSubscriptionStatus(m); else if (!strcmp("queueStatus", method)) ParseQueueStatus(m); else if (!strcmp("signalStatus", method)) ParseSignalStatus(m); else if (!strcmp("timeshiftStatus", method)) ParseTimeshiftStatus(m); else if (!strcmp("descrambleInfo", method)) ParseDescrambleInfo(m); else if (!strcmp("subscriptionStart", method)) ParseSubscriptionStart(m); else if (!strcmp("subscriptionStop", method)) ParseSubscriptionStop(m); else if (!strcmp("subscriptionSkip", method)) ParseSubscriptionSkip(m); else if (!strcmp("subscriptionSpeed", method)) ParseSubscriptionSpeed(m); else if (!strcmp("subscriptionGrace", method)) ParseSubscriptionGrace(m); else Logger::Log(LogLevel::LEVEL_DEBUG, "demux unhandled subscription message [%s]", method); return true; } void HTSPDemuxer::ProcessRDS(uint32_t idx, const void* bin, size_t binlen) { if (idx != m_rdsIdx) return; const uint8_t* data = static_cast(bin); const size_t offset = binlen - 1; static const uint8_t RDS_IDENTIFIER = 0xFD; if (data[offset] == RDS_IDENTIFIER) { // RDS data present, obtain length. uint8_t rdslen = data[offset - 1]; if (rdslen > 0) { const uint32_t rdsIdx = idx - TVH_STREAM_INDEX_OFFSET; if (m_streamStat.find(rdsIdx) == m_streamStat.end()) { // No RDS stream yet. Create and announce it. if (!AddRDSStream(idx, rdsIdx)) return; // Update streams. Logger::Log(LogLevel::LEVEL_DEBUG, "demux stream change"); DemuxPacket* pktSpecial = PVR->AllocateDemuxPacket(0); pktSpecial->iStreamId = DMX_SPECIALID_STREAMCHANGE; m_pktBuffer.Push(pktSpecial); } DemuxPacket* pkt = PVR->AllocateDemuxPacket(rdslen); if (!pkt) return; uint8_t* rdsdata = new uint8_t[rdslen]; // Reassemble UECP block. mpeg stream contains data in reverse order! for (size_t i = offset - 2, j = 0; i > 3 && i > offset - 2 - rdslen; i--, j++) rdsdata[j] = data[i]; memcpy(pkt->pData, rdsdata, rdslen); pkt->iSize = rdslen; pkt->iStreamId = rdsIdx; m_pktBuffer.Push(pkt); delete [] rdsdata; } } } void HTSPDemuxer::ParseMuxPacket ( htsmsg_t *m ) { uint32_t idx, u32; int64_t s64; const void *bin; size_t binlen; DemuxPacket *pkt; char type = 0; int ignore; CLockObject lock(m_mutex); /* Ignore packets while switching channels */ if (!m_subscription.IsActive()) { Logger::Log(LogLevel::LEVEL_DEBUG, "Ignored mux packet due to channel switch"); return; } /* Validate fields */ if (htsmsg_get_u32(m, "stream", &idx) || htsmsg_get_bin(m, "payload", &bin, &binlen)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed muxpkt: 'stream'/'payload' missing"); return; } idx += TVH_STREAM_INDEX_OFFSET; /* Drop packets for unknown streams */ if (m_streamStat.find(idx) == m_streamStat.end()) { Logger::Log(LogLevel::LEVEL_DEBUG, "Dropped packet with unknown stream index %i", idx); return; } /* Record */ m_streamStat[idx]++; /* Allocate buffer */ if (!(pkt = PVR->AllocateDemuxPacket(binlen))) return; memcpy(pkt->pData, bin, binlen); pkt->iSize = binlen; pkt->iStreamId = idx; /* Duration */ if (!htsmsg_get_u32(m, "duration", &u32)) pkt->duration = TVH_TO_DVD_TIME(u32); /* Timestamps */ if (!htsmsg_get_s64(m, "dts", &s64)) pkt->dts = TVH_TO_DVD_TIME(s64); else pkt->dts = DVD_NOPTS_VALUE; if (!htsmsg_get_s64(m, "pts", &s64)) pkt->pts = TVH_TO_DVD_TIME(s64); else pkt->pts = DVD_NOPTS_VALUE; /* Type (for debug only) */ if (!htsmsg_get_u32(m, "frametype", &u32)) type = (char)u32; if (!type) type = '_'; ignore = m_seeking; Logger::Log(LogLevel::LEVEL_TRACE, "demux pkt idx %d:%d type %c pts %lf len %lld%s", idx, pkt->iStreamId, type, pkt->pts, (long long)binlen, ignore ? " IGNORE" : ""); /* Store */ if (!ignore) { if (m_startTime == 0) { // first paket for this subscription m_startTime = time(nullptr); } m_pktBuffer.Push(pkt); // Process RDS data, if present. ProcessRDS(idx, bin, binlen); } else PVR->FreeDemuxPacket(pkt); } bool HTSPDemuxer::AddRDSStream(uint32_t audioIdx, uint32_t rdsIdx) { for (const auto& stream : m_streams) { if (stream.iPID != audioIdx) continue; // Found the stream with the embedded RDS data. Create corresponding RDS stream. const CodecDescriptor codecDescriptor = CodecDescriptor::GetCodecByName("rds"); const xbmc_codec_t codec = codecDescriptor.Codec(); if (codec.codec_type == XBMC_CODEC_TYPE_UNKNOWN) return false; m_streamStat[rdsIdx] = 0; PVR_STREAM_PROPERTIES::PVR_STREAM rdsStream = {}; rdsStream.iCodecType = codec.codec_type; rdsStream.iCodecId = codec.codec_id; rdsStream.iPID = rdsIdx; strncpy(rdsStream.strLanguage, stream.strLanguage, sizeof(rdsStream.strLanguage) - 1); // We can only use PVR_STREAM_MAX_STREAMS streams if (m_streams.size() < PVR_STREAM_MAX_STREAMS) { Logger::Log(LogLevel::LEVEL_DEBUG, "Adding rds stream. id: %d", rdsIdx); m_streams.emplace_back(rdsStream); return true; } else { Logger::Log(LogLevel::LEVEL_INFO, "Maximum stream limit reached ignoring id: %d, type rds, codec: %u", rdsIdx, rdsStream.iCodecId); return false; } } // stream with embedded RDS data not found return false; } bool HTSPDemuxer::AddTVHStream(uint32_t idx, const char* type, htsmsg_field_t *f) { const CodecDescriptor codecDescriptor = CodecDescriptor::GetCodecByName(type); const xbmc_codec_t codec = codecDescriptor.Codec(); if (codec.codec_type == XBMC_CODEC_TYPE_UNKNOWN) return false; m_streamStat[idx] = 0; PVR_STREAM_PROPERTIES::PVR_STREAM stream = {}; stream.iCodecType = codec.codec_type; stream.iCodecId = codec.codec_id; stream.iPID = idx; /* Subtitle ID */ if ((stream.iCodecType == XBMC_CODEC_TYPE_SUBTITLE) && !strcmp("DVBSUB", type)) { uint32_t composition_id = 0, ancillary_id = 0; htsmsg_get_u32(&f->hmf_msg, "composition_id", &composition_id); htsmsg_get_u32(&f->hmf_msg, "ancillary_id" , &ancillary_id); stream.iSubtitleInfo = (composition_id & 0xffff) | ((ancillary_id & 0xffff) << 16); } /* Language */ if (stream.iCodecType == XBMC_CODEC_TYPE_SUBTITLE || stream.iCodecType == XBMC_CODEC_TYPE_AUDIO || stream.iCodecType == XBMC_CODEC_TYPE_RDS) { const char *language; if ((language = htsmsg_get_str(&f->hmf_msg, "language")) != NULL) strncpy(stream.strLanguage, language, sizeof(stream.strLanguage) - 1); } /* Audio data */ if (stream.iCodecType == XBMC_CODEC_TYPE_AUDIO) { stream.iChannels = htsmsg_get_u32_or_default(&f->hmf_msg, "channels", 2); stream.iSampleRate = htsmsg_get_u32_or_default(&f->hmf_msg, "rate", 48000); if (strcmp("MPEG2AUDIO", type) == 0) { // mpeg2 audio streams may contain embedded RDS data. // We will find out when the first stream packet arrives. m_rdsIdx = idx; } } /* Video */ if (stream.iCodecType == XBMC_CODEC_TYPE_VIDEO) { stream.iWidth = htsmsg_get_u32_or_default(&f->hmf_msg, "width", 0); stream.iHeight = htsmsg_get_u32_or_default(&f->hmf_msg, "height", 0); /* Ignore this message if the stream details haven't been determined yet, a new message will be sent once they have. This is fixed in some versions of tvheadend and is here for backward compatibility. */ if (stream.iWidth == 0 || stream.iHeight == 0) { Logger::Log(LogLevel::LEVEL_DEBUG, "Ignoring subscriptionStart, stream details missing"); return false; } /* Setting aspect ratio to zero will cause XBMC to handle changes in it */ stream.fAspect = 0.0f; uint32_t duration; if ((duration = htsmsg_get_u32_or_default(&f->hmf_msg, "duration", 0)) > 0) { stream.iFPSScale = duration; stream.iFPSRate = DVD_TIME_BASE; } } /* We can only use PVR_STREAM_MAX_STREAMS streams */ if (m_streams.size() < PVR_STREAM_MAX_STREAMS) { Logger::Log(LogLevel::LEVEL_DEBUG, " id: %d, type %s, codec: %u", idx, type, stream.iCodecId); m_streams.emplace_back(stream); return true; } else { Logger::Log(LogLevel::LEVEL_INFO, "Maximum stream limit reached ignoring id: %d, type %s, codec: %u", idx, type, stream.iCodecId); return false; } } void HTSPDemuxer::ParseSubscriptionStart ( htsmsg_t *m ) { /* Validate */ htsmsg_t* l; if ((l = htsmsg_get_list(m, "streams")) == NULL) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed subscriptionStart: 'streams' missing"); return; } CLockObject lock(m_mutex); m_streamStat.clear(); m_streams.clear(); m_rdsIdx = 0; Logger::Log(LogLevel::LEVEL_DEBUG, "demux subscription start"); /* Process each */ htsmsg_field_t* f; HTSMSG_FOREACH(f, l) { if (f->hmf_type != HMF_MAP) continue; const char *type; if ((type = htsmsg_get_str(&f->hmf_msg, "type")) == NULL) continue; uint32_t idx; if (htsmsg_get_u32(&f->hmf_msg, "index", &idx)) continue; idx += TVH_STREAM_INDEX_OFFSET; AddTVHStream(idx, type, f); } /* Update streams */ Logger::Log(LogLevel::LEVEL_DEBUG, "demux stream change"); DemuxPacket* pkt = PVR->AllocateDemuxPacket(0); pkt->iStreamId = DMX_SPECIALID_STREAMCHANGE; m_pktBuffer.Push(pkt); /* Source data */ ParseSourceInfo(htsmsg_get_map(m, "sourceinfo")); } void HTSPDemuxer::ParseSourceInfo ( htsmsg_t *m ) { const char *str; /* Ignore */ if (!m) return; Logger::Log(LogLevel::LEVEL_TRACE, "demux sourceInfo:"); /* include position in mux name * as users might receive multiple satellite positions */ m_sourceInfo.si_mux.clear(); if ((str = htsmsg_get_str(m, "satpos")) != NULL) { Logger::Log(LogLevel::LEVEL_TRACE, " satpos : %s", str); m_sourceInfo.si_mux.append(str); m_sourceInfo.si_mux.append(": "); } if ((str = htsmsg_get_str(m, "mux")) != NULL) { Logger::Log(LogLevel::LEVEL_TRACE, " mux : %s", str); m_sourceInfo.si_mux.append(str); } if ((str = htsmsg_get_str(m, "adapter")) != NULL) { Logger::Log(LogLevel::LEVEL_TRACE, " adapter : %s", str); m_sourceInfo.si_adapter = str; } if ((str = htsmsg_get_str(m, "network")) != NULL) { Logger::Log(LogLevel::LEVEL_TRACE, " network : %s", str); m_sourceInfo.si_network = str; } if ((str = htsmsg_get_str(m, "provider")) != NULL) { Logger::Log(LogLevel::LEVEL_TRACE, " provider : %s", str); m_sourceInfo.si_provider = str; } if ((str = htsmsg_get_str(m, "service")) != NULL) { Logger::Log(LogLevel::LEVEL_TRACE, " service : %s", str); m_sourceInfo.si_service = str; } } void HTSPDemuxer::ParseSubscriptionStop(htsmsg_t*) { //CLockObject lock(m_mutex); } void HTSPDemuxer::ParseSubscriptionSkip ( htsmsg_t *m ) { int64_t s64; CLockObject lock(m_conn.Mutex()); if (htsmsg_get_s64(m, "time", &s64)) { m_seekTime = INVALID_SEEKTIME; } else { m_seekTime = s64 < 0 ? 1 : s64 + 1; /* it must not be zero! */ Flush(); /* flush old packets (with wrong pts) */ } m_seeking = false; m_seekCond.Broadcast(); } void HTSPDemuxer::ParseSubscriptionSpeed ( htsmsg_t *m ) { int32_t s32; if (!htsmsg_get_s32(m, "speed", &s32)) Logger::Log(LogLevel::LEVEL_TRACE, "recv speed %d", s32); } void HTSPDemuxer::ParseSubscriptionGrace ( htsmsg_t *m ) { } void HTSPDemuxer::ParseQueueStatus (htsmsg_t* m) { uint32_t u32; std::map::const_iterator it; CLockObject lock(m_mutex); Logger::Log(LogLevel::LEVEL_TRACE, "stream stats:"); for (it = m_streamStat.begin(); it != m_streamStat.end(); ++it) Logger::Log(LogLevel::LEVEL_TRACE, " idx:%d num:%d", it->first, it->second); Logger::Log(LogLevel::LEVEL_TRACE, "queue stats:"); if (!htsmsg_get_u32(m, "packets", &u32)) Logger::Log(LogLevel::LEVEL_TRACE, " pkts %d", u32); if (!htsmsg_get_u32(m, "bytes", &u32)) Logger::Log(LogLevel::LEVEL_TRACE, " bytes %d", u32); if (!htsmsg_get_u32(m, "delay", &u32)) Logger::Log(LogLevel::LEVEL_TRACE, " delay %d", u32); if (!htsmsg_get_u32(m, "Idrops", &u32)) Logger::Log(LogLevel::LEVEL_TRACE, " Idrop %d", u32); if (!htsmsg_get_u32(m, "Pdrops", &u32)) Logger::Log(LogLevel::LEVEL_TRACE, " Pdrop %d", u32); if (!htsmsg_get_u32(m, "Bdrops", &u32)) Logger::Log(LogLevel::LEVEL_TRACE, " Bdrop %d", u32); } void HTSPDemuxer::ParseSignalStatus ( htsmsg_t *m ) { uint32_t u32; const char *str; CLockObject lock(m_mutex); /* Reset */ m_signalInfo.Clear(); /* Parse */ Logger::Log(LogLevel::LEVEL_TRACE, "signalStatus:"); if ((str = htsmsg_get_str(m, "feStatus")) != NULL) { Logger::Log(LogLevel::LEVEL_TRACE, " status : %s", str); m_signalInfo.fe_status = str; } else { Logger::Log(LogLevel::LEVEL_ERROR, "malformed signalStatus: 'feStatus' missing, ignoring"); } if (!htsmsg_get_u32(m, "feSNR", &u32)) { Logger::Log(LogLevel::LEVEL_TRACE, " snr : %d", u32); m_signalInfo.fe_snr = u32; } if (!htsmsg_get_u32(m, "feBER", &u32)) { Logger::Log(LogLevel::LEVEL_TRACE, " ber : %d", u32); m_signalInfo.fe_ber = u32; } if (!htsmsg_get_u32(m, "feUNC", &u32)) { Logger::Log(LogLevel::LEVEL_TRACE, " unc : %d", u32); m_signalInfo.fe_unc = u32; } if (!htsmsg_get_u32(m, "feSignal", &u32)) { Logger::Log(LogLevel::LEVEL_TRACE, " signal : %d", u32); m_signalInfo.fe_signal = u32; } } void HTSPDemuxer::ParseTimeshiftStatus ( htsmsg_t *m ) { uint32_t u32; int64_t s64; CLockObject lock(m_mutex); /* Parse */ Logger::Log(LogLevel::LEVEL_TRACE, "timeshiftStatus:"); if (!htsmsg_get_u32(m, "full", &u32)) { Logger::Log(LogLevel::LEVEL_TRACE, " full : %d", u32); m_timeshiftStatus.full = u32 == 0 ? false : true; } else { Logger::Log(LogLevel::LEVEL_ERROR, "malformed timeshiftStatus: 'full' missing, ignoring"); } if (!htsmsg_get_s64(m, "shift", &s64)) { Logger::Log(LogLevel::LEVEL_TRACE, " shift : %lld", s64); m_timeshiftStatus.shift = s64; } else { Logger::Log(LogLevel::LEVEL_ERROR, "malformed timeshiftStatus: 'shift' missing, ignoring"); } if (!htsmsg_get_s64(m, "start", &s64)) { Logger::Log(LogLevel::LEVEL_TRACE, " start : %lld", s64); m_timeshiftStatus.start = s64; } if (!htsmsg_get_s64(m, "end", &s64)) { Logger::Log(LogLevel::LEVEL_TRACE, " end : %lld", s64); m_timeshiftStatus.end = s64; } } void HTSPDemuxer::ParseDescrambleInfo(htsmsg_t *m) { uint32_t pid = 0, caid = 0, provid = 0, ecmtime = 0, hops = 0; const char *cardsystem, *reader, *from, *protocol; /* Parse mandatory fields */ if (htsmsg_get_u32(m, "pid", &pid) || htsmsg_get_u32(m, "caid", &caid) || htsmsg_get_u32(m, "provid", &provid) || htsmsg_get_u32(m, "ecmtime", &ecmtime) || htsmsg_get_u32(m, "hops", &hops)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed descrambleInfo, mandatory parameters missing"); return; } /* Parse optional fields */ cardsystem = htsmsg_get_str(m, "cardsystem"); reader = htsmsg_get_str(m, "reader"); from = htsmsg_get_str(m, "from"); protocol = htsmsg_get_str(m, "protocol"); CLockObject lock(m_mutex); /* Reset */ m_descrambleInfo.Clear(); /* Store */ m_descrambleInfo.SetPid(pid); m_descrambleInfo.SetCaid(caid); m_descrambleInfo.SetProvid(provid); m_descrambleInfo.SetEcmTime(ecmtime); m_descrambleInfo.SetHops(hops); if (cardsystem) m_descrambleInfo.SetCardSystem(cardsystem); if (reader) m_descrambleInfo.SetReader(reader); if (from) m_descrambleInfo.SetFrom(from); if (protocol) m_descrambleInfo.SetProtocol(protocol); /* Log */ Logger::Log(LogLevel::LEVEL_TRACE, "descrambleInfo:"); Logger::Log(LogLevel::LEVEL_TRACE, " pid: %d", pid); Logger::Log(LogLevel::LEVEL_TRACE, " caid: 0x%X", caid); Logger::Log(LogLevel::LEVEL_TRACE, " provid: %d", provid); Logger::Log(LogLevel::LEVEL_TRACE, " ecmtime: %d", ecmtime); Logger::Log(LogLevel::LEVEL_TRACE, " hops: %d", hops); Logger::Log(LogLevel::LEVEL_TRACE, " cardsystem: %s", cardsystem); Logger::Log(LogLevel::LEVEL_TRACE, " reader: %s", reader); Logger::Log(LogLevel::LEVEL_TRACE, " from: %s", from); Logger::Log(LogLevel::LEVEL_TRACE, " protocol: %s", protocol); } pvr.hts-4.4.20-Leia/src/tvheadend/HTSPDemuxer.h000066400000000000000000000076041355512543200211030ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2017 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 #include #include #include #include extern "C" { #include "libhts/htsmsg.h" } #include "kodi/libXBMC_pvr.h" #include "p8-platform/threads/mutex.h" #include "p8-platform/util/buffer.h" #include "Subscription.h" #include "status/DescrambleInfo.h" #include "status/Quality.h" #include "status/SourceInfo.h" #include "status/TimeshiftStatus.h" namespace tvheadend { class HTSPConnection; /* * HTSP Demuxer - live streams */ class HTSPDemuxer { public: HTSPDemuxer(HTSPConnection &conn); ~HTSPDemuxer(); bool ProcessMessage(const char *method, htsmsg_t *m); void Connected(); bool Open(uint32_t channelId, tvheadend::eSubscriptionWeight weight = tvheadend::SUBSCRIPTION_WEIGHT_NORMAL); void Close(); DemuxPacket *Read(); void Trim(); void Flush(); void Abort(); bool Seek(double time, bool backwards, double *startpts); void Speed(int speed); void Weight(tvheadend::eSubscriptionWeight weight); PVR_ERROR CurrentStreams(PVR_STREAM_PROPERTIES *streams); PVR_ERROR CurrentSignal(PVR_SIGNAL_STATUS &sig); PVR_ERROR CurrentDescrambleInfo(PVR_DESCRAMBLE_INFO *info); bool IsTimeShifting() const; bool IsRealTimeStream() const; PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES *times) const; uint32_t GetSubscriptionId() const; uint32_t GetChannelId() const; time_t GetLastUse() const; bool IsPaused() const; /** * Tells each demuxer to use the specified profile for new subscriptions * @param profile the profile to use */ void SetStreamingProfile(const std::string &profile); private: void Close0(); void Abort0(); /** * Resets the signal, quality, timeshift info and optionally the starttime * @param resetStartTime if true, startTime will be reset */ void ResetStatus(bool resetStartTime = true); void ParseMuxPacket(htsmsg_t *m); void ParseSourceInfo(htsmsg_t *m); void ParseSubscriptionStart(htsmsg_t *m); void ParseSubscriptionStop(htsmsg_t *m); void ParseSubscriptionSkip(htsmsg_t *m); void ParseSubscriptionSpeed(htsmsg_t *m); void ParseSubscriptionGrace(htsmsg_t *m); void ParseQueueStatus(htsmsg_t *m); void ParseSignalStatus(htsmsg_t *m); void ParseTimeshiftStatus(htsmsg_t *m); void ParseDescrambleInfo(htsmsg_t *m); bool AddTVHStream(uint32_t idx, const char* type, htsmsg_field_t *f); bool AddRDSStream(uint32_t audioIdx, uint32_t rdsIdx); void ProcessRDS(uint32_t idx, const void* bin, size_t binlen); mutable P8PLATFORM::CMutex m_mutex; HTSPConnection &m_conn; P8PLATFORM::SyncedBuffer m_pktBuffer; std::vector m_streams; std::map m_streamStat; int64_t m_seekTime; P8PLATFORM::CCondition m_seekCond; bool m_seeking; tvheadend::status::SourceInfo m_sourceInfo; tvheadend::status::Quality m_signalInfo; tvheadend::status::TimeshiftStatus m_timeshiftStatus; tvheadend::status::DescrambleInfo m_descrambleInfo; tvheadend::Subscription m_subscription; std::atomic m_lastUse; std::atomic m_startTime; uint32_t m_rdsIdx; }; } // namespace tvheadend pvr.hts-4.4.20-Leia/src/tvheadend/HTSPMessage.h000066400000000000000000000034211355512543200210470ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2017 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 * */ extern "C" { #include "libhts/htsmsg.h" } #include namespace tvheadend { /* * HTSP Message */ class HTSPMessage { public: HTSPMessage(const std::string& method = "", htsmsg_t* msg = nullptr) : m_method(method), m_msg(msg) { } HTSPMessage(const HTSPMessage& msg) : m_method(msg.m_method), m_msg(msg.m_msg) { msg.m_msg = nullptr; } ~HTSPMessage() { if (m_msg) htsmsg_destroy(m_msg); } HTSPMessage& operator=(const HTSPMessage &msg) { if (this != &msg) { if (m_msg) htsmsg_destroy(m_msg); m_method = msg.m_method; m_msg = msg.m_msg; msg.m_msg = nullptr; // ownership is passed } return *this; } const std::string& GetMethod() const { return m_method; } htsmsg_t* GetMessage() const { return m_msg; } void ClearMessage() { htsmsg_destroy(m_msg); m_msg = nullptr; } private: std::string m_method; mutable htsmsg_t *m_msg; }; } // namespace tvheadend pvr.hts-4.4.20-Leia/src/tvheadend/HTSPTypes.h000066400000000000000000000102421355512543200205660ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 #include #include #include #include #include "kodi/libXBMC_pvr.h" #include "entity/Event.h" namespace tvheadend { typedef enum { DVR_PRIO_IMPORTANT = 0, DVR_PRIO_HIGH = 1, DVR_PRIO_NORMAL = 2, DVR_PRIO_LOW = 3, DVR_PRIO_UNIMPORTANT = 4, DVR_PRIO_NOT_SET = 5, DVR_PRIO_DEFAULT = 6 } dvr_prio_t; typedef enum { DVR_ACTION_TYPE_CUT, DVR_ACTION_TYPE_MUTE, DVR_ACTION_TYPE_SCENE, DVR_ACTION_TYPE_COMBREAK, } dvr_action_type_t; typedef enum { DVR_AUTOREC_RECORD_ALL = 0, DVR_AUTOREC_RECORD_UNIQUE = 14, // Unique episode in EPG/XMLTV DVR_AUTOREC_RECORD_DIFFERENT_EPISODE_NUMBER = 1, DVR_AUTOREC_RECORD_DIFFERENT_SUBTITLE = 2, DVR_AUTOREC_RECORD_DIFFERENT_DESCRIPTION = 3, DVR_AUTOREC_RECORD_ONCE_PER_MONTH = 12, DVR_AUTOREC_RECORD_ONCE_PER_WEEK = 4, DVR_AUTOREC_RECORD_ONCE_PER_DAY = 5, DVR_AUTOREC_LRECORD_DIFFERENT_EPISODE_NUMBER = 6, DVR_AUTOREC_LRECORD_DIFFERENT_TITLE = 7, DVR_AUTOREC_LRECORD_DIFFERENT_SUBTITLE = 8, DVR_AUTOREC_LRECORD_DIFFERENT_DESCRIPTION = 9, DVR_AUTOREC_LRECORD_ONCE_PER_MONTH = 13, DVR_AUTOREC_LRECORD_ONCE_PER_WEEK = 10, DVR_AUTOREC_LRECORD_ONCE_PER_DAY = 11, } dvr_autorec_dedup_t; /* * Defines for both the retention and removal of a dvr entry * retention = lifetime of the database entry * removal = lifetime of the actual recording on disk */ typedef enum { DVR_RET_DVRCONFIG = 0, // the server will use it's own default value DVR_RET_1DAY = 1, // the server will delete the db entry or recording after 1 day DVR_RET_3DAY = 3, // ... DVR_RET_5DAY = 5, DVR_RET_1WEEK = 7, DVR_RET_2WEEK = 14, DVR_RET_3WEEK = 21, DVR_RET_1MONTH = 31, DVR_RET_2MONTH = 62, DVR_RET_3MONTH = 92, DVR_RET_6MONTH = 183, DVR_RET_1YEAR = 366, DVR_RET_2YEARS = 731, DVR_RET_3YEARS = 1096, DVR_RET_SPACE = INT32_MAX-1, // the server may delete this recording if space for a new recording is needed (removal only) DVR_RET_FOREVER = INT32_MAX // the server should never delete this recording or database entry, only the user can do this } dvr_retention_t; typedef enum { CHANNEL_TYPE_OTHER = 0, CHANNEL_TYPE_TV = 1, CHANNEL_TYPE_RADIO = 2 } channel_type_t; typedef enum { HTSP_DVR_PLAYCOUNT_RESET = 0, HTSP_DVR_PLAYCOUNT_SET = 1, HTSP_DVR_PLAYCOUNT_KEEP = INT32_MAX-1, HTSP_DVR_PLAYCOUNT_INCR = INT32_MAX } dvr_playcount_t; enum eHTSPEventType { HTSP_EVENT_NONE = 0, HTSP_EVENT_CHN_UPDATE = 1, HTSP_EVENT_TAG_UPDATE = 2, HTSP_EVENT_EPG_UPDATE = 3, HTSP_EVENT_REC_UPDATE = 4, }; struct SHTSPEvent { eHTSPEventType m_type; // params for HTSP_EVENT_EPG_UPDATE tvheadend::entity::Event m_epg; EPG_EVENT_STATE m_state; SHTSPEvent (eHTSPEventType type = HTSP_EVENT_NONE) : m_type(type), m_state(EPG_EVENT_CREATED) { } SHTSPEvent (eHTSPEventType type, const tvheadend::entity::Event &epg, EPG_EVENT_STATE state) : m_type(type), m_epg(epg), m_state(state) { } bool operator==(const SHTSPEvent &right) const { return m_type == right.m_type && m_epg == right.m_epg && m_state && right.m_state; } bool operator!=(const SHTSPEvent &right) const { return !(*this == right); } }; typedef std::vector SHTSPEventList; } // namespace tvheadend pvr.hts-4.4.20-Leia/src/tvheadend/HTSPVFS.cpp000066400000000000000000000216311355512543200204570ustar00rootroot00000000000000/* * Copyright (C) 2014 Adam Sutton * 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 "HTSPVFS.h" extern "C" { #include "libhts/htsmsg_binary.h" } #include #include #include #include "p8-platform/threads/mutex.h" #include "p8-platform/util/StringUtils.h" #include "HTSPConnection.h" #include "Settings.h" #include "utilities/Logger.h" using namespace P8PLATFORM; using namespace tvheadend; using namespace tvheadend::utilities; /* * VFS handler */ HTSPVFS::HTSPVFS ( HTSPConnection &conn ) : m_conn(conn), m_path(""), m_fileId(0), m_offset(0), m_eofOffsetSecs(-1), m_pauseTime(0), m_paused(false), m_isRealTimeStream(false) { } HTSPVFS::~HTSPVFS () { } void HTSPVFS::Connected ( void ) { /* Re-open */ if (m_fileId != 0) { Logger::Log(LogLevel::LEVEL_DEBUG, "vfs re-open file"); if (!SendFileOpen(true) || !SendFileSeek(m_offset, SEEK_SET, true)) { Logger::Log(LogLevel::LEVEL_ERROR, "vfs failed to re-open file"); Close(); } } } /* ************************************************************************** * VFS API * *************************************************************************/ bool HTSPVFS::Open ( const PVR_RECORDING &rec ) { /* Close existing */ Close(); /* Cache details */ m_path = StringUtils::Format("dvr/%s", rec.strRecordingId); m_fileStart = rec.recordingTime; /* Send open */ if (!SendFileOpen()) { Logger::Log(LogLevel::LEVEL_ERROR, "vfs failed to open file"); return false; } /* Done */ return true; } void HTSPVFS::Close ( void ) { if (m_fileId != 0) SendFileClose(); m_offset = 0; m_fileId = 0; m_path = ""; m_eofOffsetSecs = -1; m_pauseTime = 0; m_paused = false; m_isRealTimeStream = false; } ssize_t HTSPVFS::Read ( unsigned char *buf, unsigned int len, bool inprogress ) { /* Not opened */ if (!m_fileId) return -1; /* Tvheadend may briefly return 0 bytes when playing an in-progress recording at end-of-file we'll retry 50 times with 10ms pauses (~500ms) before giving up */ int tries = inprogress ? 50 : 1; ssize_t read = 0; for (int i = 1; i <= tries; i++) { read = SendFileRead(buf, len); if (read > 0) { m_offset += read; return read; } else if (i < tries) std::this_thread::sleep_for(std::chrono::milliseconds(10)); } Logger::Log(LogLevel::LEVEL_DEBUG, "vfs read failed after %d attempts", tries); return read; } long long HTSPVFS::Seek ( long long pos, int whence, bool inprogress ) { if (m_fileId == 0) return -1; long long ret = SendFileSeek(pos, whence); /* for inprogress recordings see whether we need to toggle IsRealTimeStream */ if (inprogress) { int64_t fileLengthSecs = std::time(nullptr) - m_fileStart; int64_t fileSize = Size(); int64_t bitrate = 0; m_eofOffsetSecs = -1; if (fileLengthSecs > 0) bitrate = fileSize / fileLengthSecs; if (bitrate > 0) m_eofOffsetSecs = (fileSize - m_offset) > 0 ? (fileSize - m_offset) / bitrate : 0; /* only set m_isRealTimeStream within last 10 secs of an inprogress recording */ m_isRealTimeStream = (m_eofOffsetSecs >=0 && m_eofOffsetSecs < 10); Logger::Log(LogLevel::LEVEL_TRACE, "vfs seek inprogress recording m_eofOffsetSecs=%lld m_isRealTimeStream=%d", static_cast(m_eofOffsetSecs), m_isRealTimeStream); /* if we've seeked whilst paused then update m_pauseTime this is so we correctly recalculate m_eofOffsetSecs when returning to normal playback */ if (m_paused) m_pauseTime = std::time(nullptr); } return ret; } long long HTSPVFS::Size ( void ) { int64_t ret = -1; htsmsg_t *m; /* Build */ m = htsmsg_create_map(); htsmsg_add_u32(m, "id", m_fileId); Logger::Log(LogLevel::LEVEL_TRACE, "vfs stat id=%d", m_fileId); /* Send */ { CLockObject lock(m_conn.Mutex()); m = m_conn.SendAndWait("fileStat", m); } if (m == NULL) return -1; /* Get size. Note: 'size' field is optional. */ if (htsmsg_get_s64(m, "size", &ret)) ret = -1; else Logger::Log(LogLevel::LEVEL_TRACE, "vfs stat size=%lld", (long long)ret); htsmsg_destroy(m); return ret; } void HTSPVFS::PauseStream ( bool paused ) { m_paused = paused; if (paused) { m_pauseTime = std::time(nullptr); } else { if (m_eofOffsetSecs >= 0 && m_pauseTime > 0) { /* correct m_eofOffsetSecs based on how long we've been paused */ m_eofOffsetSecs += (std::time(nullptr) - m_pauseTime); m_isRealTimeStream = (m_eofOffsetSecs >=0 && m_eofOffsetSecs < 10); Logger::Log(LogLevel::LEVEL_TRACE, "vfs unpause inprogress recording m_eofOffsetSecs=%lld m_isRealTimeStream=%d", static_cast(m_eofOffsetSecs), m_isRealTimeStream); } m_pauseTime = 0; } } bool HTSPVFS::IsRealTimeStream ( void ) { return m_isRealTimeStream; } /* ************************************************************************** * HTSP Messages * *************************************************************************/ bool HTSPVFS::SendFileOpen ( bool force ) { htsmsg_t *m; /* Build Message */ m = htsmsg_create_map(); htsmsg_add_str(m, "file", m_path.c_str()); Logger::Log(LogLevel::LEVEL_DEBUG, "vfs open file=%s", m_path.c_str()); /* Send */ { CLockObject lock(m_conn.Mutex()); if (force) m = m_conn.SendAndWait0("fileOpen", m); else m = m_conn.SendAndWait("fileOpen", m); } if (m == NULL) return false; /* Get ID */ if (htsmsg_get_u32(m, "id", &m_fileId)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed fileOpen response: 'id' missing"); m_fileId = 0; } else Logger::Log(LogLevel::LEVEL_TRACE, "vfs opened id=%d", m_fileId); htsmsg_destroy(m); return m_fileId > 0; } void HTSPVFS::SendFileClose ( void ) { htsmsg_t *m; /* Build */ m = htsmsg_create_map(); htsmsg_add_u32(m, "id", m_fileId); /* If setting set, we will increase play count with CTvheadend::SetPlayCount */ if (m_conn.GetProtocol() >= 27) htsmsg_add_u32(m, "playcount", Settings::GetInstance().GetDvrPlayStatus() ? HTSP_DVR_PLAYCOUNT_KEEP : HTSP_DVR_PLAYCOUNT_INCR); Logger::Log(LogLevel::LEVEL_DEBUG, "vfs close id=%d", m_fileId); /* Send */ { CLockObject lock(m_conn.Mutex()); m = m_conn.SendAndWait("fileClose", m); } if (m) htsmsg_destroy(m); } long long HTSPVFS::SendFileSeek ( int64_t pos, int whence, bool force ) { htsmsg_t *m; int64_t ret = -1; /* Build Message */ m = htsmsg_create_map(); htsmsg_add_u32(m, "id", m_fileId); htsmsg_add_s64(m, "offset", pos); if (whence == SEEK_CUR) htsmsg_add_str(m, "whence", "SEEK_CUR"); else if (whence == SEEK_END) htsmsg_add_str(m, "whence", "SEEK_END"); Logger::Log(LogLevel::LEVEL_TRACE, "vfs seek id=%d whence=%d pos=%lld", m_fileId, whence, (long long)pos); /* Send */ { CLockObject lock(m_conn.Mutex()); if (force) m = m_conn.SendAndWait0("fileSeek", m); else m = m_conn.SendAndWait("fileSeek", m); } if (m == NULL) { Logger::Log(LogLevel::LEVEL_ERROR, "vfs fileSeek failed"); return -1; } /* Get new offset */ if (htsmsg_get_s64(m, "offset", &ret)) { ret = -1; Logger::Log(LogLevel::LEVEL_ERROR, "vfs fileSeek response: 'offset' missing'"); /* Update */ } else { Logger::Log(LogLevel::LEVEL_TRACE, "vfs seek offset=%lld", (long long)ret); m_offset = ret; } /* Cleanup */ htsmsg_destroy(m); return ret; } ssize_t HTSPVFS::SendFileRead(unsigned char *buf, unsigned int len) { htsmsg_t *m; const void *buffer; size_t read; /* Build */ m = htsmsg_create_map(); htsmsg_add_u32(m, "id", m_fileId); htsmsg_add_s64(m, "size", len); Logger::Log(LogLevel::LEVEL_TRACE, "vfs read id=%d size=%d", m_fileId, len); /* Send */ { CLockObject lock(m_conn.Mutex()); m = m_conn.SendAndWait("fileRead", m); } if (m == NULL) { Logger::Log(LogLevel::LEVEL_ERROR, "vfs fileRead failed"); return -1; } /* Get Data */ if (htsmsg_get_bin(m, "data", &buffer, &read)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed fileRead response: 'data' missing"); return -1; /* Store */ } else { memcpy(buf, buffer, read); } /* Cleanup */ htsmsg_destroy(m); return read; } pvr.hts-4.4.20-Leia/src/tvheadend/HTSPVFS.h000066400000000000000000000033701355512543200201240ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2017 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 #include "p8-platform/os.h" struct PVR_RECORDING; namespace tvheadend { class HTSPConnection; /* * HTSP VFS - recordings */ class HTSPVFS { public: HTSPVFS(HTSPConnection &conn); ~HTSPVFS(); void Connected(); bool Open(const PVR_RECORDING &rec); void Close(); ssize_t Read(unsigned char *buf, unsigned int len, bool inprogress); long long Seek(long long pos, int whence, bool inprogress); long long Size(); void PauseStream(bool paused); bool IsRealTimeStream(); private: bool SendFileOpen(bool force = false); void SendFileClose(); ssize_t SendFileRead(unsigned char *buf, unsigned int len); long long SendFileSeek(int64_t pos, int whence, bool force = false); HTSPConnection &m_conn; std::string m_path; uint32_t m_fileId; int64_t m_offset; int64_t m_fileStart; int64_t m_eofOffsetSecs; int64_t m_pauseTime; bool m_paused; bool m_isRealTimeStream; }; } // namespace tvheadend pvr.hts-4.4.20-Leia/src/tvheadend/IHTSPConnectionListener.h000066400000000000000000000022541355512543200234040ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2017 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 * */ extern "C" { #include "libhts/htsmsg.h" } namespace tvheadend { /* * HTSP Connection Listener interface */ class IHTSPConnectionListener { public: virtual ~IHTSPConnectionListener() = default; virtual void Disconnected() = 0; virtual bool Connected() = 0; virtual bool ProcessMessage(const char *method, htsmsg_t *msg) = 0; }; } // namespace tvheadend pvr.hts-4.4.20-Leia/src/tvheadend/Profile.h000066400000000000000000000031241355512543200203640ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team Kodi * 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 #include namespace tvheadend { class Profile; typedef std::vector Profiles; /** * Represents a single streaming profile */ class Profile { public: std::string GetUuid() const { return m_uuid; } void SetUuid(const std::string &uuid) { m_uuid = uuid; } std::string GetName() const { return m_name; } void SetName(const std::string &name) { m_name = name; } std::string GetComment() const { return m_comment; } void SetComment(const std::string &comment) { m_comment = comment; } private: /* * The profile UUID */ std::string m_uuid; /** * The profile name */ std::string m_name; /** * The profile comment */ std::string m_comment; }; } pvr.hts-4.4.20-Leia/src/tvheadend/Settings.cpp000066400000000000000000000221631355512543200211230ustar00rootroot00000000000000/* * 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 * */ #include "../client.h" #include "utilities/Logger.h" #include "Settings.h" using namespace tvheadend; using namespace tvheadend::utilities; const std::string Settings::DEFAULT_HOST = "127.0.0.1"; const int Settings::DEFAULT_HTTP_PORT = 9981; const int Settings::DEFAULT_HTSP_PORT = 9982; const std::string Settings::DEFAULT_USERNAME = ""; const std::string Settings::DEFAULT_PASSWORD = ""; const int Settings::DEFAULT_CONNECT_TIMEOUT = 10000; // millisecs const int Settings::DEFAULT_RESPONSE_TIMEOUT = 5000; // millisecs const bool Settings::DEFAULT_TRACE_DEBUG = false; const bool Settings::DEFAULT_ASYNC_EPG = true; const bool Settings::DEFAULT_PRETUNER_ENABLED = false; const int Settings::DEFAULT_TOTAL_TUNERS = 1; // total tuners > 1 => predictive tuning active const int Settings::DEFAULT_PRETUNER_CLOSEDELAY = 10; // secs const int Settings::DEFAULT_AUTOREC_MAXDIFF = 15; // mins. Maximum difference between real and approximate start time for auto recordings const int Settings::DEFAULT_APPROX_TIME = 0; // don't use an approximate start time, use a fixed time instead for auto recordings const std::string Settings::DEFAULT_STREAMING_PROFILE = ""; const int Settings::DEFAULT_DVR_PRIO = DVR_PRIO_NORMAL; const int Settings::DEFAULT_DVR_LIFETIME = 8; // enum 8 = 3 months const int Settings::DEFAULT_DVR_DUPDETECT = DVR_AUTOREC_RECORD_ALL; const bool Settings::DEFAULT_DVR_PLAYSTATUS = true; const int Settings::DEFAULT_STREAM_CHUNKSIZE = 64; // KB const bool Settings::DEFAULT_DVR_IGNORE_DUPLICATE_SCHEDULES = true; void Settings::ReadSettings() { /* Connection */ SetHostname(ReadStringSetting("host", DEFAULT_HOST)); SetPortHTSP(ReadIntSetting("htsp_port", DEFAULT_HTSP_PORT)); SetPortHTTP(ReadIntSetting("http_port", DEFAULT_HTTP_PORT)); SetUsername(ReadStringSetting("user", DEFAULT_USERNAME)); SetPassword(ReadStringSetting("pass", DEFAULT_PASSWORD)); /* Note: Timeouts in settings UI are defined in seconds but we expect them to be in milliseconds. */ SetConnectTimeout(ReadIntSetting("connect_timeout", DEFAULT_CONNECT_TIMEOUT / 1000) * 1000); SetResponseTimeout(ReadIntSetting("response_timeout", DEFAULT_RESPONSE_TIMEOUT / 1000) * 1000); /* Debug */ SetTraceDebug(ReadBoolSetting("trace_debug", DEFAULT_TRACE_DEBUG)); /* Data Transfer */ SetAsyncEpg(ReadBoolSetting("epg_async", DEFAULT_ASYNC_EPG)); /* Predictive Tuning */ m_bPretunerEnabled = ReadBoolSetting("pretuner_enabled", DEFAULT_PRETUNER_ENABLED); SetTotalTuners(m_bPretunerEnabled ? ReadIntSetting("total_tuners", DEFAULT_TOTAL_TUNERS) : 1); SetPreTunerCloseDelay(m_bPretunerEnabled ? ReadIntSetting("pretuner_closedelay", DEFAULT_PRETUNER_CLOSEDELAY) : 0); /* Auto recordings */ SetAutorecApproxTime(ReadIntSetting("autorec_approxtime", DEFAULT_APPROX_TIME)); SetAutorecMaxDiff(ReadIntSetting("autorec_maxdiff", DEFAULT_AUTOREC_MAXDIFF)); /* Streaming */ SetStreamingProfile(ReadStringSetting("streaming_profile", DEFAULT_STREAMING_PROFILE)); /* Default dvr settings */ SetDvrPriority(ReadIntSetting("dvr_priority", DEFAULT_DVR_PRIO)); SetDvrLifetime(ReadIntSetting("dvr_lifetime", DEFAULT_DVR_LIFETIME)); SetDvrDupdetect(ReadIntSetting("dvr_dubdetect", DEFAULT_DVR_DUPDETECT)); /* Sever based play status */ SetDvrPlayStatus(ReadBoolSetting("dvr_playstatus", DEFAULT_DVR_PLAYSTATUS)); /* Stream read chunk size */ SetStreamReadChunkSizeKB(ReadIntSetting("stream_readchunksize", DEFAULT_STREAM_CHUNKSIZE)); /* Scheduled recordings */ SetIgnoreDuplicateSchedules(ReadBoolSetting("dvr_ignore_duplicates", DEFAULT_DVR_IGNORE_DUPLICATE_SCHEDULES)); } ADDON_STATUS Settings::SetSetting(const std::string &key, const void *value) { /* Connection */ if (key == "host") return SetStringSetting(GetHostname(), value); else if (key == "htsp_port") return SetIntSetting(GetPortHTSP(), value); else if (key == "http_port") return SetIntSetting(GetPortHTTP(), value); else if (key == "user") return SetStringSetting(GetUsername(), value); else if (key == "pass") return SetStringSetting(GetPassword(), value); else if (key == "connect_timeout") { if (GetConnectTimeout() == (*(reinterpret_cast(value)) * 1000)) return ADDON_STATUS_OK; else return ADDON_STATUS_NEED_RESTART; } else if (key == "response_timeout") { if (GetResponseTimeout() == (*(reinterpret_cast(value)) * 1000)) return ADDON_STATUS_OK; else return ADDON_STATUS_NEED_RESTART; } /* Debug */ else if (key == "trace_debug") return SetBoolSetting(GetTraceDebug(), value); /* Data Transfer */ else if (key == "epg_async") return SetBoolSetting(GetAsyncEpg(), value); /* Predictive Tuning */ else if (key == "pretuner_enabled") return SetBoolSetting(m_bPretunerEnabled, value); else if (key == "total_tuners") { if (!m_bPretunerEnabled) return ADDON_STATUS_OK; else return SetIntSetting(GetTotalTuners(), value); } else if (key == "pretuner_closedelay") { if (!m_bPretunerEnabled) return ADDON_STATUS_OK; else return SetIntSetting(GetPreTunerCloseDelay(), value); } /* Auto recordings */ else if (key == "autorec_approxtime") return SetIntSetting(GetAutorecApproxTime(), value); else if (key == "autorec_maxdiff") return SetIntSetting(GetAutorecMaxDiff(), value); /* Streaming */ else if (key == "streaming_profile") return SetStringSetting(GetStreamingProfile(), value); /* Default dvr settings */ else if (key == "dvr_priority") return SetIntSetting(GetDvrPriority(), value); else if (key == "dvr_lifetime") return SetIntSetting(GetDvrLifetime(true), value); else if (key == "dvr_dubdetect") return SetIntSetting(GetDvrDupdetect(), value); /* Server based play status */ else if (key == "dvr_playstatus") return SetBoolSetting(GetDvrPlayStatus(), value); else if (key == "stream_readchunksize") return SetIntSetting(GetStreamReadChunkSize(), value); else if (key == "dvr_ignore_duplicates") return SetBoolSetting(GetIgnoreDuplicateSchedules(), value); else { Logger::Log(LogLevel::LEVEL_ERROR, "Settings::SetSetting - unknown setting '%s'", key.c_str()); return ADDON_STATUS_UNKNOWN; } } std::string Settings::ReadStringSetting(const std::string &key, const std::string &def) { char value[1024]; if (XBMC->GetSetting(key.c_str(), value)) return value; return def; } int Settings::ReadIntSetting(const std::string &key, int def) { int value; if (XBMC->GetSetting(key.c_str(), &value)) return value; return def; } bool Settings::ReadBoolSetting(const std::string &key, bool def) { bool value; if (XBMC->GetSetting(key.c_str(), &value)) return value; return def; } ADDON_STATUS Settings::SetStringSetting(const std::string &oldValue, const void *newValue) { if (oldValue == std::string(reinterpret_cast(newValue))) return ADDON_STATUS_OK; return ADDON_STATUS_NEED_RESTART; } ADDON_STATUS Settings::SetIntSetting(int oldValue, const void *newValue) { if (oldValue == *(reinterpret_cast(newValue))) return ADDON_STATUS_OK; return ADDON_STATUS_NEED_RESTART; } ADDON_STATUS Settings::SetBoolSetting(bool oldValue, const void *newValue) { if (oldValue == *(reinterpret_cast(newValue))) return ADDON_STATUS_OK; return ADDON_STATUS_NEED_RESTART; } int Settings::GetDvrLifetime(bool asEnum) const { if (asEnum) return m_iDvrLifetime; else { switch (m_iDvrLifetime) { case 0: return DVR_RET_1DAY; case 1: return DVR_RET_3DAY; case 2: return DVR_RET_5DAY; case 3: return DVR_RET_1WEEK; case 4: return DVR_RET_2WEEK; case 5: return DVR_RET_3WEEK; case 6: return DVR_RET_1MONTH; case 7: return DVR_RET_2MONTH; case 8: return DVR_RET_3MONTH; case 9: return DVR_RET_6MONTH; case 10: return DVR_RET_1YEAR; case 11: return DVR_RET_2YEARS; case 12: return DVR_RET_3YEARS; case 13: return DVR_RET_SPACE; default: return DVR_RET_FOREVER; } } } pvr.hts-4.4.20-Leia/src/tvheadend/Settings.h000066400000000000000000000202111355512543200205600ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2014 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 #include "HTSPTypes.h" #include "kodi/xbmc_addon_types.h" namespace tvheadend { /** * Represents the current addon settings */ class Settings { public: // Default values. static const std::string DEFAULT_HOST; static const int DEFAULT_HTTP_PORT; static const int DEFAULT_HTSP_PORT; static const std::string DEFAULT_USERNAME; static const std::string DEFAULT_PASSWORD; static const int DEFAULT_CONNECT_TIMEOUT; // millisecs static const int DEFAULT_RESPONSE_TIMEOUT; // millisecs static const bool DEFAULT_TRACE_DEBUG; static const bool DEFAULT_ASYNC_EPG; static const bool DEFAULT_PRETUNER_ENABLED; static const int DEFAULT_TOTAL_TUNERS; static const int DEFAULT_PRETUNER_CLOSEDELAY; // secs static const int DEFAULT_AUTOREC_MAXDIFF; // mins. Maximum difference between real and approximate start time for auto recordings static const int DEFAULT_APPROX_TIME; // 0..1 (0 = use a fixed start time, 1 = use an approximate start time for auto recordings) static const std::string DEFAULT_STREAMING_PROFILE; static const int DEFAULT_DVR_PRIO; // any dvr_prio_t numeric value static const int DEFAULT_DVR_LIFETIME; // 0..14 (0 = 1 day, 14 = forever) static const int DEFAULT_DVR_DUPDETECT; // 0..5 (0 = record all, 5 = limit to once a day) static const bool DEFAULT_DVR_PLAYSTATUS; static const int DEFAULT_STREAM_CHUNKSIZE; // KB static const bool DEFAULT_DVR_IGNORE_DUPLICATE_SCHEDULES; /** * Singleton getter for the instance */ static Settings& GetInstance() { static Settings settings; return settings; } /** * Read all settings defined in settings.xml */ void ReadSettings(); /** * Set a value according to key definition in settings.xml */ ADDON_STATUS SetSetting(const std::string &key, const void *value); /** * Getters for the settings values */ std::string GetHostname() const { return m_strHostname; } const char *GetConstCharHostname() const { return m_strHostname.c_str(); } int GetPortHTSP() const { return m_iPortHTSP; } int GetPortHTTP() const { return m_iPortHTTP; } std::string GetUsername() const { return m_strUsername; } std::string GetPassword() const { return m_strPassword; } int GetConnectTimeout() const { return m_iConnectTimeout; } int GetResponseTimeout() const { return m_iResponseTimeout; } bool GetTraceDebug() const { return m_bTraceDebug; } bool GetAsyncEpg() const { return m_bAsyncEpg; } int GetTotalTuners() const { return m_iTotalTuners; } int GetPreTunerCloseDelay() const { return m_iPreTunerCloseDelay; } int GetAutorecApproxTime() const { return m_iAutorecApproxTime; } int GetAutorecMaxDiff() const { return m_iAutorecMaxDiff; } std::string GetStreamingProfile() const { return m_strStreamingProfile; } int GetDvrPriority() const { return m_iDvrPriority; } int GetDvrDupdetect() const { return m_iDvrDupdetect; } int GetDvrLifetime(bool asEnum = false) const; bool GetDvrPlayStatus() const { return m_bDvrPlayStatus; } int GetStreamReadChunkSize() const { return m_iStreamReadChunkSizeKB; } bool GetIgnoreDuplicateSchedules() const { return m_bIgnoreDuplicateSchedules; } private: Settings() : m_strHostname(DEFAULT_HOST), m_iPortHTSP(DEFAULT_HTTP_PORT), m_iPortHTTP(DEFAULT_HTSP_PORT), m_strUsername(DEFAULT_USERNAME), m_strPassword(DEFAULT_PASSWORD), m_iConnectTimeout(DEFAULT_CONNECT_TIMEOUT), m_iResponseTimeout(DEFAULT_RESPONSE_TIMEOUT), m_bTraceDebug(DEFAULT_TRACE_DEBUG), m_bAsyncEpg(DEFAULT_ASYNC_EPG), m_bPretunerEnabled(DEFAULT_PRETUNER_ENABLED), m_iTotalTuners(DEFAULT_TOTAL_TUNERS), m_iPreTunerCloseDelay(DEFAULT_PRETUNER_CLOSEDELAY), m_iAutorecApproxTime(DEFAULT_APPROX_TIME), m_iAutorecMaxDiff(DEFAULT_AUTOREC_MAXDIFF), m_strStreamingProfile(DEFAULT_STREAMING_PROFILE), m_iDvrPriority(DEFAULT_DVR_PRIO), m_iDvrLifetime(DEFAULT_DVR_LIFETIME), m_iDvrDupdetect(DEFAULT_DVR_DUPDETECT), m_bDvrPlayStatus(DEFAULT_DVR_PLAYSTATUS), m_iStreamReadChunkSizeKB(DEFAULT_STREAM_CHUNKSIZE), m_bIgnoreDuplicateSchedules(DEFAULT_DVR_IGNORE_DUPLICATE_SCHEDULES) {} Settings(Settings const &) = delete; void operator=(Settings const &) = delete; /** * Setters */ void SetHostname(const std::string& value) { m_strHostname = value; } void SetPortHTSP(int value) { m_iPortHTSP = value; } void SetPortHTTP(int value) { m_iPortHTTP = value; } void SetUsername(const std::string& value) { m_strUsername = value; } void SetPassword(const std::string& value) { m_strPassword = value; } void SetConnectTimeout(int value) { m_iConnectTimeout = value; } void SetResponseTimeout(int value) { m_iResponseTimeout = value; } void SetTraceDebug(bool value) { m_bTraceDebug = value; } void SetAsyncEpg(bool value) { m_bAsyncEpg = value; } void SetTotalTuners(int value) { m_iTotalTuners = value; } void SetPreTunerCloseDelay(int value) { m_iPreTunerCloseDelay = value; } void SetAutorecApproxTime(int value) { m_iAutorecApproxTime = value; } void SetAutorecMaxDiff(int value) { m_iAutorecMaxDiff = value; } void SetStreamingProfile(const std::string &value) { m_strStreamingProfile = value; } void SetDvrPriority(int value) { m_iDvrPriority = value; } void SetDvrLifetime(int value) { m_iDvrLifetime = value; } void SetDvrDupdetect(int value) { m_iDvrDupdetect = value; } void SetDvrPlayStatus(bool value) { m_bDvrPlayStatus = value; } void SetStreamReadChunkSizeKB(int value) { m_iStreamReadChunkSizeKB = value; } void SetIgnoreDuplicateSchedules(bool value) { m_bIgnoreDuplicateSchedules = value; } /** * Read/Set values according to definition in settings.xml */ static std::string ReadStringSetting(const std::string &key, const std::string &def); static int ReadIntSetting(const std::string &key, int def); static bool ReadBoolSetting(const std::string &key, bool def); // @return ADDON_STATUS_OK if value has not changed, ADDON_STATUS_NEED_RESTART otherwise static ADDON_STATUS SetStringSetting(const std::string &oldValue, const void *newValue); static ADDON_STATUS SetIntSetting(int oldValue, const void *newValue); static ADDON_STATUS SetBoolSetting(bool oldValue, const void *newValue); std::string m_strHostname; int m_iPortHTSP; int m_iPortHTTP; std::string m_strUsername; std::string m_strPassword; int m_iConnectTimeout; int m_iResponseTimeout; bool m_bTraceDebug; bool m_bAsyncEpg; bool m_bPretunerEnabled; int m_iTotalTuners; int m_iPreTunerCloseDelay; bool m_iAutorecApproxTime; int m_iAutorecMaxDiff; std::string m_strStreamingProfile; int m_iDvrPriority; int m_iDvrLifetime; int m_iDvrDupdetect; bool m_bDvrPlayStatus; int m_iStreamReadChunkSizeKB; bool m_bIgnoreDuplicateSchedules; }; } pvr.hts-4.4.20-Leia/src/tvheadend/Subscription.cpp000066400000000000000000000211261355512543200220050ustar00rootroot00000000000000/* * 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 * */ #include "Subscription.h" #include "utilities/LocalizedString.h" #include "utilities/Logger.h" #include "HTSPConnection.h" using namespace P8PLATFORM; using namespace tvheadend; using namespace tvheadend::utilities; Subscription::Subscription(HTSPConnection &conn) : m_id(0), m_channelId(0), m_weight(SUBSCRIPTION_WEIGHT_NORMAL), m_speed(1000), m_state(SUBSCRIPTION_STOPPED), m_conn(conn) { } bool Subscription::IsActive() const { CLockObject lock(m_mutex); return (GetState() != SUBSCRIPTION_STOPPED); } uint32_t Subscription::GetId() const { CLockObject lock(m_mutex); return m_id; } void Subscription::SetId(uint32_t id) { CLockObject lock(m_mutex); m_id = id; } uint32_t Subscription::GetChannelId() const { CLockObject lock(m_mutex); return m_channelId; } void Subscription::SetChannelId(uint32_t id) { CLockObject lock(m_mutex); m_channelId = id; } uint32_t Subscription::GetWeight() const { CLockObject lock(m_mutex); return m_weight; } void Subscription::SetWeight(uint32_t weight) { CLockObject lock(m_mutex); m_weight = weight; } int32_t Subscription::GetSpeed() const { CLockObject lock(m_mutex); return m_speed; } void Subscription::SetSpeed(int32_t speed) { CLockObject lock(m_mutex); m_speed = speed; } eSubsriptionState Subscription::GetState() const { CLockObject lock(m_mutex); return m_state; } void Subscription::SetState(eSubsriptionState state) { CLockObject lock(m_mutex); m_state = state; } std::string Subscription::GetProfile() const { CLockObject lock(m_mutex); return m_profile; } void Subscription::SetProfile(const std::string &profile) { CLockObject lock(m_mutex); m_profile = profile; } void Subscription::SendSubscribe(uint32_t channelId, uint32_t weight, bool restart) { /* We don't want to change anything when restarting a subscription */ if (!restart) { SetChannelId(channelId); SetWeight(weight); SetId(GetNextId()); SetSpeed(1000); //set back to normal } /* Build message */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_s32(m, "channelId", GetChannelId()); htsmsg_add_u32(m, "subscriptionId", GetId()); htsmsg_add_u32(m, "weight", GetWeight()); htsmsg_add_u32(m, "timeshiftPeriod", static_cast(~0)); htsmsg_add_u32(m, "normts", 1); htsmsg_add_u32(m, "queueDepth", PACKET_QUEUE_DEPTH); /* Use the specified profile if it has been set */ if (!GetProfile().empty()) htsmsg_add_str(m, "profile", GetProfile().c_str()); Logger::Log(LogLevel::LEVEL_DEBUG, "demux subscribe to %d", GetChannelId()); /* Send and Wait for response */ if (restart) m = m_conn.SendAndWait0("subscribe", m); else m = m_conn.SendAndWait("subscribe", m); if (m == NULL) return; htsmsg_destroy(m); SetState(SUBSCRIPTION_STARTING); Logger::Log(LogLevel::LEVEL_DEBUG, "demux successfully subscribed to channel id %d, subscription id %d", GetChannelId(), GetId()); } void Subscription::SendUnsubscribe(void) { /* Build message */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "subscriptionId", GetId()); Logger::Log(LogLevel::LEVEL_DEBUG, "demux unsubscribe from %d", GetChannelId()); /* Mark subscription as inactive immediately in case this command fails */ SetState(SUBSCRIPTION_STOPPED); /* Send and Wait */ if ((m = m_conn.SendAndWait("unsubscribe", m)) == NULL) return; htsmsg_destroy(m); Logger::Log(LogLevel::LEVEL_DEBUG, "demux successfully unsubscribed from channel id %d, subscription id %d", GetChannelId(), GetId()); } bool Subscription::SendSeek(double time) { /* Build message */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "subscriptionId", GetId()); htsmsg_add_s64(m, "time", static_cast(time * 1000LL)); htsmsg_add_u32(m, "absolute", 1); Logger::Log(LogLevel::LEVEL_DEBUG, "demux send seek %d", time); /* Send and Wait */ { CLockObject lock(m_conn.Mutex()); m = m_conn.SendAndWait("subscriptionSeek", m); } if (m) { htsmsg_destroy(m); return true; } return false; } void Subscription::SendSpeed(int32_t speed, bool restart) { /* We don't want to change the speed when restarting a subscription */ if (!restart) SetSpeed(speed); /* Build message */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "subscriptionId", GetId()); htsmsg_add_s32(m, "speed", GetSpeed() / 10); // Kodi uses values an order of magnitude larger than tvheadend Logger::Log(LogLevel::LEVEL_DEBUG, "demux send speed %d", GetSpeed() / 10); if (restart) m = m_conn.SendAndWait0("subscriptionSpeed", m); else m = m_conn.SendAndWait("subscriptionSpeed", m); if (m) htsmsg_destroy(m); } void Subscription::SendWeight(uint32_t weight) { SetWeight(weight); /* Build message */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "subscriptionId", GetId()); htsmsg_add_s32(m, "weight", GetWeight()); Logger::Log(LogLevel::LEVEL_DEBUG, "demux send weight %u", GetWeight()); /* Send and Wait */ { CLockObject lock(m_conn.Mutex()); m = m_conn.SendAndWait("subscriptionChangeWeight", m); } if (m) htsmsg_destroy(m); } void Subscription::ParseSubscriptionStatus ( htsmsg_t *m ) { /* Not for preTuning and postTuning subscriptions */ if (GetWeight() == static_cast(SUBSCRIPTION_WEIGHT_PRETUNING) || GetWeight() == static_cast(SUBSCRIPTION_WEIGHT_POSTTUNING)) { SetState(SUBSCRIPTION_PREPOSTTUNING); return; } const char *status = htsmsg_get_str(m, "status"); /* 'subscriptionErrors' was added in htsp v20, use 'status' for older backends */ if (m_conn.GetProtocol() >= 20) { const char *error = htsmsg_get_str(m, "subscriptionError"); /* This field is absent when everything is fine */ if (error != NULL) { if (!strcmp("badSignal", error)) SetState(SUBSCRIPTION_NOSIGNAL); else if (!strcmp("scrambled", error)) SetState(SUBSCRIPTION_SCRAMBLED); else if (!strcmp("userLimit", error)) SetState(SUBSCRIPTION_USERLIMIT); else if (!strcmp("noFreeAdapter", error)) SetState(SUBSCRIPTION_NOFREEADAPTER); else if (!strcmp("tuningFailed", error)) SetState(SUBSCRIPTION_TUNINGFAILED); else if (!strcmp("userAccess", error)) SetState(SUBSCRIPTION_NOACCESS); else SetState(SUBSCRIPTION_UNKNOWN); /* Show an OSD message */ ShowStateNotification(); } else SetState(SUBSCRIPTION_RUNNING); } else { /* This field is absent when everything is fine */ if (status != NULL) { SetState(SUBSCRIPTION_UNKNOWN); /* Show an OSD message */ XBMC->QueueNotification(ADDON::QUEUE_INFO, status); } else SetState(SUBSCRIPTION_RUNNING); } } void Subscription::ShowStateNotification(void) { if (GetState() == SUBSCRIPTION_NOFREEADAPTER) XBMC->QueueNotification(ADDON::QUEUE_WARNING, LocalizedString(30450).Get().c_str()); else if (GetState() == SUBSCRIPTION_SCRAMBLED) XBMC->QueueNotification(ADDON::QUEUE_WARNING, LocalizedString(30451).Get().c_str()); else if (GetState() == SUBSCRIPTION_NOSIGNAL) XBMC->QueueNotification(ADDON::QUEUE_WARNING, LocalizedString(30452).Get().c_str()); else if (GetState() == SUBSCRIPTION_TUNINGFAILED) XBMC->QueueNotification(ADDON::QUEUE_WARNING, LocalizedString(30453).Get().c_str()); else if (GetState() == SUBSCRIPTION_USERLIMIT) XBMC->QueueNotification(ADDON::QUEUE_WARNING, LocalizedString(30454).Get().c_str()); else if (GetState() == SUBSCRIPTION_NOACCESS) XBMC->QueueNotification(ADDON::QUEUE_WARNING, LocalizedString(30455).Get().c_str()); else if (GetState() == SUBSCRIPTION_UNKNOWN) XBMC->QueueNotification(ADDON::QUEUE_WARNING, LocalizedString(30456).Get().c_str()); } uint32_t Subscription::GetNextId() { static uint32_t id = 0; return ++id; } pvr.hts-4.4.20-Leia/src/tvheadend/Subscription.h000066400000000000000000000122501355512543200214500ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 #include "p8-platform/threads/mutex.h" extern "C" { #include "libhts/htsmsg.h" } namespace tvheadend { class HTSPConnection; /* streaming uses a weight of 100 by default on the tvh side */ /* lowest configurable streaming weight in tvh is 50 */ /* predictive tuning should be lower to avoid conflicts */ /* weight 0 means that tvh will use the weight of it's config */ enum eSubscriptionWeight { SUBSCRIPTION_WEIGHT_NORMAL = 100, SUBSCRIPTION_WEIGHT_PRETUNING = 40, SUBSCRIPTION_WEIGHT_POSTTUNING = 30, SUBSCRIPTION_WEIGHT_SERVERCONF = 0, }; enum eSubsriptionState { SUBSCRIPTION_STOPPED = 0, /* subscription is stopped or not started yet */ SUBSCRIPTION_STARTING = 1, /* subscription is starting */ SUBSCRIPTION_RUNNING = 2, /* subscription is running normal */ SUBSCRIPTION_NOFREEADAPTER = 3, /* subscription has no free adapter to use */ SUBSCRIPTION_SCRAMBLED = 4, /* subscription is not running because the channel is scrambled */ SUBSCRIPTION_NOSIGNAL = 5, /* subscription is not running because of a weak/no input signal */ SUBSCRIPTION_TUNINGFAILED = 6, /* subscription could not be started because of a tuning error */ SUBSCRIPTION_USERLIMIT = 7, /* userlimit is reached, so we could not start this subscription */ SUBSCRIPTION_NOACCESS = 8, /* we have no rights to watch this channel */ SUBSCRIPTION_UNKNOWN = 9, /* subscription state is unknown, also used for pretuning and posttuning subscriptions */ SUBSCRIPTION_PREPOSTTUNING = 10, /* used for pre and posttuning subscriptions (we do not care what the actual state is) */ }; static const int PACKET_QUEUE_DEPTH = 10000000; class Subscription { public: Subscription(HTSPConnection &conn); bool IsActive() const; uint32_t GetId() const; uint32_t GetChannelId() const; uint32_t GetWeight() const; int32_t GetSpeed() const; eSubsriptionState GetState() const; std::string GetProfile() const; /** * Subscribe to a channel on the backend * @param channelId the channel to subscribe to * @param weight the desired subscription weight * @param restart restart the current subscription (i.e. after lost connection), other parameters will be ignored */ void SendSubscribe(uint32_t channelId, uint32_t weight, bool restart = false); /** * Unsubscribe from a channel on the backend */ void SendUnsubscribe(); /** * Send a seek to the backend * @param time timestamp to seek to * @return false if the command failed, true otherwise */ bool SendSeek(double time); /** * Change the subscription speed on the backend * @param speed the desired speed of the subscription * @param restart resent the current subscription speed (i.e. after lost connection), other parameters will be ignored */ void SendSpeed(int32_t speed, bool restart = false); /** * Change the subscription weight on the backend * @param weight the desired subscription weight */ void SendWeight(uint32_t weight); /** * Parse the subscription status out of the incoming htsp data * @param m message containing the status field */ void ParseSubscriptionStatus(htsmsg_t *m); /** * Use the specified profile for all new subscriptions * @param profile the profile */ void SetProfile(const std::string &profile); private: void SetId(uint32_t id); void SetChannelId(uint32_t id); void SetWeight(uint32_t weight); void SetSpeed(int32_t speed); void SetState(eSubsriptionState state); /** * Show a notification to the user depending on the subscription state */ void ShowStateNotification(); /** * Get the next unique subscription Id */ static uint32_t GetNextId(); uint32_t m_id; uint32_t m_channelId; uint32_t m_weight; int32_t m_speed; eSubsriptionState m_state; std::string m_profile; HTSPConnection &m_conn; mutable P8PLATFORM::CMutex m_mutex; }; } pvr.hts-4.4.20-Leia/src/tvheadend/TimeRecordings.cpp000066400000000000000000000274031355512543200222430ustar00rootroot00000000000000/* * Copyright (C) 2005-2015 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Kodi; 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 "TimeRecordings.h" #include "HTSPConnection.h" #include "entity/Recording.h" #include "utilities/Utilities.h" #include "utilities/Logger.h" #include "utilities/LifetimeMapper.h" using namespace P8PLATFORM; using namespace tvheadend; using namespace tvheadend::entity; using namespace tvheadend::utilities; TimeRecordings::TimeRecordings(HTSPConnection &conn) : m_conn(conn) { } TimeRecordings::~TimeRecordings() { } void TimeRecordings::Connected() { /* Flag all async fields in case they've been deleted */ for (auto it = m_timeRecordings.begin(); it != m_timeRecordings.end(); ++it) it->second.SetDirty(true); } void TimeRecordings::SyncDvrCompleted() { utilities::erase_if(m_timeRecordings, [](const TimeRecordingMapEntry &entry) { return entry.second.IsDirty(); }); } int TimeRecordings::GetTimerecTimerCount() const { return m_timeRecordings.size(); } void TimeRecordings::GetTimerecTimers(std::vector &timers) { for (auto tit = m_timeRecordings.begin(); tit != m_timeRecordings.end(); ++tit) { /* Setup entry */ PVR_TIMER tmr = { 0 }; tmr.iClientIndex = tit->second.GetId(); tmr.iClientChannelUid = (tit->second.GetChannel() > 0) ? tit->second.GetChannel() : PVR_TIMER_ANY_CHANNEL; tmr.startTime = tit->second.GetStart(); tmr.endTime = tit->second.GetStop(); strncpy(tmr.strTitle, tit->second.GetName().c_str(), sizeof(tmr.strTitle) - 1); strncpy(tmr.strEpgSearchString, "", sizeof(tmr.strEpgSearchString) - 1); // n/a for manual timers strncpy(tmr.strDirectory, tit->second.GetDirectory().c_str(), sizeof(tmr.strDirectory) - 1); strncpy(tmr.strSummary, "", sizeof(tmr.strSummary) - 1); // n/a for repeating timers tmr.state = tit->second.IsEnabled() ? PVR_TIMER_STATE_SCHEDULED : PVR_TIMER_STATE_DISABLED; tmr.iTimerType = TIMER_REPEATING_MANUAL; tmr.iPriority = tit->second.GetPriority(); tmr.iLifetime = tit->second.GetLifetime(); tmr.iMaxRecordings = 0; // not supported by tvh tmr.iRecordingGroup = 0; // not supported by tvh tmr.iPreventDuplicateEpisodes = 0; // n/a for manual timers tmr.firstDay = 0; // not supported by tvh tmr.iWeekdays = tit->second.GetDaysOfWeek(); tmr.iEpgUid = PVR_TIMER_NO_EPG_UID; // n/a for manual timers tmr.iMarginStart = 0; // n/a for manual timers tmr.iMarginEnd = 0; // n/a for manual timers tmr.iGenreType = 0; // not supported by tvh? tmr.iGenreSubType = 0; // not supported by tvh? tmr.bFullTextEpgSearch = false; // n/a for manual timers tmr.iParentClientIndex = 0; timers.emplace_back(tmr); } } const unsigned int TimeRecordings::GetTimerIntIdFromStringId(const std::string &strId) const { for (auto tit = m_timeRecordings.begin(); tit != m_timeRecordings.end(); ++tit) { if (tit->second.GetStringId() == strId) return tit->second.GetId(); } Logger::Log(LogLevel::LEVEL_ERROR, "Timerec: Unable to obtain int id for string id %s", strId.c_str()); return 0; } const std::string TimeRecordings::GetTimerStringIdFromIntId(unsigned int intId) const { for (auto tit = m_timeRecordings.begin(); tit != m_timeRecordings.end(); ++tit) { if (tit->second.GetId() == intId) return tit->second.GetStringId(); } Logger::Log(LogLevel::LEVEL_ERROR, "Timerec: Unable to obtain string id for int id %s", intId); return ""; } PVR_ERROR TimeRecordings::SendTimerecAdd(const PVR_TIMER &timer) { return SendTimerecAddOrUpdate(timer, false); } PVR_ERROR TimeRecordings::SendTimerecUpdate(const PVR_TIMER &timer) { if (m_conn.GetProtocol() >= 25) return SendTimerecAddOrUpdate(timer, true); /* Note: there is no "updateTimerec" htsp method for htsp version < 25, thus delete + add. */ PVR_ERROR error = SendTimerecDelete(timer); if (error == PVR_ERROR_NO_ERROR) error = SendTimerecAdd(timer); return error; } PVR_ERROR TimeRecordings::SendTimerecAddOrUpdate(const PVR_TIMER &timer, bool update) { uint32_t u32; const std::string method = update ? "updateTimerecEntry" : "addTimerecEntry"; /* Build message */ htsmsg_t *m = htsmsg_create_map(); if (update) { std::string strId = GetTimerStringIdFromIntId(timer.iClientIndex); if (strId.empty()) { htsmsg_destroy(m); return PVR_ERROR_FAILED; } htsmsg_add_str(m, "id", strId.c_str()); // Autorec DVR Entry ID (string!) } char title[PVR_ADDON_NAME_STRING_LENGTH+6]; const char *titleExt = "%F-%R"; // timerec title should contain the pattern (e.g. %F-%R) for the generated recording files. Scary... snprintf(title, sizeof(title), "%s-%s", timer.strTitle, titleExt); htsmsg_add_str(m, "name", timer.strTitle); htsmsg_add_str(m, "title", title); time_t startTime = timer.startTime; struct tm *tm_start = localtime(&startTime); htsmsg_add_u32(m, "start", tm_start->tm_hour * 60 + tm_start->tm_min); // start time in minutes from midnight time_t endTime = timer.endTime; struct tm *tm_stop = localtime(&endTime); htsmsg_add_u32(m, "stop", tm_stop->tm_hour * 60 + tm_stop->tm_min); // end time in minutes from midnight if (m_conn.GetProtocol() >= 25) { htsmsg_add_u32(m, "removal", timer.iLifetime); // remove from disk htsmsg_add_s64(m, "channelId", timer.iClientChannelUid); // channelId is signed for >= htspv25 } else { htsmsg_add_u32(m, "retention", LifetimeMapper::KodiToTvh(timer.iLifetime)); // remove from tvh database htsmsg_add_u32(m, "channelId", timer.iClientChannelUid); // channelId is unsigned for < htspv25 } htsmsg_add_u32(m, "daysOfWeek", timer.iWeekdays); htsmsg_add_u32(m, "priority", timer.iPriority); htsmsg_add_u32(m, "enabled", timer.state == PVR_TIMER_STATE_DISABLED ? 0 : 1); /* Note: As a result of internal filename cleanup, for "directory" == "/", */ /* tvh would put recordings into a folder named "-". Not a big issue */ /* but ugly. */ if (strcmp(timer.strDirectory, "/") != 0) htsmsg_add_str(m, "directory", timer.strDirectory); /* Send and Wait */ { CLockObject lock(m_conn.Mutex()); m = m_conn.SendAndWait(method.c_str(), m); } if (m == NULL) return PVR_ERROR_SERVER_ERROR; /* Check for error */ if (htsmsg_get_u32(m, "success", &u32)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed %s response: 'success' missing", method.c_str()); u32 = PVR_ERROR_FAILED; } htsmsg_destroy(m); return u32 == 1 ? PVR_ERROR_NO_ERROR : PVR_ERROR_FAILED; } PVR_ERROR TimeRecordings::SendTimerecDelete(const PVR_TIMER &timer) { uint32_t u32; std::string strId = GetTimerStringIdFromIntId(timer.iClientIndex); if (strId.empty()) return PVR_ERROR_FAILED; htsmsg_t *m = htsmsg_create_map(); htsmsg_add_str(m, "id", strId.c_str()); // Timerec DVR Entry ID (string!) /* Send and Wait */ { CLockObject lock(m_conn.Mutex()); m = m_conn.SendAndWait("deleteTimerecEntry", m); } if (m == NULL) return PVR_ERROR_SERVER_ERROR; /* Check for error */ if (htsmsg_get_u32(m, "success", &u32)) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed deleteTimerecEntry response: 'success' missing"); } htsmsg_destroy(m); return u32 == 1 ? PVR_ERROR_NO_ERROR : PVR_ERROR_FAILED; } bool TimeRecordings::ParseTimerecAddOrUpdate(htsmsg_t *msg, bool bAdd) { const char *str; uint32_t u32; int32_t s32; /* Validate/set mandatory fields */ if ((str = htsmsg_get_str(msg, "id")) == NULL) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed timerecEntryAdd/timerecEntryUpdate: 'id' missing"); return false; } /* Locate/create entry */ TimeRecording &rec = m_timeRecordings[std::string(str)]; rec.SetStringId(std::string(str)); rec.SetDirty(false); /* Validate/set fields mandatory for timerecEntryAdd */ if (!htsmsg_get_u32(msg, "enabled", &u32)) { rec.SetEnabled(u32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed timerecEntryAdd: 'enabled' missing"); return false; } if (!htsmsg_get_u32(msg, "daysOfWeek", &u32)) { rec.SetDaysOfWeek(u32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed timerecEntryAdd: 'daysOfWeek' missing"); return false; } if (m_conn.GetProtocol() >= 25) { if (!htsmsg_get_u32(msg, "removal", &u32)) { rec.SetLifetime(u32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed timerecEntryAdd: 'removal' missing"); return false; } } else { if (!htsmsg_get_u32(msg, "retention", &u32)) { rec.SetLifetime(u32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed timerecEntryAdd: 'retention' missing"); return false; } } if (!htsmsg_get_u32(msg, "priority", &u32)) { rec.SetPriority(u32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed timerecEntryAdd: 'priority' missing"); return false; } if (!htsmsg_get_s32(msg, "start", &s32)) { rec.SetStart(s32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed timerecEntryAdd: 'start' missing"); return false; } if (!htsmsg_get_s32(msg, "stop", &s32)) { rec.SetStop(s32); } else if (bAdd) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed timerecEntryAdd: 'stop' missing"); return false; } /* Add optional fields */ if ((str = htsmsg_get_str(msg, "title")) != NULL) { rec.SetTitle(str); } if ((str = htsmsg_get_str(msg, "name")) != NULL) { rec.SetName(str); } if ((str = htsmsg_get_str(msg, "directory")) != NULL) { rec.SetDirectory(str); } if ((str = htsmsg_get_str(msg, "owner")) != NULL) { rec.SetOwner(str); } if ((str = htsmsg_get_str(msg, "creator")) != NULL) { rec.SetCreator(str); } if (!htsmsg_get_u32(msg, "channel", &u32)) { rec.SetChannel(u32); } else { /* A timerec can also have an empty channel field, * the user can delete a channel or even an automated bouquet update can do this * let kodi know that no channel is assigned, in this way the user can assign a new channel to this timerec * note: "any channel" will be interpreted as "no channel" for timerecs by kodi */ rec.SetChannel(PVR_TIMER_ANY_CHANNEL); } return true; } bool TimeRecordings::ParseTimerecDelete(htsmsg_t *msg) { const char *id; /* Validate/set mandatory fields */ if ((id = htsmsg_get_str(msg, "id")) == NULL) { Logger::Log(LogLevel::LEVEL_ERROR, "malformed timerecEntryDelete: 'id' missing"); return false; } Logger::Log(LogLevel::LEVEL_TRACE, "delete timerec entry %s", id); /* Erase */ m_timeRecordings.erase(std::string(id)); return true; } pvr.hts-4.4.20-Leia/src/tvheadend/TimeRecordings.h000066400000000000000000000037361355512543200217130ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Kodi; 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 extern "C" { #include #include "libhts/htsmsg.h" } #include "kodi/libXBMC_pvr.h" #include "entity/TimeRecording.h" namespace tvheadend { class HTSPConnection; class TimeRecordings { public: TimeRecordings(HTSPConnection &conn); ~TimeRecordings(); /* state updates */ void Connected(); void SyncDvrCompleted(); /* data access */ int GetTimerecTimerCount() const; void GetTimerecTimers(std::vector &timers); const unsigned int GetTimerIntIdFromStringId(const std::string &strId) const; /* client to server messages */ PVR_ERROR SendTimerecAdd (const PVR_TIMER &timer); PVR_ERROR SendTimerecUpdate(const PVR_TIMER &timer); PVR_ERROR SendTimerecDelete(const PVR_TIMER &timer); /* server to client messages */ bool ParseTimerecAddOrUpdate(htsmsg_t *msg, bool bAdd); bool ParseTimerecDelete(htsmsg_t *msg); private: const std::string GetTimerStringIdFromIntId(unsigned int intId) const; PVR_ERROR SendTimerecAddOrUpdate(const PVR_TIMER &timer, bool update); HTSPConnection &m_conn; tvheadend::entity::TimeRecordingsMap m_timeRecordings; }; } // namespace tvheadend pvr.hts-4.4.20-Leia/src/tvheadend/entity/000077500000000000000000000000001355512543200201275ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/src/tvheadend/entity/AutoRecording.cpp000066400000000000000000000075651355512543200234150ustar00rootroot00000000000000/* * 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 * */ #include "AutoRecording.h" #include "../Settings.h" using namespace tvheadend; using namespace tvheadend::entity; AutoRecording::AutoRecording(const std::string &id /*= ""*/) : RecordingBase(id), m_startWindowBegin(0), m_startWindowEnd(0), m_startExtra(0), m_stopExtra(0), m_dupDetect(0), m_fulltext(0) { } bool AutoRecording::operator==(const AutoRecording &right) { return RecordingBase::operator==(right) && m_startWindowBegin == right.m_startWindowBegin && m_startWindowEnd == right.m_startWindowEnd && m_startExtra == right.m_startExtra && m_stopExtra == right.m_stopExtra && m_dupDetect == right.m_dupDetect && m_fulltext == right.m_fulltext && m_seriesLink == right.m_seriesLink; } bool AutoRecording::operator!=(const AutoRecording &right) { return !(*this == right); } time_t AutoRecording::GetStart() const { if (Settings::GetInstance().GetAutorecApproxTime()) { /* Calculate the approximate start time from the starting window */ if ((m_startWindowBegin == -1) || (m_startWindowEnd == -1)) // no starting window set => "any time" return 0; else if (m_startWindowEnd < m_startWindowBegin) { /* End of start window is a day in the future */ int32_t newEnd = m_startWindowEnd + (24 * 60); int32_t newStart = m_startWindowBegin + (newEnd - m_startWindowBegin) / 2; if (newStart > (24 * 60)) newStart -= (24 * 60); return LocaltimeToUTC(newStart); } else return LocaltimeToUTC(m_startWindowBegin + (m_startWindowEnd - m_startWindowBegin) / 2); } else { if (m_startWindowBegin == -1) // "any time" return 0; return LocaltimeToUTC(m_startWindowBegin); } } void AutoRecording::SetStartWindowBegin(int32_t start) { m_startWindowBegin = start; } time_t AutoRecording::GetStop() const { if (Settings::GetInstance().GetAutorecApproxTime()) { /* Tvh doesn't have an approximate stop time => "any time" */ return 0; } else { if (m_startWindowEnd == -1) // "any time" return 0; return LocaltimeToUTC(m_startWindowEnd); } } void AutoRecording::SetStartWindowEnd(int32_t end) { m_startWindowEnd = end; } int64_t AutoRecording::GetMarginStart() const { return m_startExtra; } void AutoRecording::SetMarginStart(int64_t startExtra) { m_startExtra = startExtra; } int64_t AutoRecording::GetMarginEnd() const { return m_stopExtra; } void AutoRecording::SetMarginEnd(int64_t stopExtra) { m_stopExtra = stopExtra; } uint32_t AutoRecording::GetDupDetect() const { return m_dupDetect; } void AutoRecording::SetDupDetect(uint32_t dupDetect) { m_dupDetect = dupDetect; } bool AutoRecording::GetFulltext() const { return m_fulltext > 0; } void AutoRecording::SetFulltext(uint32_t fulltext) { m_fulltext = fulltext; } const std::string& AutoRecording::GetSeriesLink() const { return m_seriesLink; } void AutoRecording::SetSeriesLink(const std::string &seriesLink) { m_seriesLink = seriesLink; } pvr.hts-4.4.20-Leia/src/tvheadend/entity/AutoRecording.h000066400000000000000000000045561355512543200230570ustar00rootroot00000000000000#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 * */ #include "RecordingBase.h" #include namespace tvheadend { namespace entity { class AutoRecording : public RecordingBase { public: AutoRecording(const std::string &id = ""); bool operator==(const AutoRecording &right); bool operator!=(const AutoRecording &right); time_t GetStart() const; void SetStartWindowBegin(int32_t begin); time_t GetStop() const; void SetStartWindowEnd(int32_t end); int64_t GetMarginStart() const; void SetMarginStart(int64_t startExtra); int64_t GetMarginEnd() const; void SetMarginEnd(int64_t stopExtra); uint32_t GetDupDetect() const; void SetDupDetect(uint32_t dupDetect); bool GetFulltext() const; void SetFulltext(uint32_t fulltext); const std::string& GetSeriesLink() const; void SetSeriesLink(const std::string &seriesLink); private: int32_t m_startWindowBegin; // Begin of the starting window (minutes from midnight). int32_t m_startWindowEnd; // End of the starting window (minutes from midnight). int64_t m_startExtra; // Extra start minutes (pre-time). int64_t m_stopExtra; // Extra stop minutes (post-time). uint32_t m_dupDetect; // duplicate episode detect (numeric values: see dvr_autorec_dedup_t). uint32_t m_fulltext; // Fulltext epg search. std::string m_seriesLink; // Series link. }; typedef std::map AutoRecordingsMap; typedef std::pair AutoRecordingMapEntry; } } pvr.hts-4.4.20-Leia/src/tvheadend/entity/Channel.h000066400000000000000000000053511355512543200216540ustar00rootroot00000000000000#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 * */ #include #include #include #include "Entity.h" #include "../HTSPTypes.h" namespace tvheadend { namespace entity { class Channel; typedef std::pair ChannelMapEntry; typedef std::map Channels; /** * Represents a channel */ class Channel : public Entity { public: Channel() : m_num(0), m_numMinor(0), m_type(CHANNEL_TYPE_OTHER), m_caid(0) { } bool operator<(const Channel &right) const { return m_num < right.m_num; } bool operator==(const Channel &other) const { return m_id == other.m_id && m_num == other.m_num && m_numMinor == other.m_numMinor && m_type == other.m_type && m_caid == other.m_caid && m_name == other.m_name && m_icon == other.m_icon; } bool operator!=(const Channel &other) const { return !(*this == other); } uint32_t GetNum() const { return m_num; } void SetNum(uint32_t num) { m_num = num; } uint32_t GetNumMinor() const { return m_numMinor; } void SetNumMinor(uint32_t numMinor) { m_numMinor = numMinor; } uint32_t GetType() const { return m_type; } void SetType(uint32_t type) { m_type = type; } uint32_t GetCaid() const { return m_caid; } void SetCaid(uint32_t caid) { m_caid = caid; } const std::string& GetName() const { return m_name; } void SetName(const std::string &name) { m_name = name; } const std::string& GetIcon() const { return m_icon; } void SetIcon(const std::string &icon) { m_icon = icon; } private: uint32_t m_num; uint32_t m_numMinor; uint32_t m_type; uint32_t m_caid; std::string m_name; std::string m_icon; }; } } pvr.hts-4.4.20-Leia/src/tvheadend/entity/Entity.h000066400000000000000000000033301355512543200215530ustar00rootroot00000000000000#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 * */ #include namespace tvheadend { namespace entity { /** * Abstract entity. An entity can be dirty or clean and has a numeric ID. */ class Entity { public: Entity() : m_id(0), m_dirty(false) {}; virtual ~Entity() = default; /** * @return if the entity is dirty */ virtual bool IsDirty() const { return m_dirty; } /** * Marks the entity as dirty or not * @param dirty */ virtual void SetDirty(bool dirty) { m_dirty = dirty; } /** * @return the entity ID */ uint32_t GetId() const { return m_id; } /** * Sets the entity ID * @param id */ void SetId(uint32_t id) { m_id = id; } protected: uint32_t m_id; private: bool m_dirty; }; } } pvr.hts-4.4.20-Leia/src/tvheadend/entity/Event.cpp000066400000000000000000000027471355512543200217260ustar00rootroot00000000000000/* * Copyright (C) 2017 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 "Event.h" #include "p8-platform/util/StringUtils.h" #include "kodi/xbmc_epg_types.h" using namespace tvheadend::entity; void Event::SetWriters(const std::vector &writers) { m_writers = StringUtils::Join(writers, EPG_STRING_TOKEN_SEPARATOR); } void Event::SetDirectors(const std::vector &directors) { m_directors = StringUtils::Join(directors, EPG_STRING_TOKEN_SEPARATOR); } void Event::SetCast(const std::vector &cast) { m_cast = StringUtils::Join(cast, EPG_STRING_TOKEN_SEPARATOR); } void Event::SetCategories(const std::vector &categories) { m_categories = StringUtils::Join(categories, EPG_STRING_TOKEN_SEPARATOR); } pvr.hts-4.4.20-Leia/src/tvheadend/entity/Event.h000066400000000000000000000145101355512543200213620ustar00rootroot00000000000000#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 * */ #include "Entity.h" #include #include #include #include namespace tvheadend { namespace entity { class Event; typedef std::pair EventMapEntry; typedef std::map Events; /** * Represents an event/programme */ class Event : public Entity { public: Event() : m_next(0), m_channel(0), m_content(0), m_start(0), m_stop(0), m_stars(0), m_age(0), m_aired(0), m_season(0), m_episode(0), m_part(0), m_recordingId(0), m_year(0) { } bool operator==(const Event &other) const { return m_id == other.m_id && m_next == other.m_next && m_channel == other.m_channel && m_content == other.m_content && m_start == other.m_start && m_stop == other.m_stop && m_stars == other.m_stars && m_age == other.m_age && m_aired == other.m_aired && m_season == other.m_season && m_episode == other.m_episode && m_part == other.m_part && m_title == other.m_title && m_subtitle == other.m_subtitle && m_desc == other.m_desc && m_summary == other.m_summary && m_image == other.m_image && m_recordingId == other.m_recordingId && m_seriesLink == other.m_seriesLink && m_year == other.m_year && m_writers == other.m_writers && m_directors == other.m_directors && m_cast == other.m_cast && m_categories == other.m_categories; } bool operator!=(const Event &other) const { return !(*this == other); } uint32_t GetNext() const { return m_next; } void SetNext(uint32_t next) { m_next = next; } uint32_t GetChannel() const { return m_channel; } void SetChannel(uint32_t channel) { m_channel = channel; } uint32_t GetContent() const { return m_content; } void SetContent(uint32_t content) { m_content = content; } uint32_t GetGenreType() const { return m_content & 0xF0; } uint32_t GetGenreSubType() const { return m_content & 0x0F; } time_t GetStart() const { return m_start; } void SetStart(time_t start) { m_start = start; } time_t GetStop() const { return m_stop; } void SetStop(time_t stop) { m_stop = stop; } uint32_t GetStars() const { return m_stars; } void SetStars(uint32_t stars) { m_stars = stars; } uint32_t GetAge() const { return m_age; } void SetAge(uint32_t age) { m_age = age; } time_t GetAired() const { return m_aired; } void SetAired(time_t aired) { m_aired = aired; } uint32_t GetSeason() const { return m_season; } void SetSeason(uint32_t season) { m_season = season; } uint32_t GetEpisode() const { return m_episode; } void SetEpisode(uint32_t episode) { m_episode = episode; } uint32_t GetPart() const { return m_part; } void SetPart(uint32_t part) { m_part = part; } const std::string& GetTitle() const { return m_title; } void SetTitle(const std::string &title) { m_title = title; } const std::string& GetSubtitle() const { return m_subtitle; } void SetSubtitle(const std::string &subtitle) { m_subtitle = subtitle; } // TODO: Rename to GetDescription to match Recording const std::string& GetDesc() const { return m_desc; } void SetDesc(const std::string &desc) { m_desc = desc; } const std::string& GetSummary() const { return m_summary; } void SetSummary(const std::string &summary) { m_summary = summary; } const std::string& GetImage() const { return m_image; } void SetImage(const std::string &image) { m_image = image; } uint32_t GetRecordingId() const { return m_recordingId; } void SetRecordingId(uint32_t recordingId) { m_recordingId = recordingId; } const std::string& GetSeriesLink() const { return m_seriesLink; } void SetSeriesLink(const std::string &seriesLink) { m_seriesLink = seriesLink; } uint32_t GetYear() const { return m_year; } void SetYear(uint32_t year) { m_year = year; } const std::string& GetWriters() const { return m_writers; } void SetWriters(const std::vector &writers); const std::string& GetDirectors() const { return m_directors; } void SetDirectors(const std::vector &directors); const std::string& GetCast() const { return m_cast; } void SetCast(const std::vector &cast); const std::string& GetCategories() const { return m_categories; } void SetCategories(const std::vector &categories); private: uint32_t m_next; uint32_t m_channel; uint32_t m_content; time_t m_start; time_t m_stop; uint32_t m_stars; /* 1 - 5 */ uint32_t m_age; /* years */ time_t m_aired; uint32_t m_season; uint32_t m_episode; uint32_t m_part; std::string m_title; std::string m_subtitle; /* episode name */ std::string m_desc; std::string m_summary; std::string m_image; uint32_t m_recordingId; std::string m_seriesLink; uint32_t m_year; std::string m_writers; std::string m_directors; std::string m_cast; std::string m_categories; }; } } pvr.hts-4.4.20-Leia/src/tvheadend/entity/Recording.h000066400000000000000000000236011355512543200222160ustar00rootroot00000000000000#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 * */ #include #include #include #include "kodi/xbmc_pvr_types.h" #include "Entity.h" #include "../utilities/LifetimeMapper.h" // Timer types #define TIMER_ONCE_MANUAL (PVR_TIMER_TYPE_NONE + 1) #define TIMER_ONCE_EPG (PVR_TIMER_TYPE_NONE + 2) #define TIMER_ONCE_CREATED_BY_TIMEREC (PVR_TIMER_TYPE_NONE + 3) #define TIMER_ONCE_CREATED_BY_AUTOREC (PVR_TIMER_TYPE_NONE + 4) #define TIMER_REPEATING_MANUAL (PVR_TIMER_TYPE_NONE + 5) #define TIMER_REPEATING_EPG (PVR_TIMER_TYPE_NONE + 6) #define TIMER_REPEATING_SERIESLINK (PVR_TIMER_TYPE_NONE + 7) namespace tvheadend { namespace entity { class Recording; typedef std::pair RecordingMapEntry; typedef std::map Recordings; /** * Represents a recording or a timer * TODO: Create separate classes for recordings and timers since a * recording obviously can't have a "timer type" */ class Recording : public Entity { public: Recording() : m_enabled(0), m_channel(0), m_channelType(0), m_eventId(0), m_start(0), m_stop(0), m_startExtra(0), m_stopExtra(0), m_filesStart(0), m_filesStop(0), m_state(PVR_TIMER_STATE_ERROR), m_lifetime(0), m_priority(50), // Kodi default - "normal" m_playCount(0), m_playPosition(0), m_contentType(0), m_season(0), m_episode(0), m_part(0) { } bool operator==(const Recording &other) const { return m_id == other.m_id && m_enabled == other.m_enabled && m_channel == other.m_channel && m_channelType == other.m_channelType && m_channelName == other.m_channelName && m_eventId == other.m_eventId && m_start == other.m_start && m_stop == other.m_stop && m_startExtra == other.m_startExtra && m_stopExtra == other.m_stopExtra && m_filesStart == other.m_filesStart && m_filesStop == other.m_filesStop && m_title == other.m_title && m_path == other.m_path && m_description == other.m_description && m_image == other.m_image && m_fanartImage == other.m_fanartImage && m_timerecId == other.m_timerecId && m_autorecId == other.m_autorecId && m_state == other.m_state && m_error == other.m_error && m_lifetime == other.m_lifetime && m_priority == other.m_priority && m_playCount == other.m_playCount && m_playPosition == other.m_playPosition && m_contentType == other.m_contentType && m_season == other.m_season && m_episode == other.m_episode && m_part == other.m_part; } bool operator!=(const Recording &other) const { return !(*this == other); } bool IsRecording() const { return m_state == PVR_TIMER_STATE_COMPLETED || m_state == PVR_TIMER_STATE_ABORTED || m_state == PVR_TIMER_STATE_RECORDING || m_state == PVR_TIMER_STATE_CONFLICT_NOK; } bool IsTimer() const { return m_state == PVR_TIMER_STATE_SCHEDULED || m_state == PVR_TIMER_STATE_RECORDING || m_state == PVR_TIMER_STATE_CONFLICT_NOK; } /** * @return the type of timer */ unsigned int GetTimerType() const { if (!m_timerecId.empty()) return TIMER_ONCE_CREATED_BY_TIMEREC; else if (!m_autorecId.empty()) return TIMER_ONCE_CREATED_BY_AUTOREC; else if (m_eventId != 0) return TIMER_ONCE_EPG; else return TIMER_ONCE_MANUAL; } bool IsEnabled() const { return m_enabled > 0; } void SetEnabled(uint32_t enabled) { m_enabled = enabled; } uint32_t GetChannel() const { return m_channel; } void SetChannel(uint32_t channel) { m_channel = channel; } uint32_t GetChannelType() const { return m_channelType; } void SetChannelType(uint32_t channelType) { m_channelType = channelType; } const std::string& GetChannelName() const { return m_channelName; } void SetChannelName(const std::string &channelName) { m_channelName = channelName; } uint32_t GetEventId() const { return m_eventId; } void SetEventId(uint32_t eventId) { m_eventId = eventId; } // TODO: Change to time_t int64_t GetStart() const { return m_start; } void SetStart(int64_t start) { m_start = start; } // TODO: Change to time_t int64_t GetStop() const { return m_stop; } void SetStop(int64_t stop) { m_stop = stop; } // TODO: Change to time_t int64_t GetStartExtra() const { return m_startExtra; } void SetStartExtra(int64_t startExtra) { m_startExtra = startExtra; } // TODO: Change to time_t int64_t GetStopExtra() const { return m_stopExtra; } void SetStopExtra(int64_t stopExtra) { m_stopExtra = stopExtra; } int64_t GetFilesStart() const { return m_filesStart; } void SetFilesStart(int64_t start) { m_filesStart = start; } int64_t GetFilesStop() const { return m_filesStop; } void SetFilesStop(int64_t stop) { m_filesStop = stop; } const std::string& GetTitle() const { return m_title; } void SetTitle(const std::string &title) { m_title = title; } const std::string& GetSubtitle() const { return m_subtitle; } void SetSubtitle(const std::string &subtitle) { m_subtitle = subtitle; } const std::string& GetPath() const { return m_path; } void SetPath(const std::string &path) { m_path = path; } const std::string& GetDescription() const { return m_description; } void SetDescription(const std::string &description) { m_description = description; } const std::string& GetImage() const { return m_image; } void SetImage(const std::string &image) { m_image = image; } const std::string& GetFanartImage() const { return m_fanartImage; } void SetFanartImage(const std::string &image) { m_fanartImage = image; } const std::string& GetTimerecId() const { return m_timerecId; } void SetTimerecId(const std::string &autorecId) { m_timerecId = autorecId; } const std::string& GetAutorecId() const { return m_autorecId; } void SetAutorecId(const std::string &title) { m_autorecId = title; } PVR_TIMER_STATE GetState() const { return m_state; } void SetState(const PVR_TIMER_STATE &state) { m_state = state; } const std::string& GetError() const { return m_error; } void SetError(const std::string &error) { m_error = error; } int GetLifetime() const { return utilities::LifetimeMapper::TvhToKodi(m_lifetime); } void SetLifetime(uint32_t lifetime) { m_lifetime = lifetime; } uint32_t GetPriority() const { return m_priority; } void SetPriority(uint32_t priority) { m_priority = priority; } uint32_t GetPlayCount() const { return m_playCount; } void SetPlayCount(uint32_t playCount) { m_playCount = playCount; } uint32_t GetPlayPosition() const { return m_playPosition; } void SetPlayPosition(uint32_t playPosition) { m_playPosition = playPosition; } void SetContentType(uint32_t content) { m_contentType = content; } uint32_t GetContentType() const { return m_contentType; } // tvh returns only the major DVB category for recordings in the // bottom four bits and no sub-category uint32_t GetGenreType() const { return m_contentType * 0x10; } uint32_t GetGenreSubType() const { return 0; } uint32_t GetSeason() const { return m_season; } void SetSeason(uint32_t season) { m_season = season; } uint32_t GetEpisode() const { return m_episode; } void SetEpisode(uint32_t episode) { m_episode = episode; } uint32_t GetPart() const { return m_part; } void SetPart(uint32_t part) { m_part = part; } private: uint32_t m_enabled; uint32_t m_channel; uint32_t m_channelType; std::string m_channelName; uint32_t m_eventId; int64_t m_start; int64_t m_stop; int64_t m_startExtra; int64_t m_stopExtra; int64_t m_filesStart; int64_t m_filesStop; std::string m_title; std::string m_subtitle; std::string m_path; std::string m_description; std::string m_image; std::string m_fanartImage; std::string m_timerecId; std::string m_autorecId; PVR_TIMER_STATE m_state; std::string m_error; uint32_t m_lifetime; uint32_t m_priority; uint32_t m_playCount; uint32_t m_playPosition; uint32_t m_contentType; uint32_t m_season; uint32_t m_episode; uint32_t m_part; }; } } pvr.hts-4.4.20-Leia/src/tvheadend/entity/RecordingBase.cpp000066400000000000000000000075141355512543200233510ustar00rootroot00000000000000/* * 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 * */ #include #include "RecordingBase.h" #include "../utilities/LifetimeMapper.h" using namespace tvheadend::entity; RecordingBase::RecordingBase(const std::string &id /*= ""*/) : m_sid(id), m_enabled(0), m_daysOfWeek(0), m_lifetime(0), m_priority(0), m_channel(0) { m_id = GetNextIntId(); } bool RecordingBase::operator==(const RecordingBase &right) { return m_id == right.m_id && m_enabled == right.m_enabled && m_daysOfWeek == right.m_daysOfWeek && m_lifetime == right.m_lifetime && m_priority == right.m_priority && m_title == right.m_title && m_name == right.m_name && m_directory == right.m_directory && m_owner == right.m_owner && m_creator == right.m_creator && m_channel == right.m_channel; } bool RecordingBase::operator!=(const RecordingBase &right) { return !(*this == right); } std::string RecordingBase::GetStringId() const { return m_sid; } void RecordingBase::SetStringId(const std::string &id) { m_sid = id; } bool RecordingBase::IsEnabled() const { return m_enabled != 0; } void RecordingBase::SetEnabled(uint32_t enabled) { m_enabled = enabled; } int RecordingBase::GetDaysOfWeek() const { return m_daysOfWeek; } void RecordingBase::SetDaysOfWeek(uint32_t daysOfWeek) { m_daysOfWeek = daysOfWeek; } int RecordingBase::GetLifetime() const { return utilities::LifetimeMapper::TvhToKodi(m_lifetime); } void RecordingBase::SetLifetime(uint32_t lifetime) { m_lifetime = lifetime; } uint32_t RecordingBase::GetPriority() const { return m_priority; } void RecordingBase::SetPriority(uint32_t priority) { m_priority = priority; } const std::string& RecordingBase::GetTitle() const { return m_title; } void RecordingBase::SetTitle(const std::string &title) { m_title = title; } const std::string& RecordingBase::GetName() const { return m_name; } void RecordingBase::SetName(const std::string &name) { m_name = name; } const std::string& RecordingBase::GetDirectory() const { return m_directory; } void RecordingBase::SetDirectory(const std::string &directory) { m_directory = directory; } void RecordingBase::SetOwner(const std::string &owner) { m_owner = owner; } void RecordingBase::SetCreator(const std::string &creator) { m_creator = creator; } uint32_t RecordingBase::GetChannel() const { return m_channel; } void RecordingBase::SetChannel(uint32_t channel) { m_channel = channel; } // static time_t RecordingBase::LocaltimeToUTC(int32_t lctime) { /* Note: lctime contains minutes from midnight (up to 24*60) as local time. */ /* complete lctime with current year, month, day, ... */ time_t t = time(NULL); struct tm *tm_time = localtime(&t); tm_time->tm_hour = lctime / 60; tm_time->tm_min = lctime % 60; tm_time->tm_sec = 0; return mktime(tm_time); } // static unsigned int RecordingBase::GetNextIntId() { static unsigned int intId = 0; return ++intId; } pvr.hts-4.4.20-Leia/src/tvheadend/entity/RecordingBase.h000066400000000000000000000055741355512543200230220ustar00rootroot00000000000000#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 * */ #include "Entity.h" #include #include #include namespace tvheadend { namespace entity { class RecordingBase : public Entity { protected: RecordingBase(const std::string &id = ""); bool operator==(const RecordingBase &right); bool operator!=(const RecordingBase &right); public: std::string GetStringId() const; void SetStringId(const std::string &id); bool IsEnabled() const; void SetEnabled(uint32_t enabled); int GetDaysOfWeek() const; void SetDaysOfWeek(uint32_t daysOfWeek); int GetLifetime() const; void SetLifetime(uint32_t retention); uint32_t GetPriority() const; void SetPriority(uint32_t priority); const std::string &GetTitle() const; void SetTitle(const std::string &title); const std::string &GetName() const; void SetName(const std::string &name); const std::string &GetDirectory() const; void SetDirectory(const std::string &directory); void SetOwner(const std::string &owner); void SetCreator(const std::string &creator); uint32_t GetChannel() const; void SetChannel(uint32_t channel); protected: static time_t LocaltimeToUTC(int32_t lctime); private: static unsigned int GetNextIntId(); std::string m_sid; // ID (string!) of dvr[Time|Auto]recEntry. uint32_t m_enabled; // If [time|auto]rec entry is enabled (activated). uint32_t m_daysOfWeek; // Bitmask - Days of week (0x01 = Monday, 0x40 = Sunday, 0x7f = Whole Week, 0 = Not set). uint32_t m_lifetime; // Lifetime (in days). uint32_t m_priority; // Priority (0 = Important, 1 = High, 2 = Normal, 3 = Low, 4 = Unimportant). std::string m_title; // Title (pattern) for the recording files. std::string m_name; // Name. std::string m_directory; // Directory for the recording files. std::string m_owner; // Owner. std::string m_creator; // Creator. uint32_t m_channel; // Channel ID. }; } } pvr.hts-4.4.20-Leia/src/tvheadend/entity/Schedule.cpp000066400000000000000000000022651355512543200223740ustar00rootroot00000000000000/* * 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 * */ #include "Schedule.h" using namespace tvheadend::entity; void Schedule::SetDirty(bool dirty) { Entity::SetDirty(dirty); if (dirty) { // Mark all events as dirty too for (auto &entry : m_events) entry.second.SetDirty(dirty); } } EventUids& Schedule::GetEvents() { return m_events; } const EventUids& Schedule::GetEvents() const { return m_events; } pvr.hts-4.4.20-Leia/src/tvheadend/entity/Schedule.h000066400000000000000000000033111355512543200220320ustar00rootroot00000000000000#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 * */ #include #include #include "Entity.h" namespace tvheadend { namespace entity { class Schedule; typedef std::pair ScheduleMapEntry; typedef std::map Schedules; typedef std::pair EventUidsMapEntry; typedef std::map EventUids; /** * Represents a schedule. A schedule has a channel and a bunch of events. * The schedule ID matches the channel it belongs to. */ class Schedule : public Entity { public: virtual void SetDirty(bool dirty); /** * @return read-write reference to the events in this schedule */ EventUids& GetEvents(); /** * @return read-only reference to the events in this schedule */ const EventUids& GetEvents() const; private: EventUids m_events; // event uids }; } } pvr.hts-4.4.20-Leia/src/tvheadend/entity/Tag.cpp000066400000000000000000000037671355512543200213630ustar00rootroot00000000000000/* * Copyright (C) 2005-2015 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 "Tag.h" using namespace tvheadend; using namespace tvheadend::entity; Tag::Tag() : m_index(0) { } bool Tag::operator==(const Tag &right) { return m_id == right.m_id && m_index == right.m_index && m_name == right.m_name && m_icon == right.m_icon && m_channels == right.m_channels; } bool Tag::operator!=(const Tag &right) { return !(*this == right); } uint32_t Tag::GetIndex() const { return m_index; } void Tag::SetIndex(uint32_t index) { m_index = index; } const std::string& Tag::GetName() const { return m_name; } void Tag::SetName(const std::string& name) { m_name = name; } void Tag::SetIcon(const std::string& icon) { m_icon = icon; } const std::vector& Tag::GetChannels() const { return m_channels; } std::vector& Tag::GetChannels() { return m_channels; } bool Tag::ContainsChannelType(channel_type_t eType, const Channels& channels) const { std::vector::const_iterator it; Channels::const_iterator cit; for (it = m_channels.begin(); it != m_channels.end(); ++it) { if ((cit = channels.find(*it)) != channels.end()) { if (cit->second.GetType() == eType) return true; } } return false; } pvr.hts-4.4.20-Leia/src/tvheadend/entity/Tag.h000066400000000000000000000035451355512543200210220ustar00rootroot00000000000000#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 * */ #include #include #include #include #include "Entity.h" #include "../HTSPTypes.h" #include "Channel.h" namespace tvheadend { namespace entity { class Tag; typedef std::pair TagMapEntry; typedef std::map Tags; /** * Represents a channel tag */ class Tag : public Entity { public: Tag(); bool operator==(const Tag &right); bool operator!=(const Tag &right); uint32_t GetIndex() const; void SetIndex(uint32_t index); const std::string& GetName() const; void SetName(const std::string& name); void SetIcon(const std::string& icon); const std::vector& GetChannels() const; std::vector& GetChannels(); bool ContainsChannelType(channel_type_t eType, const Channels& channels) const; private: uint32_t m_index; std::string m_name; std::string m_icon; std::vector m_channels; }; } } pvr.hts-4.4.20-Leia/src/tvheadend/entity/TimeRecording.cpp000066400000000000000000000032421355512543200233670ustar00rootroot00000000000000/* * 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 * */ #include "TimeRecording.h" using namespace tvheadend::entity; TimeRecording::TimeRecording(const std::string &id /*= ""*/) : RecordingBase(id), m_start(0), m_stop(0) { } bool TimeRecording::operator==(const TimeRecording &right) { return RecordingBase::operator==(right) && m_start == right.m_start && m_stop == right.m_stop; } bool TimeRecording::operator!=(const TimeRecording &right) { return !(*this == right); } time_t TimeRecording::GetStart() const { if (m_start == int32_t(-1)) // "any time" return 0; return LocaltimeToUTC(m_start); } void TimeRecording::SetStart(int32_t start) { m_start = start; } time_t TimeRecording::GetStop() const { if (m_stop == int32_t(-1)) // "any time" return 0; return LocaltimeToUTC(m_stop); } void TimeRecording::SetStop(int32_t stop) { m_stop = stop; }pvr.hts-4.4.20-Leia/src/tvheadend/entity/TimeRecording.h000066400000000000000000000031001355512543200230250ustar00rootroot00000000000000#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 * */ #include "RecordingBase.h" #include namespace tvheadend { namespace entity { class TimeRecording : public RecordingBase { public: TimeRecording(const std::string &id = ""); bool operator==(const TimeRecording &right); bool operator!=(const TimeRecording &right); time_t GetStart() const; void SetStart(int32_t start); time_t GetStop() const; void SetStop(int32_t stop); private: int32_t m_start; // Start time in minutes from midnight (up to 24*60). int32_t m_stop; // Stop time in minutes from midnight (up to 24*60). }; typedef std::map TimeRecordingsMap; typedef std::pair TimeRecordingMapEntry; } } pvr.hts-4.4.20-Leia/src/tvheadend/status/000077500000000000000000000000001355512543200201365ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/src/tvheadend/status/DescrambleInfo.cpp000066400000000000000000000054321355512543200235230ustar00rootroot00000000000000/* * Copyright (C) 2005-2016 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 "DescrambleInfo.h" #include "kodi/xbmc_pvr_types.h" using namespace tvheadend::status; DescrambleInfo::DescrambleInfo() : m_pid(PVR_DESCRAMBLE_INFO_NOT_AVAILABLE), m_caid(PVR_DESCRAMBLE_INFO_NOT_AVAILABLE), m_provid(PVR_DESCRAMBLE_INFO_NOT_AVAILABLE), m_ecmTime(PVR_DESCRAMBLE_INFO_NOT_AVAILABLE), m_hops(PVR_DESCRAMBLE_INFO_NOT_AVAILABLE) { } void DescrambleInfo::Clear() { m_pid = PVR_DESCRAMBLE_INFO_NOT_AVAILABLE; m_caid = PVR_DESCRAMBLE_INFO_NOT_AVAILABLE; m_provid = PVR_DESCRAMBLE_INFO_NOT_AVAILABLE; m_ecmTime = PVR_DESCRAMBLE_INFO_NOT_AVAILABLE; m_hops = PVR_DESCRAMBLE_INFO_NOT_AVAILABLE; m_cardSystem.clear(); m_reader.clear(); m_from.clear(); m_protocol.clear(); } int64_t DescrambleInfo::GetPid() const { return m_pid; } void DescrambleInfo::SetPid(uint32_t pid) { m_pid = pid; } int64_t DescrambleInfo::GetCaid() const { return m_caid; } void DescrambleInfo::SetCaid(uint32_t caid) { m_caid = caid; } int64_t DescrambleInfo::GetProvid() const { return m_provid; } void DescrambleInfo::SetProvid(uint32_t provid) { m_provid = provid; } int64_t DescrambleInfo::GetEcmTime() const { return m_ecmTime; } void DescrambleInfo::SetEcmTime(uint32_t ecmTime) { m_ecmTime = ecmTime; } int64_t DescrambleInfo::GetHops() const { return m_hops; } void DescrambleInfo::SetHops(uint32_t hops) { m_hops = hops; } std::string DescrambleInfo::GetCardSystem() const { return m_cardSystem; } void DescrambleInfo::SetCardSystem(const std::string &cardSystem) { m_cardSystem = cardSystem; } std::string DescrambleInfo::GetReader() const { return m_reader; } void DescrambleInfo::SetReader(const std::string &reader) { m_reader = reader; } std::string DescrambleInfo::GetFrom() const { return m_from; } void DescrambleInfo::SetFrom(const std::string &from) { m_from = from; } std::string DescrambleInfo::GetProtocol() const { return m_protocol; } void DescrambleInfo::SetProtocol(const std::string &protocol) { m_protocol = protocol; } pvr.hts-4.4.20-Leia/src/tvheadend/status/DescrambleInfo.h000066400000000000000000000037741355512543200231770ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2016 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 #include namespace tvheadend { namespace status { /** * Contains information about the descrambler used */ class DescrambleInfo { public: DescrambleInfo(); void Clear(); int64_t GetPid() const; void SetPid(uint32_t pid); int64_t GetCaid() const; void SetCaid(uint32_t caid); int64_t GetProvid() const; void SetProvid(uint32_t provid); int64_t GetEcmTime() const; void SetEcmTime(uint32_t ecmTime); int64_t GetHops() const; void SetHops(uint32_t hops); std::string GetCardSystem() const; void SetCardSystem(const std::string &cardSystem); std::string GetReader() const; void SetReader(const std::string &reader); std::string GetFrom() const; void SetFrom(const std::string &from); std::string GetProtocol() const; void SetProtocol(const std::string &protocol); private: int64_t m_pid; int64_t m_caid; int64_t m_provid; int64_t m_ecmTime; int64_t m_hops; std::string m_cardSystem; std::string m_reader; std::string m_from; std::string m_protocol; }; } } pvr.hts-4.4.20-Leia/src/tvheadend/status/Quality.h000066400000000000000000000033041355512543200217370ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 namespace tvheadend { namespace status { /** * Represents the current signal quality */ struct Quality { /** * Frontend status */ std::string fe_status; /** * Signal to noise ratio */ uint32_t fe_snr; /** * Signal status percentage */ uint32_t fe_signal; /** * Bit error rate */ uint32_t fe_ber; /** * Uncorrected blocks */ uint32_t fe_unc; /** * Constructor */ Quality() : fe_snr(0), fe_signal(0), fe_ber(0), fe_unc(0) { } /** * Clears the current status */ void Clear() { fe_status.clear(); fe_snr = 0; fe_signal = 0; fe_ber = 0; fe_unc = 0; } }; } } pvr.hts-4.4.20-Leia/src/tvheadend/status/QueueStatus.h000066400000000000000000000032201355512543200225740ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 * */ namespace tvheadend { namespace status { /** * Represents the current demuxer packet queue */ struct QueueStatus { /** * Number of data packets in queue */ uint32_t packets; /** * Number of bytes in queue. */ uint32_t bytes; /** * Estimated delay of queue (in µs) */ uint32_t delay; /** * Number of B-frames dropped */ uint32_t bdrops; /** * Number of P-frames dropped */ uint32_t pdrops; /** * Number of I-frames dropped */ uint32_t idrops; /** * Constructor */ QueueStatus() : packets(0), bytes(0), delay(0), bdrops(0), pdrops(0), idrops(0) { } }; } } pvr.hts-4.4.20-Leia/src/tvheadend/status/SourceInfo.h000066400000000000000000000031231355512543200223620ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 namespace tvheadend { namespace status { /** * Represents information about the current service */ struct SourceInfo { /** * The current adapter used */ std::string si_adapter; /** * The network */ std::string si_network; /** * The mux */ std::string si_mux; /** * The service provider */ std::string si_provider; /** * The service name */ std::string si_service; /** * Clears the current status */ void Clear() { si_adapter.clear(); si_network.clear(); si_mux.clear(); si_provider.clear(); si_service.clear(); } }; } } pvr.hts-4.4.20-Leia/src/tvheadend/status/TimeshiftStatus.h000066400000000000000000000030741355512543200234530ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 * */ namespace tvheadend { namespace status { /** * Represents the current timeshift status */ struct TimeshiftStatus { /** * Whether the buffer is full or not */ bool full; /** * Current position relative to live */ int64_t shift; /** * PTS of the first frame in the buffer */ int64_t start; /** * PTS of the last frame in the buffer */ int64_t end; /** * Constructor */ TimeshiftStatus() { Clear(); } /** * Clears the current status */ void Clear() { full = false; shift = 0; start = 0;; end = 0; } }; } } pvr.hts-4.4.20-Leia/src/tvheadend/utilities/000077500000000000000000000000001355512543200206265ustar00rootroot00000000000000pvr.hts-4.4.20-Leia/src/tvheadend/utilities/AsyncState.cpp000066400000000000000000000031471355512543200234150ustar00rootroot00000000000000/* * Copyright (C) 2005-2014 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 "AsyncState.h" using namespace tvheadend::utilities; using namespace P8PLATFORM; struct Param { eAsyncState state; AsyncState *self; }; AsyncState::AsyncState(int timeout) { m_state = ASYNC_NONE; m_timeout = timeout; } eAsyncState AsyncState::GetState() { P8PLATFORM::CLockObject lock(m_mutex); return m_state; } void AsyncState::SetState(eAsyncState state) { CLockObject lock(m_mutex); m_state = state; m_condition.Broadcast(); } bool AsyncState::PredicateCallback ( void *p ) { Param *param = (Param*)p; return param->self->m_state >= param->state; } bool AsyncState::WaitForState(eAsyncState state) { Param p; p.state = state; p.self = this; CLockObject lock(m_mutex); return m_condition.Wait(m_mutex, AsyncState::PredicateCallback, (void*)&p, m_timeout); } pvr.hts-4.4.20-Leia/src/tvheadend/utilities/AsyncState.h000066400000000000000000000037761355512543200230720ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2014 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 "p8-platform/threads/mutex.h" namespace tvheadend { namespace utilities { /** * Represents the possible states */ enum eAsyncState { ASYNC_NONE = 0, ASYNC_CHN = 1, ASYNC_DVR = 2, ASYNC_EPG = 3, ASYNC_DONE = 4 }; /** * State tracker for the initial sync process. This class is thread-safe. */ class AsyncState { public: AsyncState(int timeout); virtual ~AsyncState() { }; /** * @return the current state */ eAsyncState GetState(); /** * Changes the current state to "state" * @param state the new state */ void SetState(eAsyncState state); /** * Waits for the current state to change into "state" or higher * before the timeout is reached * @param state the minimum state desired * @return whether the state changed or not */ bool WaitForState(eAsyncState state); private: static bool PredicateCallback ( void *param ); eAsyncState m_state; P8PLATFORM::CMutex m_mutex; P8PLATFORM::CCondition m_condition; int m_timeout; }; } } pvr.hts-4.4.20-Leia/src/tvheadend/utilities/LifetimeMapper.h000066400000000000000000000031621355512543200237040ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2017 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 "../HTSPTypes.h" namespace tvheadend { namespace utilities { /** * Maps "lifetime" values from Kodi to Tvheadend and vica versa */ class LifetimeMapper { public: static int TvhToKodi(uint32_t tvhLifetime) { // pvr addon api: addon defined special values must be less than zero if (tvhLifetime == DVR_RET_SPACE) return -2; else if (tvhLifetime == DVR_RET_FOREVER) return -1; else return tvhLifetime; // lifetime in days } static uint32_t KodiToTvh(int kodiLifetime) { if (kodiLifetime == -2) return DVR_RET_SPACE; else if (kodiLifetime == -1) return DVR_RET_FOREVER; else return kodiLifetime; // lifetime in days } }; } } pvr.hts-4.4.20-Leia/src/tvheadend/utilities/LocalizedString.h000066400000000000000000000030641355512543200240770ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2017 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 #include "../../client.h" namespace tvheadend { namespace utilities { /** * Encapsulates an localized string. */ class LocalizedString { public: explicit LocalizedString(int stringId) : m_localizedString(XBMC->GetLocalizedString(stringId)) { } ~LocalizedString() { XBMC->FreeString(m_localizedString); } std::string Get() const { return m_localizedString ? std::string(m_localizedString) : std::string(); } private: LocalizedString() = delete; LocalizedString(const LocalizedString&) = delete; LocalizedString &operator =(const LocalizedString&) = delete; char* m_localizedString; }; } } pvr.hts-4.4.20-Leia/src/tvheadend/utilities/Logger.cpp000066400000000000000000000034211355512543200225510ustar00rootroot00000000000000/* * Copyright (C) 2005-2015 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 "Logger.h" #include "p8-platform/util/StringUtils.h" using namespace tvheadend::utilities; Logger::Logger() { // Use an empty implementation by default SetImplementation([](LogLevel level, const char *message) { }); } Logger &Logger::GetInstance() { static Logger instance; return instance; } void Logger::Log(LogLevel level, const char *message, ...) { auto &logger = GetInstance(); std::string logMessage; // Prepend the prefix when set const std::string prefix = logger.m_prefix; if (!prefix.empty()) logMessage = prefix + " - "; logMessage += message; va_list arguments; va_start(arguments, message); logMessage = StringUtils::FormatV(logMessage.c_str(), arguments); va_end(arguments); logger.m_implementation(level, logMessage.c_str()); } void Logger::SetImplementation(LoggerImplementation implementation) { m_implementation = implementation; } void Logger::SetPrefix(const std::string &prefix) { m_prefix = prefix; } pvr.hts-4.4.20-Leia/src/tvheadend/utilities/Logger.h000066400000000000000000000046501355512543200222230ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2015 Team Kodi * http://kodi.tv * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with 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 #include namespace tvheadend { namespace utilities { /** * Represents the log level */ enum LogLevel { LEVEL_ERROR, LEVEL_INFO, LEVEL_DEBUG, LEVEL_TRACE }; /** * Short-hand for a function that acts as the logger implementation */ typedef std::function LoggerImplementation; /** * The logger class. It is a singleton that by default comes with no * underlying implementation. It is up to the user to supply a suitable * implementation as a lambda using SetImplementation(). */ class Logger { public: /** * Returns the singleton instance * @return */ static Logger &GetInstance(); /** * Logs the specified message using the specified log level * @param level the log level * @param message the log message * @param ... parameters for the log message */ static void Log(LogLevel level, const char *message, ...); /** * Configures the logger to use the specified implementation * @param implementation lambda */ void SetImplementation(LoggerImplementation implementation); /** * Sets the prefix to use in log messages * @param prefix */ void SetPrefix(const std::string &prefix); private: Logger(); /** * The logger implementation */ LoggerImplementation m_implementation; /** * The log message prefix */ std::string m_prefix; }; } } pvr.hts-4.4.20-Leia/src/tvheadend/utilities/Utilities.h000066400000000000000000000024721355512543200227570ustar00rootroot00000000000000#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 * */ namespace tvheadend { namespace utilities { /** * std::remove_if() for maps. Borrowed from: * http://stackoverflow.com/questions/800955/remove-if-equivalent-for-stdmap */ template< typename ContainerT, typename PredicateT > void erase_if(ContainerT& items, const PredicateT& predicate) { for (auto it = items.begin(); it != items.end();) { if (predicate(*it)) it = items.erase(it); else ++it; } }; } } pvr.hts-4.4.20-Leia/src/tvheadend/xbmc_codec_descriptor.hpp000066400000000000000000000037311355512543200236540ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2013 Team XBMC * http://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, see * . * */ #include "kodi/libXBMC_pvr.h" /** * Adapter which converts codec names used by tvheadend and VDR into their * FFmpeg equivalents. */ class CodecDescriptor { public: CodecDescriptor(void) { m_codec.codec_id = XBMC_INVALID_CODEC_ID; m_codec.codec_type = XBMC_CODEC_TYPE_UNKNOWN; } CodecDescriptor(xbmc_codec_t codec, const char* name) : m_codec(codec), m_strName(name) {} virtual ~CodecDescriptor(void) {} xbmc_codec_t Codec(void) const { return m_codec; } static CodecDescriptor GetCodecByName(const char* strCodecName) { CodecDescriptor retVal; // some of Tvheadend's and VDR's codec names don't match ffmpeg's, so translate them to something ffmpeg understands if (!strcmp(strCodecName, "MPEG2AUDIO")) retVal = CodecDescriptor(PVR->GetCodecByName("MP2"), strCodecName); else if (!strcmp(strCodecName, "MPEGTS")) retVal = CodecDescriptor(PVR->GetCodecByName("MPEG2VIDEO"), strCodecName); else if (!strcmp(strCodecName, "TEXTSUB")) retVal = CodecDescriptor(PVR->GetCodecByName("TEXT"), strCodecName); else retVal = CodecDescriptor(PVR->GetCodecByName(strCodecName), strCodecName); return retVal; } private: xbmc_codec_t m_codec; std::string m_strName; };