pax_global_header00006660000000000000000000000064126002002640014502gustar00rootroot0000000000000052 comment=016b0b3251d6d5bffaf68baf59010e4347759c4a kodi-pvr-hts-2.1.18/000077500000000000000000000000001260020026400141225ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/CMakeLists.txt000066400000000000000000000027751260020026400166750ustar00rootroot00000000000000project(pvr.hts) cmake_minimum_required(VERSION 2.6) enable_language(CXX) find_package(kodi REQUIRED) find_package(kodiplatform REQUIRED) find_package(platform REQUIRED) include_directories(${kodiplatform_INCLUDE_DIRS} ${platform_INCLUDE_DIRS} ${KODI_INCLUDE_DIR} ${PROJECT_SOURCE_DIR}/lib) add_definitions(-DUSE_DEMUX) # Sources and headers set(HTS_SOURCES src/AsyncState.cpp src/AsyncState.h src/client.h src/client.cpp src/HTSPConnection.cpp src/HTSPDemuxer.cpp src/HTSPTypes.h src/HTSPTypes.cpp src/HTSPVFS.cpp src/Settings.h src/Tvheadend.cpp src/Tvheadend.h src/xbmc_codec_descriptor.hpp) source_group("Source Files" FILES ${HTS_SOURCES}) # 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_RESOURCES}) add_subdirectory(lib/libhts) set(DEPLIBS ${platform_LIBRARIES} hts) if(WIN32) list(APPEND DEPLIBS ws2_32) endif() build_addon(pvr.hts HTS DEPLIBS) include(CPack) kodi-pvr-hts-2.1.18/README.md000066400000000000000000000004051260020026400154000ustar00rootroot00000000000000# Tvheadend HTSP PVR Tvheadend HTSP PVR client addon for [Kodi] (http://kodi.tv) ##### 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) kodi-pvr-hts-2.1.18/debian/000077500000000000000000000000001260020026400153445ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/debian/changelog000066400000000000000000000002401260020026400172120ustar00rootroot00000000000000kodi-pvr-hts (2.1.17-1~trusty) trusty; urgency=low [ kodi ] * autogenerated dummy changelog -- Nobody Sat, 01 Jun 2013 00:59:22 +0200 kodi-pvr-hts-2.1.18/debian/changelog.in000066400000000000000000000002611260020026400176220ustar00rootroot00000000000000kodi-pvr-hts (#PACKAGEVERSION#-#TAGREV#~#DIST#) #DIST#; urgency=low [ kodi ] * autogenerated dummy changelog -- Nobody Sat, 01 Jun 2013 00:59:22 +0200 kodi-pvr-hts-2.1.18/debian/compat000066400000000000000000000000021260020026400165420ustar00rootroot000000000000009 kodi-pvr-hts-2.1.18/debian/control000066400000000000000000000017421260020026400167530ustar00rootroot00000000000000Source: kodi-pvr-hts Priority: extra Maintainer: Arne Morten Kvarving Build-Depends: debhelper (>= 9.0.0), cmake, kodi-pvr-dev, 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.1.17) Provides: kodi-pvr-hts, kodi-pvr-tvheadend-hts Breaks: kodi-pvr-tvheadend-hts (<< 2.1.17) 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. kodi-pvr-hts-2.1.18/debian/copyright000066400000000000000000000027451260020026400173070ustar00rootroot00000000000000Format: 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. kodi-pvr-hts-2.1.18/debian/kodi-pvr-hts.install000066400000000000000000000001371260020026400212640ustar00rootroot00000000000000usr/lib/*/addons/pvr.hts/pvr.hts.so* usr/lib/kodi/addons/pvr.hts usr/share/kodi/addons/pvr.hts kodi-pvr-hts-2.1.18/debian/rules000077500000000000000000000012541260020026400164260ustar00rootroot00000000000000#!/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 kodi-pvr-hts-2.1.18/debian/source/000077500000000000000000000000001260020026400166445ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/debian/source/format000066400000000000000000000000151260020026400200530ustar00rootroot000000000000003.0 (native) kodi-pvr-hts-2.1.18/lib/000077500000000000000000000000001260020026400146705ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/lib/libhts/000077500000000000000000000000001260020026400161555ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/lib/libhts/CMakeLists.txt000066400000000000000000000007211260020026400207150ustar00rootroot00000000000000PROJECT(hts) ENABLE_LANGUAGE(C) CMAKE_MINIMUM_REQUIRED(VERSION 2.6) 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}) kodi-pvr-hts-2.1.18/lib/libhts/OSXGNUReplacements.h000066400000000000000000000047131260020026400217210ustar00rootroot00000000000000#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 kodi-pvr-hts-2.1.18/lib/libhts/Win32/000077500000000000000000000000001260020026400170575ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/lib/libhts/Win32/include/000077500000000000000000000000001260020026400205025ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/lib/libhts/Win32/include/getopt.h000066400000000000000000000054641260020026400221660ustar00rootroot00000000000000/* * 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__ */ kodi-pvr-hts-2.1.18/lib/libhts/Win32/include/inttypes.h000066400000000000000000000175171260020026400225450ustar00rootroot00000000000000// 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_ ] kodi-pvr-hts-2.1.18/lib/libhts/Win32/include/msvc.h000066400000000000000000000011231260020026400216200ustar00rootroot00000000000000#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 kodi-pvr-hts-2.1.18/lib/libhts/Win32/include/sys/000077500000000000000000000000001260020026400213205ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/lib/libhts/Win32/include/sys/queue.h000066400000000000000000000461221260020026400226220ustar00rootroot00000000000000/* * 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 */kodi-pvr-hts-2.1.18/lib/libhts/Win32/include/unistd.h000066400000000000000000000013311260020026400221570ustar00rootroot00000000000000/* * 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 */ kodi-pvr-hts-2.1.18/lib/libhts/Win32/libhts_2010.vcxproj000066400000000000000000000113601260020026400224240ustar00rootroot00000000000000 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 kodi-pvr-hts-2.1.18/lib/libhts/Win32/libhts_2010.vcxproj.filters000066400000000000000000000034271260020026400241000ustar00rootroot00000000000000 {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 kodi-pvr-hts-2.1.18/lib/libhts/hts_strtab.h000066400000000000000000000031221260020026400205010ustar00rootroot00000000000000/* * 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_ */ kodi-pvr-hts-2.1.18/lib/libhts/htsbuf.c000066400000000000000000000110301260020026400176070ustar00rootroot00000000000000/* * 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); } kodi-pvr-hts-2.1.18/lib/libhts/htsbuf.h000066400000000000000000000041051260020026400176210ustar00rootroot00000000000000/* * 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__ */ kodi-pvr-hts-2.1.18/lib/libhts/htsmsg.c000066400000000000000000000246061260020026400176360ustar00rootroot00000000000000/* * 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); 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; } kodi-pvr-hts-2.1.18/lib/libhts/htsmsg.h000066400000000000000000000166501260020026400176430ustar00rootroot00000000000000/* * 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_ */ kodi-pvr-hts-2.1.18/lib/libhts/htsmsg_binary.c000066400000000000000000000121201260020026400211660ustar00rootroot00000000000000/* * 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; } kodi-pvr-hts-2.1.18/lib/libhts/htsmsg_binary.h000066400000000000000000000022151260020026400211770ustar00rootroot00000000000000/* * 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_ */ kodi-pvr-hts-2.1.18/lib/libhts/htsq.h000066400000000000000000000077601260020026400173170ustar00rootroot00000000000000/* * 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 */ kodi-pvr-hts-2.1.18/lib/libhts/htsstr.c000066400000000000000000000075511260020026400176600ustar00rootroot00000000000000/* * 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; } kodi-pvr-hts-2.1.18/lib/libhts/htsstr.h000066400000000000000000000020651260020026400176600ustar00rootroot00000000000000/* * 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__ */ kodi-pvr-hts-2.1.18/lib/libhts/net.h000066400000000000000000000027651260020026400171260ustar00rootroot00000000000000/* * 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__ */ kodi-pvr-hts-2.1.18/lib/libhts/net_posix.c000066400000000000000000000151651260020026400203410ustar00rootroot00000000000000/* * 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); } kodi-pvr-hts-2.1.18/lib/libhts/net_winsock.c000066400000000000000000000172311260020026400206500ustar00rootroot00000000000000/* * 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); } kodi-pvr-hts-2.1.18/lib/libhts/sha1.c000066400000000000000000000146161260020026400171650ustar00rootroot00000000000000/* * 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 kodi-pvr-hts-2.1.18/lib/libhts/sha1.h000066400000000000000000000023321260020026400171620ustar00rootroot00000000000000/* * 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 */ kodi-pvr-hts-2.1.18/pvr.hts/000077500000000000000000000000001260020026400155265ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/addon.xml000066400000000000000000000626541260020026400173520ustar00rootroot00000000000000 Kodi se voorprogram vir Tvheadend Kodi's frontend for Tvheadend Kodi клиент за Tvheadend Frontal del Kodi pel Tvheadend Rozhraní Kodi pro Tvheadend Blaen Kodi ar gyfer Tvheadend Kodi's frontend 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 Kodi esi Tvheadend'ile Kodi:n Tvheadend-tuki Frontal Kodi pour Tvheadend Interface logicielle pour Tvheadend Interface do Kodi para Tvheadend לקוח טלוויזיה חיה עבור Tvheadend Kodi sučelje za Tvheadend Kodi TVHeadend előtér-kiszolgáló Frontend Kodi untuk Tvheadend Kodi framendi fyrir Tvheadend Frontend di Kodi per Tvheadend TVheadend 用 Kodi フロントエンド Tvheadend 을 위한 Kodi 프론트엔드 Kodi sąsaja skirta Tvheadend Kodi galasistēma Tvheadend Kodi's frontend for Tvheadend Tvheadend зориулагдсан Kodi-ийн нүүр Bahagian hadapan Kodi untuk Kodi sitt frontend for Tvheadend Kodi's frontend voor Tvheadend Klient TV dla Tvheadend Frontend Kodi para Tvheadend Frontend Kodi para Tvheadend Frontend Kodi pentru Tvheadend Интерфейс Kodi для Tvheadend Kodi rozhranie pre Tvheadend Kodijev vmesnik za Tvheadend Frontend i Kodi'së për 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 клиент. Поддържа поточна телевизия и записване, електронен програмен справочник и броячи. Interfície per al Tvheadend; compatible amb la transmissió de TV en viu i enregistraments, EPG, temporitzadors Rozhraní Tvheadend. Podporuje proudové vysílání živého vysílání a nahrávek, poslech kanálů rádia, EPG, a časovače. Blaen Tvheadend: cefnogi ffrydio Teledu Byw a Recordio, Amserlenni, Amseryddion Tvheadend frontend; understøtter streaming af direkte TV og optagelser, EPG og timere PVR-Client für Tvheadend. Unterstützt TV & Aufnahmen, TV-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 Tvheadend esi. Toetab telekanalite striimimist ja salvestamist ning elektroonilist saatekava. Tvheadend; tukee reaaliaikaisen television ja nauhoituksien streamausta, EPGtä ja nauhoituksien ajastusta. Frontal pour Tvheadend, prenant en charge la lecture en transit des télés en direct & les enregistrements, le GÉP et minuteries. Interface logicielle pour Tvheadend supportant la lecture en continu du direct télévision et des enregistrements, les guides de programme TV, les minuteries 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ér-kiszolgáló. Élő adások és felvételek sugárzásának 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 sjónvarpi 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 sąsaja remia transliacijos Live TV & Įrašus, EPG, Laikmačiai 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 penstirman Langsung & Rakaman, EPG, Pemasa TV Tvheadend frontend; støtte for visning av direkte TV og opptakk, EPG, tidstakere Tvheadend frontend; ondersteuning van streaming, Live TV & opnames, EPG, Timers Klient Tvheadend obsługuje strumieniowanie kanałów radiowych i telewizyjnych, nagrywanie i harmonogram nagrań oraz funkcje przewodnika telewizyjnego. Tvheadend; suporta streaming de TV Ao Vivo e Gravada, EPG, Agendamentos Frontend Tvheadend; suporta transmissão de TV em directo e gravações, EPG, temporizadores Frontend Tvheadend; se poate difuza î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 frontend; stödjer strömning av direktsänd 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前端,支援的串流媒體包含有直播電視和錄製節目,電子節目表,定時器 等 Hierdie is onstabiele sagteware! Die outeurs is op geen manier verantwoordelik vir gefaalde opnames, inkorrekte tydhouers, vermorsde ure, of enige ander ongewensde effekte... This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. Тази програма е нестабилна! Авторите не носят отговорност за неуспешно записване, некоректни броячи, пропиляното време и други нежелани ефекти. Això és programari inestable! Els autors no són de cap manera responsables dels enregistraments que han fallat, temporitzadors incorrectes, hores perdudes, o qualssevol altres efectes no desitjats.. Tento software není stabilní. Autoři nejsou žádným způsobem zodpovědní za selhání při nahrávání, neplatné časovače, ztracený čas, či jakékoliv jiné nežádoucí události... Mae hwn yn feddalwedd ansad! Nid yw'r awduron yn gyfrifol mewn unrhyw ffordd am fethu recordio, amseru gwallus, oriau wedi eu gwastraffu nac effeithiau anymunol eraill. Dette er ustabil software! Ophavsmændene er på ingen måde ansvarlige for mislykkede optagelser, ukorrekte timere, spildte timer, eller andre uønskede konsekvenser. Dies ist instabile Software! Die Autoren sind in keiner Weise verantwortlich für fehlgeschlagene Aufnahmen, falsche Timer, verschwendete Zeit oder andere ungewünschte Effekte. Ασταθές πρόγραμμα! Οι δημιουργοί δεν είναι σε καμία περίπτωση υπεύθυνοι για αποτυχημένες εγγραφές, λανθασμένους χρονοδιακόπτες, χαμένες ώρες, ή κάθε είδους ανεπιθύμητα αποτελέσματα.. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. ¡Este software es inestable! Los autores no se responsabilizan por grabaciones fallidas, temporizadores incorrectos, horas perdidas, o cualquier otro efecto no deseado.. ¡Este software es inestable! Los autores no se responsabilizan de grabaciones fallidas, temporizadores incorrectos, horas perdidas, o cualquier otro efecto no deseado... ¡Esto es software inestable! Los autores no son de ninguna manera responsables por grabaciones fallidas, temporizadores incorrectos, horas perdidas o cualquier otro efecto no deseado... See on ebastabiilne tarkvara! Autorid ei ole kuidagi moodi vastutavad nurjunud salvestiste, ebaõige aegrelee, raisatud tundide ega muude soovimatute asjade eest. Tämä on epävakaa ohjelma! Ohjelman kirjoittavat eivät vastaa millään tavalla epäonnistuneista nauhoituksista, ajastimen väärästä toiminnasta, hukatusta ajasta tai muista ei-halutuista tapahtumista. Ce logiciel est instable! Les auteurs ne sont aucunement responsables des enregistrements défaillants, des minuteries erronées, des heures perdues ou tout autre effet indésirable. Ce programme est instable ! Les auteurs ne sont en aucun cas responsables de l'échec des enregistrements, des minuteries inexactes, du temps perdu ou tous autres effets indésirables. Este é software non estable, os autores non se fan responsábeis dos erros na gravacións, temporizadores incorrectos, e outros efectos non desexados. זוהי איננה הרחבה יציבה! המפתחים אינם אחראים על כשלון בניגון, זמנים שגויים במדריך השידורים, שעות מבוזבזות או כל תופעה לא רצויה אחרת. Ovo je nestabilan softver! Autori nisu ni na koji način odgovorni za neuspjelo snimanje, netočna vremena snimanja, izgubljene sate, ili bilo koje druge nepoželjne učinke... Ez nem stabil szoftver! A készítők nem vállalnak felelősséget, a hibás felvételért, rossz időzítésért, elvesztegetett időért... Սա անկայուն ծրագրային ապահովում է: Հեղինակները պատասխանատու չեն վատ ձայնագրումների, սխալ ժամանակացույցերի, կորած ժամանակի կամ այլ ոչ ցանկալի երևույթների համար: Ini merupakan software yang tidak stabil! Penulis tidak bertanggung jawab untuk rekaman gagal, timer salah, waktu terbuang, atau efek tak diinginkan lainnya... Þetta er óstöðugur hugbúnaður! Höfundarnir eru á engann hátt ábyrgir fyrir misheppnuðum upptökum, röngum upptökutímum, klukkustundum sem að fóru í súginn eða nokkrum öðrum óæskilegum áhrifum. Questo software è instabile! Gli autori non sono in alcun modo responsabili per registrazioni fallite, timers incorretti, ore perse, o qualsiasi altro effetto indesiderato. これは不安定なソフトウェアです!本プログラムの作者は、録画の失敗、正確に作動しなかったタイマー、無駄にした時間、その他あらゆる好ましくない結果について責任を負わないものとします。 이 소프트웨어는 불안정합니다! 제작자는 녹화 실패, 부정확한 타이머, 시간 낭비 및 기타 예상하지 못한 결과에 대해 책임지지 않습니다.. Tai yra nestabili programinė įranga! Autorius jokiu būdu neatsakingas už nepavykusius įrašus, neteisingus laikmačius, iššvaistytas valandas, ar nutikus kitiems nepageidaujamiems poveikiams ...[COLOR=red](Kodi.lt siūlo/rekomenduoja testuojant šį priedą persijungti į Anglų [orinali] kalbą)[/COLOR] Šī ir nestabila programmatūra! Autori nav atbildīgi par nesanākušiem ierakstiem, nepareiziem taimeriem, iztērētām stundām vai jebkādiem citiem nevēlamiem efektiem.. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects. Тус програм нь гүйцэд хийгдэж дуусаагүй! Зохиогч нь алдаатай бичлэг, цагийн буруу хөтлөлт, алдагдсан цаг хугацаа эсвэл бусад ямар нэгэн хүсээгүй үр дүнд хариуцлага хүлээхгүй. Ini merupakan perisian tidak stabil! Pengarang tidak bertanggungjawab atas kegagalan rakaman, pemasa tidak betul, masa yang dibazirkan, atau apa jua kesan yang tidak dikehendaki.. Dette er ustabilt programvare! Forfatterne er ikke ansvarlig på noen måte for ødelagte opptak, feile timere, bortkastede timer, eller andre uønskede hendinger... Dit is instabiele software! De auteurs zijn op geen enkele wijze verantwoordelijk voor de mislukte opnames, onjuiste timers, verspilde uren, of een andere ongewenste effecten. Oprogramowanie nadal jest w fazie rozwoju i jest niestabilne! Autorzy w żaden sposób nie są odpowiedzialni za nieudane nagrania, błędy w harmonogramie nagrań, zmarnowany czas ani jakiekolwiek inne niepożądane efekty. Este é um software instável! Os autores não são responsáveis por falhas nas gravações, agendamentos incorretos, horas desperdiçadas, ou quaisquer outros efeitos indesejáveis... Este software é instável! Os autores não são de forma alguma responsáveis por gravações falhadas, temporizadores incorrectos, horas desperdiçadas, ou qualquer outro tipo de efeitos indesejáveis.. Acest software nu este stabil! Autorii nu sunt în niciun caz responsabili pentru înregistrările eșuate, cronometre incorecte, ore pierdute sau orice alt efect nedorit. Это нестабильная программа! Авторы не несут ответственности за неудачную запись, неправильные таймеры, потраченное время и другие нежелательные последствия. මෙය අස්ථිර මෘදුකාංගයකි! මෙහි සිදුවන පටිගත කිරීම් අසාර්ථක වීම්, සාවද්‍ය මුහුර්තක, නාස්ති වූ කාලයන්, හෝ වෙනත් යමිකිසි නුසුදුසු බලපෑම් සඳහා කතෘ වග කියනු නොලැබේ. Tento softvér nie je stabilný! Autori nenesú žiadnu zodpovednosť za chybné nahrávky vysielania, nesprávne časovače alebo iné neželané udalosti spôsobené týmto softvérom.. To je nestabilna programska oprema! Avtorji niso odgovorni za neuspela snemanja, nepravilne časovnike, zapravljen čas in katerikoli drug neželen učinek... Ky program nuk është ende stabil! Autorët e këtij programi nuk janë në as një menyr përgjegjës për rregistrime të gabuara, timer të pasaktë, kohë të humbur ose efekte të tilla të padëshirueshme. Овај софтвер је нестабилан! Аутори ни на који начин нису одговорни за неуспела снимања, неисправна заказана снимања, изгубљене сате или друге нежељене ефекте. Detta är ostabil programvara! Upphovsmännen är inte ansvariga för felaktiga inspelningar, inkorrekta timers, slösad tid eller andra oönskade effekter.. To je niystabilny softwer! Autōry niy sōm ôdpedzialne za niypodarzōne graniy, niynŏleżne godziny EPG, stracōne godziny i inksze niychciane efekty. ఇది అస్థిర సాఫ్ట్వేర్! విఫలమైన రికార్డింగ్లు, తప్పు టైమర్లు, వృధా గంటల, లేదా ఏ ఇతర అవాంఛనీయ ప్రభావాలకు ఏ విధంగా రచయితలు భాద్యుతులు కారు. Ин нармафзори ноустувор аст! Муаллифон барои вайрониҳои сабт, вақтсанҷҳои нодуруст, соатҳои бефоида ва дигар таъсирҳои номатлуб ҷавобгар намебошанд. Bu stabil olmayan program! Yapımcılar hatalı kayıtlardan, bozuk sürelerden, harcanan vakitten veya herhangi bir olumsuz etkiden dolayı sorumlu tutulamaz. Це нестабільна програма! Автори не несуть відповідальності за зіпсовані записи, неправильні таймери, втрачений час та інші небажані ефекти. Đây là phần mềm không ổn định! Các tác giả không chịu trách nhiệm đối với bản ghi âm thất bại, giờ không chính xác, giờ lãng phí, hoặc bất kỳ tác dụng không mong muốn khác.. 这是不稳定版的软件!作者不对录像失败、错误定时造成时间浪费或其它不良影响负责。 這是測試版軟體!其原創作者並無法對於以下情況負責,包含:錄影失敗,不正確的定時設定,多餘時數,或任何產生的其它不良影響... all kodi-pvr-hts-2.1.18/pvr.hts/changelog.txt000066400000000000000000000130231260020026400202150ustar00rootroot000000000000002.1.18 - added: include satpos in mux description - improved: Do not try to reconnect to tvh while suspending or not fully awake again. - 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 2.1.17 - fixed: provide a transitional package to fix upgrade path 2.1.16 - fixed: Debian packaging: fix library install path - fixed: Miscellaneous backend fixes 2.1.15 - fixed: recordings from older tvheadend versions weren't displayed 2.1.14 - libplatform dependency update - Fix CMakeLists.txt language resource folder 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 kodi-pvr-hts-2.1.18/pvr.hts/icon.png000066400000000000000000001577761260020026400172130ustar00rootroot00000000000000PNG  IHDR\rf pHYs   OiCCPPhotoshop ICC profilexڝSgTS=BKKoR RB&*! J!QEEȠQ, !{kּ> H3Q5 B.@ $pd!s#~<<+"x M0B\t8K@zB@F&S`cbP-`'{[! eDh;VEX0fK9-0IWfH  0Q){`##xFW<+*x<$9E[-qWW.(I+6aa@.y24x6_-"bbϫp@t~,/;m%h^ uf@Wp~<5j>{-]cK'Xto(hw?G%fIq^D$.Tʳ?D*A, `6B$BB dr`)B(Ͱ*`/@4Qhp.U=pa( Aa!ڈbX#!H$ ɈQ"K5H1RT UH=r9\F;2G1Q= C7F dt1r=6Ыhڏ>C03l0.B8, c˱" VcϱwE 6wB aAHXLXNH $4 7 Q'"K&b21XH,#/{C7$C2'ITFnR#,4H#dk9, +ȅ3![ b@qS(RjJ4e2AURݨT5ZBRQ4u9̓IKhhitݕNWGw Ljg(gwLӋT071oUX**| J&*/Tު UUT^S}FU3S ԖUPSSg;goT?~YYLOCQ_ cx,!k u5&|v*=9C3J3WRf?qtN (~))4L1e\kXHQG6EYAJ'\'GgSSݧ M=:.kDwn^Loy}/TmG X $ <5qo</QC]@Caaᄑ.ȽJtq]zۯ6iܟ4)Y3sCQ? 0k߬~OCOg#/c/Wװwa>>r><72Y_7ȷOo_C#dz%gA[z|!?:eAAA!h쐭!ΑiP~aa~ 'W?pX15wCsDDDޛg1O9-J5*>.j<74?.fYXXIlK9.*6nl {/]py.,:@LN8A*%w% yg"/6шC\*NH*Mz쑼5y$3,幄'L Lݛ:v m2=:1qB!Mggfvˬen/kY- BTZ(*geWf͉9+̳ې7ᒶKW-X潬j9(xoʿܔĹdff-[n ڴ VE/(ۻCɾUUMfeI?m]Nmq#׹=TR+Gw- 6 U#pDy  :v{vg/jBFS[b[O>zG499?rCd&ˮ/~јѡ򗓿m|x31^VwwO| (hSЧc3- cHRMz%u0`:o_F)IDATxWdY >Kleڵ{h+3<`"̹=Wf5[UJ-#CVm%bm, Qbv3szB?/9pmxlMOV/9K(~u"J/!/!?"/!+_v/!/!?߬{ok/!?|c WpDx<%_B%Vs  , YBwF𼿄K]@ r_B%@Ͽ, [?./!yo ?{e/ ?#-!/!%宿B^o,%_B`  ߗkYXJȳYzYKȿ(%_BMC z/!7K)M]ƭ[L&ܻw}EQϟQ\i6W\?!׮]l$ RJʪ$x>fwo_tؙ8-!ݿ_J(XYY?ƍiJ(JIR(s%vv?` {?wG MYHNEիWyO~B%"1IB٤l1R+RXkr9wg-Kȿc$iU޽˫ݻwI=eQP%CݢtȲ Y&1{|<~xL F8os[źY/n);;;ܹsW_}u(CUU QDբ[jH=ٌc>|9>9f:R%J) gY/yߤWJjvܸ~w /jRb( < YAӥigAh qxx ?f2Zh%q|-1)VD;$xc9i#w!RF[[[\z SE?ޟV;)!$EQ)>tFQLGCNw{ãjZ% (V*OS ݉'Y㈢(6{OaP/ K[/!mnݺ۷Y]]%ğEi;qL=шC ̊(O8|t݇S1dE0!tRN&BJLUb],<^@EbAQ_ƽ2 dlllp]v.]jbgw}&_!$i&)UU.Lt1ӳ}9gПGݓ\)ñ;A, VA NrǬJe `jqZͿ%b@K-l.v+++4 i4(?/Z4F(||c?z8ʪb::cz|]rKQ@-XkZSi#`)8Ay& 7 O+Q8/)kR,^1YBooZC[fs EFoPU n!Gܿ} N1;}L $\jVS֞Q l6%HKAS T8!D8Xk")H~_`aK9fhmoljj-fx,h4TŨ99=XqqCGՄXZGH!NOq#d[lX9/{A7E_bX%"8(%y'-!7 !p޳͛7vhgx^,RJ,#IO%q8iɥK;mYrrrʬ(qΓO h@I<ʃM%B(&yOCWX³Ьez:(!8:bIn<II'`¡ %Jb'/=Bj'E,Ge(A}fIڵk #~A#x;͌m\Lc8o^./ei|;4"PZG$9VL%) Na%B!rIrs^9ӋK$ЉS NHr!,\gss+WFe MN" ]qeP|o `<sc!s9^-=ὣtDZsx/pSYB{Ů yVX+L hi$*i$-AbW) hGKvGh4ʃ3H&=%1UEU޷9a0|bm_5J>!;wpΝM|V|-꩛fY]YזXPJ"7{O&đD)].?x,I,hda8 ;#$DJl@̬%iF^JUA:B)YO/N t`9“ƂL;< qFLp~| Fr+ wl6)rѕ~vFݿ.ʋE4 VWzoAK윃wDJý<}>| >G'(,fD)/(!ƃKAY <.-B( m + ֣(%J HƎԑDphĒq1BϨR Dj༧*&YZ'שBpSE7$$҄SH $J` SKdځtjȍck aV5Y,8E luHҔ`J^ہ]Df3Ѐ z_I=K{yxȲ `a=C]^  Ј36klmmCXggLƓEG[ G}ț}h:X)Ǜ+{a+LF-N=úpDbhiO "t Oi,XЈ4B*1Du_+>^!_),o-p>5e^&iGnnJ#q+)'/wZ(V/ $Ijp,FA~)%Zk̍7R. "igg'F^/twv$R??,KDmh9 ywy׿b#R_JnlzXȍ0a7vQ9f!DZD tSOl8;&ȓIAM9Faf𳂖:EeϪp:&qbGa-L*n$ G+˫M'd(` {z?y4/OSVWWBO;?_S Ct]VWW Evqqz~=Ɠ邷c#~ y O+( -C"24ptX_yǒKU D$I $Byb x/B^x$:TNPL'~w }xlFG4  K`Q{ q3<9gg|(%yTF,h',r(hG C D:y0! Db)D{Ȥ#Qñ%5u ӆBQ:*ιE?wiחBمݮ3/GDQp׹x/:Q'M6lllAyp8 C)Z=w{o2:9TJ4'yA3'#uc-:"C^szq;gJPz69*뉕$a(%7$Z T.&<x`^ٔlfM;mR T5ğӀ$yJ _^ܼy^zia5N?3 gѝsC^6YvY[[c}s qG9R*TNyxч|D;4/$3x!#G״[${s45(/)G< }!%w:\x^Ff,bAs MD-$èKBkBPyJK(!+,l7Mj@>"ܽO~t:DQ <{_yD4[Mz++^Yrzz)84b4[o}F֬w[m(n  SrP^FfcLRvwoqrxDYxZGӇw0=W EZG)8$'cXd2) |wY/BT)THI 4`QC JKп(&F 'b]X?\B/F6@Ŏ=v_z'\r8~18rn1%H(g4IhZt;]:qaa4  S"sC}Wܻ Mql A"(+K頬R ĚJbSV!S!C]( /%X,VA/sB܄kI,J#TiHZn4WT냂A ?ڎ.8@aSfLZYYUUE#UwV[B/2gƥKHtQ9䟓D(j#8Njv;EQxt:y^ oG(E#4A#!x#2l(X-xa*os;h-@z2%TpP =JS*b0kNf`C{ ]ʇq8zdlȃ%%^B7\F#Ie`[Rh'QFF Uéa\^Q5l61|`B,t[n-  3O. n:R*8:S>k4h42T0L&Lgf)?W%!qɢX+ɛA$u&ld=zҊE.!Yt$VO@xNP40Ch, UYoqx…Ԅi\fa#YI h%|~꯬+nBi yNgN rE7ys.Z/!K9;w?"FJINj_@,v0ӑ&A&Ib(Fy1c02(j"99>7?Ĺ$I4P9Oi&]{(4G+A`fI]  Z8Ht# !$0 ʽT  cw G3A&UA3 S9"$ZYs6<Ք$21? d0HŭU01,""$tg'C`ID`LŴn]w݅{Y_ZM͵k]y( $k 0T&V:4"I\7欵LSFq3,=~/:y NNN"2$&Vsx(l#˜ ;ydpǵpT6Ĝ2@RTa깿#'3WǺqkE73vJQ M4 W|#֎(ƃP4I"ڰ 9~vW{n" ['$D҈?uN^Ae-n3L<,K^Sٝ~ӟr9^krAs,[C )QRDiQsiMe&Lcg:{ć{'Xu:x!JΥ.ͽ9 34ӊ*#DXv`:¤`C/ Svej;Z23a֨$x4#kA#Qt-BR8գ "A2=wfaZA3lR-$%3MDt649`T A8+`+CtQZcmKsϋ5B~5[[[ɟ W^E)d2Y3|d4 bB\d:;>Lg 5s}>ky][:YFӢr"VY42%=[gՖڱ^&Ă\0(dVN#=DӉZZ31 A$%Jݴx>q*qk3QJVHc!v%+L?n¸()$F:V K ^a/RP>ÂiXihH05ԶߞQ!tҐKXIEi%kMxԈ/Ic힤eQ,hI2@_E{]y54HꎾXE(i޽B e2*He/^&<U7z[@8O$ Z=Ev3ͯ-.Q# &e; 3 ٲ3>3+\]Zy zqs5/{¨"4ȡcpCO*&F{6T0x1,}{ G`8 YSTȚ` ,p{Bc<"$TV`âM0 u+B~߭ _*:zJ1aX{Hgx;`;s0J Yd1tSzA`0 f(|y|hG^*(\p$U$KwϠIֲz>s=dD8A401l|괄_ L/^`m 6nw_ƍ-d4R%o<)%q }ݥ#zT8N9>>a:lIFePSo(TGHT1b+NqS 20٤Th^xD`:3t=IY(4_8ptL;V83!#ӊJk| ŌsH%iEҳږWMǬ phZdk$fIH(R`==cRy:HJQB-M' XhL+pWrN(mPUzezb@a<8 1.yǯ /!d: zZGqG~!bWox&J?)6s'$`塴kzR$H[PZJG3D: Xo(i8 Q c%ZriF[لapBغ!8zF#¹}Ps!nKr#N;= |f4ݑ>xzF"iyFJ2\U}jj9E#/\/ #._LUU A3N ==i9}!l!ssןpxza%:IHь$Hҍ$miuW0BS'C~Y_ K`z`q^6*C3g]ǜ/E؋2<a;;4MNq}g)K px$dFJ,,2  p֗81&ӈ8of<'mƠ,['03Ϭr8A-JI'd=bVz&H-* ZKc;l\ʽ7q'0r63 %Hg)Xk^GKz ՞K4HbR:F<4H)~G+tbhiIШy %Ewﰏ_4s Nr0Mu{(!1,^:|f3V譬p||dpx5A;@+TSи"G' 7NAh2 Z,̅̌>D) J9_p8J tLp<4"<(+G,-Ҵn+nȭ/I e>34&gȢ@vWڂn$Zp>8J&aKΦ!5#E,Bn`,MhihTLE Ϙ~Si㏹~b+r[,PIXdmu%.s * #Es‹-' EXF&6t(9(:SVh,S S(kq-7ØL.] L~F<|ӏSv3ǣHB/=`璼$DJP4u mGTI"(Fʕ+:xNQ[E!Wz=(핯M1E9UӉqGz>c"C_AzV,AsO{Ci+STgj$20+ґH4q xqОy3+=#RIjd:rv?䄃ܽvFvۣcΨ*Cw_2! aO??EI"H&tcI;Lj*!%0L QwQ\_$I)%D?MSf|$ΐ$1Z+UŊlNJX[y32O{4/$*RH%!0.tӐfJK!3$ݠ 6Idś S(OCIN cf±# CJ"hŒ IvxNŕj~uhi%FM]"srzlmnnelomi}&3@n9d23}}vL>3=gl&V)MbHv әgfبa,hZ(,b~~D  FYLYDqLY5O}Fw`8R9k$.'I$@lj_)k;mk?i64X3\ZwD@:aH]ȔR@- 普 uC_ZA@$YafsHG4g4ESWr8L<2o3b&jh< }_I>ng23ORj$e6a} w;$Y4~b`쌲,t:loo}(#ӎHx-Ш`ymv†9 6$2m)=B J]y/B/"=hiM*\H#A G;$"Ge[^Zl64E$$2zRj_\ J8}o_~e!]csm^M$ilSr,׈UuOٝs4>3Oc=L`\yrQ&'NUtחv%|NO CYV 0';<\:??_7\Ͽ< $DRkr7~a)V`A)hhPZ0Ue8Z#jʱO%!J;B@I@ Ȣ I`ښK`8GӉ@{J(gd *T)B=8c1ơtVsϽ?w:;7ټn޼^U"X AV\˴cܻ>':st.%Y o-Dn? pkF)a53yނ7wtL!U„K|G\g,`00LX]]뤑$4bE<q/sPU‡Yams#T-pO0!ˇhk-3ErY^aM0 "W"?-or8 J:mAd$EŨ hflٺ^<(y\ƞf ANiITg5tݎ$+$ՎM)bUUUF"ں`R9VRAA+dZpVXn(z37u!{k\aC{}v.]kllnG1RҠ7x皍Y^W^a8?9looj%D_XufNjUs=Qy^`j=ZW?K q`YƵW_>fSyPsm F)P~yITKr(f@HNrpMҳPz6x2覒V$DGh8*#ijOK fvPN N+P$F3=} {\&.f<, D=ϲl!o F!we{{rt6T~}EQDߧs`^R 8&Mhcc$I>~?cz[Rp&|^7"U~ IH%:?8 &l02X~פ`&Hcd^^"8Iϴ~ υ 8A҈%+9J+ gT$nO&iagVXXЈ$+'RTŘ$Rlg-6UqBeL'XNc<yxMdZZfV $%&4c(8zp@qx/}K/NVt:e4-f:nOVWWY[[ü*?fŢ sB0'.@n^/$ E^P^Gp1]@)%`Kmn4'2Dk J2UR_,k=e=0V2@hG "rʆl)t܆kr{oVyƑ!/LYDY Ud4$"!8>!d=UQ 4bGY96DF0(<,yaM03q!x0px@( +h *eOCfG8}XrllNv8c @)ō7qɄ?~)~*y;QF8jߥ BP%Ǽz=667H [)Dܖ<^kiB ,Q>lQӀEV g01,I N[[[lFHtשqm\1{Ez/kkZ_, ;/8.5 D\,C/zI$G@:*] 4i5L t=S-ÙZ$0u(JOnalZ&HS6t>6dYKsp|t ҔW^!դϽZA; =a 9-Hh%Cp:/[I@S+" RCnBXCĪ,ӳ!ofH5R2h3qeiwb`L` ?/V+W/t'1|]3AA.Qli|WwƒJEاY !Nܼyk׮QUq~~N'(Ԁ`#!ݡ/@TPfZbAT]]$-GGi,w%8Z6aKK78 I phut3ɝb!i7,9 6R͵vB?Z8Z#=cow7/Ujajt DTx8q)Ц%@ڈUP..$4Yh֓(0a|f$ 9=N F3˗ܢn l p a;;;Klmm-r+wn*XyOݢlد[Y lllh4?g!9wvA.hXQ⿤fOGֻ-8(a pJh,R@dJ4#GU|XTV~Y="Dr+'i&4qwj6D"j4H"8 ZMJ٘,M16Nˢ ICG(JV09%4"Z4=+$%XbK%u7`RZrDRQpMcZyRP&Z{!CL nIsiFe:/5n7+7X][ʝ;w pxϠ?2UJ-zIyҥK\~l[oŇ|@0pZ@EtJ^G^ Rڬp4zj%,} PW,um )![j/@ A > vTSU x>  2,Zt#G{*kbrC:` S<`F\jKbm-xdNXO9QFhB^UIlB7̳p-fT`>E02ӊ D2*O 'އNI0=z)Z>,d6~e{?#:RzA}$=$i@ 'TcZ:US{((!ZD`8tcO WII aR8I7+y&m_Rdg[f㍘u=sY$Mspf,{0aVN)9o@h_/_]GᅤKn44!$ sKa!%J:" b(HT@LZS>DN`|xNR F&Ieppbfwwp@s\%F???1{{{wa0|}&%1zLdHNÐu(r<n6ie:7 =<<i79>;yNѬ{rAjAKnS/೬fMz['%bZZ*_w#Bn)BA3ʄIEB֒H/nu2R~qx/RX˸0\mGl?T?д#Z^]5S;`!yyUs6G,=ZwLHG((g-4YAib$K/Ӽ&RxV$l >N5߸[7ptt`8Y.1Nloͯk>C\_-] 4 ʪb8qvzd:a  FIx6 Bpttt<&M37wc46H|uȸwcYa>][޽Y__yKVX]]auenszz1gLKWmY$IO~^{5=zs|MNNN~BC~9lll,RNk$,$ Vk{lv~k{\|,L)+-ֺ( xo(D)ؒ{]ӈ5{CMx&֩p2ˢ9Y5S7{;+,cU͋7 Q fgu=chB%8Ng =p$ TM2T]|SL+Cr%d႔[<-Ivz&e`zfYMŇoɣߥ͵;/͛7ڤjh4;\|hDg2SE0NJ4My&;;;k?W{{{Oؾ]3?c<0EcNNNǴ[MC1hyg ʲdooU:5C0X B>B)0΋U8;aAR'Њ`Z9KA&2ʥC+B0H^(m_∗VoL[n9Jàљ`*|1Q-Z,[oy>:OŊ`)6; xqMKͬ L ƥE ōFbx2uYw ~\ r';$H gJ;T)Z.ر9.x9.$xZq0? Iә-IcVrWN&!yHzTcΦZ ,( VNx&Ʋݑ7{cˤlI?,̱7*ǤHIiQR9 G7P0ftEֻ{,kJ Z>NDs@bB1,Sa9d:׿y~ ^y%_XY]%,akk+l2UE1+(bMpѰ{͛7͛ 碯U ~O$ܽ{,9;=W$qo I^hZt:8f|ZSxLa{g;x83H$J B{0Z8oDBޖU$RHHhMB!ld.@-Y=kf5LKhn64ŎG;/XbjSDTO 8g#d54R [LgR%Ɣv+b֛9;|p0xV45xxdA 4c3E5Wn\ZBs<S FFh;4Hj3"M="d9$R I!HKTl7$gfE{LhKxQTc-goGG;.n҄,h7g1U1k y#ĻG?'!'QXOR褊4*WSXK=DЊ%= 8"SrK9l4?ԁ?}~纐*p#B?Q{ YIvdJiNvC)"NF^[p'xΉlRzhJo:FTJJ6Z|0uV`$C,LDR(rR <tSA+ Qm\DTgZX `V AT@a4t ^j KcJx$=Pxn#^ӟrY]]!K8&ʲED>,677+^}U~{1p <3?OiBY2 X[[E)Ե!sloo#x08>>lmmfeQA,|Ja뮮xjl\hlE"x< d Γ[BE`%ދIJր^z$- fHR ;Ͽ7s)0E4%g3o+` 78e,~ƝOſ~6IGfYR ;bȋm//yWyyי'a%N>&|Yk999 ]Tstrgᅡ$˲s=G eTU- %F4h! g`6|͘ fƌCH^^bh.V*3+edP9g=U)2+Zqp"xձT v6r,?[d29g[\E_3C_ x<' CYjYF-4\X^}ESA'cs_U|W,>r==\rŴ8~8Gԙ84RgHL; ;e z%Vq?44D__+++W@;˜' G"J*l,"I= SbQ*b(ZB8E5~lEa`{36k)R'c w%ۗ\\^WA)8r RSWCRJEE,F4 Qi;}vySg>_GkObбGzh:(f47)#jUt/ _ӄQZCizS2Wx Xa!! P-0w`]<05-I1MHӽQYakML645*vSJZ;Jsw kL"WިdR$jYVl".]baafAJj#G8~!'NR&D "!XX\\016x ) qܹ 4X,dtxs`Vhi4m² EhĕZвȻVJDKPNQCD&"rp,~eTsOWTӪ%)7$Ն)ͱ6eи@G4yyאX|?ܸ8|hCZrJ`Q2b%7>f<\.ijif` sB+rj \el+4 \c[&*-&dL7@tMW l F*-5cPƷV Qm62LRpG( Q!!xflehexgMaHZa4l<סhXXiJ|iSv]D0ŀkZk{{]!ϷWxI_V0sf?TEB4%h$ iIǚFpq1^ΕW>)kjU,ǣ%.4L 4+6 'nHr't%Hʂ%=EKg]IxD>XWY\IЌc.~dz<# 6 ؐ3q V#( %M7L1ZR !KIS'0x:jXqwAF& -Z8|NsY^J.?QB||5O=bnn?f lQȿp!(!V0cGq\&_n@A/^.Y^^f=OMzfVq1_,H™#T,FXxq̈n3dQ ֍!l9-*\}!S}69Xp-3-l)#q U{J(icJ#T@_M#YoDfyK_/| 89y4Kk3YsE$$SvV T|0Z4g"0%XnHrfT]@bHN9p`lv]w3 [z+RhC #A-0JD2橑8sUS]*p?q:77ÄPdƵ5l[q,* 6KKF:?fffaxxzҊ\>Ç9z(og|@XZzboe&''czl3>ccckwk'ZfXB3>>F&WV*Ḏ!(V^Z 6–-pӯϹF5H0$mCRHRWhZLTB,\ 3p`cSŦnHM+cQR3 =(aْ;zݯ3{?qI_GE!1 R ]ӸCE!5h_?Qòr(MiΧKUjaSʌ6?/(-J]0'1ՖKh)Uͥuž!5sadԗ Ӿ <hkrq0KM( :pX2KLt9hȌ{V BjY@JmSI6SA2u㺩E3ex9&''9t4j5 `hxml6ӧ BBJR:/dekke2XQ|ellk׮~gB"a2:6IOoJ 22߶m`<@ /ֵϻ6Rj5Mq͎Ճm|P5_]M5 ")8r+*!Z!&gkȄko6XFey|~4׮\lbg&v~[t!NfTd䅙T\m)ꡦ%%RkT4Pk@3U?o1k31qaMQ 4seF _ڲH98Xm*fN߈XlZxTAOFIeKz٬ К(BN3Mhؖ99tZFfXK*S鷅E^#cd"")2 |Ge (s=fg̬@,iUUN:Eoo/Zc.zjJ6%p…Y}l&}jfiv$)(+,/kv7a[6 p]volo0L CC rJLo-l2D@.c9f6~ڢ%eC YV|iHZIKG/AU-F1fɇ+uƞKc& $dKw҇r:mL\?VLie|.V %!sYz-Y 4b$YF$)zc=Cẙ$TBƢsP3h2qoIYz& ^x-ReB"L~i3B6NJ,*BX'Z-RX(# 61R`?2ؘdm%Ĝ+~h daCn-DcF0 MuM+cİM#,jLuꁢՌ+s_ ʵ*o:R 5|>&eZڥKK%fqL8@IɊ*RZgيӢZЄa Jw-V[9rIJ\4VP|RR0jǂJKq+|za,54 c [ B3aY["0"zrNl.joxYTŞ-X9=CEgfܹs4}SdLmߌM1%9 ԧ/gp,-`aa!{ڥj5xQz{{q<#ϧhEMȥ5L2;9z'd%( M56(z311䠜)flu1WQB, )jBf-⛶b,  2FYY r:Fk{TM6#(ߌ$FLؐ +6Bj\R&MЎg&P&#,HQ̠!eFҥ\zb( >|{bYFhtt'jP"K_UH)'Ⱥ\bՍXZf:JG-rT}cV4 C9fАm 29Xx1"*З\+ rZ M{q59 dhi ͺVc,1ni3\dkMeWЛB#GjZal WFLkzue%M߶tH}}}xGE%BcEk4݁vq )!Tϳ~,2"1==͉'Ө7[>"aZPCSi@da81dYY7b@?Eab&ҕs3DxAoAXoE( 'j% U_sܵiH|EђAԌW6B54 Cv,'jڠ[+$tA$LPZaw%іq6h5GZ-055E\T*m?ר0ؼ"F*i7n{}Tȿs&}*&s&ÈE \˾233C6D$Z %R"Cņ倊96qO"nyyݕm>E3džRR̳{/ٵΞ? N@ GMړO>ݻVelNQ֚˿K}Vo9p8_4G6VxoT!@ޣ¯l?~3>îZtlX?SCV;&d2t^so/^^3f25h*-PLwU`'b8êBlt+h}o2W$J @7%-ݘ @V. M]kC+XX#sv5DRXѢB5_YKPWωBC%FYH#K+VaB$|KZ7")ezZ/l( c5jzz&]x~TJ-lTٻwL($3==ŋ7;@;X]]M+k:-?[ ܦ`eǿՙ#xZ~ / cPhܸ4tҍԷ"Y4Y3CCCqU&&T{7ARJj===fL5YXX$ [8j2ݻw/oԞI)RF S )ıD׏U__Q6HUm rMXa_`T?ogϞݲ 8GСC8p??СC4 ϒm۩eY4M]B&?/gK|Vh0 eьkH{\7D7e#b2=ejjKS}yyNş=μ66ߝdi]bW96!V[l=.x$Tl zKS ō,3E7NPՖ+[2hy/KL3}5P1+SVSXy v??4jĎhE&tJٓ"mۉ&hIcxbjZ'P)244mT" 9/wq3ȱcR辶a }X__'lt E eTFJw~?S"o)dc ۿ[|_TZW^h8NzFݻ<:pvZƁh4,//X-Y]]sLMOcY%>.\}=8O>yt\]]bwf~@(A yWdL=rNDeQ P5c%M5#Ŋba9c1k3 YkplzPuWqVdz❼ 1@02nZJamm-%`W&;IC .xKF2RkmݘH҃l~VKQP ϣh V( y$l &'8sg~SKH=[C~E"/eƅ.xO)Ν;˵Ν~;Ʈ]s8,//s…T2-a)RnKd&''p?xOksssDQDd׮YOߝYe'6ȌC,|eQYOAS1R#zPXizG0YT}kQL^kA5?R|f¦ksΡ6,B2P Hd4#hF 2H͹x?mk*3I,|gbL^pFA>߀TR̤TD22 (|2kk8AZ kDύȴzz( YXG)cfQ s[0:8qPwXBL$ q3](VH2>9_ sT x5YG߾rd"-L:!$d!% =) /rI~-xqj"a|i|YF( |^/qszI]7YdEb,1fgu%NB ۊZܐ,-ƊKeENຂzTg  TQ -VЊ$BP BmܛdNw=sXn([ƾMhH D,0殁(igwq 5$|>l6DWJq5.\v׉*Djߡ_?BKK7h4f%>ke2vڕ(:+}+Jj8==kT؝Bk#%'̘6?Y^KL2wuivRH@OXѣ߿۶ӂ8j&|*qo9vBXk8u/^^#&gΜ_$P*3w*#??ϙ?xyr58Ԃ--&{!+ǀa-@+h1_,UMP 4cFR^+!z4Yc7 {o~ lV5ajA}'^ \[5،UbFDڊBEmMƅ#YR,..nmGo=c||Ƕlx5HI߅rJW"ѝ9>,baaǏqm}2}WH( (qrڳprADhEFGf2GQZ'qEar|eܳDJsij$S=xIA`&,+Uq'͓?-J'(JM/W\ԩS\~V7)\W>h4(ʔtvӟL_o-7Ju/xftѢ#AXT&y/"Nu%8]EA%Ym(C0>advsёE+O1#X6va30o9衄rK`c-#b]@ӿ+-"y(("0=m( ɱ] `xd0IKTܹs,/sڵʹ'Qӹ0CR0::ʅ %biZ 08<̵kװY3;*h>$+OM*A EMړU?( 4h1'!$,h $0T*1??Ϲs82*aB RP˯R?0kkk$aE<j:wkej;؟?hD:T̚2EACVި\r% f|3!_(ﳰ`Dic+*!Ď/E PJh;s_ "+Ԫ4堻 1%{"drfJ2^tk_RlR.Y\\ŋ;={6 f)%~lҚl!P*x7crr2M&AʥK)W*~|/P/qTB k%(43DQ1W~@?seSvu\.yFhf6dA Ƶ^T<)n% W )P}H/"?ǥR)ֹoQM }'vߞIJy\ٳg~:f3=V+Mlb@o_B!-?eYa~3\ooӓ5~p/7@\h5m@ڸBjB>?Ey>uݕņIZif0.Lг}p;?C(F#q7|[H,c<%qKQt+ ` Bz?7j^@ՕV{ ARJeiiiSo_~=gdeee T JI"g}|dy,O~{?I}z`kۑ@{H@jT.^ŋqc0,I[ov̎h6@e[144NQ|(NRtO=TaB<Ο;套~}?x@*.`}cݽρ!WP|N+~t_d) h(z\ 8A1=2 S ΖKZ(-yMj 9 F@e\ْ$ R!}}}7`,.- [;4&=[2a񂔆TZ_'"zzzĉ[с VFFFL/Ц]&Цؾ}ʯ {M =w a(j1$j%(ӃeYiܹscÎMԲX@hr fjjAn,/S.$rܹ];::Jj|ϩS'4g#T,vaА":k-/Ox/PɑP a,oQbeR l B+IJ_-,#}.F2@3 M2<8K$фQamjksiQx}}@g#eY,//UmVVhs93o>gvv6M; KKKuz{{̙3q !D7'䧞d`pۊ]iv$~{?!$<ͦOG&Zr%Ν;¼q vZΜ'U~˲s)u8Iڋoc96 BRjQVyWСCqBi=v__[[9x -S@̊RYߢsכ=Pbs9֟ TDތfXksad7-dLڨ7m&EZ:8M3(ƖJ;aR%A&&&-ʜ#O<)NwӷӏAg}UjZ*J}OO 'k|ΞԪU=/FNֈ Enl5jBh4p]\. m}!nsDF:55Eoo/+++e,crǏܹsS(R|ϝku_?RLA[~$8Z 7dQ ,&z}z=>e,g!,?XrEkIԒT}E{B#1ZtT)Ji@3L.׮]# NLNN @s<+իWw|Zq9R Q&Sx^V L juGh8p/`[VZ~mtȑ#LMOS(6Hw7t۶7n C2L*I5߶mFGG$SVM;ǵkרUkTMS!3DQByCN,c.C.=cxxu9x O=amrecիWW/<<{ÿ[Nwๆ#N.FZЈ42Jߜ p&3ptBkJz\A搱m2R4A,Bla$#HVRFY#Bh,S&OMO#LNi>4MFFFkfȪ؎m|?B O?߶m_HJ(Wf4spa._ P/( ul}x0dvfLLLǝD nn O`~RHajj X__\CkA{r|}rrȏ)q(ZZʩa:hR`դEL244DTbddl6G&vdnnFj8'?ŋ |_ߤVoL΃:^kkk.8~|! 333;I'!zz"4Bcgmhݴ/_d2 żzpp}1>>*._KX^ZVǶqs[~^&@l67-:CnZyx1aAX֎lV3O3>> YLoo/ K|ygWW><A*MԂ7UQ(Xlu?<dzSB@"ZA IhX !gG3B:?, b4>J30X4U 0"Rb1 v$:֚.qdi j|Zd2nΝKFͻW0ვu_F*\*V?!YK6g#D1Ķ"axt!y]zzo}i_6C$W^^oS,b'}' CGj266R*Os=j-# 2==MOOώJ 02z6NrXrlY\\drr'x NQcmVETJsz,rlMta?|Ƕ-UmUP*-hc.6}7|~󥴾glNP<.G!+,g? Ο!gcZ 3-\G1f$&+Z PyAK~Hޥ?$A $:v ̈́6Ơcc^% 3} Ҩ׹zJJ㽂<h&jccc|ejfwlt˾Lrj,~R*ؿ?_ftt>3[o˗YZZbuuz s:IpuʥM!ٱ384a;rI(؎m/ot"Ƕ:ǩSxꩧ]-LJlB6euujK*M ??_ʛ~Y[/ϛ:r?-B͙uEeT׼䣄Q/Vhh Gǭ wb2ޓ?cۂ)MPJbӓ~)]A&eeeť%<:*DVVV[-A@Xdrr? yA m43$P|aa';w. 5.^gxꩧXZZڵkܸqu麟iI'jrj {~jL4*0;IR(- a纨. €74SԧZI2!\B@>7l.-.pv}q{zJ[o253g_2o((< emz$7(K`i1(Dؤc2aA=|d42VяFVdFdCgh6: ɐm;8˵k))93wCX__' 4T*J2b;f]Evڕvr.\`^C.sȨs7oBy뭷xWX__OuhhR_sEMWv ~}|wTJRD7qSB(HKP3{&ٴDl4O8LمI+175x\t^=RJ?>gN_U_};,X%sbK|;?a8YJ} NFoS#{3 gmRS%P`rb06^AظN3h&Aݞ!i>VVV8p`JeM,r`' 4N^)</ӧSO&arr}_1X6 tZE%D\Gk* r9MUb\k6; n*J"%$^ QfSe;u]ۯ}t(Rw|>gϞl_ι/گawߊd3ڌq 3̜6٠Q4@3*=f<{]V&!FFpbڿLI>p@|5k4]u}}eGGGA[=w^2z=-+iKo_y7۶ =ktN[.]JIEpp E8r^QK^'Q"& ? tYږEk(6lf!f}}r}}})IZ;P,~ƂI+D蹳gx{xK_bdlK/SX"zk$$Al1b(ҒTg1QtS/:oonr=:O?4gT._X^~hx/ h+8p ]tDQD000SO=oo3;;bt;w|7OJutt45+ h,E$1*i6vr0s"avkHN@ߡj[Y)(aK ]u8{, #z I q!{1~188{̙3\v_"_<|o_zG=sрV<-ӅxHp;;6ԂKu9ݳ`ͥ@2dYb`h6 So0KPVMSR,OD_*< L&ố|1K.~7n۶dhh{ϼt׹zh2"!]\Y,@ 1s(sLLL$P zJ,SU{ َ BG2:ׇY[[cjj qҁAO<׿u}? n| Ɏ~ꫯ4ۄһk.&&&$%b'lj4شN`tg'w7 [(ڪ 3 pqlSN!Oق[&IIرcٳ?!8s0 y 1k6WeYeYXX```_|U q \^Zٳg4$_W*-m* Nk@7@_Occ,2^I$RR(X[_T*y+n M(H^ZZJ֚eR  pR N,$Y"kFۛB4PƀkL4;Qg0cB>>zmK;y% ]и%Qsh4xطo|>-&kyyjJ.} Bztxgɓ_>u]\*Ǟ,M>8qm1`a6.i q)34FNEMJԬg/>}}},Ʋuo; !@%mɟ vP(MßɺE~r 7˲dٛ-m#"DjFAzlMITmˢ^܂|[bl?t>li&rfQ%-2W\.< ?xVLe MP2.A:{qڵi8FǮݻ8?7VR6m{pXX1HR&rʕn8l6tflkIjG?D}VkM!\MϗGjn,7|_~95|Hm3<2́]V5}6>?}yaUʄaeP?Wlo'urZahq(^\\G?+++|ӟfjj*%SyFGGd2j dRё~}Y.\@X$ z WO=^]ak;)zSm@o&ïҮBhLNNN"z\\\<|߿)u ]'݋B5ԦR˕&''SqʤYy3' wÉ'6$?55޽{QD"}2aFnZB*ݥHYV7Lm>"losDe膴#yѴWk2۶RᑤЧ7`iig}C188Iaa!9%E6{lwB<ϣZ)sR$G޽G/'su!4G)UJݭ|Qp0RJy,-- fffҬTe&~>]YsVW׸z*O={! tH+'l4i}]1^,S\Zo`O?&g'N r#@"=SSSIjiH&R X(re0 XYY1En@t'{eeeâ][[lӓztwZn:$Lz`~E>}aDtB;!'UfR~oվg~: Z?Kl2 B>vJdе֔J|cǎ188[%ĢI^h4{cn~ZE!3g?T K>"ü\g0WIM8m'=/ '/dHpf.g$r9._7MVWWs\{ ;xMyѭCQ q ӖW7JzN®jM?js-An(!$mW}rؖ>\ze!gM]eNL&ҌG(^x1>5͏^~ ?6 >G׺R233cˍX>$LJ"]YYa:&* r.FI*xw6% 7i;zBQ)KB0Fh-Zlsk;혙uw2l .f,NAPlq q1mSl6Y__'S,Ӊdٶm,& a :9N`MȯSml|0 ZR)WE%~+_oAJQ0w\qmJE+++)]dWe/{/;|ӟ'&sFk{=A4MZ Oεݼ^[%DɈf̧HZqZ%۱\.W~__kզ"c8T* SӞ_|ڎel,;`64 -d0C?f>%_`eyb5n|,_Ep]7E&ʆ$趿˼ΈU$?~<-$je2XR 7%Q; Cϒ)jN,'? /_Pk? !'H{ΝC1<0,rJV^>+_ cccʉ'Ӻɓ'onAC?b-q855SO=eY۷TԩS)޻~:<_c49)C~+Y~QM| w (4=ryۥ-ih Q';iMY\7$IԒsbȞ={R` ]zׯdxwK' ܻwozwqEߏm žZFTPjܓG.g'䚵bU ;̒@l+=X0I"?lOÆ@޽i6={:*A5b~Μ9[zOߜ>?NTY]hL=݊ no6a&-@{z{imfH׮`ߎ$~Jz-FGG0ܥf``u9uB_˗(=<[SS?W-E$o2;<S.SMggQoشE LzǏ׃ȴ?M/J)9qkkkl6[ousП??yd2FGG76|zҫ\*Z˯;,) (,Nt-QJ4q"ڎ6!mZkW%!MMMB3oqqK.199I?m366 ׮]ŋNxQa\ǍoDM4; ;o?'=FJmvt`wρ|n@%`6v}׉:@ l6i yT*>0޽7x|;\ziyvLzXP8xIAk՗rYg'#jobGjֿ N;9&mY MOIHFmmz}\ejjFN'& r ssse/2!Y"}&L3LZIROm3;e0 C1I2at߷Rx$2af()!F,J<iT*mB+++{)]AwBn5Xg[]/j'-8=aa[6Ji(D)Ib'6 gTp1Z&#fS1Amo8z%ol&###i];K9"HO\{I3ޠӨ7Lg25-w; Nm@J3ܰf$pLIB0M/AП?̐G poѨ7`n"m0:Ԃ='ž{qs? VoVdžn?koem7d?JT]JI>XaS|  E2l84Ru-ujq,1]6o#ȿ붒 ܋mvd\+2Qd lo)E.? Ѓ !RRI&`nƅ{@A ;ު]Wktێxn =_Cq'+IF$n?z9! |%%MvM#! :|SO/QMRJm]"=訕B7*9uK;rA n t>,Kl$%b"QXCN`{!"lB1[mAo1.Q n6cEȿ{;S0Ӻ[)G쐺XΔ"}q%(B>w:Ny$#m3v' lݝWe_俭-yyv -[e{>w߉ݴ],Izn𐣄ӋoWOxlȿv!<7Nx=̐VcĺN;保H~CcGAo|P!TΉjlY!GYcۭy>|"[$AO&ϱ0 ۝qy!@>VAc=6ߒvfNC<yG; A{q&_uxlAG AG#%GG ?AqTx9w ?#?4 AGG AOtoAGD~^@`IENDB`kodi-pvr-hts-2.1.18/pvr.hts/resources/000077500000000000000000000000001260020026400175405ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/000077500000000000000000000000001260020026400213235ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.af_za/000077500000000000000000000000001260020026400260135ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.af_za/strings.po000066400000000000000000000022041260020026400300420ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#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 "#30007" msgid "Response timeout in seconds" msgstr "Antwoord tydverstreke in sekondes" msgctxt "#30200" msgid "Debugging" msgstr "Ontfouting" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.am_et/000077500000000000000000000000001260020026400260205ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.am_et/strings.po000066400000000000000000000017721260020026400300600ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#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 "#30007" msgid "Response timeout in seconds" msgstr "መመለሻ ጊዜ በ ሰከንዶች" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ar_sa/000077500000000000000000000000001260020026400260205ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ar_sa/strings.po000066400000000000000000000020551260020026400300530ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "التصحيح" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.be_by/000077500000000000000000000000001260020026400260135ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.be_by/strings.po000066400000000000000000000023121260020026400300420ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30007" msgid "Response timeout in seconds" msgstr "Response timeout in seconds" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.bg_bg/000077500000000000000000000000001260020026400257735ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.bg_bg/strings.po000066400000000000000000000033341260020026400300270ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "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 in seconds" msgstr "Време на изчакване при свързване в секунди" msgctxt "#30007" msgid "Response timeout in seconds" 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 "Проследяване (подробно)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.bs_ba/000077500000000000000000000000001260020026400260015ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.bs_ba/strings.po000066400000000000000000000016471260020026400300420ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ca_es/000077500000000000000000000000001260020026400260055ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ca_es/strings.po000066400000000000000000000021771260020026400300450ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30001" msgid "Tvheadend hostname or IP address" msgstr "Nom de màquina o IP del 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 "#30007" msgid "Response timeout in seconds" msgstr "Temps d'espera de la resposta en segons" msgctxt "#30200" msgid "Debugging" msgstr "Depurant" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.cs_cz/000077500000000000000000000000001260020026400260345ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.cs_cz/strings.po000066400000000000000000000030761260020026400300730ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 počítače, 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 in seconds" msgstr "Limit pro ukončení spojení v sekundách" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Časový limit odpovědi v sekundách" msgctxt "#30100" msgid "Data Transfer" msgstr "Přenos dat" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Asynchronní přenos EPG" msgctxt "#30200" msgid "Debugging" msgstr "Ladění" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Trace (detailní)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.cy_gb/000077500000000000000000000000001260020026400260165ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.cy_gb/strings.po000066400000000000000000000022641260020026400300530ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30007" msgid "Response timeout in seconds" msgstr "Ymateb amser allan mewn eiliadau" msgctxt "#30200" msgid "Debugging" msgstr "Dadfygio" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.da_dk/000077500000000000000000000000001260020026400257755ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.da_dk/strings.po000066400000000000000000000022021260020026400300220ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#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 "#30007" msgid "Response timeout in seconds" msgstr "Tidsfrist for svar i sekunder" msgctxt "#30200" msgid "Debugging" msgstr "Foretag fejlretning" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.de_de/000077500000000000000000000000001260020026400257735ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.de_de/strings.po000066400000000000000000000035301260020026400300250ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "Verbindungseinstellungen" 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 in seconds" msgstr "Zeitüberschreitung für Verbindungsaufbau zu Tvheadend (in Sekunden)" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Zeitüberschreitung für Antworten von Tvheadend (in Sekunden)" msgctxt "#30100" msgid "Data Transfer" msgstr "Datentransfer" 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." kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.el_gr/000077500000000000000000000000001260020026400260235ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.el_gr/strings.po000066400000000000000000000033741260020026400300630ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Χρονικό όριο σύνδεσης σε δευτερόλεπτα" msgctxt "#30007" msgid "Response timeout in seconds" 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 "Ανίχνευση (αναλυτικά)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.en_au/000077500000000000000000000000001260020026400260225ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.en_au/strings.po000066400000000000000000000021571260020026400300600ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30007" msgid "Response timeout in seconds" msgstr "Response timeout in seconds" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.en_gb/000077500000000000000000000000001260020026400260055ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.en_gb/strings.po000066400000000000000000000030501260020026400300340ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "" #empty strings from id 30008 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 "" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.en_nz/000077500000000000000000000000001260020026400260445ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.en_nz/strings.po000066400000000000000000000027661260020026400301100ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Connection timeout in seconds" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Response timeout in seconds" 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)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.en_us/000077500000000000000000000000001260020026400260445ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.en_us/strings.po000066400000000000000000000032731260020026400301020ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Connection timeout in seconds" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Response timeout in seconds" 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." kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.eo/000077500000000000000000000000001260020026400253365ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.eo/strings.po000066400000000000000000000013731260020026400273730ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.es_ar/000077500000000000000000000000001260020026400260245ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.es_ar/strings.po000066400000000000000000000030561260020026400300610ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Spanish (Argentina) (http://www.transifex.com/projects/p/kodi-main/language/es_AR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es_AR\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "Connection Settings" msgstr "Ajuste 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 in seconds" msgstr "Tiempo de espera máxima de conexión en segundos" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Tiempo de espera de respuesta en segundos" msgctxt "#30100" msgid "Data Transfer" msgstr "Transferencia de datos" 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)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.es_es/000077500000000000000000000000001260020026400260315ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.es_es/strings.po000066400000000000000000000030431260020026400300620ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Tiempo de espera de conexión en segundos" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Tiempo de espera de respuesta en segundos" 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)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.es_mx/000077500000000000000000000000001260020026400260465ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.es_mx/strings.po000066400000000000000000000016621260020026400301040ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#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 "#30200" msgid "Debugging" msgstr "Debugging" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.et_ee/000077500000000000000000000000001260020026400260145ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.et_ee/strings.po000066400000000000000000000021661260020026400300520ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30007" msgid "Response timeout in seconds" msgstr "Vastuse aegumine sekundites" msgctxt "#30200" msgid "Debugging" msgstr "Silumine" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.eu_es/000077500000000000000000000000001260020026400260335ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.eu_es/strings.po000066400000000000000000000015011260020026400300610ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30004" msgid "Username" msgstr "Erabiltzailea" msgctxt "#30005" msgid "Password" msgstr "Pasahitza" msgctxt "#30200" msgid "Debugging" msgstr "Arazketa" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.fa_af/000077500000000000000000000000001260020026400257675ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.fa_af/strings.po000066400000000000000000000014311260020026400300170ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "کلمه عبور" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.fa_ir/000077500000000000000000000000001260020026400260135ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.fa_ir/strings.po000066400000000000000000000015101260020026400300410ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30004" msgid "Username" msgstr "نام کاربری" msgctxt "#30005" msgid "Password" msgstr "رمز عبور" msgctxt "#30200" msgid "Debugging" msgstr "دیباگ" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.fi_fi/000077500000000000000000000000001260020026400260075ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.fi_fi/strings.po000066400000000000000000000022071260020026400300410ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#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 "#30007" msgid "Response timeout in seconds" msgstr "Vastauksen aikakatkaisu sekunneissa" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.fo_fo/000077500000000000000000000000001260020026400260235ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.fo_fo/strings.po000066400000000000000000000014231260020026400300540ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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ð" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.fr_ca/000077500000000000000000000000001260020026400260055ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.fr_ca/strings.po000066400000000000000000000030611260020026400300360ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Délai d'attente de connexion en secondes" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Délai d'attente de réponse en secondes" 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)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.fr_fr/000077500000000000000000000000001260020026400260315ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.fr_fr/strings.po000066400000000000000000000033561260020026400300710ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 de Tvheadend" msgctxt "#30002" msgid "HTTP port" msgstr "Port HTTP" msgctxt "#30003" msgid "HTSP port" msgstr "Port HTSP" msgctxt "#30004" msgid "Username" msgstr "Utilisateur" msgctxt "#30005" msgid "Password" msgstr "Mot de passe" msgctxt "#30006" msgid "Connection timeout in seconds" msgstr "Timeout de connexion en secondes" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Temporisation de réponse en secondes" msgctxt "#30100" msgid "Data Transfer" msgstr "Transfert de données" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Transfert EPG asynchronisé" msgctxt "#30200" msgid "Debugging" msgstr "Débogage" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Trace (détaillé)" msgctxt "#30300" msgid "HTSP version mismatch (supported: v%d, required: v%d). Please update tvheadend." msgstr "Version HTSP différente (supportée : v%d, requise : v%d). Veuillez mettre à jour tvheadend." kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.gl_es/000077500000000000000000000000001260020026400260245ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.gl_es/strings.po000066400000000000000000000030561260020026400300610ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Tempo de espera da conexión en segundos" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Tempo de espera da resposta en segundos" 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)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.he_il/000077500000000000000000000000001260020026400260135ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.he_il/strings.po000066400000000000000000000032051260020026400300440ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "זמן מירבי לניסיון חיבור בשניות" msgctxt "#30007" msgid "Response timeout in seconds" 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 "מעקב תקשורת (מפורט)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.hi_in/000077500000000000000000000000001260020026400260215ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.hi_in/strings.po000066400000000000000000000014621260020026400300550ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "डिबगिंग" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.hr_hr/000077500000000000000000000000001260020026400260355ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.hr_hr/strings.po000066400000000000000000000031351260020026400300700ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Istek povezivanja u sekundama" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Vrijeme odaziva u sekundama" msgctxt "#30100" msgid "Data Transfer" msgstr "Prijenos podataka" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Neusklađen EPG prijenos" msgctxt "#30200" msgid "Debugging" msgstr "Otklanjanje grešaka" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Praćenje (opširnije)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.hu_hu/000077500000000000000000000000001260020026400260435ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.hu_hu/strings.po000066400000000000000000000030551260020026400300770ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Kapcsolódási időtullépés másodpercben" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Válasz időkorlát másodpercben" 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 "Nyomonkövetés (részletes)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.hy_am/000077500000000000000000000000001260020026400260305ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.hy_am/strings.po000066400000000000000000000013361260020026400300640ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "Գաղտնաբառ" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.id_id/000077500000000000000000000000001260020026400260035ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.id_id/strings.po000066400000000000000000000027511260020026400300410ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Indonesian (Indonesia) (http://www.transifex.com/projects/p/kodi-main/language/id_ID/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: id_ID\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "Connection Settings" msgstr "Pengaturan Koneksi" 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 in seconds" msgstr "Koneksi timeout dalam detik" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Timeout response dalam deti" msgctxt "#30100" msgid "Data Transfer" msgstr "Transfer Data" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "Transfer EPG Asinkron" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Jejak (rinci)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.is_is/000077500000000000000000000000001260020026400260415ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.is_is/strings.po000066400000000000000000000030411260020026400300700ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 tala 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 in seconds" msgstr "Tengitími rennur út eftir sekúndur" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Tímatakmörk svartíma í sekúndum" 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)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.it_it/000077500000000000000000000000001260020026400260435ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.it_it/strings.po000066400000000000000000000030241260020026400300730ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Timeout di connessione in secondi" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Timeout della risposta in secondi" 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)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ja_jp/000077500000000000000000000000001260020026400260165ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ja_jp/strings.po000066400000000000000000000022361260020026400300520ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#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 "#30007" msgid "Response timeout in seconds" msgstr "レスポンスのタイムアウト (秒)" msgctxt "#30200" msgid "Debugging" msgstr "デバッグ" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ko_kr/000077500000000000000000000000001260020026400260405ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ko_kr/strings.po000066400000000000000000000027571260020026400301040ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "연결 타임아웃 (초)" msgctxt "#30007" msgid "Response timeout in seconds" 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 "추적 (상세)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.lt_lt/000077500000000000000000000000001260020026400260515ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.lt_lt/strings.po000066400000000000000000000031421260020026400301020ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 host pavadinimas arba IP adresas" msgctxt "#30002" msgid "HTTP port" msgstr "HTTP portas" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP portas" msgctxt "#30004" msgid "Username" msgstr "Vartotojo vardas" msgctxt "#30005" msgid "Password" msgstr "Slaptažodis" msgctxt "#30006" msgid "Connection timeout in seconds" msgstr "Prisijungimo laukimo laikas sekundėmis" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Atsakymo laikas sek." 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)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.lv_lv/000077500000000000000000000000001260020026400260555ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.lv_lv/strings.po000066400000000000000000000031071260020026400301070ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "Savienojuma 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 in seconds" msgstr "Savienojuma noilgums pēc dažām sekundēm" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Atbildes noilgums sekundēs" msgctxt "#30100" msgid "Data Transfer" msgstr "Datu pārsūtīšana" 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)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.mi/000077500000000000000000000000001260020026400253405ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.mi/strings.po000066400000000000000000000014641260020026400273760ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.mk_mk/000077500000000000000000000000001260020026400260315ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.mk_mk/strings.po000066400000000000000000000033261260020026400300660ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Macedonian (Macedonia) (http://www.transifex.com/projects/p/kodi-main/language/mk_MK/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: mk_MK\n" "Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" msgctxt "#30000" msgid "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 in seconds" msgstr "Прекин на поврзувањето во секунди" msgctxt "#30007" msgid "Response timeout in seconds" 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 "Следи (детално)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.mn_mn/000077500000000000000000000000001260020026400260375ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.mn_mn/strings.po000066400000000000000000000033171260020026400300740ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#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 in seconds" msgstr "Холболтын хугацаа хэтрэлт, секундээр" msgctxt "#30007" msgid "Response timeout in seconds" 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 "Мөр (дэлгэрэнгүй)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ms_my/000077500000000000000000000000001260020026400260575ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ms_my/strings.po000066400000000000000000000030041260020026400301050ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Had masa tamat sambungan dalam saat" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Had masa tamat respons dalam saat" 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)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.mt_mt/000077500000000000000000000000001260020026400260535ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.mt_mt/strings.po000066400000000000000000000015161260020026400301070ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30004" msgid "Username" msgstr "Username" msgctxt "#30005" msgid "Password" msgstr "Sigriet" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.my_mm/000077500000000000000000000000001260020026400260515ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.my_mm/strings.po000066400000000000000000000014631260020026400301060ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "စကားဝှက်" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.nb_no/000077500000000000000000000000001260020026400260265ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.nb_no/strings.po000066400000000000000000000030201260020026400300520ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Tilkoblings-tidsavbrudd i sekunder" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Respons-tidsavbrudd i sekunder" 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)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.nl_nl/000077500000000000000000000000001260020026400260355ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.nl_nl/strings.po000066400000000000000000000030241260020026400300650ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 server naam 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 in seconds" msgstr "Verbindingswachttijd in seconden" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Antwoord timeout in seconden" msgctxt "#30100" msgid "Data Transfer" msgstr "Gegevensoverdracht" 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)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.pl_pl/000077500000000000000000000000001260020026400260415ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.pl_pl/strings.po000066400000000000000000000031241260020026400300720ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Limit czasu połączenia w sekundach" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Limit czasu odpowiedzi w sekundach" 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 "Rejestracja (szczegółowa)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.pt_br/000077500000000000000000000000001260020026400260415ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.pt_br/strings.po000066400000000000000000000033771260020026400301040ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Tempo limite para conexão em segundos" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Tempo limite para resposta em segundos" 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." kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.pt_pt/000077500000000000000000000000001260020026400260615ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.pt_pt/strings.po000066400000000000000000000031011260020026400301050ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "Configurações de conexão" msgctxt "#30001" msgid "Tvheadend hostname or IP address" msgstr "Nome do servidor Tvheadend 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 "Palavra-passe" msgctxt "#30006" msgid "Connection timeout in seconds" msgstr "Tempo limite de conexão em segundos" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Tempo limite para resposta em segundos" msgctxt "#30100" msgid "Data Transfer" msgstr "Transferência de dados" msgctxt "#30101" msgid "Asynchronous EPG transfer" msgstr "EPG transferência assíncrona" msgctxt "#30200" msgid "Debugging" msgstr "Depuração" msgctxt "#30201" msgid "Trace (detailed)" msgstr "Localizar (detalhada)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ro_ro/000077500000000000000000000000001260020026400260535ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ro_ro/strings.po000066400000000000000000000027231260020026400301100ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "Setări 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 "#30007" msgid "Response timeout in seconds" msgstr "Așteptare răspuns în secunde" 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ă)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ru_ru/000077500000000000000000000000001260020026400260675ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ru_ru/strings.po000066400000000000000000000033661260020026400301300ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Ожидание подключения (сек.)" msgctxt "#30007" msgid "Response timeout in seconds" 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 "Трассировка (подробнее)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.si_lk/000077500000000000000000000000001260020026400260345ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.si_lk/strings.po000066400000000000000000000020051260020026400300620ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "නිදොස්කරමින් " kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.sk_sk/000077500000000000000000000000001260020026400260455ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.sk_sk/strings.po000066400000000000000000000022611260020026400300770ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#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 "#30007" msgid "Response timeout in seconds" msgstr "Časový limit pre odpoveď v sekundách" msgctxt "#30200" msgid "Debugging" msgstr "Ladenie / Debug" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.sl_si/000077500000000000000000000000001260020026400260445ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.sl_si/strings.po000066400000000000000000000031141260020026400300740ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Časovni pretek povezave v sekundah" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Časovni pretek odgovora v sekundah" msgctxt "#30100" msgid "Data Transfer" msgstr "Prenos podatkov" 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)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.sq_al/000077500000000000000000000000001260020026400260325ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.sq_al/strings.po000066400000000000000000000021741260020026400300670ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30007" msgid "Response timeout in seconds" msgstr "Timeout i përgjigjjes në eskonda" msgctxt "#30200" msgid "Debugging" msgstr "Debugging" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.sr_rs/000077500000000000000000000000001260020026400260635ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.sr_rs/strings.po000066400000000000000000000024561260020026400301230ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#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 "#30007" msgid "Response timeout in seconds" msgstr "Чекање одговора у секундама" msgctxt "#30200" msgid "Debugging" msgstr "Тражење грешака" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.sr_rs@latin/000077500000000000000000000000001260020026400272135ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.sr_rs@latin/strings.po000066400000000000000000000016531260020026400312510ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30004" msgid "Username" msgstr "Korisničko ime" msgctxt "#30005" msgid "Password" msgstr "Lozinka" msgctxt "#30200" msgid "Debugging" msgstr "Traženje grešaka" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.sv_se/000077500000000000000000000000001260020026400260525ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.sv_se/strings.po000066400000000000000000000030041260020026400301000ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "Anslutningstimeout i sekunder" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Responstimeout i sekunder" 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 "Trace (detaljerad)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.szl/000077500000000000000000000000001260020026400255435ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.szl/strings.po000066400000000000000000000031251260020026400275750ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "Nasztalowania 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 in seconds" msgstr "Czas na skuplowaniy w sekundach" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Czas na ôdpowiydź w sekundach" msgctxt "#30100" msgid "Data Transfer" msgstr "Transfer datōw" 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)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ta_in/000077500000000000000000000000001260020026400260255ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.ta_in/strings.po000066400000000000000000000022421260020026400300560ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30200" msgid "Debugging" msgstr "வழுநீக்கு" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.te_in/000077500000000000000000000000001260020026400260315ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.te_in/strings.po000066400000000000000000000035301260020026400300630ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#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 in seconds" msgstr "సెకన్లలో కనెక్షన్ టైమ్అవుట్" msgctxt "#30007" msgid "Response timeout in seconds" 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 "ట్రేస్ (వివరణాత్మక)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.tg_tj/000077500000000000000000000000001260020026400260425ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.tg_tj/strings.po000066400000000000000000000023201260020026400300700ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30007" msgid "Response timeout in seconds" msgstr "Хотимаи вақти посух дар сонияҳо" msgctxt "#30200" msgid "Debugging" msgstr "Ислоҳи хатоҳо" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.th_th/000077500000000000000000000000001260020026400260415ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.th_th/strings.po000066400000000000000000000015721260020026400300770ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30200" msgid "Debugging" msgstr "แก้จุดบกพร่อง" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.tr_tr/000077500000000000000000000000001260020026400260655ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.tr_tr/strings.po000066400000000000000000000030601260020026400301150ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 portu" msgctxt "#30003" msgid "HTSP port" msgstr "HTSP portu" msgctxt "#30004" msgid "Username" msgstr "Kullanıcı adı" msgctxt "#30005" msgid "Password" msgstr "Parola" msgctxt "#30006" msgid "Connection timeout in seconds" msgstr "Saniye cinsinden bağlantı zamanaşımı" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Saniye cinsinden yanıt zaman aşımı süresi" msgctxt "#30100" msgid "Data Transfer" msgstr "Veri Aktarımı" 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ı)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.uk_ua/000077500000000000000000000000001260020026400260375ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.uk_ua/strings.po000066400000000000000000000024441260020026400300740ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30007" msgid "Response timeout in seconds" msgstr "Затримка відклику в секундах" msgctxt "#30200" msgid "Debugging" msgstr "Налагодження" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.uz_uz/000077500000000000000000000000001260020026400261075ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.uz_uz/strings.po000066400000000000000000000014171260020026400301430ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.vi_vn/000077500000000000000000000000001260020026400260545ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.vi_vn/strings.po000066400000000000000000000022241260020026400301050ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#30007" msgid "Response timeout in seconds" msgstr "Số giây tự ngắt chờ" msgctxt "#30200" msgid "Debugging" msgstr "Tìm sửa lỗi" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.zh_cn/000077500000000000000000000000001260020026400260345ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.zh_cn/strings.po000066400000000000000000000027271260020026400300750ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 in seconds" msgstr "连接超时(秒)" msgctxt "#30007" msgid "Response timeout in seconds" 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 "跟踪(细节)" kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.zh_tw/000077500000000000000000000000001260020026400260665ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/pvr.hts/resources/language/resource.language.zh_tw/strings.po000066400000000000000000000021321260020026400301150ustar00rootroot00000000000000# 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: http://trac.kodi.tv/\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 "#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 "#30007" msgid "Response timeout in seconds" msgstr "回應超時(秒)" msgctxt "#30200" msgid "Debugging" msgstr "除錯" kodi-pvr-hts-2.1.18/pvr.hts/resources/settings.xml000066400000000000000000000023061260020026400221230ustar00rootroot00000000000000 kodi-pvr-hts-2.1.18/src/000077500000000000000000000000001260020026400147115ustar00rootroot00000000000000kodi-pvr-hts-2.1.18/src/AsyncState.cpp000066400000000000000000000027601260020026400175000ustar00rootroot00000000000000/* * 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" #include "client.h" struct Param { eAsyncState state; AsyncState *self; }; using namespace PLATFORM; AsyncState::AsyncState(int timeout) { m_state = ASYNC_NONE; m_timeout = timeout; } 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); } kodi-pvr-hts-2.1.18/src/AsyncState.h000066400000000000000000000036301260020026400171420ustar00rootroot00000000000000/* * 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 * */ #ifndef ASYNCSTATE_H #define ASYNCSTATE_H #include "platform/threads/mutex.h" /** * 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 */ inline eAsyncState GetState() { PLATFORM::CLockObject lock(m_mutex); return m_state; } /** * 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; PLATFORM::CMutex m_mutex; PLATFORM::CCondition m_condition; int m_timeout; }; #endif /* ASYNCSTATE_H */ kodi-pvr-hts-2.1.18/src/HTSPConnection.cpp000066400000000000000000000333101260020026400202130ustar00rootroot00000000000000/* * 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 "platform/threads/mutex.h" #include "platform/threads/atomics.h" #include "platform/util/timeutils.h" #include "platform/sockets/tcp.h" extern "C" { #include "libhts/htsmsg_binary.h" #include "libhts/sha1.h" } #include "Tvheadend.h" #include "client.h" using namespace std; using namespace ADDON; using namespace PLATFORM; /* * HTSP Response objct */ CHTSPResponse::CHTSPResponse () : m_flag(false), m_msg(NULL) { } CHTSPResponse::~CHTSPResponse () { if (m_msg) htsmsg_destroy(m_msg); Set(NULL); // ensure signal is sent } void CHTSPResponse::Set ( htsmsg_t *msg ) { m_msg = msg; m_flag = true; m_cond.Broadcast(); } htsmsg_t *CHTSPResponse::Get ( 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; } /* * Registration thread */ CHTSPRegister::CHTSPRegister ( CHTSPConnection *conn ) : m_conn(conn) { } CHTSPRegister::~CHTSPRegister () { StopThread(0); } void *CHTSPRegister::Process ( void ) { m_conn->Register(); return NULL; } /* * HTSP Connection handler */ CHTSPConnection::CHTSPConnection () : m_socket(NULL), m_regThread(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) { } CHTSPConnection::~CHTSPConnection() { StopThread(-1); Disconnect(); StopThread(0); } /* * Info */ CStdString CHTSPConnection::GetWebURL ( const char *fmt, ... ) { va_list va; CStdString auth, url; tvheadend::Settings settings = tvh->GetSettings(); auth = settings.strUsername; if (auth != "" && settings.strPassword != "") auth += ":" + settings.strPassword; if (auth != "") auth += "@"; url.Format("http://%s%s:%d", auth.c_str(), settings.strHostname.c_str(), settings.iPortHTTP); CLockObject lock(m_mutex); va_start(va, fmt); url += m_webRoot; url.AppendFormatV(fmt, va); va_end(va); return url; } bool CHTSPConnection::WaitForConnection ( void ) { if (!m_ready) { tvhtrace("waiting for registration..."); m_regCond.Wait(m_mutex, m_ready, tvh->GetSettings().iConnectTimeout); } return m_ready; } const char *CHTSPConnection::GetServerName ( void ) { static CStdString str; CLockObject lock(m_mutex); str = m_serverName; return str.c_str(); } const char *CHTSPConnection::GetServerVersion ( void ) { static CStdString str; CLockObject lock(m_mutex); str.Format("%s (HTSPv%d)", m_serverVersion.c_str(), m_htspVersion); return str.c_str(); } const char *CHTSPConnection::GetServerString ( void ) { static CStdString str; tvheadend::Settings settings = tvh->GetSettings(); CLockObject lock(m_mutex); str.Format("%s:%d [%s]", settings.strHostname.c_str(), settings.iPortHTSP, m_ready ? "connected" : "disconnected"); return str.c_str(); } bool CHTSPConnection::HasCapability(const std::string &capability) const { return std::find(m_capabilities.begin(), m_capabilities.end(), capability) != m_capabilities.end(); } void CHTSPConnection::OnSleep ( void ) { CLockObject lock(m_mutex); tvhtrace("going to sleep (OnSleep)"); /* close connection, prevent reconnect while suspending/suspended */ m_suspended = true; } void CHTSPConnection::OnWake ( void ) { CLockObject lock(m_mutex); tvhtrace("waking up (OnWake)"); /* recreate connection */ m_suspended = false; } /* * Close the connection */ void CHTSPConnection::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 CHTSPConnection::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, tvh->GetSettings().iResponseTimeout); if (r < 0) { tvherror("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. */ tvherror("failed to decode message"); return false; } /* Sequence number - response */ if (htsmsg_get_u32(msg, "seq", &seq) == 0) { tvhtrace("received response [%d]", seq); CLockObject lock(m_mutex); CHTSPResponseList::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"))) { tvherror("message without a method"); htsmsg_destroy(msg); return true; } tvhtrace("receive message [%s]", method); /* Pass (if return is true, message is finished) */ if (tvh->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 CHTSPConnection::SendMessage0 ( const char *method, htsmsg_t *msg ) { int e; void *buf; size_t len; ssize_t c = -1; uint32_t seq; if (!htsmsg_get_u32(msg, "seq", &seq)) { tvhtrace("sending message [%s : %d]", method, seq); } else { tvhtrace("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) { tvherror("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 *CHTSPConnection::SendAndWait0 ( const char *method, htsmsg_t *msg, int iResponseTimeout ) { if (iResponseTimeout == -1) iResponseTimeout = tvh->GetSettings().iResponseTimeout; uint32_t seq; /* Add Sequence number */ CHTSPResponse 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); tvherror("failed to transmit"); return NULL; } /* Wait for response */ msg = resp.Get(m_mutex, iResponseTimeout); m_messages.erase(seq); if (!msg) { //XBMC->QueueNotification(QUEUE_ERROR, "Command %s failed: No response received", method); tvherror("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 //XBMC->QueueNotification(QUEUE_ERROR, "Command %s failed: Access denied", method); tvherror("Command %s failed: Access denied", method); htsmsg_destroy(msg); return NULL; } else { const char* strError; if((strError = htsmsg_get_str(msg, "error")) != NULL) { //XBMC->QueueNotification(QUEUE_ERROR, "Command %s failed: %s", method, strError); tvherror("Command %s failed: %s", method, strError); htsmsg_destroy(msg); return NULL; } } return msg; } /* * Send and wait for response */ htsmsg_t *CHTSPConnection::SendAndWait ( const char *method, htsmsg_t *msg, int iResponseTimeout ) { if (iResponseTimeout == -1) iResponseTimeout = tvh->GetSettings().iResponseTimeout; if (!WaitForConnection()) return NULL; return SendAndWait0(method, msg, iResponseTimeout); } bool CHTSPConnection::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 : ""; tvhdebug("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.push_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 CHTSPConnection::SendAuth ( const CStdString &user, const CStdString &pass ) { 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); return (msg != NULL); } /** * Register the connection, hello+auth */ void CHTSPConnection::Register ( void ) { CStdString user, pass; user = tvh->GetSettings().strUsername; pass = tvh->GetSettings().strPassword; { CLockObject lock(m_mutex); /* Send Greeting */ tvhdebug("sending hello"); if (!SendHello()) { tvherror("failed to send hello"); goto fail; } /* Check htsp server version against client minimum htsp version */ if (m_htspVersion < HTSP_MIN_SERVER_VERSION) { tvherror("server htsp version (v%d) does not match minimum htsp version required by client (v%d)", m_htspVersion, HTSP_MIN_SERVER_VERSION); Disconnect(); m_ready = false; m_regCond.Broadcast(); return; } /* Send Auth */ tvhdebug("sending auth"); if (!SendAuth(user, pass)) goto fail; /* Rebuild state */ tvhdebug("rebuilding state"); if (!tvh->Connected()) goto fail; tvhdebug("registered"); m_ready = true; m_regCond.Broadcast(); return; } fail: if (!m_suspended) Disconnect(); } /* * Main thread loop for connection and rx handling */ void* CHTSPConnection::Process ( void ) { static bool log = false; static unsigned int retryAttempt = 0; tvheadend::Settings settings = tvh->GetSettings(); while (!IsStopped()) { tvhdebug("new connection requested"); CStdString host = settings.strHostname; int port, timeout; port = settings.iPortHTSP; timeout = settings.iConnectTimeout; /* Create socket (ensure mutex protection) */ { CLockObject lock(m_mutex); if (m_socket) delete m_socket; tvh->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) { tvhdebug("suspended. Waiting for wakeup..."); /* Wait for wakeup */ Sleep(1000); } if (!log) { tvhdebug("connecting to %s:%d", host.c_str(), port); log = true; } else { tvhtrace("connecting to %s:%d", host.c_str(), port); } /* Connect */ tvhtrace("waiting for connection..."); if (!m_socket->Open(timeout)) { /* Unable to connect */ tvherror("unable to connect to %s:%d", host.c_str(), port); // 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; } tvhdebug("connected"); log = false; retryAttempt = 0; /* Start connect thread */ m_regThread.CreateThread(true); /* Receive loop */ while (!IsStopped()) { if (!ReadMessage()) { tvhdebug("attempting reconnect"); break; } } /* Stop connect thread (if not already) */ m_regThread.StopThread(0); } return NULL; } kodi-pvr-hts-2.1.18/src/HTSPDemuxer.cpp000066400000000000000000000441321260020026400175310ustar00rootroot00000000000000/* * 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 "Tvheadend.h" #include "client.h" #include "platform/threads/mutex.h" #include "platform/threads/atomics.h" #include "platform/util/timeutils.h" #include "platform/sockets/tcp.h" extern "C" { #include "libhts/htsmsg_binary.h" #include "libhts/sha1.h" } #include "xbmc_codec_descriptor.hpp" #define TVH_TO_DVD_TIME(x) ((double)x * DVD_TIME_BASE / 1000000.0) using namespace std; using namespace ADDON; using namespace PLATFORM; CHTSPDemuxer::CHTSPDemuxer ( CHTSPConnection &conn ) : m_conn(conn), m_pktBuffer((size_t)-1), m_seekTime(INVALID_SEEKTIME) { } CHTSPDemuxer::~CHTSPDemuxer ( void ) { } void CHTSPDemuxer::Connected ( void ) { /* Re-subscribe */ if (m_subscription.active) { tvhdebug("demux re-starting stream"); SendSubscribe(true); SendSpeed(true); } } /* ************************************************************************** * Demuxer API * *************************************************************************/ void CHTSPDemuxer::Close0 ( void ) { /* Send unsubscribe */ if (m_subscription.active) SendUnsubscribe(); /* Clear */ Flush(); Abort0(); } void CHTSPDemuxer::Abort0 ( void ) { CLockObject lock(m_mutex); m_streams.Clear(); m_streamStat.clear(); } bool CHTSPDemuxer::Open ( const PVR_CHANNEL &chn ) { CLockObject lock(m_conn.Mutex()); tvhdebug("demux open"); /* Close current stream */ Close0(); /* Create new subscription */ m_subscription = SSubscription(); m_subscription.channelId = chn.iUniqueId; /* Open */ SendSubscribe(); /* Send unsubscribe if subscribing failed */ if (!m_subscription.active) SendUnsubscribe(); return m_subscription.active; } void CHTSPDemuxer::Close ( void ) { CLockObject lock(m_conn.Mutex()); Close0(); tvhdebug("demux close"); } DemuxPacket *CHTSPDemuxer::Read ( void ) { DemuxPacket *pkt = NULL; if (m_pktBuffer.Pop(pkt, 1000)) { tvhtrace("demux read idx :%d pts %lf len %lld", pkt->iStreamId, pkt->pts, (long long)pkt->iSize); return pkt; } tvhtrace("demux read nothing"); return PVR->AllocateDemuxPacket(0); } void CHTSPDemuxer::Flush ( void ) { DemuxPacket *pkt; tvhtrace("demux flush"); while (m_pktBuffer.Pop(pkt)) PVR->FreeDemuxPacket(pkt); } void CHTSPDemuxer::Abort ( void ) { tvhtrace("demux abort"); CLockObject lock(m_conn.Mutex()); Abort0(); } bool CHTSPDemuxer::Seek ( int time, bool _unused(backwards), double *startpts ) { htsmsg_t *m; CLockObject lock(m_conn.Mutex()); if (!m_subscription.active) return false; tvhdebug("demux seek %d", time); /* Build message */ m = htsmsg_create_map(); htsmsg_add_u32(m, "subscriptionId", m_subscription.subscriptionId); htsmsg_add_s64(m, "time", (int64_t)time * 1000LL); htsmsg_add_u32(m, "absolute", 1); /* Send and Wait */ m = m_conn.SendAndWait("subscriptionSeek", m); if (!m) return false; htsmsg_destroy(m); /* Wait for time */ if (!m_seekCond.Wait(m_conn.Mutex(), m_seekTime, tvh->GetSettings().iResponseTimeout)) { tvherror("failed to get subscriptionSeek response"); return false; } if (m_seekTime == INVALID_SEEKTIME) return false; /* Store */ *startpts = TVH_TO_DVD_TIME(m_seekTime); tvhtrace("demux seek startpts = %lf", *startpts); return true; } void CHTSPDemuxer::Speed ( int speed ) { CLockObject lock(m_conn.Mutex()); if (!m_subscription.active) return; m_subscription.speed = speed; SendSpeed(); } PVR_ERROR CHTSPDemuxer::CurrentStreams ( PVR_STREAM_PROPERTIES *streams ) { CLockObject lock(m_mutex); return m_streams.GetProperties(streams) ? PVR_ERROR_NO_ERROR : PVR_ERROR_SERVER_ERROR; } PVR_ERROR CHTSPDemuxer::CurrentSignal ( PVR_SIGNAL_STATUS &sig ) { CLockObject lock(m_mutex); memset(&sig, 0, sizeof(sig)); 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; } /* ************************************************************************** * Send Messages * *************************************************************************/ void CHTSPDemuxer::SendSubscribe ( bool force ) { htsmsg_t *m; /* Reset status */ m_signalInfo.Clear(); m_sourceInfo.Clear(); /* Build message */ m = htsmsg_create_map(); htsmsg_add_s32(m, "channelId", m_subscription.channelId); htsmsg_add_u32(m, "subscriptionId", m_subscription.subscriptionId); htsmsg_add_u32(m, "timeshiftPeriod", (uint32_t)~0); htsmsg_add_u32(m, "normts", 1); htsmsg_add_u32(m, "queueDepth", 2000000); /* Send and Wait for response */ tvhdebug("demux subscribe to %d", m_subscription.channelId); if (force) m = m_conn.SendAndWait0("subscribe", m); else m = m_conn.SendAndWait("subscribe", m); if (m == NULL) return; htsmsg_destroy(m); m_subscription.active = true; tvhdebug("demux successfully subscribed to %d", m_subscription.channelId); } void CHTSPDemuxer::SendUnsubscribe ( void ) { htsmsg_t *m; /* Build message */ m = htsmsg_create_map(); htsmsg_add_u32(m, "subscriptionId", m_subscription.subscriptionId); /* Mark subscription as inactive immediately in case this command fails */ m_subscription.active = false; /* Send and Wait */ tvhdebug("demux unsubscribe from %d", m_subscription.channelId); if ((m = m_conn.SendAndWait("unsubscribe", m)) == NULL) return; htsmsg_destroy(m); tvhdebug("demux successfully unsubscribed %d", m_subscription.channelId); } void CHTSPDemuxer::SendSpeed ( bool force ) { htsmsg_t *m; int speed = m_subscription.speed / 10; // XBMC uses values an order of magnitude larger than tvheadend /* Build message */ m = htsmsg_create_map(); htsmsg_add_u32(m, "subscriptionId", m_subscription.subscriptionId); htsmsg_add_s32(m, "speed", speed); tvhdebug("demux send speed %d", speed); /* Send and Wait */ if (force) m = m_conn.SendAndWait0("subscriptionSpeed", m); else m = m_conn.SendAndWait("subscriptionSpeed", m); if (m) htsmsg_destroy(m); } /* ************************************************************************** * Parse incoming data * *************************************************************************/ bool CHTSPDemuxer::ProcessMessage ( const char *method, htsmsg_t *m ) { uint32_t subId; CLockObject lock(m_mutex); /* No subscriptionId - not for demuxer */ if (htsmsg_get_u32(m, "subscriptionId", &subId)) return false; /* Not current subscription - ignore */ else if (subId != m_subscription.subscriptionId) return true; /* Subscription messages */ else if (!strcmp("muxpkt", method)) ParseMuxPacket(m); else if (!strcmp("subscriptionStatus", method)) 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("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 tvhdebug("demux unhandled subscription message [%s]", method); return true; } void CHTSPDemuxer::ParseMuxPacket ( htsmsg_t *m ) { uint32_t idx, u32; int64_t s64; const void *bin; size_t binlen; DemuxPacket *pkt; char _unused(type) = 0; int iStreamId; /* Ignore packets while switching channels */ if (!m_subscription.active) { tvhdebug("Ignored mux packet due to channel switch"); return; } /* Validate fields */ if (htsmsg_get_u32(m, "stream", &idx) || htsmsg_get_bin(m, "payload", &bin, &binlen)) { tvherror("malformed muxpkt: 'stream'/'payload' missing"); return; } /* Record */ m_streamStat[idx]++; /* Drop packets for unknown streams */ if (-1 == (iStreamId = m_streams.GetStreamId(idx))) { tvhdebug("Dropped packet with unknown stream index %i", idx); return; } /* Allocate buffer */ if (!(pkt = PVR->AllocateDemuxPacket(binlen))) return; memcpy(pkt->pData, bin, binlen); pkt->iSize = binlen; pkt->iStreamId = iStreamId; /* 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 = '_'; tvhtrace("demux pkt idx %d:%d type %c pts %lf len %lld", idx, pkt->iStreamId, type, pkt->pts, (long long)binlen); /* Store */ m_pktBuffer.Push(pkt); } void CHTSPDemuxer::ParseSubscriptionStart ( htsmsg_t *m ) { vector streams; htsmsg_t *l; htsmsg_field_t *f; DemuxPacket *pkt; /* Validate */ if ((l = htsmsg_get_list(m, "streams")) == NULL) { tvherror("malformed subscriptionStart: 'streams' missing"); return; } m_streamStat.clear(); /* Process each */ HTSMSG_FOREACH(f, l) { uint32_t idx, u32; const char *type; XbmcPvrStream stream; if (f->hmf_type != HMF_MAP) continue; if ((type = htsmsg_get_str(&f->hmf_msg, "type")) == NULL) continue; if (htsmsg_get_u32(&f->hmf_msg, "index", &idx)) continue; /* Find stream */ m_streamStat[idx] = 0; m_streams.GetStreamData(idx, &stream); tvhdebug("demux subscription start"); CodecDescriptor codecDescriptor = CodecDescriptor::GetCodecByName(type); xbmc_codec_t codec = codecDescriptor.Codec(); if (codec.codec_type != XBMC_CODEC_TYPE_UNKNOWN) { stream.iCodecType = codec.codec_type; stream.iCodecId = codec.codec_id; stream.iPhysicalId = 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.iIdentifier = (composition_id & 0xffff) | ((ancillary_id & 0xffff) << 16); } /* Language */ if (stream.iCodecType == XBMC_CODEC_TYPE_SUBTITLE || stream.iCodecType == XBMC_CODEC_TYPE_AUDIO) { 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); } /* 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) { tvhinfo("Ignoring subscriptionStart, stream details missing"); return; } /* Setting aspect ratio to zero will cause XBMC to handle changes in it */ stream.fAspect = 0.0f; if ((u32 = htsmsg_get_u32_or_default(&f->hmf_msg, "duration", 0)) > 0) { stream.iFPSScale = u32; stream.iFPSRate = DVD_TIME_BASE; } } streams.push_back(stream); tvhdebug(" id: %d, type %s, codec: %u", idx, type, stream.iCodecId); } } /* Update streams */ tvhdebug("demux stream change"); m_streams.UpdateStreams(streams); pkt = PVR->AllocateDemuxPacket(0); pkt->iStreamId = DMX_SPECIALID_STREAMCHANGE; m_pktBuffer.Push(pkt); /* Source data */ ParseSourceInfo(htsmsg_get_map(m, "sourceinfo")); } void CHTSPDemuxer::ParseSourceInfo ( htsmsg_t *m ) { const char *str; /* Ignore */ if (!m) return; tvhtrace("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) { tvhtrace(" satpos : %s", str); m_sourceInfo.si_mux.append(str); m_sourceInfo.si_mux.append(": "); } if ((str = htsmsg_get_str(m, "mux")) != NULL) { tvhtrace(" mux : %s", str); m_sourceInfo.si_mux.append(str); } if ((str = htsmsg_get_str(m, "adapter")) != NULL) { tvhtrace(" adapter : %s", str); m_sourceInfo.si_adapter = str; } if ((str = htsmsg_get_str(m, "network")) != NULL) { tvhtrace(" network : %s", str); m_sourceInfo.si_network = str; } if ((str = htsmsg_get_str(m, "provider")) != NULL) { tvhtrace(" provider : %s", str); m_sourceInfo.si_provider = str; } if ((str = htsmsg_get_str(m, "service")) != NULL) { tvhtrace(" service : %s", str); m_sourceInfo.si_service = str; } } void CHTSPDemuxer::ParseSubscriptionStop ( htsmsg_t *_unused(m) ) { } void CHTSPDemuxer::ParseSubscriptionSkip ( htsmsg_t *m ) { CLockObject lock(m_conn.Mutex()); int64_t s64; if (htsmsg_get_s64(m, "time", &s64)) { m_seekTime = INVALID_SEEKTIME; } else { m_seekTime = s64; } m_seekCond.Broadcast(); } void CHTSPDemuxer::ParseSubscriptionSpeed ( htsmsg_t *m ) { uint32_t u32; if (!htsmsg_get_u32(m, "speed", &u32)) tvhtrace("recv speed %d", u32); } void CHTSPDemuxer::ParseSubscriptionStatus ( htsmsg_t *m ) { const char *status; status = htsmsg_get_str(m, "status"); // this field is absent when everything is fine if (status != NULL) { tvhinfo("Bad subscription status: %s", status); XBMC->QueueNotification(QUEUE_INFO, status); } } void CHTSPDemuxer::ParseQueueStatus ( htsmsg_t *_unused(m) ) { uint32_t u32; map::const_iterator it; tvhtrace("stream stats:"); for (it = m_streamStat.begin(); it != m_streamStat.end(); ++it) tvhtrace(" idx:%d num:%d", it->first, it->second); tvhtrace("queue stats:"); if (!htsmsg_get_u32(m, "packets", &u32)) tvhtrace(" pkts %d", u32); if (!htsmsg_get_u32(m, "bytes", &u32)) tvhtrace(" bytes %d", u32); if (!htsmsg_get_u32(m, "delay", &u32)) tvhtrace(" delay %d", u32); if (!htsmsg_get_u32(m, "Idrops", &u32)) tvhtrace(" Idrop %d", u32); if (!htsmsg_get_u32(m, "Pdrops", &u32)) tvhtrace(" Pdrop %d", u32); if (!htsmsg_get_u32(m, "Bdrops", &u32)) tvhtrace(" Bdrop %d", u32); } void CHTSPDemuxer::ParseSignalStatus ( htsmsg_t *m ) { uint32_t u32; const char *str; /* Reset */ m_signalInfo.Clear(); /* Parse */ tvhtrace("signalStatus:"); if ((str = htsmsg_get_str(m, "feStatus")) != NULL) { tvhtrace(" status : %s", str); m_signalInfo.fe_status = str; } else { tvherror("malformed signalStatus: 'feStatus' missing, ignoring"); } if (!htsmsg_get_u32(m, "feSNR", &u32)) { tvhtrace(" snr : %d", u32); m_signalInfo.fe_snr = u32; } if (!htsmsg_get_u32(m, "feBER", &u32)) { tvhtrace(" ber : %d", u32); m_signalInfo.fe_ber = u32; } if (!htsmsg_get_u32(m, "feUNC", &u32)) { tvhtrace(" unc : %d", u32); m_signalInfo.fe_unc = u32; } if (!htsmsg_get_u32(m, "feSignal", &u32)) { tvhtrace(" signal : %d", u32); m_signalInfo.fe_signal = u32; } } void CHTSPDemuxer::ParseTimeshiftStatus ( htsmsg_t *m ) { uint32_t u32; int64_t s64; /* Parse */ tvhtrace("timeshiftStatus:"); if (!htsmsg_get_u32(m, "full", &u32)) { tvhtrace(" full : %d", m_timeshiftStatus.full); m_timeshiftStatus.full = (bool)u32; } else { tvherror("malformed timeshiftStatus: 'full' missing, ignoring"); } if (!htsmsg_get_s64(m, "shift", &s64)) { tvhtrace(" shift : %lld", m_timeshiftStatus.shift); m_timeshiftStatus.shift = s64; } else { tvherror("malformed timeshiftStatus: 'shift' missing, ignoring"); } if (!htsmsg_get_s64(m, "start", &s64)) { tvhtrace(" start : %lld", m_timeshiftStatus.start); m_timeshiftStatus.start = s64; } if (!htsmsg_get_s64(m, "end", &s64)) { tvhtrace(" end : %lld", m_timeshiftStatus.end); m_timeshiftStatus.end = s64; } } kodi-pvr-hts-2.1.18/src/HTSPTypes.cpp000066400000000000000000000044041260020026400172220ustar00rootroot00000000000000/* * Copyright (C) 2005-2015 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 "HTSPTypes.h" namespace htsp { Tag::Tag(uint32_t id /*= 0*/) : m_dirty(false), m_id (id), 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); } bool Tag::IsDirty() const { return m_dirty; } void Tag::SetDirty(bool bDirty) { m_dirty = bDirty; } uint32_t Tag::GetId() const { return m_id; } 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(bool bRadio) const { std::vector::const_iterator it; SChannels::const_iterator cit; const SChannels& channels = tvh->GetChannels(); for (it = m_channels.begin(); it != m_channels.end(); ++it) { if ((cit = channels.find(*it)) != channels.end()) { if (bRadio == cit->second.radio) return true; } } return false; } } // namespace htsp kodi-pvr-hts-2.1.18/src/HTSPTypes.h000066400000000000000000000153361260020026400166750ustar00rootroot00000000000000#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 "platform/util/StdString.h" #include "client.h" typedef enum { DVR_PRIO_IMPORTANT, DVR_PRIO_HIGH, DVR_PRIO_NORMAL, DVR_PRIO_LOW, DVR_PRIO_UNIMPORTANT } 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; 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, }; namespace htsp { class Tag { public: Tag(uint32_t id = 0); bool operator==(const Tag &right); bool operator!=(const Tag &right); bool IsDirty() const; void SetDirty(bool bDirty); uint32_t GetId() const; 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(bool bRadio) const; private: bool m_dirty; uint32_t m_id; uint32_t m_index; std::string m_name; std::string m_icon; std::vector m_channels; }; typedef std::map Tags; } // namespace htsp struct SChannel { bool del; uint32_t id; uint32_t num; uint32_t numMinor; bool radio; uint32_t caid; std::string name; std::string icon; SChannel() : del (false), id (0), num (0), numMinor(0), radio (false), caid (0) { } bool operator<(const SChannel &right) const { return num < right.num; } }; struct SRecording { bool del; uint32_t id; uint32_t channel; uint32_t eventId; int64_t start; int64_t stop; int64_t startExtra; int64_t stopExtra; std::string title; std::string path; std::string description; std::string timerecId; std::string autorecId; PVR_TIMER_STATE state; std::string error; uint32_t retention; uint32_t priority; SRecording() : del (false), id (0), channel (0), eventId (0), start (0), stop (0), startExtra(0), stopExtra (0), state (PVR_TIMER_STATE_ERROR), retention (99), // Kodi default - "99 days" priority (50) // Kodi default - "normal" { } bool IsRecording () const { return state == PVR_TIMER_STATE_COMPLETED || state == PVR_TIMER_STATE_ABORTED || state == PVR_TIMER_STATE_RECORDING; } bool IsTimer () const { return state == PVR_TIMER_STATE_SCHEDULED || state == PVR_TIMER_STATE_RECORDING; } }; struct SEvent { bool del; uint32_t id; uint32_t next; uint32_t channel; uint32_t content; time_t start; time_t stop; uint32_t stars; /* 1 - 5 */ uint32_t age; /* years */ time_t aired; uint32_t season; uint32_t episode; uint32_t part; std::string title; std::string subtitle; /* episode name */ std::string desc; std::string summary; std::string image; uint32_t recordingId; SEvent() : del (false), id (0), next (0), channel (0), content (0), start (0), stop (0), stars (0), age (0), aired (0), season (0), episode (0), part (0), recordingId(0) { } }; typedef std::map SChannels; typedef std::map SEvents; typedef std::map SRecordings; struct SSchedule { bool del; uint32_t channel; SEvents events; SSchedule() : del (false), channel(0) { } }; typedef std::map SSchedules; struct SQueueStatus { uint32_t packets; // Number of data packets in queue. uint32_t bytes; // Number of bytes in queue. uint32_t delay; // Estimated delay of queue (in µs) uint32_t bdrops; // Number of B-frames dropped uint32_t pdrops; // Number of P-frames dropped uint32_t idrops; // Number of I-frames dropped SQueueStatus() : packets(0), bytes (0), delay (0), bdrops (0), pdrops (0), idrops (0) { } }; struct STimeshiftStatus { bool full; int64_t shift; int64_t start; int64_t end; STimeshiftStatus() : full (0), shift(0), start(0), end (0) { } }; struct SQuality { std::string fe_status; uint32_t fe_snr; uint32_t fe_signal; uint32_t fe_ber; uint32_t fe_unc; SQuality() : fe_snr (0), fe_signal(0), fe_ber (0), fe_unc (0) { } void Clear () { fe_status.clear(); fe_snr = 0; fe_signal = 0; fe_ber = 0; fe_unc = 0; } }; struct SSourceInfo { std::string si_adapter; std::string si_network; std::string si_mux; std::string si_provider; std::string si_service; void Clear () { si_adapter.clear(); si_network.clear(); si_mux.clear(); si_provider.clear(); si_service.clear(); } }; struct SHTSPEvent { eHTSPEventType m_type; uint32_t m_idx; SHTSPEvent (eHTSPEventType type = HTSP_EVENT_NONE, uint32_t idx = 0) : m_type(type), m_idx (idx) { } bool operator==(const SHTSPEvent &right) const { return m_type == right.m_type && m_idx == right.m_idx; } bool operator!=(const SHTSPEvent &right) const { return !(*this == right); } }; typedef std::vector SHTSPEventList; struct SSubscription { uint32_t subscriptionId; uint32_t channelId; int speed; bool active; SSubscription() : channelId(0), speed (1000), active(false) { static int previousId = 0; subscriptionId = ++previousId; } }; kodi-pvr-hts-2.1.18/src/HTSPVFS.cpp000066400000000000000000000135121260020026400165540ustar00rootroot00000000000000/* * 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 "platform/threads/mutex.h" extern "C" { #include "libhts/htsmsg_binary.h" } #include "Tvheadend.h" using namespace std; using namespace PLATFORM; /* * VFS handler */ CHTSPVFS::CHTSPVFS ( CHTSPConnection &conn ) : m_conn(conn), m_path(""), m_fileId(0), m_offset(0) { } CHTSPVFS::~CHTSPVFS ( void ) { } void CHTSPVFS::Connected ( void ) { /* Re-open */ if (m_fileId != 0) { tvhdebug("vfs re-open file"); if (!SendFileOpen(true) || !SendFileSeek(m_offset, SEEK_SET, true)) { tvherror("vfs failed to re-open file"); Close(); } } } /* ************************************************************************** * VFS API * *************************************************************************/ bool CHTSPVFS::Open ( const PVR_RECORDING &rec ) { /* Close existing */ Close(); /* Cache details */ m_path.Format("dvr/%s", rec.strRecordingId); /* Send open */ if (!SendFileOpen()) { tvherror("vfs failed to open file"); return false; } /* Done */ return true; } void CHTSPVFS::Close ( void ) { if (m_fileId != 0) SendFileClose(); m_offset = 0; m_fileId = 0; m_path = ""; } ssize_t CHTSPVFS::Read ( unsigned char *buf, unsigned int len ) { /* Not opened */ if (!m_fileId) return -1; /* Read */ int read = SendFileRead(buf, len); /* Update */ if (read > 0) m_offset += read; return read; } long long CHTSPVFS::Seek ( long long pos, int whence ) { if (m_fileId == 0) return -1; return SendFileSeek(pos, whence); } long long CHTSPVFS::Tell ( void ) { if (m_fileId == 0) return -1; return m_offset; } long long CHTSPVFS::Size ( void ) { int64_t ret = -1; htsmsg_t *m; /* Build */ m = htsmsg_create_map(); htsmsg_add_u32(m, "id", m_fileId); tvhtrace("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 tvhtrace("vfs stat size=%lld", (long long)ret); htsmsg_destroy(m); return ret; } /* ************************************************************************** * HTSP Messages * *************************************************************************/ bool CHTSPVFS::SendFileOpen ( bool force ) { htsmsg_t *m; /* Build Message */ m = htsmsg_create_map(); htsmsg_add_str(m, "file", m_path.c_str()); tvhdebug("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)) { tvherror("malformed fileOpen response: 'id' missing"); m_fileId = 0; } else tvhtrace("vfs opened id=%d", m_fileId); htsmsg_destroy(m); return m_fileId > 0; } void CHTSPVFS::SendFileClose ( void ) { htsmsg_t *m; /* Build */ m = htsmsg_create_map(); htsmsg_add_u32(m, "id", m_fileId); tvhdebug("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 CHTSPVFS::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"); tvhtrace("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) { tvherror("vfs fileSeek failed"); return -1; } /* Get new offset */ if (htsmsg_get_s64(m, "offset", &ret)) { ret = -1; tvherror("vfs fileSeek response: 'offset' missing'"); /* Update */ } else { tvhtrace("vfs seek offset=%lld", (long long)ret); m_offset = ret; } /* Cleanup */ htsmsg_destroy(m); return ret; } ssize_t CHTSPVFS::SendFileRead(unsigned char *buf, unsigned int len) { htsmsg_t *m; const void *buffer; ssize_t read; /* Build */ m = htsmsg_create_map(); htsmsg_add_u32(m, "id", m_fileId); htsmsg_add_s64(m, "size", len); tvhtrace("vfs read id=%d size=%d", m_fileId, len); /* Send */ { CLockObject lock(m_conn.Mutex()); m = m_conn.SendAndWait("fileRead", m); } if (m == NULL) { tvherror("vfs fileRead failed"); return -1; } /* Get Data */ if (htsmsg_get_bin(m, "data", &buffer, reinterpret_cast(&read))) { tvherror("malformed fileRead response: 'data' missing"); read = -1; /* Store */ } else { memcpy(buf, buffer, read); } /* Cleanup */ htsmsg_destroy(m); return read; } kodi-pvr-hts-2.1.18/src/Settings.h000066400000000000000000000022021260020026400166560ustar00rootroot00000000000000#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 namespace tvheadend { struct Settings { std::string strHostname; int iPortHTSP; int iPortHTTP; std::string strUsername; std::string strPassword; int iConnectTimeout; int iResponseTimeout; bool bTraceDebug; bool bAsyncEpg; }; }kodi-pvr-hts-2.1.18/src/Tvheadend.cpp000066400000000000000000001252431260020026400173260ustar00rootroot00000000000000/* * 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 "Tvheadend.h" #include "platform/util/util.h" #include "platform/threads/atomics.h" extern "C" { #include "libhts/htsmsg_binary.h" } #define UPDATE(x, y)\ if ((x) != (y))\ {\ (x) = (y);\ update = true;\ } using namespace std; using namespace ADDON; using namespace PLATFORM; CTvheadend::CTvheadend(tvheadend::Settings settings) : m_settings(settings), m_dmx(m_conn), m_vfs(m_conn), m_queue((size_t)-1), m_asyncState(settings.iResponseTimeout) { } CTvheadend::~CTvheadend() { m_conn.StopThread(-1); m_conn.Disconnect(); StopThread(); } void CTvheadend::Start ( void ) { CreateThread(); m_conn.CreateThread(); } /* ************************************************************************** * 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); tvherror("malformed getDiskSpace response: 'totaldiskspace'/'freediskspace' missing"); return PVR_ERROR_SERVER_ERROR; } CStdString 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); } } /* ************************************************************************** * 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); htsp::Tags::const_iterator it; for (it = m_tags.begin(); it != m_tags.end(); ++it) { /* 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 (!it->second.ContainsChannelType(bRadio)) continue; PVR_CHANNEL_GROUP tag; memset(&tag, 0, sizeof(tag)); strncpy(tag.strGroupName, it->second.GetName().c_str(), sizeof(tag.strGroupName) - 1); tag.bIsRadio = bRadio; tag.iPosition = it->second.GetIndex(); tags.push_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); vector::const_iterator it; SChannels::const_iterator cit; htsp::Tags::const_iterator tit = m_tags.begin(); while (tit != m_tags.end()) { if (tit->second.GetName() == group.strGroupName) { for (it = tit->second.GetChannels().begin(); it != tit->second.GetChannels().end(); ++it) { if ((cit = m_channels.find(*it)) != m_channels.end()) { if (group.bIsRadio != cit->second.radio) continue; PVR_CHANNEL_GROUP_MEMBER gm; memset(&gm, 0, sizeof(PVR_CHANNEL_GROUP_MEMBER)); strncpy( gm.strGroupName, group.strGroupName, sizeof(gm.strGroupName) - 1); gm.iChannelUniqueId = cit->second.id; gm.iChannelNumber = cit->second.num; gms.push_back(gm); } } break; } ++tit; } } 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); SChannels::const_iterator it; for (it = m_channels.begin(); it != m_channels.end(); ++it) { if (radio != it->second.radio) continue; PVR_CHANNEL chn; memset(&chn, 0 , sizeof(PVR_CHANNEL)); chn.iUniqueId = it->second.id; chn.bIsRadio = it->second.radio; chn.iChannelNumber = it->second.num; chn.iSubChannelNumber = it->second.numMinor; chn.iEncryptionSystem = it->second.caid; chn.bIsHidden = false; strncpy(chn.strChannelName, it->second.name.c_str(), sizeof(chn.strChannelName) - 1); strncpy(chn.strIconPath, it->second.icon.c_str(), sizeof(chn.strIconPath) - 1); channels.push_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, m_settings.iResponseTimeout))) == NULL) return PVR_ERROR_SERVER_ERROR; /* Check for error */ if (htsmsg_get_u32(m, "success", &u32)) { tvherror("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)) { tvherror("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; int ret = 0; SRecordings::const_iterator rit; CLockObject lock(m_mutex); for (rit = m_recordings.begin(); rit != m_recordings.end(); ++rit) if (rit->second.IsRecording()) ret++; return ret; } PVR_ERROR CTvheadend::GetRecordings ( ADDON_HANDLE handle ) { if (!m_asyncState.WaitForState(ASYNC_EPG)) return PVR_ERROR_FAILED; std::vector recs; { CLockObject lock(m_mutex); SRecordings::const_iterator rit; SChannels::const_iterator cit; char buf[128]; for (rit = m_recordings.begin(); rit != m_recordings.end(); ++rit) { if (!rit->second.IsRecording()) continue; /* Setup entry */ PVR_RECORDING rec; memset(&rec, 0, sizeof(rec)); /* Channel name and icon */ if ((cit = m_channels.find(rit->second.channel)) != m_channels.end()) { strncpy(rec.strChannelName, cit->second.name.c_str(), sizeof(rec.strChannelName) - 1); strncpy(rec.strIconPath, cit->second.icon.c_str(), sizeof(rec.strIconPath) - 1); } /* URL ( HTSP < v7 ) */ // TODO: do I care! /* ID */ snprintf(buf, sizeof(buf), "%i", rit->second.id); strncpy(rec.strRecordingId, buf, sizeof(rec.strRecordingId) - 1); /* Title */ strncpy(rec.strTitle, rit->second.title.c_str(), sizeof(rec.strTitle) - 1); /* Description */ strncpy(rec.strPlot, rit->second.description.c_str(), sizeof(rec.strPlot) - 1); /* Time/Duration */ rec.recordingTime = (time_t)rit->second.start; rec.iDuration = (time_t)(rit->second.stop - rit->second.start); /* Priority */ rec.iPriority = rit->second.priority; /* Retention */ rec.iLifetime = rit->second.retention; /* Directory */ if (rit->second.path != "") { size_t idx = rit->second.path.rfind("/"); if (idx == 0 || idx == string::npos) strncpy(rec.strDirectory, "/", sizeof(rec.strDirectory) - 1); else { CStdString d = rit->second.path.substr(0, idx); if (d[0] != '/') d = "/" + d; strncpy(rec.strDirectory, d.c_str(), sizeof(rec.strDirectory) - 1); } } /* EPG event id */ rec.iEpgEventId = rit->second.eventId; recs.push_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 ) { /* Not supported */ if (m_conn.GetProtocol() < 12) return PVR_ERROR_NOT_IMPLEMENTED; 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)); tvhdebug("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)) { tvherror("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++; tvhdebug("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 ) { /* 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); } int CTvheadend::GetTimerCount ( void ) { if (!m_asyncState.WaitForState(ASYNC_EPG)) return 0; int ret = 0; SRecordings::const_iterator rit; CLockObject lock(m_mutex); for (rit = m_recordings.begin(); rit != m_recordings.end(); ++rit) if (rit->second.IsTimer()) ret++; return ret; } PVR_ERROR CTvheadend::GetTimers ( ADDON_HANDLE handle ) { if (!m_asyncState.WaitForState(ASYNC_EPG)) return PVR_ERROR_FAILED; std::vector timers; { CLockObject lock(m_mutex); SRecordings::const_iterator rit; for (rit = m_recordings.begin(); rit != m_recordings.end(); ++rit) { if (!rit->second.IsTimer()) continue; /* Setup entry */ PVR_TIMER tmr; memset(&tmr, 0, sizeof(tmr)); tmr.iClientIndex = rit->second.id; tmr.iClientChannelUid = rit->second.channel; tmr.startTime = (time_t)rit->second.start; tmr.endTime = (time_t)rit->second.stop; strncpy(tmr.strTitle, rit->second.title.c_str(), sizeof(tmr.strTitle) - 1); strncpy(tmr.strSummary, rit->second.description.c_str(), sizeof(tmr.strSummary) - 1); tmr.state = rit->second.state; tmr.iPriority = rit->second.priority; tmr.iLifetime = rit->second.retention; tmr.bIsRepeating = false; // unused tmr.firstDay = 0; // unused tmr.iWeekdays = 0; // unused tmr.iEpgUid = 0; // unused tmr.iMarginStart = rit->second.startExtra; tmr.iMarginEnd = rit->second.stopExtra; tmr.iGenreType = 0; // unused tmr.iGenreSubType = 0; // unused timers.push_back(tmr); } } 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 ) { uint32_t u32; dvr_prio_t prio; if (timer.bIsRepeating && timer.iWeekdays) { if (m_conn.GetProtocol() >= 18) return AddTimeRecording(timer); else return PVR_ERROR_NOT_IMPLEMENTED; } /* Build message */ htsmsg_t *m = htsmsg_create_map(); if (timer.iEpgUid > 0) { htsmsg_add_u32(m, "eventId", timer.iEpgUid); } else { htsmsg_add_str(m, "title", timer.strTitle); htsmsg_add_s64(m, "start", timer.startTime); htsmsg_add_s64(m, "stop", timer.endTime); htsmsg_add_u32(m, "channelId", timer.iClientChannelUid); 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() > 12) htsmsg_add_u32(m, "retention", timer.iLifetime); /* Priority */ if (timer.iPriority > 80) prio = DVR_PRIO_IMPORTANT; else if (timer.iPriority > 60) prio = DVR_PRIO_HIGH; else if (timer.iPriority > 40) prio = DVR_PRIO_NORMAL; else if (timer.iPriority > 20) prio = DVR_PRIO_LOW; else prio = DVR_PRIO_UNIMPORTANT; htsmsg_add_u32(m, "priority", (int)prio); /* 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)) { tvherror("malformed addDvrEntry response: 'success' missing"); u32 = PVR_ERROR_FAILED; } htsmsg_destroy(m); return u32 > 0 ? PVR_ERROR_NO_ERROR : PVR_ERROR_FAILED; } PVR_ERROR CTvheadend::DeleteTimer ( const PVR_TIMER &timer, bool _unused(force) ) { return SendDvrDelete(timer.iClientIndex, "cancelDvrEntry"); } PVR_ERROR CTvheadend::UpdateTimer ( const PVR_TIMER &timer ) { /* Build message */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "id", timer.iClientIndex); htsmsg_add_str(m, "title", timer.strTitle); htsmsg_add_s64(m, "start", timer.startTime); 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() > 12) { dvr_prio_t prio; htsmsg_add_u32(m, "retention", timer.iLifetime); /* Priority */ if (timer.iPriority > 80) prio = DVR_PRIO_IMPORTANT; else if (timer.iPriority > 60) prio = DVR_PRIO_HIGH; else if (timer.iPriority > 40) prio = DVR_PRIO_NORMAL; else if (timer.iPriority > 20) prio = DVR_PRIO_LOW; else prio = DVR_PRIO_UNIMPORTANT; htsmsg_add_u32(m, "priority", (int)prio); } return SendDvrUpdate(m); } PVR_ERROR CTvheadend::AddTimeRecording ( const PVR_TIMER &timer ) { uint32_t u32; dvr_prio_t prio; /* Build message */ htsmsg_t *m = htsmsg_create_map(); htsmsg_add_u32(m, "daysOfWeek", timer.iWeekdays); htsmsg_add_str(m, "title", timer.strTitle); htsmsg_add_str(m, "name", timer.strTitle); htsmsg_add_u32(m, "channelId", timer.iClientChannelUid); htsmsg_add_str(m, "description", timer.strSummary); htsmsg_add_str(m, "comment", "Created by Kodi Media Center"); /* Convert start and stop time to time after midnight */ struct tm *tmi; tmi = localtime(&timer.startTime); htsmsg_add_u32(m, "start", (tmi->tm_hour*60 + tmi->tm_min)); tmi = localtime(&timer.endTime); htsmsg_add_u32(m, "stop", (tmi->tm_hour*60 + tmi->tm_min)); /* Retention */ if (m_conn.GetProtocol() > 12) htsmsg_add_u32(m, "retention", timer.iLifetime); /* Priority */ if (timer.iPriority > 80) prio = DVR_PRIO_IMPORTANT; else if (timer.iPriority > 60) prio = DVR_PRIO_HIGH; else if (timer.iPriority > 40) prio = DVR_PRIO_NORMAL; else if (timer.iPriority > 20) prio = DVR_PRIO_LOW; else prio = DVR_PRIO_UNIMPORTANT; htsmsg_add_u32(m, "priority", (int)prio); /* Send and Wait */ CLockObject lock(m_conn.Mutex()); m = m_conn.SendAndWait("addTimerecEntry", m); if (m == NULL) return PVR_ERROR_SERVER_ERROR; /* Check for error */ if (htsmsg_get_u32(m, "success", &u32)) { tvherror("malformed addTimerecEntry response: 'success' missing"); u32 = PVR_ERROR_FAILED; } htsmsg_destroy(m); return u32 > 0 ? PVR_ERROR_NO_ERROR : PVR_ERROR_FAILED; } /* ************************************************************************** * EPG * *************************************************************************/ /* Transfer schedule to XBMC */ void CTvheadend::TransferEvent ( ADDON_HANDLE handle, const SEvent &event ) { /* Build */ EPG_TAG epg; memset(&epg, 0, sizeof(EPG_TAG)); epg.iUniqueBroadcastId = event.id; epg.strTitle = event.title.c_str(); epg.iChannelNumber = event.channel; epg.startTime = event.start; epg.endTime = event.stop; epg.strPlotOutline = event.summary.c_str(); epg.strPlot = event.desc.c_str(); epg.strOriginalTitle = NULL; /* not supported by tvh */ epg.strCast = NULL; /* not supported by tvh */ epg.strDirector = NULL; /* not supported by tvh */ epg.strWriter = NULL; /* not supported by tvh */ epg.iYear = 0; /* not supported by tvh */ epg.strIMDBNumber = NULL; /* not supported by tvh */ epg.strIconPath = event.image.c_str(); epg.iGenreType = event.content & 0xF0; epg.iGenreSubType = event.content & 0x0F; epg.strGenreDescription = NULL; /* not supported by tvh */ epg.firstAired = event.aired; epg.iParentalRating = event.age; epg.iStarRating = event.stars; epg.bNotify = false; /* not supported by tvh */ epg.iSeriesNumber = event.season; epg.iEpisodeNumber = event.episode; epg.iEpisodePartNumber = event.part; epg.strEpisodeName = event.subtitle.c_str(); /* Callback. */ PVR->TransferEpgEntry(handle, &epg); } PVR_ERROR CTvheadend::GetEpg ( ADDON_HANDLE handle, const PVR_CHANNEL &chn, time_t start, time_t end ) { SSchedules::const_iterator sit; SEvents::const_iterator eit; htsmsg_field_t *f; int n = 0; tvhtrace("get epg channel %d start %ld stop %ld", chn.iUniqueId, (long long)start, (long long)end); /* Async transfer */ if (m_settings.bAsyncEpg) { if (!m_asyncState.WaitForState(ASYNC_DONE)) return PVR_ERROR_FAILED; std::vector events; { CLockObject lock(m_mutex); sit = m_schedules.find(chn.iUniqueId); if (sit != m_schedules.end()) { for (eit = sit->second.events.begin(); eit != sit->second.events.end(); ++eit) { if (eit->second.start > end) continue; if (eit->second.stop < start) continue; events.push_back(eit->second); ++n; } } } std::vector::const_iterator it; for (it = events.begin(); it != events.end(); ++it) { /* Callback. */ TransferEvent(handle, *it); } /* Synchronous transfer */ } else { /* 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); tvherror("malformed getEvents response: 'events' missing"); return PVR_ERROR_SERVER_ERROR; } HTSMSG_FOREACH(f, l) { SEvent event; if (f->hmf_type == HMF_MAP) { if (ParseEvent(&f->hmf_msg, true, event)) { /* Callback. */ TransferEvent(handle, event); ++n; } } } htsmsg_destroy(msg); } tvhtrace("get epg channel %d events %d", chn.iUniqueId, n); return PVR_ERROR_NO_ERROR; } /* ************************************************************************** * Connection * *************************************************************************/ void CTvheadend::Disconnected ( void ) { m_asyncState.SetState(ASYNC_NONE); } bool CTvheadend::Connected ( void ) { htsmsg_t *msg; htsp::Tags::iterator tit; SChannels::iterator cit; SRecordings::iterator rit; SSchedules::iterator sit; SEvents::iterator eit; /* Rebuild state */ m_dmx.Connected(); m_vfs.Connected(); /* Flag all async fields in case they've been deleted */ for (cit = m_channels.begin(); cit != m_channels.end(); ++cit) cit->second.del = true; for (tit = m_tags.begin(); tit != m_tags.end(); ++tit) tit->second.SetDirty(true); for (rit = m_recordings.begin(); rit != m_recordings.end(); ++rit) rit->second.del = true; for (sit = m_schedules.begin(); sit != m_schedules.end(); ++sit) { sit->second.del = true; for (eit = sit->second.events.begin(); eit != sit->second.events.end(); ++eit) eit->second.del = true; } /* Request Async data */ m_asyncState.SetState(ASYNC_NONE); msg = htsmsg_create_map(); htsmsg_add_u32(msg, "epg", m_settings.bAsyncEpg); //htsmsg_add_u32(msg, "epgMaxTime", 0); //htsmsg_add_s64(msg, "lastUpdate", 0); if ((msg = m_conn.SendAndWait0("enableAsyncMetadata", msg)) == NULL) return false; htsmsg_destroy(msg); tvhdebug("async updates requested"); return true; } /* ************************************************************************** * Message handling * *************************************************************************/ bool CTvheadend::ProcessMessage ( const char *method, htsmsg_t *msg ) { /* Demuxer */ if (m_dmx.ProcessMessage(method, msg)) return true; /* Store */ m_queue.Push(CHTSPMessage(method, msg)); return false; } void* CTvheadend::Process ( void ) { CHTSPMessage msg; const char *method; while (!IsStopped()) { /* Check Q */ // this is a bit horrible, but meh if (!m_queue.Pop(msg, 2000)) continue; if (!msg.m_msg) continue; method = msg.m_method.c_str(); /* Scope lock for processing */ { CLockObject lock(m_mutex); /* Channels */ if (!strcmp("channelAdd", method)) ParseChannelAddOrUpdate(msg.m_msg, true); else if (!strcmp("channelUpdate", method)) ParseChannelAddOrUpdate(msg.m_msg, false); else if (!strcmp("channelDelete", method)) ParseChannelDelete(msg.m_msg); /* Channel Tags (aka channel groups)*/ else if (!strcmp("tagAdd", method)) ParseTagAddOrUpdate(msg.m_msg, true); else if (!strcmp("tagUpdate", method)) ParseTagAddOrUpdate(msg.m_msg, false); else if (!strcmp("tagDelete", method)) ParseTagDelete(msg.m_msg); /* Recordings */ else if (!strcmp("dvrEntryAdd", method)) ParseRecordingAddOrUpdate(msg.m_msg, true); else if (!strcmp("dvrEntryUpdate", method)) ParseRecordingAddOrUpdate(msg.m_msg, false); else if (!strcmp("dvrEntryDelete", method)) ParseRecordingDelete(msg.m_msg); /* EPG */ else if (!strcmp("eventAdd", method)) ParseEventAddOrUpdate(msg.m_msg, true); else if (!strcmp("eventUpdate", method)) ParseEventAddOrUpdate(msg.m_msg, false); else if (!strcmp("eventDelete", method)) ParseEventDelete(msg.m_msg); /* ASync complete */ else if (!strcmp("initialSyncCompleted", method)) SyncCompleted(); /* Unknown */ else tvhdebug("unhandled message [%s]", method); } /* Manual delete rather than waiting */ htsmsg_destroy(msg.m_msg); msg.m_msg = NULL; /* Process events * Note: due to potential deadly embrace this must be done without the * m_mutex held! */ SHTSPEventList::const_iterator it; for (it = m_events.begin(); it != m_events.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: PVR->TriggerEpgUpdate(it->m_idx); break; case HTSP_EVENT_NONE: break; } } m_events.clear(); } /* Local */ return NULL; } void CTvheadend::SyncCompleted ( void ) { /* The complete calls are probably redundant, but its a safety feature */ SyncChannelsCompleted(); SyncDvrCompleted(); SyncEpgCompleted(); m_asyncState.SetState(ASYNC_DONE); } void CTvheadend::SyncChannelsCompleted ( void ) { /* Already done */ if (m_asyncState.GetState() > ASYNC_CHN) return; bool update; SChannels::iterator cit = m_channels.begin(); htsp::Tags::iterator tit = m_tags.begin(); /* Tags */ update = false; while (tit != m_tags.end()) { if (tit->second.IsDirty()) { update = true; m_tags.erase(tit++); } else ++tit; } TriggerChannelGroupsUpdate(); if (update) tvhinfo("tags updated"); /* Channels */ update = false; while (cit != m_channels.end()) { if (cit->second.del) { update = true; m_channels.erase(cit++); } else ++cit; } TriggerChannelUpdate(); if (update) tvhinfo("channels updated"); /* Next */ m_asyncState.SetState(ASYNC_DVR); } void CTvheadend::SyncDvrCompleted ( void ) { /* Done */ if (m_asyncState.GetState() > ASYNC_DVR) return; bool update; SRecordings::iterator rit = m_recordings.begin(); /* Recordings */ update = false; while (rit != m_recordings.end()) { if (rit->second.del) { update = true; m_recordings.erase(rit++); } else ++rit; } TriggerRecordingUpdate(); TriggerTimerUpdate(); if (update) tvhinfo("recordings updated"); /* Next */ m_asyncState.SetState(ASYNC_EPG); } void CTvheadend::SyncEpgCompleted ( void ) { /* Done */ if (!m_settings.bAsyncEpg || m_asyncState.GetState() > ASYNC_EPG) return; bool update; SSchedules::iterator sit = m_schedules.begin(); SEvents::iterator eit; /* Events */ update = false; while (sit != m_schedules.end()) { uint32_t channelId = sit->second.channel; if (sit->second.del) { update = true; m_schedules.erase(sit++); } else { eit = sit->second.events.begin(); while (eit != sit->second.events.end()) { if (eit->second.del) { update = true; sit->second.events.erase(eit++); } else ++eit; } ++sit; } TriggerEpgUpdate(channelId); } if (update) tvhinfo("epg updated"); } 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)) { tvherror("malformed tagAdd/tagUpdate: 'tagId' missing"); return; } /* Locate object */ htsp::Tag &existingTag = m_tags[u32]; existingTag.SetDirty(false); /* Create new object */ htsp::Tag tag(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) { tvherror("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().push_back((int)f->hmf_s64); } } /* Update */ if (existingTag != tag) { existingTag = tag; tvhdebug("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)) { tvherror("malformed tagDelete: 'tagId' missing"); return; } tvhdebug("delete tag %u", u32); /* Erase */ m_tags.erase(u32); TriggerChannelGroupsUpdate(); } void CTvheadend::ParseChannelAddOrUpdate ( htsmsg_t *msg, bool bAdd ) { bool update = false; uint32_t u32; const char *str; htsmsg_t *list; /* Validate */ if (htsmsg_get_u32(msg, "channelId", &u32)) { tvherror("malformed channelAdd/channelUpdate: 'channelId' missing"); return; } /* Locate channel object */ SChannel &channel = m_channels[u32]; channel.id = u32; channel.del = false; /* Channel name */ if ((str = htsmsg_get_str(msg, "channelName")) != NULL) { UPDATE(channel.name, str); } else if (bAdd) { tvherror("malformed channelAdd: 'channelName' missing"); return; } /* Channel number */ if (!htsmsg_get_u32(msg, "channelNumber", &u32)) { if (!u32) u32 = GetNextUnnumberedChannelNumber(); UPDATE(channel.num, u32); } else if (bAdd) { tvherror("malformed channelAdd: 'channelNumber' missing"); return; } else if (!channel.num) { UPDATE(channel.num, GetNextUnnumberedChannelNumber()); } /* ATSC subchannel number */ if (!htsmsg_get_u32(msg, "channelNumberMinor", &u32)) { UPDATE(channel.numMinor, u32); } /* Channel icon */ if ((str = htsmsg_get_str(msg, "channelIcon")) != NULL) { CStdString url = GetImageURL(str); UPDATE(channel.icon, url); } /* Services */ if ((list = htsmsg_get_list(msg, "services")) != NULL) { htsmsg_field_t *f; uint32_t caid = 0; bool radio = false; HTSMSG_FOREACH(f, list) { if (f->hmf_type != HMF_MAP) continue; /* Radio? */ if ((str = htsmsg_get_str(&f->hmf_msg, "type")) != NULL) { if (!strcmp(str, "Radio")) radio = true; } /* CAID */ if (caid == 0) htsmsg_get_u32(&f->hmf_msg, "caid", &caid); } UPDATE(channel.radio, radio); UPDATE(channel.caid, caid); } /* Update Kodi */ if (update) { tvhdebug("channel update id:%u, name:%s", channel.id, channel.name.c_str()); if (m_asyncState.GetState() > ASYNC_CHN) TriggerChannelUpdate(); } } void CTvheadend::ParseChannelDelete ( htsmsg_t *msg ) { uint32_t u32; /* Validate */ if (htsmsg_get_u32(msg, "channelId", &u32)) { tvherror("malformed channelDelete: 'channelId' missing"); return; } tvhdebug("delete channel %u", u32); /* Erase */ m_channels.erase(u32); TriggerChannelUpdate(); } void CTvheadend::ParseRecordingAddOrUpdate ( htsmsg_t *msg, bool bAdd ) { bool update = false; const char *state, *str; uint32_t id, channel, eventId, retention, priority; int64_t start, stop, startExtra, stopExtra; /* Channels must be complete */ SyncChannelsCompleted(); /* Validate */ if (htsmsg_get_u32(msg, "id", &id)) { tvherror("malformed dvrEntryAdd/dvrEntryUpdate: 'id' missing"); return; } if (htsmsg_get_s64(msg, "start", &start) && bAdd) { tvherror("malformed dvrEntryAdd: 'start' missing"); return; } if (htsmsg_get_s64(msg, "stop", &stop) && bAdd) { tvherror("malformed dvrEntryAdd: 'stop' missing"); return; } if (((state = htsmsg_get_str(msg, "state")) == NULL) && bAdd) { tvherror("malformed dvrEntryAdd: 'state' missing"); return; } /* Get entry */ SRecording &rec = m_recordings[id]; rec.id = id; rec.del = false; UPDATE(rec.start, start); UPDATE(rec.stop, stop); /* Channel is optional, it may not exist anymore */ if (!htsmsg_get_u32(msg, "channel", &channel)) { UPDATE(rec.channel, channel); } if (!htsmsg_get_s64(msg, "startExtra", &startExtra)) { UPDATE(rec.startExtra, startExtra); } else if (bAdd && (m_conn.GetProtocol() > 12)) { tvherror("malformed dvrEntryAdd: 'startExtra' missing"); return; } if (!htsmsg_get_s64(msg, "stopExtra", &stopExtra)) { UPDATE(rec.stopExtra, stopExtra); } else if (bAdd && (m_conn.GetProtocol() > 12)) { tvherror("malformed dvrEntryAdd: 'stopExtra' missing"); return; } if (!htsmsg_get_u32(msg, "retention", &retention)) { UPDATE(rec.retention, retention); } else if (bAdd && (m_conn.GetProtocol() > 12)) { tvherror("malformed dvrEntryAdd: 'retention' missing"); return; } if (!htsmsg_get_u32(msg, "priority", &priority)) { switch (priority) { case DVR_PRIO_IMPORTANT: UPDATE(rec.priority, 100); break; case DVR_PRIO_HIGH: UPDATE(rec.priority, 75); break; case DVR_PRIO_NORMAL: UPDATE(rec.priority, 50); break; case DVR_PRIO_LOW: UPDATE(rec.priority, 25); break; case DVR_PRIO_UNIMPORTANT: UPDATE(rec.priority, 0); break; default: tvherror("malformed dvrEntryAdd/dvrEntryUpdate: unknown priority value"); return; } } else if (bAdd && (m_conn.GetProtocol() > 12)) { tvherror("malformed dvrEntryAdd: 'priority' missing"); return; } if (state != NULL) { /* Parse state */ if (strstr(state, "scheduled") != NULL) { UPDATE(rec.state, PVR_TIMER_STATE_SCHEDULED); } else if (strstr(state, "recording") != NULL) { UPDATE(rec.state, PVR_TIMER_STATE_RECORDING); } else if (strstr(state, "completed") != NULL) { UPDATE(rec.state, PVR_TIMER_STATE_COMPLETED); } else if (strstr(state, "missed") != NULL) { UPDATE(rec.state, PVR_TIMER_STATE_ERROR); } else if (strstr(state, "invalid") != NULL) { UPDATE(rec.state, PVR_TIMER_STATE_ERROR); } } /* Add optional fields */ if (!htsmsg_get_u32(msg, "eventId", &eventId)) { UPDATE(rec.eventId, eventId); } if ((str = htsmsg_get_str(msg, "title")) != NULL) { UPDATE(rec.title, str); } if ((str = htsmsg_get_str(msg, "path")) != NULL) { UPDATE(rec.path, str); } if ((str = htsmsg_get_str(msg, "description")) != NULL) { UPDATE(rec.description, str); } else if ((str = htsmsg_get_str(msg, "summary")) != NULL) { UPDATE(rec.description, str); } if ((str = htsmsg_get_str(msg, "autorecId")) != NULL) { UPDATE(rec.autorecId, str); } if ((str = htsmsg_get_str(msg, "timerecId")) != NULL) { UPDATE(rec.timerecId, str); } /* Error */ if ((str = htsmsg_get_str(msg, "error")) != NULL) { if (!strcmp(str, "300")) { UPDATE(rec.state, PVR_TIMER_STATE_ABORTED); } else if (strstr(str, "missing") != NULL) { UPDATE(rec.state, PVR_TIMER_STATE_ERROR); } else { UPDATE(rec.error, str); } } /* Update */ if (update) { std::string error = rec.error.empty() ? "none" : rec.error; tvhdebug("recording id:%d, state:%s, title:%s, desc:%s, error:%s", rec.id, state, rec.title.c_str(), rec.description.c_str(), error.c_str()); if (m_asyncState.GetState() > ASYNC_DVR) { TriggerTimerUpdate(); if (rec.state == PVR_TIMER_STATE_RECORDING) TriggerRecordingUpdate(); } } } void CTvheadend::ParseRecordingDelete ( htsmsg_t *msg ) { uint32_t u32; /* Validate */ if (htsmsg_get_u32(msg, "id", &u32)) { tvherror("malformed dvrEntryDelete: 'id' missing"); return; } tvhdebug("delete recording %u", u32); /* Erase */ m_recordings.erase(u32); /* Update */ TriggerTimerUpdate(); TriggerRecordingUpdate(); } bool CTvheadend::ParseEvent ( htsmsg_t *msg, bool bAdd, SEvent &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)) { tvherror("malformed eventAdd/eventUpdate: 'eventId' missing"); return false; } if (htsmsg_get_u32(msg, "channelId", &channel) && bAdd) { tvherror("malformed eventAdd: 'channelId' missing"); return false; } if (htsmsg_get_s64(msg, "start", &start) && bAdd) { tvherror("malformed eventAdd: 'start' missing"); return false; } if (htsmsg_get_s64(msg, "stop", &stop) && bAdd) { tvherror("malformed eventAdd: 'stop' missing"); return false; } evt.id = id; evt.channel = channel; evt.start = (time_t)start; evt.stop = (time_t)stop; /* Add optional fields */ if ((str = htsmsg_get_str(msg, "title")) != NULL) evt.title = str; if ((str = htsmsg_get_str(msg, "subtitle")) != NULL) evt.subtitle = str; if ((str = htsmsg_get_str(msg, "summary")) != NULL) evt.summary = str; if ((str = htsmsg_get_str(msg, "description")) != NULL) evt.desc = str; if ((str = htsmsg_get_str(msg, "image")) != NULL) evt.image = str; if (!htsmsg_get_u32(msg, "nextEventId", &u32)) evt.next = u32; if (!htsmsg_get_u32(msg, "contentType", &u32)) evt.content = u32; if (!htsmsg_get_u32(msg, "starRating", &u32)) evt.stars = u32; if (!htsmsg_get_u32(msg, "ageRating", &u32)) evt.age = u32; if (!htsmsg_get_s64(msg, "firstAired", &s64)) evt.aired = (time_t)s64; if (!htsmsg_get_u32(msg, "seasonNumber", &u32)) evt.season = u32; if (!htsmsg_get_u32(msg, "episodeNumber", &u32)) evt.episode = u32; if (!htsmsg_get_u32(msg, "partNumber", &u32)) evt.part = u32; /* Add optional recording link */ for (SRecordings::const_iterator it = m_recordings.begin(); it != m_recordings.end(); ++it) { if (it->second.eventId == evt.id) { evt.recordingId = evt.id; break; } } return true; } void CTvheadend::ParseEventAddOrUpdate ( htsmsg_t *msg, bool bAdd ) { bool update = false; SEvent tmp; /* Parse */ if (!ParseEvent(msg, bAdd, tmp)) return; /* Get event handle */ SSchedule &sched = m_schedules[tmp.channel]; SEvent &evt = sched.events[tmp.id]; sched.channel = tmp.channel; evt.id = tmp.id; evt.del = false; /* Store */ UPDATE(evt.title, tmp.title); UPDATE(evt.subtitle, tmp.subtitle); UPDATE(evt.start, tmp.start); UPDATE(evt.stop, tmp.stop); UPDATE(evt.channel, tmp.channel); UPDATE(evt.summary, tmp.summary); UPDATE(evt.desc, tmp.desc); UPDATE(evt.image, tmp.image); UPDATE(evt.next, tmp.next); UPDATE(evt.content, tmp.content); UPDATE(evt.stars, tmp.stars); UPDATE(evt.age, tmp.age); UPDATE(evt.aired, tmp.aired); UPDATE(evt.season, tmp.season); UPDATE(evt.episode, tmp.episode); UPDATE(evt.part, tmp.part); UPDATE(evt.recordingId, tmp.recordingId); /* Update */ if (update) { tvhtrace("event id:%d channel:%d start:%d stop:%d title:%s desc:%s", evt.id, evt.channel, (int)evt.start, (int)evt.stop, evt.title.c_str(), evt.desc.c_str()); if (m_asyncState.GetState() > ASYNC_EPG) TriggerEpgUpdate(tmp.channel); } } void CTvheadend::ParseEventDelete ( htsmsg_t *msg ) { uint32_t u32; /* Validate */ if (htsmsg_get_u32(msg, "eventId", &u32)) { tvherror("malformed eventDelete: 'eventId' missing"); return; } tvhtrace("delete event %u", u32); /* Erase */ SSchedules::iterator sit; for (sit = m_schedules.begin(); sit != m_schedules.end(); ++sit) { // Find the event so we can get the channel number SEvents::iterator eit = sit->second.events.find(u32); if (eit != sit->second.events.end()) { tvhtrace("deleted event %d from channel %d", u32, sit->second.channel); sit->second.events.erase(eit); TriggerEpgUpdate(sit->second.channel); return; } } } uint32_t CTvheadend::GetNextUnnumberedChannelNumber() { static uint32_t number = UNNUMBERED_CHANNEL; return number++; } kodi-pvr-hts-2.1.18/src/Tvheadend.h000066400000000000000000000372001260020026400167660ustar00rootroot00000000000000#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 "client.h" #include "platform/sockets/tcp.h" #include "platform/threads/threads.h" #include "platform/threads/mutex.h" #include "platform/util/buffer.h" #include "kodi/xbmc_codec_types.h" #include "kodi/xbmc_stream_utils.hpp" #include "kodi/libXBMC_addon.h" #include "Settings.h" #include "HTSPTypes.h" #include "AsyncState.h" #include #include #include #include extern "C" { #include #include "libhts/htsmsg.h" } /* * Miscellaneous */ #if defined(__GNUC__) #define _unused(x) x __attribute__((unused)) #else #define _unused(x) x #endif /* * Configuration defines */ #define HTSP_MIN_SERVER_VERSION (10) // Server must support at least this htsp version (10 == tvheadend 3.4) #define HTSP_CLIENT_VERSION (18) // 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). #define FAST_RECONNECT_ATTEMPTS (5) #define FAST_RECONNECT_INTERVAL (500) // ms #define UNNUMBERED_CHANNEL (10000) #define INVALID_SEEKTIME (-1) /* * Log wrappers */ #define tvhdebug(...) tvhlog(ADDON::LOG_DEBUG, ##__VA_ARGS__) #define tvhinfo(...) tvhlog(ADDON::LOG_INFO, ##__VA_ARGS__) #define tvherror(...) tvhlog(ADDON::LOG_ERROR, ##__VA_ARGS__) #define tvhtrace(...) if (tvh->GetSettings().bTraceDebug) tvhlog(ADDON::LOG_DEBUG, ##__VA_ARGS__) static inline void tvhlog ( ADDON::addon_log_t lvl, const char *fmt, ... ) { char buf[16384]; size_t c = sprintf(buf, "pvr.hts - "); va_list va; va_start(va, fmt); vsnprintf(buf + c, sizeof(buf) - c, fmt, va); va_end(va); XBMC->Log(lvl, "%s", buf); } /* * Forward decleration of classes */ class CHTSPConnection; class CHTSPDemuxer; class CHTSPVFS; class CHTSPResponse; class CHTSPMessage; /* Typedefs */ typedef std::map CHTSPResponseList; typedef PLATFORM::SyncedBuffer CHTSPMessageQueue; /* * HTSP Response handler */ class CHTSPResponse { public: CHTSPResponse(void); ~CHTSPResponse(); htsmsg_t *Get ( PLATFORM::CMutex &mutex, uint32_t timeout ); void Set ( htsmsg_t *m ); private: PLATFORM::CCondition m_cond; bool m_flag; htsmsg_t *m_msg; }; /* * HTSP Message */ class CHTSPMessage { public: CHTSPMessage(std::string method = "", htsmsg_t *msg = NULL) : m_method(method), m_msg(msg) { } CHTSPMessage(const CHTSPMessage& msg) : m_method(msg.m_method), m_msg(msg.m_msg) { msg.m_msg = NULL; } ~CHTSPMessage() { if (m_msg) htsmsg_destroy(m_msg); } CHTSPMessage& operator=(const CHTSPMessage &msg) { if (this != &msg) { if (m_msg) htsmsg_destroy(m_msg); m_method = msg.m_method; m_msg = msg.m_msg; msg.m_msg = NULL; // ownership is passed } return *this; } std::string m_method; mutable htsmsg_t *m_msg; }; /* * HTSP Connection registration thread */ class CHTSPRegister : public PLATFORM::CThread { friend class CHTSPConnection; public: CHTSPRegister ( CHTSPConnection *conn ); ~CHTSPRegister ( void ); private: CHTSPConnection *m_conn; void *Process ( void ); }; /* * HTSP Connection */ class CHTSPConnection : public PLATFORM::CThread { friend class CHTSPRegister; public: CHTSPConnection(); ~CHTSPConnection(); void Disconnect ( void ); 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 ); inline int GetProtocol ( void ) const { return m_htspVersion; } CStdString GetWebURL ( const char *fmt, ... ); const char *GetServerName ( void ); const char *GetServerVersion ( void ); const char *GetServerString ( void ); bool HasCapability(const std::string &capability) const; inline bool IsConnected ( void ) const { return m_ready; } bool WaitForConnection ( void ); inline PLATFORM::CMutex& Mutex ( void ) { return m_mutex; } void OnSleep ( void ); void OnWake ( void ); private: void* Process ( void ); void Register ( void ); bool ReadMessage ( void ); bool SendHello ( void ); bool SendAuth ( const CStdString &u, const CStdString &p ); PLATFORM::CTcpSocket *m_socket; PLATFORM::CMutex m_mutex; CHTSPRegister m_regThread; PLATFORM::CCondition m_regCond; bool m_ready; uint32_t m_seq; CStdString m_serverName; CStdString m_serverVersion; int m_htspVersion; CStdString m_webRoot; void* m_challenge; int m_challengeLen; CHTSPResponseList m_messages; std::vector m_capabilities; bool m_suspended; }; /* * HTSP Demuxer - live streams */ class CHTSPDemuxer { friend class CTvheadend; public: CHTSPDemuxer( CHTSPConnection &conn ); ~CHTSPDemuxer(); bool ProcessMessage ( const char *method, htsmsg_t *m ); void Connected ( void ); inline time_t GetTimeshiftTime() const { return (time_t)m_timeshiftStatus.shift; } private: PLATFORM::CMutex m_mutex; CHTSPConnection &m_conn; PLATFORM::SyncedBuffer m_pktBuffer; ADDON::XbmcStreamProperties m_streams; std::map m_streamStat; int64_t m_seekTime; PLATFORM::CCondition m_seekCond; SSourceInfo m_sourceInfo; SQuality m_signalInfo; STimeshiftStatus m_timeshiftStatus; SSubscription m_subscription; void Close0 ( void ); void Abort0 ( void ); bool Open ( const PVR_CHANNEL &chn ); void Close ( void ); DemuxPacket *Read ( void ); void Flush ( void ); void Abort ( void ); bool Seek ( int time, bool backwards, double *startpts ); void Speed ( int speed ); int CurrentId ( void ); PVR_ERROR CurrentStreams ( PVR_STREAM_PROPERTIES *streams ); PVR_ERROR CurrentSignal ( PVR_SIGNAL_STATUS &sig ); void SendSubscribe ( bool force = false ); void SendUnsubscribe ( void ); void SendSpeed ( bool force = false ); 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 ParseSubscriptionStatus ( htsmsg_t *m ); void ParseQueueStatus ( htsmsg_t *m ); void ParseSignalStatus ( htsmsg_t *m ); void ParseTimeshiftStatus ( htsmsg_t *m ); }; /* * HTSP VFS - recordings */ class CHTSPVFS { friend class CTvheadend; public: CHTSPVFS ( CHTSPConnection &conn ); ~CHTSPVFS (); void Connected ( void ); private: CHTSPConnection &m_conn; CStdString m_path; uint32_t m_fileId; int64_t m_offset; bool Open ( const PVR_RECORDING &rec ); void Close ( void ); ssize_t Read ( unsigned char *buf, unsigned int len ); long long Seek ( long long pos, int whence ); long long Tell ( void ); long long Size ( void ); bool SendFileOpen ( bool force = false ); void SendFileClose ( void ); ssize_t SendFileRead ( unsigned char *buf, unsigned int len ); long long SendFileSeek ( int64_t pos, int whence, bool force = false ); }; /* * Root object for Tvheadend connection */ class CTvheadend : public PLATFORM::CThread { public: CTvheadend(tvheadend::Settings settings); ~CTvheadend(); void Start ( void ); void Disconnected ( void ); bool Connected ( void ); bool ProcessMessage ( const char *method, htsmsg_t *msg ); inline const tvheadend::Settings& GetSettings () const { return m_settings; }; inline const SChannels& 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 ); 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 AddTimeRecording ( const PVR_TIMER &tmr ); PVR_ERROR GetEpg ( ADDON_HANDLE handle, const PVR_CHANNEL &chn, time_t start, time_t end ); private: uint32_t GetNextUnnumberedChannelNumber ( void ); PLATFORM::CMutex m_mutex; const tvheadend::Settings m_settings; CHTSPConnection m_conn; CHTSPDemuxer m_dmx; CHTSPVFS m_vfs; CHTSPMessageQueue m_queue; SChannels m_channels; htsp::Tags m_tags; SRecordings m_recordings; SSchedules m_schedules; SHTSPEventList m_events; AsyncState m_asyncState; CStdString GetImageURL ( const char *str ); /* * Message processing */ void *Process ( void ); /* * Event handling */ inline void TriggerChannelGroupsUpdate ( void ) { m_events.push_back(SHTSPEvent(HTSP_EVENT_TAG_UPDATE)); } inline void TriggerChannelUpdate ( void ) { m_events.push_back(SHTSPEvent(HTSP_EVENT_CHN_UPDATE)); } inline void TriggerRecordingUpdate ( void ) { m_events.push_back(SHTSPEvent(HTSP_EVENT_REC_UPDATE)); } inline void TriggerTimerUpdate ( void ) { m_events.push_back(SHTSPEvent(HTSP_EVENT_REC_UPDATE)); } inline void TriggerEpgUpdate ( uint32_t idx ) { SHTSPEvent event = SHTSPEvent(HTSP_EVENT_EPG_UPDATE, idx); if (std::find(m_events.begin(), m_events.end(), event) == m_events.end()) m_events.push_back(event); } /* * Epg Handling */ void TransferEvent ( ADDON_HANDLE handle, const SEvent &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, SEvent &evt ); public: /* * Connection (pass-thru) */ bool WaitForConnection ( void ) { PLATFORM::CLockObject lock(m_conn.Mutex()); return m_conn.WaitForConnection(); } inline const char *GetServerName ( void ) { return m_conn.GetServerName(); } inline const char *GetServerVersion ( void ) { return m_conn.GetServerVersion(); } inline const char *GetServerString ( void ) { return m_conn.GetServerString(); } inline int GetProtocol ( void ) const { return m_conn.GetProtocol(); } inline bool HasCapability(const std::string &capability) const { return m_conn.HasCapability(capability); } inline bool IsConnected ( void ) const { return m_conn.IsConnected(); } inline void Disconnect ( void ) { m_conn.Disconnect(); } inline void OnSleep ( void ) { m_conn.OnSleep(); } inline void OnWake ( void ) { m_conn.OnWake(); } /* * Demuxer (pass-thru) */ inline bool DemuxOpen ( const PVR_CHANNEL &chn ) { return m_dmx.Open(chn); } inline void DemuxClose ( void ) { m_dmx.Close(); } inline DemuxPacket *DemuxRead ( void ) { return m_dmx.Read(); } inline void DemuxFlush ( void ) { m_dmx.Flush(); } inline void DemuxAbort ( void ) { m_dmx.Abort(); } inline bool DemuxSeek ( int time, bool backward, double *startpts ) { return m_dmx.Seek(time, backward, startpts); } inline void DemuxSpeed ( int speed ) { return m_dmx.Speed(speed); } inline PVR_ERROR DemuxCurrentStreams ( PVR_STREAM_PROPERTIES *streams ) { return m_dmx.CurrentStreams(streams); } inline PVR_ERROR DemuxCurrentSignal ( PVR_SIGNAL_STATUS &sig ) { return m_dmx.CurrentSignal(sig); } inline time_t DemuxGetTimeshiftTime() const { return m_dmx.GetTimeshiftTime(); } /* * VFS (pass-thru) */ inline bool VfsOpen ( const PVR_RECORDING &rec ) { return m_vfs.Open(rec); } inline void VfsClose ( void ) { m_vfs.Close(); } inline ssize_t VfsRead ( unsigned char *buf, unsigned int len ) { return m_vfs.Read(buf, len); } inline long long VfsSeek ( long long position, int whence ) { return m_vfs.Seek(position, whence); } inline long long VfsTell ( void ) { return m_vfs.Tell(); } inline long long VfsSize ( void ) { return m_vfs.Size(); } }; kodi-pvr-hts-2.1.18/src/client.cpp000066400000000000000000000373151260020026400167040ustar00rootroot00000000000000/* * 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 "platform/threads/mutex.h" #include "platform/threads/atomics.h" #include "platform/util/util.h" #include "Settings.h" #include "Tvheadend.h" using namespace std; using namespace ADDON; using namespace PLATFORM; /* ************************************************************************** * Global variables * *************************************************************************/ /* * Client state */ ADDON_STATUS m_CurStatus = ADDON_STATUS_UNKNOWN; bool m_bAlertHtspVersionMismatch = true; /* * Global configuration */ CMutex g_mutex; string g_strHostname = DEFAULT_HOST; int g_iPortHTSP = DEFAULT_HTSP_PORT; int g_iPortHTTP = DEFAULT_HTTP_PORT; int g_iConnectTimeout = DEFAULT_CONNECT_TIMEOUT; int g_iResponseTimeout = DEFAULT_RESPONSE_TIMEOUT; string g_strUsername = ""; string g_strPassword = ""; bool g_bTraceDebug = false; bool g_bAsyncEpg = false; /* * Global state */ CHelper_libXBMC_addon *XBMC = NULL; CHelper_libXBMC_pvr *PVR = NULL; CHelper_libXBMC_codec *CODEC = NULL; PVR_MENUHOOK *menuHook = NULL; CTvheadend *tvh = NULL; /* ************************************************************************** * ADDON setup * *************************************************************************/ extern "C" { void ADDON_ReadSettings(void) { #define UPDATE_INT(var, key, def)\ if (!XBMC->GetSetting(key, &var))\ var = def; #define UPDATE_STR(var, key, tmp, def)\ if (XBMC->GetSetting(key, tmp))\ var = tmp;\ else\ var = def; char buffer[1024]; /* Connection */ UPDATE_STR(g_strHostname, "host", buffer, DEFAULT_HOST); UPDATE_STR(g_strUsername, "user", buffer, ""); UPDATE_STR(g_strPassword, "pass", buffer, ""); UPDATE_INT(g_iPortHTSP, "htsp_port", DEFAULT_HTSP_PORT); UPDATE_INT(g_iPortHTTP, "http_port", DEFAULT_HTTP_PORT); UPDATE_INT(g_iConnectTimeout, "connect_timeout", DEFAULT_CONNECT_TIMEOUT); UPDATE_INT(g_iResponseTimeout, "response_timeout", DEFAULT_RESPONSE_TIMEOUT); /* Data Transfer */ UPDATE_INT(g_bAsyncEpg, "epg_async", false); /* Debug */ UPDATE_INT(g_bTraceDebug, "trace_debug", false); /* TODO: Transcoding */ #undef UPDATE_INT #undef UPDATE_STR } ADDON_STATUS ADDON_Create(void* hdl, void* _unused(props)) { if (!hdl) return m_CurStatus; /* Instantiate helpers */ XBMC = new CHelper_libXBMC_addon; CODEC = new CHelper_libXBMC_codec; PVR = new CHelper_libXBMC_pvr; if (!XBMC->RegisterMe(hdl) || !CODEC->RegisterMe(hdl) || !PVR->RegisterMe(hdl)) { SAFE_DELETE(PVR); SAFE_DELETE(CODEC); SAFE_DELETE(XBMC); return ADDON_STATUS_PERMANENT_FAILURE; } tvhinfo("starting PVR client"); ADDON_ReadSettings(); /* Create a settings object that can be used without locks */ tvheadend::Settings settings; settings.strHostname = g_strHostname; settings.iPortHTSP = g_iPortHTSP; settings.iPortHTTP = g_iPortHTTP; settings.strUsername = g_strUsername; settings.strPassword = g_strPassword; settings.bTraceDebug = g_bTraceDebug; settings.bAsyncEpg = g_bAsyncEpg; /* Timeouts are defined in seconds but we expect them to be in milliseconds. Furthermore, the value from the settings is actually the index of the selected value, which is zero-based, so we need to increment by one. */ settings.iConnectTimeout = (g_iConnectTimeout + 1) * 1000; settings.iResponseTimeout = (g_iResponseTimeout + 1) * 1000; tvh = new CTvheadend(settings); tvh->Start(); /* Wait for connection */ if (!tvh->WaitForConnection()) { if (m_bAlertHtspVersionMismatch && (tvh->GetProtocol() > 0) && // 0 => tvh server down (tvh->GetProtocol() < HTSP_MIN_SERVER_VERSION)) { m_bAlertHtspVersionMismatch = false; // alert max once during addon lifetime /* client/server API version mismatch */ XBMC->QueueNotification( QUEUE_ERROR, XBMC->GetLocalizedString(30300), tvh->GetProtocol(), HTSP_MIN_SERVER_VERSION); } SAFE_DELETE(tvh); SAFE_DELETE(PVR); SAFE_DELETE(CODEC); SAFE_DELETE(XBMC); return ADDON_STATUS_LOST_CONNECTION; } m_CurStatus = ADDON_STATUS_OK; return m_CurStatus; } ADDON_STATUS ADDON_GetStatus() { CLockObject lock(g_mutex); // Check that we're still connected if (m_CurStatus == ADDON_STATUS_OK && !tvh->IsConnected()) m_CurStatus = ADDON_STATUS_LOST_CONNECTION; return m_CurStatus; } void ADDON_Destroy() { CLockObject lock(g_mutex); SAFE_DELETE(tvh); SAFE_DELETE(PVR); SAFE_DELETE(CODEC); SAFE_DELETE(XBMC); SAFE_DELETE(menuHook); m_CurStatus = ADDON_STATUS_UNKNOWN; } bool ADDON_HasSettings() { return true; } unsigned int ADDON_GetSettings (ADDON_StructSetting ***_unused(sSet)) { return 0; } ADDON_STATUS ADDON_SetSetting (const char *settingName, const void *settingValue) { #define UPDATE_STR(key, var)\ if (!strcmp(settingName, key))\ {\ if (strcmp(var.c_str(), (const char*)settingValue) != 0)\ {\ tvhdebug("update %s from '%s' to '%s'",\ settingName, var.c_str(), settingValue);\ return ADDON_STATUS_NEED_RESTART;\ }\ return ADDON_STATUS_OK;\ } #define UPDATE_INT(key, type, var)\ if (!strcmp(settingName, key))\ {\ if (var != *(type*)settingValue)\ {\ tvhdebug("update %s from '%d' to '%d'",\ settingName, var, (int)*(type*)settingValue);\ return ADDON_STATUS_NEED_RESTART;\ }\ return ADDON_STATUS_OK;\ } /* Connection */ UPDATE_STR("host", g_strHostname); UPDATE_STR("user", g_strUsername); UPDATE_STR("pass", g_strPassword); UPDATE_INT("htsp_port", int, g_iPortHTSP); UPDATE_INT("http_port", int, g_iPortHTTP); UPDATE_INT("connect_timeout", int, g_iConnectTimeout); UPDATE_INT("response_timeout", int, g_iResponseTimeout); /* Data transfer */ UPDATE_INT("epg_async", bool, g_bAsyncEpg); /* Debug */ UPDATE_INT("trace_debug", bool, g_bTraceDebug); return ADDON_STATUS_OK; #undef UPDATE_INT #undef UPDATE_STR } void ADDON_Stop() { } void ADDON_FreeSettings() { } void ADDON_Announce (const char *flag, const char *sender, const char *message, const void *_unused(data)) { tvhdebug("Announce(flag=%s, sender=%s, message=%s)", flag, sender, message); /* XBMC/System */ if (!strcmp(sender, "xbmc") && !strcmp(flag, "System")) { if (!strcmp("OnSleep", message)) tvh->OnSleep(); else if (!strcmp("OnWake", message)) tvh->OnWake(); } } /* ************************************************************************** * Versioning * *************************************************************************/ const char* GetPVRAPIVersion(void) { static const char *strApiVersion = XBMC_PVR_API_VERSION; return strApiVersion; } const char* GetMininumPVRAPIVersion(void) { static const char *strMinApiVersion = XBMC_PVR_MIN_API_VERSION; return strMinApiVersion; } /* ************************************************************************** * 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->bSupportsRecordingFolders = true; pCapabilities->bSupportsRecordingEdl = true; return PVR_ERROR_NO_ERROR; } const char *GetBackendName(void) { return tvh->GetServerName(); } const char *GetBackendVersion(void) { return tvh->GetServerVersion(); } const char *GetConnectionString(void) { return tvh->GetServerString(); } const char *GetBackendHostname(void) { return g_strHostname.c_str(); } PVR_ERROR GetDriveSpace(long long *iTotal, long long *iUsed) { return tvh->GetDriveSpace(iTotal, iUsed); } /* ************************************************************************** * GUI hooks * *************************************************************************/ PVR_ERROR CallMenuHook (const PVR_MENUHOOK &_unused(menuhook), const PVR_MENUHOOK_DATA &_unused(data)) { return PVR_ERROR_NO_ERROR; } /* ************************************************************************** * Demuxer * *************************************************************************/ bool CanPauseStream(void) { return tvh->HasCapability("timeshift"); } bool CanSeekStream(void) { return tvh->HasCapability("timeshift"); } bool OpenLiveStream(const PVR_CHANNEL &channel) { return tvh->DemuxOpen(channel); } void CloseLiveStream(void) { tvh->DemuxClose(); } bool SeekTime(int time,bool backward,double *startpts) { return tvh->DemuxSeek(time, backward, startpts); } void SetSpeed(int speed) { tvh->DemuxSpeed(speed); } int GetCurrentClientChannel(void) { return -1; // XBMC doesn't even use this } bool SwitchChannel(const PVR_CHANNEL &channel) { return tvh->DemuxOpen(channel); } PVR_ERROR GetStreamProperties(PVR_STREAM_PROPERTIES* pProperties) { return tvh->DemuxCurrentStreams(pProperties); } PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS &signalStatus) { return tvh->DemuxCurrentSignal(signalStatus); } 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->GetEpg(handle, channel, iStart, iEnd); } /* ************************************************************************** * 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; } 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 PositionRecordedStream(void) { return tvh->VfsTell(); } long long LengthRecordedStream(void) { return tvh->VfsSize(); } /* ************************************************************************** * Unused Functions * *************************************************************************/ unsigned int GetChannelSwitchDelay(void) { return 0; } /* Recording History */ PVR_ERROR SetRecordingPlayCount (const PVR_RECORDING &_unused(recording), int _unused(count)) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR SetRecordingLastPlayedPosition (const PVR_RECORDING &_unused(recording), int _unused(lastplayedposition)) { return PVR_ERROR_NOT_IMPLEMENTED; } int GetRecordingLastPlayedPosition(const PVR_RECORDING &_unused(recording)) { return -1; } /* Channel Management */ PVR_ERROR OpenDialogChannelScan(void) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR DeleteChannel(const PVR_CHANNEL &_unused(channel)) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR RenameChannel(const PVR_CHANNEL &_unused(channel)) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR MoveChannel(const PVR_CHANNEL &_unused(channel)) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR OpenDialogChannelSettings(const PVR_CHANNEL &_unused(channel)) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR OpenDialogChannelAdd(const PVR_CHANNEL &_unused(channel)) { return PVR_ERROR_NOT_IMPLEMENTED; } /* Timeshift?? - not sure if we can use these? */ void PauseStream(bool _unused(bPaused)) { } time_t GetPlayingTime() { // tvheadend reports the number of microseconds the live stream is shifted but // XBMC expects it to be an absolute UNIX timestamp int seconds = (double) tvh->DemuxGetTimeshiftTime() / 1000000; return (time_t) (time(NULL) - seconds); } time_t GetBufferTimeStart() { return 0; } time_t GetBufferTimeEnd() { return 0; } /* Live stream (VFS interface - not relevant) */ int ReadLiveStream (unsigned char *_unused(pBuffer), unsigned int _unused(iBufferSize)) { return 0; } long long SeekLiveStream (long long _unused(iPosition), int _unused(iWhence)) { return -1; } long long PositionLiveStream(void) { return -1; } long long LengthLiveStream(void) { return -1; } const char * GetLiveStreamURL(const PVR_CHANNEL &_unused(channel)) { return ""; } const char* GetGUIAPIVersion(void) { return KODI_GUILIB_API_VERSION; } const char* GetMininumGUIAPIVersion(void) { return KODI_GUILIB_MIN_API_VERSION; } } /* extern "C" */ kodi-pvr-hts-2.1.18/src/client.h000066400000000000000000000025421260020026400163430ustar00rootroot00000000000000#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 "platform/os.h" #include "platform/threads/mutex.h" #include "kodi/libXBMC_addon.h" #include "kodi/libXBMC_pvr.h" #include "kodi/libXBMC_codec.h" extern ADDON::CHelper_libXBMC_addon* XBMC; extern CHelper_libXBMC_pvr* PVR; extern CHelper_libXBMC_codec* CODEC; #define DEFAULT_HOST "127.0.0.1" #define DEFAULT_HTTP_PORT 9981 #define DEFAULT_HTSP_PORT 9982 #define DEFAULT_CONNECT_TIMEOUT 10 #define DEFAULT_RESPONSE_TIMEOUT 5 class CTvheadend; extern CTvheadend *tvh; kodi-pvr-hts-2.1.18/src/xbmc_codec_descriptor.hpp000066400000000000000000000041751260020026400217550ustar00rootroot00000000000000/* * 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 * . * */ #ifndef XBMC_CODEC_DESCRIPTOR_HPP #define XBMC_CODEC_DESCRIPTOR_HPP #include "kodi/libXBMC_codec.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) {} const std::string& Name(void) const { return m_strName; } 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(CODEC->GetCodecByName("MP2"), strCodecName); else if (!strcmp(strCodecName, "MPEGTS")) retVal = CodecDescriptor(CODEC->GetCodecByName("MPEG2VIDEO"), strCodecName); else if (!strcmp(strCodecName, "TEXTSUB")) retVal = CodecDescriptor(CODEC->GetCodecByName("TEXT"), strCodecName); else retVal = CodecDescriptor(CODEC->GetCodecByName(strCodecName), strCodecName); return retVal; } private: xbmc_codec_t m_codec; std::string m_strName; }; #endif /* XBMC_CODEC_DESCRIPTOR_HPP */