From 5ec050778b2d226b5102207df8b562d51a2867ad Mon Sep 17 00:00:00 2001 From: Sam Stenvall Date: Wed, 31 Dec 2014 14:59:14 +0200 Subject: [PATCH] [pvr.hts] replace with the newer pvr.tvh fork --- addons/pvr.hts/Makefile.am | 11 +- addons/pvr.hts/addon/addon.xml.in | 2 +- .../resources/language/Afrikaans/strings.po | 65 - .../resources/language/Albanian/strings.po | 77 - .../resources/language/Amharic/strings.po | 61 - .../resources/language/Arabic/strings.po | 53 - .../resources/language/Armenian/strings.po | 25 - .../resources/language/Azerbaijani/strings.po | 21 - .../resources/language/Basque/strings.po | 37 - .../resources/language/Belarusian/strings.po | 65 - .../resources/language/Bosnian/strings.po | 37 - .../resources/language/Bulgarian/strings.po | 77 - .../resources/language/Burmese/strings.po | 29 - .../resources/language/Catalan/strings.po | 77 - .../language/Chinese (Simple)/strings.po | 77 - .../language/Chinese (Traditional)/strings.po | 77 - .../resources/language/Croatian/strings.po | 77 - .../addon/resources/language/Czech/strings.po | 77 - .../resources/language/Danish/strings.po | 77 - .../addon/resources/language/Dutch/strings.po | 77 - .../language/English (Australia)/strings.po | 77 - .../language/English (New Zealand)/strings.po | 77 - .../language/English (US)/strings.po | 77 - .../resources/language/English/strings.po | 62 +- .../resources/language/Esperanto/strings.po | 29 - .../resources/language/Estonian/strings.po | 77 - .../resources/language/Faroese/strings.po | 29 - .../resources/language/Finnish/strings.po | 65 - .../language/French (Canada)/strings.po | 77 - .../resources/language/French/strings.po | 77 - .../resources/language/Galician/strings.po | 77 - .../resources/language/Georgian/strings.po | 77 - .../resources/language/German/strings.po | 77 - .../addon/resources/language/Greek/strings.po | 77 - .../Haitian (Haitian Creole)/strings.po | 25 - .../resources/language/Hebrew/strings.po | 77 - .../language/Hindi (Devanagiri)/strings.po | 25 - .../resources/language/Hungarian/strings.po | 77 - .../resources/language/Icelandic/strings.po | 77 - .../resources/language/Indonesian/strings.po | 77 - .../resources/language/Italian/strings.po | 77 - .../resources/language/Japanese/strings.po | 77 - .../resources/language/Korean/strings.po | 77 - .../resources/language/Latvian/strings.po | 77 - .../resources/language/Lithuanian/strings.po | 77 - .../resources/language/Macedonian/strings.po | 77 - .../addon/resources/language/Malay/strings.po | 77 - .../resources/language/Malayalam/strings.po | 21 - .../resources/language/Maltese/strings.po | 29 - .../addon/resources/language/Maori/strings.po | 37 - .../language/Mongolian (Mongolia)/strings.po | 77 - .../resources/language/Norwegian/strings.po | 77 - .../language/Persian (Iran)/strings.po | 29 - .../resources/language/Persian/strings.po | 25 - .../resources/language/Polish/strings.po | 77 - .../language/Portuguese (Brazil)/strings.po | 77 - .../resources/language/Portuguese/strings.po | 77 - .../resources/language/Romanian/strings.po | 77 - .../resources/language/Russian/strings.po | 77 - .../language/Serbian (Cyrillic)/strings.po | 65 - .../resources/language/Serbian/strings.po | 37 - .../resources/language/Sinhala/strings.po | 37 - .../resources/language/Slovak/strings.po | 77 - .../resources/language/Slovenian/strings.po | 77 - .../language/Spanish (Argentina)/strings.po | 77 - .../language/Spanish (Mexico)/strings.po | 53 - .../resources/language/Spanish/strings.po | 77 - .../resources/language/Swedish/strings.po | 77 - .../addon/resources/language/Tajik/strings.po | 77 - .../resources/language/Telugu/strings.po | 25 - .../addon/resources/language/Thai/strings.po | 37 - .../resources/language/Turkish/strings.po | 77 - .../resources/language/Ukrainian/strings.po | 77 - .../addon/resources/language/Uzbek/strings.po | 29 - .../resources/language/Vietnamese/strings.po | 77 - .../addon/resources/language/Welsh/strings.po | 77 - addons/pvr.hts/addon/resources/settings.xml | 29 +- .../skins/Confluence/720p/DialogTranscode.xml | 170 -- .../VS2010Express/pvrclient_tvheadend.vcxproj | 30 +- .../pvrclient_tvheadend.vcxproj.filters | 28 +- addons/pvr.hts/src/AsyncState.cpp | 59 + addons/pvr.hts/src/AsyncState.h | 86 + addons/pvr.hts/src/CircBuffer.cpp | 16 +- addons/pvr.hts/src/CircBuffer.h | 3 +- addons/pvr.hts/src/GUIDialogTranscode.cpp | 197 -- addons/pvr.hts/src/GUIDialogTranscode.h | 59 - addons/pvr.hts/src/HTSPConnection.cpp | 952 ++++------ addons/pvr.hts/src/HTSPConnection.h | 151 -- addons/pvr.hts/src/HTSPData.cpp | 1640 ----------------- addons/pvr.hts/src/HTSPData.h | 132 -- addons/pvr.hts/src/HTSPDemux.cpp | 669 ------- addons/pvr.hts/src/HTSPDemux.h | 86 - addons/pvr.hts/src/HTSPDemuxer.cpp | 677 +++++++ addons/pvr.hts/src/HTSPTypes.h | 274 ++- addons/pvr.hts/src/HTSPVFS.cpp | 286 +++ addons/pvr.hts/src/Settings.h | 40 + addons/pvr.hts/src/Tvheadend.cpp | 1529 +++++++++++++++ addons/pvr.hts/src/Tvheadend.h | 550 ++++++ addons/pvr.hts/src/client.cpp | 839 ++++----- addons/pvr.hts/src/client.h | 44 +- 100 files changed, 4278 insertions(+), 8952 deletions(-) delete mode 100644 addons/pvr.hts/addon/resources/language/Afrikaans/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Albanian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Amharic/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Arabic/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Armenian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Azerbaijani/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Basque/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Belarusian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Bosnian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Bulgarian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Burmese/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Catalan/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Chinese (Simple)/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Chinese (Traditional)/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Croatian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Czech/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Danish/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Dutch/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/English (Australia)/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/English (New Zealand)/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/English (US)/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Esperanto/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Estonian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Faroese/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Finnish/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/French (Canada)/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/French/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Galician/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Georgian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/German/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Greek/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Haitian (Haitian Creole)/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Hebrew/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Hindi (Devanagiri)/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Hungarian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Icelandic/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Indonesian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Italian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Japanese/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Korean/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Latvian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Lithuanian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Macedonian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Malay/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Malayalam/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Maltese/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Maori/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Mongolian (Mongolia)/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Norwegian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Persian (Iran)/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Persian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Polish/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Portuguese (Brazil)/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Portuguese/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Romanian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Russian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Serbian (Cyrillic)/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Serbian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Sinhala/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Slovak/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Slovenian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Spanish (Argentina)/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Spanish (Mexico)/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Spanish/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Swedish/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Tajik/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Telugu/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Thai/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Turkish/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Ukrainian/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Uzbek/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Vietnamese/strings.po delete mode 100644 addons/pvr.hts/addon/resources/language/Welsh/strings.po delete mode 100644 addons/pvr.hts/addon/resources/skins/Confluence/720p/DialogTranscode.xml create mode 100644 addons/pvr.hts/src/AsyncState.cpp create mode 100644 addons/pvr.hts/src/AsyncState.h delete mode 100644 addons/pvr.hts/src/GUIDialogTranscode.cpp delete mode 100644 addons/pvr.hts/src/GUIDialogTranscode.h delete mode 100644 addons/pvr.hts/src/HTSPConnection.h delete mode 100644 addons/pvr.hts/src/HTSPData.cpp delete mode 100644 addons/pvr.hts/src/HTSPData.h delete mode 100644 addons/pvr.hts/src/HTSPDemux.cpp delete mode 100644 addons/pvr.hts/src/HTSPDemux.h create mode 100644 addons/pvr.hts/src/HTSPDemuxer.cpp create mode 100644 addons/pvr.hts/src/HTSPVFS.cpp create mode 100644 addons/pvr.hts/src/Settings.h create mode 100644 addons/pvr.hts/src/Tvheadend.cpp create mode 100644 addons/pvr.hts/src/Tvheadend.h diff --git a/addons/pvr.hts/Makefile.am b/addons/pvr.hts/Makefile.am index bbda35315..eae85b600 100644 --- a/addons/pvr.hts/Makefile.am +++ b/addons/pvr.hts/Makefile.am @@ -15,10 +15,11 @@ LIBS = @abs_top_srcdir@/lib/libhts/libhts.la -ldl include ../Makefile.include.am libtvheadend_addon_la_SOURCES = src/client.cpp \ - src/HTSPConnection.cpp \ - src/HTSPData.cpp \ - src/HTSPDemux.cpp \ - src/CircBuffer.cpp \ - src/GUIDialogTranscode.cpp + src/AsyncState.cpp \ + src/Tvheadend.cpp \ + src/HTSPConnection.cpp \ + src/HTSPDemuxer.cpp \ + src/HTSPVFS.cpp \ + src/CircBuffer.cpp libtvheadend_addon_la_LDFLAGS = @TARGET_LDFLAGS@ diff --git a/addons/pvr.hts/addon/addon.xml.in b/addons/pvr.hts/addon/addon.xml.in index f910ea170..d13c66bff 100644 --- a/addons/pvr.hts/addon/addon.xml.in +++ b/addons/pvr.hts/addon/addon.xml.in @@ -3,7 +3,7 @@ id="pvr.hts" version="1.9.39" name="Tvheadend HTSP Client" - provider-name="Lars Op den Kamp, Team XBMC"> + provider-name="Adam Sutton, Sam Stenvall, Lars Op den Kamp"> diff --git a/addons/pvr.hts/addon/resources/language/Afrikaans/strings.po b/addons/pvr.hts/addon/resources/language/Afrikaans/strings.po deleted file mode 100644 index f9640e5bf..000000000 --- a/addons/pvr.hts/addon/resources/language/Afrikaans/strings.po +++ /dev/null @@ -1,65 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/af/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: af\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend gasheernaam of IP adres" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP poort" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP poort" - -msgctxt "#30003" -msgid "Username" -msgstr "Gebruikersnaam" - -msgctxt "#30004" -msgid "Password" -msgstr "Wagwoord" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Konnekteer tydverstreke in sekondes" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Antwoord tydverstreke in sekondes" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Audio kodek" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Video kodek" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolusie" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Diskonnekteer van '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Herkonnekteer aan '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Albanian/strings.po b/addons/pvr.hts/addon/resources/language/Albanian/strings.po deleted file mode 100644 index 8c7c227e5..000000000 --- a/addons/pvr.hts/addon/resources/language/Albanian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/sq/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sq\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend hostname ose adresa IP" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP porti" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP porti" - -msgctxt "#30003" -msgid "Username" -msgstr "Emër-përdoruesi" - -msgctxt "#30004" -msgid "Password" -msgstr "Fjalkalimi" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Timeout i lidhjes në sekonda" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Timeout i përgjigjjes në eskonda" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Cilësimet e transkodimit për Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Cilësimet e transkodimit" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Aktivo transkodimin" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Audio codec'i" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Video codec'i" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Zbërthimi" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "U ndërpre nga '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "U rilidh me '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Amharic/strings.po b/addons/pvr.hts/addon/resources/language/Amharic/strings.po deleted file mode 100644 index e4e2cbb78..000000000 --- a/addons/pvr.hts/addon/resources/language/Amharic/strings.po +++ /dev/null @@ -1,61 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/am/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: am\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP port" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP port" - -msgctxt "#30003" -msgid "Username" -msgstr "የተጠቃሚ ስም " - -msgctxt "#30004" -msgid "Password" -msgstr "የመግቢያ ቃል" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "ግንኙነት ማስቆሚያ በ ሰከንዶች" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "መመለሻ ጊዜ በ ሰከንዶች" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "የ ድምፅ codec" - -msgctxt "#30104" -msgid "Video codec" -msgstr "የ ቪዲዮ codec" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolution" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "ግንኙነት ተቋርጧል ከ '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "እንደገና ተገናኝቷል ወደ '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Arabic/strings.po b/addons/pvr.hts/addon/resources/language/Arabic/strings.po deleted file mode 100644 index e8ffa574b..000000000 --- a/addons/pvr.hts/addon/resources/language/Arabic/strings.po +++ /dev/null @@ -1,53 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/ar/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ar\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 "#30001" -msgid "HTTP port" -msgstr "منفذ HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "منفذ HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "اسم المستخدم" - -msgctxt "#30004" -msgid "Password" -msgstr "كلمة المرور" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "ترميز الصوت" - -msgctxt "#30104" -msgid "Video codec" -msgstr "ترميز الفيديو" - -msgctxt "#30105" -msgid "Resolution" -msgstr "دقة" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "قطع الاتصال من '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "أعيد الاتصال بـ '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Armenian/strings.po b/addons/pvr.hts/addon/resources/language/Armenian/strings.po deleted file mode 100644 index b8bdb8efb..000000000 --- a/addons/pvr.hts/addon/resources/language/Armenian/strings.po +++ /dev/null @@ -1,25 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/hy/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: hy\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30004" -msgid "Password" -msgstr "Գաղտնաբառ" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Լուծում" diff --git a/addons/pvr.hts/addon/resources/language/Azerbaijani/strings.po b/addons/pvr.hts/addon/resources/language/Azerbaijani/strings.po deleted file mode 100644 index 8435443a8..000000000 --- a/addons/pvr.hts/addon/resources/language/Azerbaijani/strings.po +++ /dev/null @@ -1,21 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\n" -"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Kodi Translation Team\n" -"Language-Team: Azerbaijani (http://www.transifex.com/projects/p/xbmc-main/language/az/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: az\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Əksetmə qabiliyyəti" diff --git a/addons/pvr.hts/addon/resources/language/Basque/strings.po b/addons/pvr.hts/addon/resources/language/Basque/strings.po deleted file mode 100644 index 81a74bd6d..000000000 --- a/addons/pvr.hts/addon/resources/language/Basque/strings.po +++ /dev/null @@ -1,37 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/eu/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: eu\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30003" -msgid "Username" -msgstr "Erabiltzailea" - -msgctxt "#30004" -msgid "Password" -msgstr "Pasahitza" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Audio codec-a" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Bideo codec-a" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Bereizmena" diff --git a/addons/pvr.hts/addon/resources/language/Belarusian/strings.po b/addons/pvr.hts/addon/resources/language/Belarusian/strings.po deleted file mode 100644 index 446a35646..000000000 --- a/addons/pvr.hts/addon/resources/language/Belarusian/strings.po +++ /dev/null @@ -1,65 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/be/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: be\n" -"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend hostname or IP address" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP port" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP port" - -msgctxt "#30003" -msgid "Username" -msgstr "Username" - -msgctxt "#30004" -msgid "Password" -msgstr "Пароль" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Connect timeout in seconds" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Response timeout in seconds" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Audio codec" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Video codec" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Разрознасьць" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Disconnected from '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Reconnected to '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Bosnian/strings.po b/addons/pvr.hts/addon/resources/language/Bosnian/strings.po deleted file mode 100644 index 63dfad377..000000000 --- a/addons/pvr.hts/addon/resources/language/Bosnian/strings.po +++ /dev/null @@ -1,37 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/bs/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: bs\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 "#30003" -msgid "Username" -msgstr "Korisničko ime" - -msgctxt "#30004" -msgid "Password" -msgstr "Lozinka" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Kodek zvuka" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Video kodek" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Rezolucija" diff --git a/addons/pvr.hts/addon/resources/language/Bulgarian/strings.po b/addons/pvr.hts/addon/resources/language/Bulgarian/strings.po deleted file mode 100644 index af0a4bfdf..000000000 --- a/addons/pvr.hts/addon/resources/language/Bulgarian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/bg/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: bg\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend хост или IP адрес" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP порт" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP порт" - -msgctxt "#30003" -msgid "Username" -msgstr "Потребителско име" - -msgctxt "#30004" -msgid "Password" -msgstr "Парола" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Таймаут при свързване в секунди" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Таймаут за отговор в секунди" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Настройки за Tvheadend прекодиране" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Настройки за прекодиране" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Включи прекодирането" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Аудио кодек" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Видео кодек" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Резолюция" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Изключен от '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Повторно свързан с '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Burmese/strings.po b/addons/pvr.hts/addon/resources/language/Burmese/strings.po deleted file mode 100644 index b40509953..000000000 --- a/addons/pvr.hts/addon/resources/language/Burmese/strings.po +++ /dev/null @@ -1,29 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/my/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: my\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30003" -msgid "Username" -msgstr "အသုံးပြုသူအမည်" - -msgctxt "#30004" -msgid "Password" -msgstr "စကားဝှက်" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolution" diff --git a/addons/pvr.hts/addon/resources/language/Catalan/strings.po b/addons/pvr.hts/addon/resources/language/Catalan/strings.po deleted file mode 100644 index e576fa7b2..000000000 --- a/addons/pvr.hts/addon/resources/language/Catalan/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/ca/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ca\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Nom de màquina o IP del Tvheadend" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Port HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Port HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Nom d'usuari" - -msgctxt "#30004" -msgid "Password" -msgstr "Contrasenya" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Temps d'espera de connexió en segons" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Temps d'espera de la resposta en segons" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Configuració de la transcodificació del Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Configuració de la transcodificació" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Habilita la transcodificació" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Còdec d'àudio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Còdec de vídeo" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolució" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Desconnectat de '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Reconnectat a '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Chinese (Simple)/strings.po b/addons/pvr.hts/addon/resources/language/Chinese (Simple)/strings.po deleted file mode 100644 index dfb3dd2af..000000000 --- a/addons/pvr.hts/addon/resources/language/Chinese (Simple)/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (Simple) (http://www.transifex.com/projects/p/xbmc-main/language/zh/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend 主机名或 IP 地址" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP 端口" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP 端口" - -msgctxt "#30003" -msgid "Username" -msgstr "用户名" - -msgctxt "#30004" -msgid "Password" -msgstr "密码" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "连接超时(秒)" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "响应超时(秒)" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend 转码设置" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "转码设置" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "启用转码" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "音频编码" - -msgctxt "#30104" -msgid "Video codec" -msgstr "视频编码" - -msgctxt "#30105" -msgid "Resolution" -msgstr "分辨率" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "断开到“%s”的连接" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "重新连接到“%s”" diff --git a/addons/pvr.hts/addon/resources/language/Chinese (Traditional)/strings.po b/addons/pvr.hts/addon/resources/language/Chinese (Traditional)/strings.po deleted file mode 100644 index f12ebb1eb..000000000 --- a/addons/pvr.hts/addon/resources/language/Chinese (Traditional)/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (Traditional) (http://www.transifex.com/projects/p/xbmc-main/language/zh_TW/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_TW\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend主機名稱或IP位址" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP端口" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP端口" - -msgctxt "#30003" -msgid "Username" -msgstr "帳號" - -msgctxt "#30004" -msgid "Password" -msgstr "密碼" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "連接超時(秒)" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "回應超時(秒)" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend轉碼設定" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "轉碼設定" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "啟動轉碼" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "音效編碼" - -msgctxt "#30104" -msgid "Video codec" -msgstr "影片編碼" - -msgctxt "#30105" -msgid "Resolution" -msgstr "解析度" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "從 '%s' 斷開連線" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "從 '%s' 重新連線" diff --git a/addons/pvr.hts/addon/resources/language/Croatian/strings.po b/addons/pvr.hts/addon/resources/language/Croatian/strings.po deleted file mode 100644 index 4c9a98296..000000000 --- a/addons/pvr.hts/addon/resources/language/Croatian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/hr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: 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 "Tvheadend hostname or IP address" -msgstr "Tvheadend naziv računala ili IP adresa" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP ulaz" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP ulaz" - -msgctxt "#30003" -msgid "Username" -msgstr "Korisničko ime" - -msgctxt "#30004" -msgid "Password" -msgstr "Lozinka" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Istek vremena u sekundama" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Vrijeme odaziva u sekundama" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend postavke predkôdiranja" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Postavke predkôdiranja" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Omogući predkôdiranje" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Zvučni kôdek" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Video kôdek" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Razlučivost" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Odspojen s '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Ponovno povezan s '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Czech/strings.po b/addons/pvr.hts/addon/resources/language/Czech/strings.po deleted file mode 100644 index a2a73e8ae..000000000 --- a/addons/pvr.hts/addon/resources/language/Czech/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/cs/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: cs\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Název počítače, nebo adresa IP Tvheadend" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Port HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Port HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Uživatelské jméno" - -msgctxt "#30004" -msgid "Password" -msgstr "Heslo" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Časový limit spojení v sekundách" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Časový limit odpovědi v sekundách" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Nastavení překódování Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Nastavení překódování" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Povolit překódování" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Kodek zvuku" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Kodek videa" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Rozlišení" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Odpojeno z '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Opětovně připojeno k '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Danish/strings.po b/addons/pvr.hts/addon/resources/language/Danish/strings.po deleted file mode 100644 index 9eada962a..000000000 --- a/addons/pvr.hts/addon/resources/language/Danish/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/da/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: da\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend værtsnavn eller IP-adresse" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP-port" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP-port" - -msgctxt "#30003" -msgid "Username" -msgstr "Brugernavn" - -msgctxt "#30004" -msgid "Password" -msgstr "Adgangskode" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Tidsfrist for forbindelse i sekunder" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Tidsfrist for svar i sekunder" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend indstillinger til transcoding" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Transcoding-indstillinger" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Aktiver transcoding" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Lyd-codec" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Video-codec" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Opløsning" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Afbrudt fra '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Genforbundet til '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Dutch/strings.po b/addons/pvr.hts/addon/resources/language/Dutch/strings.po deleted file mode 100644 index 5c1a28fae..000000000 --- a/addons/pvr.hts/addon/resources/language/Dutch/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/nl/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: nl\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend server naam of IP adres" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP poort" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP poort" - -msgctxt "#30003" -msgid "Username" -msgstr "Gebruikersnaam" - -msgctxt "#30004" -msgid "Password" -msgstr "Wachtwoord" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Verbinding timeout in seconden" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Antwoord timeout in seconden" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend transcoderingsinstellingen" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Transcoderingsinstellingen" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Gebruik transcodering" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Audiocodec" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Videocodec" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolutie" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Verbinding met '%s' verbroken" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Verbinding met '%s' hersteld" diff --git a/addons/pvr.hts/addon/resources/language/English (Australia)/strings.po b/addons/pvr.hts/addon/resources/language/English (Australia)/strings.po deleted file mode 100644 index 1aed742e9..000000000 --- a/addons/pvr.hts/addon/resources/language/English (Australia)/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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/xbmc-main/language/en_AU/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: en_AU\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend hostname or IP address" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP port" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP port" - -msgctxt "#30003" -msgid "Username" -msgstr "Username" - -msgctxt "#30004" -msgid "Password" -msgstr "Password" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Connect timeout in seconds" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Response timeout in seconds" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend transcoding settings" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Transcoding settings" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Enable transcoding" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Audio codec" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Video codec" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolution" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Disconnected from '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Reconnected to '%s'" diff --git a/addons/pvr.hts/addon/resources/language/English (New Zealand)/strings.po b/addons/pvr.hts/addon/resources/language/English (New Zealand)/strings.po deleted file mode 100644 index 7c7558266..000000000 --- a/addons/pvr.hts/addon/resources/language/English (New Zealand)/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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/xbmc-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 "Tvheadend hostname or IP address" -msgstr "Tvheadend hostname or IP address" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP port" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP port" - -msgctxt "#30003" -msgid "Username" -msgstr "Username" - -msgctxt "#30004" -msgid "Password" -msgstr "Password" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Connect timeout in seconds" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Response timeout in seconds" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend transcoding settings" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Transcoding settings" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Enable transcoding" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Audio codec" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Video codec" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolution" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Disconnected from '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Reconnected to '%s'" diff --git a/addons/pvr.hts/addon/resources/language/English (US)/strings.po b/addons/pvr.hts/addon/resources/language/English (US)/strings.po deleted file mode 100644 index 8e2b5d649..000000000 --- a/addons/pvr.hts/addon/resources/language/English (US)/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (US) (http://www.transifex.com/projects/p/xbmc-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 "Tvheadend hostname or IP address" -msgstr "Tvheadend hostname or IP address" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP port" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP port" - -msgctxt "#30003" -msgid "Username" -msgstr "Username" - -msgctxt "#30004" -msgid "Password" -msgstr "Password" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Connect timeout in seconds" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Response timeout in seconds" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend transcoding settings" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Transcoding settings" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Enable transcoding" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Audio codec" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Video codec" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolution" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Disconnected from '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Reconnected to '%s'" diff --git a/addons/pvr.hts/addon/resources/language/English/strings.po b/addons/pvr.hts/addon/resources/language/English/strings.po index 28528f198..8782c3380 100644 --- a/addons/pvr.hts/addon/resources/language/English/strings.po +++ b/addons/pvr.hts/addon/resources/language/English/strings.po @@ -1,86 +1,68 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client +# XBMC Media Center language file +# Addon Name: Tvheadend Client # Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC +# Addon Provider: Adam Sutton, Sam Stenvall, Lars Op den Kamp msgid "" msgstr "" -"Project-Id-Version: XBMC Main\n" +"Project-Id-Version: XBMC Main Translation Project (Frodo)\n" "Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/en/)\n" +"Last-Translator: XBMC Translation Team\n" +"Language-Team: English (http://www.transifex.com/projects/p/XBMC-Main-Frodo/language/en/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: en\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" + #settings labels msgctxt "#30000" -msgid "Tvheadend hostname or IP address" +msgid "Connection Settings" msgstr "" msgctxt "#30001" -msgid "HTTP port" +msgid "Tvheadend hostname or IP address" msgstr "" msgctxt "#30002" -msgid "HTSP port" +msgid "HTTP port" msgstr "" msgctxt "#30003" -msgid "Username" +msgid "HTSP port" msgstr "" msgctxt "#30004" -msgid "Password" +msgid "Username" msgstr "" -#empty string with id 30005 +msgctxt "#30005" +msgid "Password" +msgstr "" msgctxt "#30006" -msgid "Connect timeout in seconds" +msgid "Connection timeout in seconds" msgstr "" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "" -#empty strings from id 30008 to 30099 - msgctxt "#30100" -msgid "Tvheadend transcoding settings" +msgid "Data Transfer" msgstr "" msgctxt "#30101" -msgid "Transcoding settings" -msgstr "" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "" - -msgctxt "#30103" -msgid "Audio codec" +msgid "Asynchronous EPG transfer" msgstr "" -msgctxt "#30104" -msgid "Video codec" -msgstr "" - -msgctxt "#30105" -msgid "Resolution" -msgstr "" - -#empty strings from id 30106 to 30499 -#notifications - -msgctxt "#30500" -msgid "Disconnected from '%s'" +msgctxt "#30200" +msgid "Debugging" msgstr "" -msgctxt "#30501" -msgid "Reconnected to '%s'" +msgctxt "#30201" +msgid "Trace (detailed)" msgstr "" diff --git a/addons/pvr.hts/addon/resources/language/Esperanto/strings.po b/addons/pvr.hts/addon/resources/language/Esperanto/strings.po deleted file mode 100644 index 60ec5b03b..000000000 --- a/addons/pvr.hts/addon/resources/language/Esperanto/strings.po +++ /dev/null @@ -1,29 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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/xbmc-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 "#30003" -msgid "Username" -msgstr "Uzulonomo" - -msgctxt "#30004" -msgid "Password" -msgstr "pasvorto" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Distingivo" diff --git a/addons/pvr.hts/addon/resources/language/Estonian/strings.po b/addons/pvr.hts/addon/resources/language/Estonian/strings.po deleted file mode 100644 index 092433c95..000000000 --- a/addons/pvr.hts/addon/resources/language/Estonian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/et/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: et\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend hosti nimi või IP aadress" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP port" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP port" - -msgctxt "#30003" -msgid "Username" -msgstr "Kasutajanimi" - -msgctxt "#30004" -msgid "Password" -msgstr "Salasõna" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Ühenduse aegumine sekundites" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Vastuse aegumine sekundites" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadendi transkodeerimis seaded" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Transkodeerimis seaded" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Luba transkodeerimine" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Audio koodek" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Video koodek" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolutsioon" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "'%s' lahti ühendatud" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "'%s' uuesti ühendatud" diff --git a/addons/pvr.hts/addon/resources/language/Faroese/strings.po b/addons/pvr.hts/addon/resources/language/Faroese/strings.po deleted file mode 100644 index 4585d106f..000000000 --- a/addons/pvr.hts/addon/resources/language/Faroese/strings.po +++ /dev/null @@ -1,29 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/fo/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fo\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30003" -msgid "Username" -msgstr "Brúkaranavn" - -msgctxt "#30004" -msgid "Password" -msgstr "Loyniorð" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Skermstødd" diff --git a/addons/pvr.hts/addon/resources/language/Finnish/strings.po b/addons/pvr.hts/addon/resources/language/Finnish/strings.po deleted file mode 100644 index ab802b2c0..000000000 --- a/addons/pvr.hts/addon/resources/language/Finnish/strings.po +++ /dev/null @@ -1,65 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/fi/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fi\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend-palvelimen nimi tai IP-osoite" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP-portti" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP-portti" - -msgctxt "#30003" -msgid "Username" -msgstr "Käyttäjänimi" - -msgctxt "#30004" -msgid "Password" -msgstr "Salasana" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Yhteyden aikakatkaisu sekunneissa" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Vastauksen aikakatkaisu sekunneissa" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Äänikoodekki" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Videokoodekki" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Näytön resoluutio" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Yhteys katkaistu palvelimeen '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Yhdistetty palvelimeen '%s'" diff --git a/addons/pvr.hts/addon/resources/language/French (Canada)/strings.po b/addons/pvr.hts/addon/resources/language/French (Canada)/strings.po deleted file mode 100644 index 2366b6357..000000000 --- a/addons/pvr.hts/addon/resources/language/French (Canada)/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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/xbmc-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 "Tvheadend hostname or IP address" -msgstr "Nom d'hôte ou adresse IP de Tvheadend " - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Port HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Port HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Nom d'utilisateur" - -msgctxt "#30004" -msgid "Password" -msgstr "Mot de passe" - -msgctxt "#30006" -msgid "Connect 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 "Tvheadend transcoding settings" -msgstr "Paramètres de transcodage de Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Paramètres de transcodage" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Activer le transcodage" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Codec audio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Codec vidéo" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Résolution" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Se déconnecter de « %s »" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Se reconnecter à « %s »" diff --git a/addons/pvr.hts/addon/resources/language/French/strings.po b/addons/pvr.hts/addon/resources/language/French/strings.po deleted file mode 100644 index ee9387555..000000000 --- a/addons/pvr.hts/addon/resources/language/French/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/fr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fr\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Nom d'hôte ou adresse IP de Tvheadend" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Port HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Port HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Nom d'utilisateur" - -msgctxt "#30004" -msgid "Password" -msgstr "Mot de passe" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Temporisation de connexion en secondes" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Temporisation de réponse en secondes" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Paramètres de transcodage pour Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Paramètres de transcodage" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Activer le transcodage" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Codec audio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Codec vidéo" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Résolution" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Déconnecté de '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Reconnecté à '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Galician/strings.po b/addons/pvr.hts/addon/resources/language/Galician/strings.po deleted file mode 100644 index 939edc283..000000000 --- a/addons/pvr.hts/addon/resources/language/Galician/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/gl/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: gl\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Nome do host ou enderezo IP" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Porto HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Porto HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Nome de usuario" - -msgctxt "#30004" -msgid "Password" -msgstr "Contrasinal" - -msgctxt "#30006" -msgid "Connect 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 "Tvheadend transcoding settings" -msgstr "Axustes da transcodificación de Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Axustes da transcodificación" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Habilitar a transcodificación" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Códec de audio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Códec de vídeo" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolución" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Desconectado dende '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Reconectado a '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Georgian/strings.po b/addons/pvr.hts/addon/resources/language/Georgian/strings.po deleted file mode 100644 index aa4808819..000000000 --- a/addons/pvr.hts/addon/resources/language/Georgian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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: Georgian (http://www.transifex.com/projects/p/xbmc-main/language/ka/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ka\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend-ის სერვერის სახელი ან IP მისამართი" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP პორტი" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP პორტი" - -msgctxt "#30003" -msgid "Username" -msgstr "მომხმარებელი" - -msgctxt "#30004" -msgid "Password" -msgstr "პაროლი" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "შეერთების დაგვიანება წამებში" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "პასუხის დაგვიანება წამებში" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend ტრანსკოდირების პარამეტრები" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "ტრანსკოდირების პარამეტრები" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "ტრანსკოდირების ჩართვა" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "აუდიო კოდეკი" - -msgctxt "#30104" -msgid "Video codec" -msgstr "ვიდეო კოდეკი" - -msgctxt "#30105" -msgid "Resolution" -msgstr "გარჩევადობა" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "'%s' გამოირთო" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "'%s' ისევ შეერთდა" diff --git a/addons/pvr.hts/addon/resources/language/German/strings.po b/addons/pvr.hts/addon/resources/language/German/strings.po deleted file mode 100644 index de917138a..000000000 --- a/addons/pvr.hts/addon/resources/language/German/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/de/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: de\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend-Hostname oder IP-Adresse" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP-Port" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP-Port" - -msgctxt "#30003" -msgid "Username" -msgstr "Benutzername" - -msgctxt "#30004" -msgid "Password" -msgstr "Passwort" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Verbindungszeitüberschreitung in Sekunden" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Antwortzeitüberschreitung in Sekunden" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend-Transkodierungseinstellungen" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Transkodierungseinstellungen" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Transkodierung aktivieren" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Audiocodec" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Videocodec" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Auflösung" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Getrennt von '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Wieder verbunden mit '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Greek/strings.po b/addons/pvr.hts/addon/resources/language/Greek/strings.po deleted file mode 100644 index 61438946c..000000000 --- a/addons/pvr.hts/addon/resources/language/Greek/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/el/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: el\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Όνομα Υπολογιστή ή διεύθυνση IP του Tvheadend" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Θύρα HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Θύρα HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Όνομα χρήστη" - -msgctxt "#30004" -msgid "Password" -msgstr "Κωδικός πρόσβασης" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Χρονικό όριο σύνδεσης σε δευτερόλεπτα" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Χρόνος απόκρισης σε δευτερόλεπτα" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Ρυθμίσεις διακωδικοποίησης του Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Ρυθμίσεις διακωδικοποίησης" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Ενεργοποίηση διακωδικοποίησης" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Κωδικοποίηση ήχου" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Κωδικοποίηση βίντεο" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Ανάλυση" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Αποσύνδεση από '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Επανασύνδεση σε '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Haitian (Haitian Creole)/strings.po b/addons/pvr.hts/addon/resources/language/Haitian (Haitian Creole)/strings.po deleted file mode 100644 index 7f1738b7a..000000000 --- a/addons/pvr.hts/addon/resources/language/Haitian (Haitian Creole)/strings.po +++ /dev/null @@ -1,25 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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: Haitian (Haitian Creole) (http://www.transifex.com/projects/p/xbmc-main/language/ht/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ht\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30003" -msgid "Username" -msgstr "nom itilizateur" - -msgctxt "#30004" -msgid "Password" -msgstr "mo de pas" diff --git a/addons/pvr.hts/addon/resources/language/Hebrew/strings.po b/addons/pvr.hts/addon/resources/language/Hebrew/strings.po deleted file mode 100644 index c3b299afd..000000000 --- a/addons/pvr.hts/addon/resources/language/Hebrew/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/he/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: he\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "שם מארח או כתובת IP" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "פורט HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "פורט HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "שם משתמש" - -msgctxt "#30004" -msgid "Password" -msgstr "סיסמה" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "זמן מירבי לניסיון חיבור בשניות" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "זמן המתנה מירבי לתגובה בשניות" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "הגדרות קידוד מחדש" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "הגדרות קידוד מחדש" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "אפשר קידוד מחדש" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "מקודד שמע" - -msgctxt "#30104" -msgid "Video codec" -msgstr "מקודד וידאו" - -msgctxt "#30105" -msgid "Resolution" -msgstr "אבחנה" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "נותק מ־'%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "חובר חזרה ל־'%s'" diff --git a/addons/pvr.hts/addon/resources/language/Hindi (Devanagiri)/strings.po b/addons/pvr.hts/addon/resources/language/Hindi (Devanagiri)/strings.po deleted file mode 100644 index 0d8f7a3cb..000000000 --- a/addons/pvr.hts/addon/resources/language/Hindi (Devanagiri)/strings.po +++ /dev/null @@ -1,25 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (Devanagiri) (http://www.transifex.com/projects/p/xbmc-main/language/hi/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: hi\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30003" -msgid "Username" -msgstr "उपयोगकर्ता नाम" - -msgctxt "#30105" -msgid "Resolution" -msgstr "संकल्प" diff --git a/addons/pvr.hts/addon/resources/language/Hungarian/strings.po b/addons/pvr.hts/addon/resources/language/Hungarian/strings.po deleted file mode 100644 index b790db2c7..000000000 --- a/addons/pvr.hts/addon/resources/language/Hungarian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/hu/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: hu\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "TVHeadend kiszolgálónév vagy IP cím" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP Port" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP port" - -msgctxt "#30003" -msgid "Username" -msgstr "Felhasználónév" - -msgctxt "#30004" -msgid "Password" -msgstr "Jelszó" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Kapcsolódási időkorlát másodpercben" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Válasz időkorlát másodpercben" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "TV fejállomás átkódolási beállítások" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Átkódolási beállítások" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Átkódolási beállítások engedélyezése" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Hang codec" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Videó codec" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Felbontás" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "'%s': Kapcsolat bontva" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "'%s': Újrakapcsolódva" diff --git a/addons/pvr.hts/addon/resources/language/Icelandic/strings.po b/addons/pvr.hts/addon/resources/language/Icelandic/strings.po deleted file mode 100644 index fc34223a0..000000000 --- a/addons/pvr.hts/addon/resources/language/Icelandic/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/is/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: is\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Nafn eða IP tala Tvheadend" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP gátt" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP gátt" - -msgctxt "#30003" -msgid "Username" -msgstr "Notandanafn" - -msgctxt "#30004" -msgid "Password" -msgstr "Lykilorð" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Tímatakmörk tengingar í sekúndum" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Tímatakmörk svartíma í sekúndum" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Stillingar umkóðara Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Stillingar umkóðara" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Virkja umkóðun" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Hljóðkóðari" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Myndkóðari" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Upplausn" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Aftengdur frá '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Endurtengdur við '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Indonesian/strings.po b/addons/pvr.hts/addon/resources/language/Indonesian/strings.po deleted file mode 100644 index fe1770b9e..000000000 --- a/addons/pvr.hts/addon/resources/language/Indonesian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/id/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: id\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Hostname atau alamat IP Tvheadend" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Port HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Port HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "NamaPengguna" - -msgctxt "#30004" -msgid "Password" -msgstr "Password" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Timeout Koneksi dalam detik" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Timeout response dalam deti" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Pengaturan transcoding Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Pengaturan Transcoding" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Fungsikan Transcoding" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Kodek Audio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Kodek video" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolusi" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Terputus dari '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Tersambung lagi pada '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Italian/strings.po b/addons/pvr.hts/addon/resources/language/Italian/strings.po deleted file mode 100644 index 327fe30cf..000000000 --- a/addons/pvr.hts/addon/resources/language/Italian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/it/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: it\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend hostname o indirizzo IP" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Porta HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Porta HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Nome utente" - -msgctxt "#30004" -msgid "Password" -msgstr "Password" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Timeout della connessione in secondi" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Timeout della risposta in secondi" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Impostazioni principali transcodifica TV" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Impostazioni transcodifica" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Abilita transcodifica" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Codec audio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Codec video" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Risoluzione" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Disconnesso da '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Riconnesso a '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Japanese/strings.po b/addons/pvr.hts/addon/resources/language/Japanese/strings.po deleted file mode 100644 index d57227e5e..000000000 --- a/addons/pvr.hts/addon/resources/language/Japanese/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/ja/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ja\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "TVheadend ホスト名または IP アドレス" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP ポート" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP ポート" - -msgctxt "#30003" -msgid "Username" -msgstr "ユーザー名" - -msgctxt "#30004" -msgid "Password" -msgstr "パスワード" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "接続タイムアウト (秒)" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "レスポンスのタイムアウト (秒)" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend のトランスコードを設定" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "トランスコード設定" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "トランスコードを有効化" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "オーディオコーデック" - -msgctxt "#30104" -msgid "Video codec" -msgstr "ビデオコーデック" - -msgctxt "#30105" -msgid "Resolution" -msgstr "画面解像度" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "'%s' との接続が切れました" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "'%s' との接続が復活しました" diff --git a/addons/pvr.hts/addon/resources/language/Korean/strings.po b/addons/pvr.hts/addon/resources/language/Korean/strings.po deleted file mode 100644 index 21105f564..000000000 --- a/addons/pvr.hts/addon/resources/language/Korean/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/ko/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ko\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend 호스트네임 또는 IP 주소" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP 포트" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP 포트" - -msgctxt "#30003" -msgid "Username" -msgstr "사용자명" - -msgctxt "#30004" -msgid "Password" -msgstr "비밀번호" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "연결시간 제한 (초)" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "응답시간 제한 (초)" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend 트랜스코딩 설정" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "트랜스코딩 설정" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "트랜스코딩 사용" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "오디오 코덱" - -msgctxt "#30104" -msgid "Video codec" -msgstr "비디오 코덱" - -msgctxt "#30105" -msgid "Resolution" -msgstr "해상도" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "'%s' 연결 해제됨" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "'%s' 다시 연결됨" diff --git a/addons/pvr.hts/addon/resources/language/Latvian/strings.po b/addons/pvr.hts/addon/resources/language/Latvian/strings.po deleted file mode 100644 index ccb01dd98..000000000 --- a/addons/pvr.hts/addon/resources/language/Latvian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/lv/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: lv\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend saimniekvārds vai IP adrese" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP ports" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP ports" - -msgctxt "#30003" -msgid "Username" -msgstr "LIetotājvārds" - -msgctxt "#30004" -msgid "Password" -msgstr "Parole" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Savienojuma noilgums sekundēs" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Atbildes noilgums sekundēs" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend pārkodēšanas iestatījumi" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Transkodēšanas iestatījumi" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Ieslēgt transkodēšanu" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Audio kodeks" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Video kodeks" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Izšķirtspēja" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Atvienots no '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Atkal savienots '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Lithuanian/strings.po b/addons/pvr.hts/addon/resources/language/Lithuanian/strings.po deleted file mode 100644 index 8b7f8a97d..000000000 --- a/addons/pvr.hts/addon/resources/language/Lithuanian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/lt/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: 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 "Tvheadend hostname or IP address" -msgstr "Tvheadend host pavadinimas arba IP adresas" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP portas" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP portas" - -msgctxt "#30003" -msgid "Username" -msgstr "Vartotojo vardas" - -msgctxt "#30004" -msgid "Password" -msgstr "Slaptažodis" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Prisijungimo užlaikymas sek." - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Atsakymo laikas sek." - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend transkodavimo nustatymai" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Transkodavimo nustatymai" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Įjungti transkodavimą" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Audio kodekai" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Vaizdo kodekai" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Rezoliucija" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Atsijungta nuo '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Prisijungta prie '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Macedonian/strings.po b/addons/pvr.hts/addon/resources/language/Macedonian/strings.po deleted file mode 100644 index 94d1bec30..000000000 --- a/addons/pvr.hts/addon/resources/language/Macedonian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/mk/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: mk\n" -"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend хост или IP адреса" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP порта" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP порта" - -msgctxt "#30003" -msgid "Username" -msgstr "Корисничко име" - -msgctxt "#30004" -msgid "Password" -msgstr "Лозинка" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Тајмаут за поврзување во секунди" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Тајмаут на реакција во секунди" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Поставки за транскодирање на Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Поставки за транскодирање" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Активирај транскодирање" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Аудио кодек" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Видео кодек" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Резолуција" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Дисконектиран од '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Повторно поврзан со '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Malay/strings.po b/addons/pvr.hts/addon/resources/language/Malay/strings.po deleted file mode 100644 index 95adba88f..000000000 --- a/addons/pvr.hts/addon/resources/language/Malay/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/ms/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ms\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Nama hos atau alamat IP Tvheadend" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Port HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Port HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Nama Pengguna" - -msgctxt "#30004" -msgid "Password" -msgstr "Kata Laluan" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Had masa tamat sambung dalam saat" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Had masa tamat respons dalam saat" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tetapan transkod " - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Tetapan transkod" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Benarkan transkod" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Kodeks audio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Kodeks video" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolusi" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Terputus dari '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Bersambung semula dengan '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Malayalam/strings.po b/addons/pvr.hts/addon/resources/language/Malayalam/strings.po deleted file mode 100644 index a0ca6b452..000000000 --- a/addons/pvr.hts/addon/resources/language/Malayalam/strings.po +++ /dev/null @@ -1,21 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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: Malayalam (http://www.transifex.com/projects/p/xbmc-main/language/ml/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ml\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30105" -msgid "Resolution" -msgstr "വ്യക്തത" diff --git a/addons/pvr.hts/addon/resources/language/Maltese/strings.po b/addons/pvr.hts/addon/resources/language/Maltese/strings.po deleted file mode 100644 index 963e585b0..000000000 --- a/addons/pvr.hts/addon/resources/language/Maltese/strings.po +++ /dev/null @@ -1,29 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/mt/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: 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 "#30003" -msgid "Username" -msgstr "Username" - -msgctxt "#30004" -msgid "Password" -msgstr "Sigriet" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolution:" diff --git a/addons/pvr.hts/addon/resources/language/Maori/strings.po b/addons/pvr.hts/addon/resources/language/Maori/strings.po deleted file mode 100644 index 32a8c0d89..000000000 --- a/addons/pvr.hts/addon/resources/language/Maori/strings.po +++ /dev/null @@ -1,37 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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/xbmc-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 "#30003" -msgid "Username" -msgstr "Ingoa kaiwhakamahi" - -msgctxt "#30004" -msgid "Password" -msgstr "Kupuhipa" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Kōtēke Ororongo" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Kōtēke Ataata" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Taumira" diff --git a/addons/pvr.hts/addon/resources/language/Mongolian (Mongolia)/strings.po b/addons/pvr.hts/addon/resources/language/Mongolian (Mongolia)/strings.po deleted file mode 100644 index 0123e783d..000000000 --- a/addons/pvr.hts/addon/resources/language/Mongolian (Mongolia)/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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/xbmc-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 "Tvheadend hostname or IP address" -msgstr "Tvheadend нэр эсвэл IP хаяг" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP порт" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP порт" - -msgctxt "#30003" -msgid "Username" -msgstr "Хэрэглэгчийн нэр" - -msgctxt "#30004" -msgid "Password" -msgstr "Нууц үг" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Холболтын хугацаа хэтрэлт, секундээр" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Хариу хугацаа хэтрэлт, секундээр" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend код хөрвүүлэлтийн тохиргоо" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Код хөрвүүлэлтийн тохиргоо" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Код хөрвүүлэлтийг идэвхижүүлэх" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Аудио кодек" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Видео кодек" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Нягтаршил" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "'%s'-с салгагдлаа" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "'%s'-д дахин холбогдлоо" diff --git a/addons/pvr.hts/addon/resources/language/Norwegian/strings.po b/addons/pvr.hts/addon/resources/language/Norwegian/strings.po deleted file mode 100644 index 840a88e94..000000000 --- a/addons/pvr.hts/addon/resources/language/Norwegian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/no/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: no\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend vertsnavn eller IP-adresse" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP-port" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP-port" - -msgctxt "#30003" -msgid "Username" -msgstr "Brukernavn" - -msgctxt "#30004" -msgid "Password" -msgstr "Passord" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Tidsavbrudd ved tilkobling" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Tidsavbrudd ved venting på respons" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Innstillinger for Tvheadend-transkoding" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Innstillinger for transkoding" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Aktiver transkoding" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Lydkodek" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Videokodek" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Oppløsning" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Koblet fra '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Koblet til på nytt til '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Persian (Iran)/strings.po b/addons/pvr.hts/addon/resources/language/Persian (Iran)/strings.po deleted file mode 100644 index 596584d92..000000000 --- a/addons/pvr.hts/addon/resources/language/Persian (Iran)/strings.po +++ /dev/null @@ -1,29 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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/xbmc-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 "#30003" -msgid "Username" -msgstr "نام کاربری" - -msgctxt "#30004" -msgid "Password" -msgstr "رمز عبور" - -msgctxt "#30105" -msgid "Resolution" -msgstr "رزولیشن" diff --git a/addons/pvr.hts/addon/resources/language/Persian/strings.po b/addons/pvr.hts/addon/resources/language/Persian/strings.po deleted file mode 100644 index d2244ee5a..000000000 --- a/addons/pvr.hts/addon/resources/language/Persian/strings.po +++ /dev/null @@ -1,25 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/fa/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fa\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30003" -msgid "Username" -msgstr "نام کاربری" - -msgctxt "#30004" -msgid "Password" -msgstr "کلمه عبور" diff --git a/addons/pvr.hts/addon/resources/language/Polish/strings.po b/addons/pvr.hts/addon/resources/language/Polish/strings.po deleted file mode 100644 index 7bfe2456e..000000000 --- a/addons/pvr.hts/addon/resources/language/Polish/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/pl/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: 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 "Tvheadend hostname or IP address" -msgstr "Nazwa hosta lub adres IP" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Port HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Port HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Użytkownik" - -msgctxt "#30004" -msgid "Password" -msgstr "Hasło" - -msgctxt "#30006" -msgid "Connect 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 "Tvheadend transcoding settings" -msgstr "Ustawienia transkodowania Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Ustawienia transkodowania" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Aktywuj transkodowanie" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Kodek audio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Kodek wideo" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Rozdzielczość" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Rozłączono z '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Połączono ponownie z '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Portuguese (Brazil)/strings.po b/addons/pvr.hts/addon/resources/language/Portuguese (Brazil)/strings.po deleted file mode 100644 index 8d718b4a1..000000000 --- a/addons/pvr.hts/addon/resources/language/Portuguese (Brazil)/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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/xbmc-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 "Tvheadend hostname or IP address" -msgstr "Tvheadend: Hostname ou endereço IP" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Porta HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Porta HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Nome do usuário" - -msgctxt "#30004" -msgid "Password" -msgstr "Senha" - -msgctxt "#30006" -msgid "Connect 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 "Tvheadend transcoding settings" -msgstr "Ajustes de transcodificação Tvheadend " - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Ajustes de transcodificação" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Ativar transcodificação" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Codec de áudio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Codec de vídeo" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolução" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Desconectado de '%s' " - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Reconectado a '%s' " diff --git a/addons/pvr.hts/addon/resources/language/Portuguese/strings.po b/addons/pvr.hts/addon/resources/language/Portuguese/strings.po deleted file mode 100644 index 2ec288a19..000000000 --- a/addons/pvr.hts/addon/resources/language/Portuguese/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/pt/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: pt\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Nome do servidor Tvheadend ou endereço IP" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Porta HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Porta HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Nome de utilizador" - -msgctxt "#30004" -msgid "Password" -msgstr "Palavra-passe" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Tempo limite para ligação em segundos" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Tempo limite para resposta em segundos" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Definições de transcodificação Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Definições de transcodificação" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Activar transcodificação" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Codec de áudio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Codec de vídeo" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolução" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Desligado de '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Ligado novamente a '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Romanian/strings.po b/addons/pvr.hts/addon/resources/language/Romanian/strings.po deleted file mode 100644 index 923acf10f..000000000 --- a/addons/pvr.hts/addon/resources/language/Romanian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/ro/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ro\n" -"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Nume gazdă sau adresă IP pentru Tvheadend" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Port HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Port HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Utilizator" - -msgctxt "#30004" -msgid "Password" -msgstr "Parolă" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Așteptare conectare în secunde" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Așteptare răspuns în secunde" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Setări transcodare Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Setări transcodare" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Activare transcodare" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Codec audio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Codec video" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Rezoluție" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Deconectat de la '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Reconectat la '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Russian/strings.po b/addons/pvr.hts/addon/resources/language/Russian/strings.po deleted file mode 100644 index 2c1819f51..000000000 --- a/addons/pvr.hts/addon/resources/language/Russian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/ru/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: 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 "Tvheadend hostname or IP address" -msgstr "Имя пользователя или IP-адрес Tvheadend" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Порт HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Порт HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Имя пользователя" - -msgctxt "#30004" -msgid "Password" -msgstr "Пароль" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Ожидание подключения (сек.)" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Ожидание ответа (сек.)" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Настройки транскодинга Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Настройки транскодирования" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Включить транскодинг" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Кодек аудио" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Кодек видео" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Разрешение" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Отключен от \"%s\"" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Переподключен к \"%s\"" diff --git a/addons/pvr.hts/addon/resources/language/Serbian (Cyrillic)/strings.po b/addons/pvr.hts/addon/resources/language/Serbian (Cyrillic)/strings.po deleted file mode 100644 index fc015f784..000000000 --- a/addons/pvr.hts/addon/resources/language/Serbian (Cyrillic)/strings.po +++ /dev/null @@ -1,65 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (Cyrillic) (http://www.transifex.com/projects/p/xbmc-main/language/sr_RS/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sr_RS\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Име хоста или ИП адреса Tvheadend-а" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP прикључак" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP прикључак" - -msgctxt "#30003" -msgid "Username" -msgstr "Корисничко име" - -msgctxt "#30004" -msgid "Password" -msgstr "Лозинка" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Чекање повезивања у секундама" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Чекање одговора у секундама" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Кодек звука" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Видео кодек" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Резолуција" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Искључен из '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Повово прикључен на '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Serbian/strings.po b/addons/pvr.hts/addon/resources/language/Serbian/strings.po deleted file mode 100644 index e986e5f3f..000000000 --- a/addons/pvr.hts/addon/resources/language/Serbian/strings.po +++ /dev/null @@ -1,37 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/sr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sr\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 "#30003" -msgid "Username" -msgstr "Korisničko ime" - -msgctxt "#30004" -msgid "Password" -msgstr "Lozinka" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Kodek zvuka" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Video kodek" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Rezolucija" diff --git a/addons/pvr.hts/addon/resources/language/Sinhala/strings.po b/addons/pvr.hts/addon/resources/language/Sinhala/strings.po deleted file mode 100644 index e8a5b93dc..000000000 --- a/addons/pvr.hts/addon/resources/language/Sinhala/strings.po +++ /dev/null @@ -1,37 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/si/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: si\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP තිර්ථය" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP තිර්ථය" - -msgctxt "#30003" -msgid "Username" -msgstr "පරිශීලක නම" - -msgctxt "#30004" -msgid "Password" -msgstr "මුරපදය" - -msgctxt "#30105" -msgid "Resolution" -msgstr "සම්මතකරනය" diff --git a/addons/pvr.hts/addon/resources/language/Slovak/strings.po b/addons/pvr.hts/addon/resources/language/Slovak/strings.po deleted file mode 100644 index e47a9f568..000000000 --- a/addons/pvr.hts/addon/resources/language/Slovak/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/sk/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sk\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Názov hostiteľa Tvheadend alebo IP adresa" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP port" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP port" - -msgctxt "#30003" -msgid "Username" -msgstr "Užívateľské meno" - -msgctxt "#30004" -msgid "Password" -msgstr "Heslo" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Časový limit pre spojenie v sekundách" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Časový limit pre odpoveď v sekundách" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Nastavenie Tvheadend prekódovania" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Nastavenie prekódovania" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Povoliť prekódovanie" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Koded audia" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Kodek videa" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Rozlíšenie" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Odpojené od '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Opätovne pripojené k '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Slovenian/strings.po b/addons/pvr.hts/addon/resources/language/Slovenian/strings.po deleted file mode 100644 index dcba79c4e..000000000 --- a/addons/pvr.hts/addon/resources/language/Slovenian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/sl/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sl\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 "Tvheadend hostname or IP address" -msgstr "Ime gostitelja ali IP strežnika Tvheadend" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Vrata HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Vrata HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Uporabniško ime" - -msgctxt "#30004" -msgid "Password" -msgstr "Geslo" - -msgctxt "#30006" -msgid "Connect 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 "Tvheadend transcoding settings" -msgstr "Nastavitve pretvarjanja za Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Nastavitve pretvarjanja" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Vključi pretvarjanje" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Zvočni kodek" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Slikovni kodek" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Ločljivost" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Povezava prekinjena z '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Povezava vzpostavljena z '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Spanish (Argentina)/strings.po b/addons/pvr.hts/addon/resources/language/Spanish (Argentina)/strings.po deleted file mode 100644 index 484a1c05d..000000000 --- a/addons/pvr.hts/addon/resources/language/Spanish (Argentina)/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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/xbmc-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 "Tvheadend hostname or IP address" -msgstr "Tvheadend nombre o dirección IP" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Puerto HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Puerto HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Usuario" - -msgctxt "#30004" -msgid "Password" -msgstr "Contraseña" - -msgctxt "#30006" -msgid "Connect 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 "Tvheadend transcoding settings" -msgstr "Ajuste de transcodificación de TVheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Ajuste de transcodificación" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "ctivar transcodificación" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Códec de audio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Códec de video" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolución" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Desconectado de '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Reconectado a '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Spanish (Mexico)/strings.po b/addons/pvr.hts/addon/resources/language/Spanish (Mexico)/strings.po deleted file mode 100644 index bbddc007d..000000000 --- a/addons/pvr.hts/addon/resources/language/Spanish (Mexico)/strings.po +++ /dev/null @@ -1,53 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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/xbmc-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 "#30001" -msgid "HTTP port" -msgstr "Puerto HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Puerto HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Usuario" - -msgctxt "#30004" -msgid "Password" -msgstr "Contraseña" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Códec de audio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Códec de video" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolución" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Desconectado desde '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Reconectado a '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Spanish/strings.po b/addons/pvr.hts/addon/resources/language/Spanish/strings.po deleted file mode 100644 index 5e55ee7c3..000000000 --- a/addons/pvr.hts/addon/resources/language/Spanish/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/es/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: es\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend nombre o dirección IP" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Puerto HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Puerto HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Usuario" - -msgctxt "#30004" -msgid "Password" -msgstr "Contraseña" - -msgctxt "#30006" -msgid "Connect 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 "Tvheadend transcoding settings" -msgstr "Ajustes de transcodificación de Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Ajustes de transcodificación" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Habilitar la transcodificación" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Códec de audio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Códec de vídeo" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Resolución" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Desconectado de '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Reconectado a '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Swedish/strings.po b/addons/pvr.hts/addon/resources/language/Swedish/strings.po deleted file mode 100644 index 6a0281e6d..000000000 --- a/addons/pvr.hts/addon/resources/language/Swedish/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/sv/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: sv\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend värdnamn eller IP-adress" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP-port" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP-port" - -msgctxt "#30003" -msgid "Username" -msgstr "Användarnamn" - -msgctxt "#30004" -msgid "Password" -msgstr "Lösenord" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Anslutningstimeout i sekunder" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Responstimeout i sekunder" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend omkodningsinställningar" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Omkodningsinställningar" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Aktivera omkodning" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Ljudcodec" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Videocodec" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Upplösning" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Koppa från '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Återanslut till '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Tajik/strings.po b/addons/pvr.hts/addon/resources/language/Tajik/strings.po deleted file mode 100644 index 9dc75cf35..000000000 --- a/addons/pvr.hts/addon/resources/language/Tajik/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/tg/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: tg\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Суроғаи IP ва номи мизбони Tvheadend" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Порти HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Порти HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Номи корбар" - -msgctxt "#30004" -msgid "Password" -msgstr "Парол" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Хотимаи вақти пайваст дар сонияҳо" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Хотимаи вақти посух дар сонияҳо" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Танзимоти рамзгузории Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Танзимоти рамзгузорӣ" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Фаъол кардани рамзгузорӣ" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Кодеки аудио" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Кодеки видео" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Возеҳӣ" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Пайваст бо '%s' қатъ шудааст" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Пайваст бо '%s' барқарор шудааст" diff --git a/addons/pvr.hts/addon/resources/language/Telugu/strings.po b/addons/pvr.hts/addon/resources/language/Telugu/strings.po deleted file mode 100644 index 92fe6bfff..000000000 --- a/addons/pvr.hts/addon/resources/language/Telugu/strings.po +++ /dev/null @@ -1,25 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/te/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: te\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -msgctxt "#30003" -msgid "Username" -msgstr "వాడుకరి పేరు" - -msgctxt "#30004" -msgid "Password" -msgstr "సంకేతపదం" diff --git a/addons/pvr.hts/addon/resources/language/Thai/strings.po b/addons/pvr.hts/addon/resources/language/Thai/strings.po deleted file mode 100644 index 688475378..000000000 --- a/addons/pvr.hts/addon/resources/language/Thai/strings.po +++ /dev/null @@ -1,37 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/th/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: th\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30003" -msgid "Username" -msgstr "ชื่อผู้ใช้" - -msgctxt "#30004" -msgid "Password" -msgstr "รหัสผ่าน" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "ตัวแปลงสัญญาณเสียง" - -msgctxt "#30104" -msgid "Video codec" -msgstr "ตัวแปลงสัญญาณวิดีโอ" - -msgctxt "#30105" -msgid "Resolution" -msgstr "ความละเอียดจอ" diff --git a/addons/pvr.hts/addon/resources/language/Turkish/strings.po b/addons/pvr.hts/addon/resources/language/Turkish/strings.po deleted file mode 100644 index 0f5c7775d..000000000 --- a/addons/pvr.hts/addon/resources/language/Turkish/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/tr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: tr\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tvheadend ana bilgisayar adı veya IP adresi" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "HTTP portu" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "HTSP portu" - -msgctxt "#30003" -msgid "Username" -msgstr "Kullanıcı adı" - -msgctxt "#30004" -msgid "Password" -msgstr "Parola" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Saniye cinsinden bağlantı zaman aşımı" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Saniye cinsinden yanıt zaman aşımı süresi" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Tvheadend dönüştürme ayarları" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Dönüştürme ayarları" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Dönüştürmeyi etkinleştir" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Ses codec" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Video codec" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Çözünürlük" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "'%s' Bağlantı kesilecek" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Tekrar bağlanmaya '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Ukrainian/strings.po b/addons/pvr.hts/addon/resources/language/Ukrainian/strings.po deleted file mode 100644 index ecac24045..000000000 --- a/addons/pvr.hts/addon/resources/language/Ukrainian/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/uk/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: uk\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 "Tvheadend hostname or IP address" -msgstr "Ім'я серверу Tvheadend або його IP адреса" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Порт HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Порт HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Ім'я користувача" - -msgctxt "#30004" -msgid "Password" -msgstr "Пароль" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Перерва у зв’язку в секундах" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Затримка відклику в секундах" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Налаштування конвертування з Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Налаштування конвертування" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Включити конвертування" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Кодування аудіо" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Кодування відео" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Роздільна здатність" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Від’єднано від '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Знову з’єднано з '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Uzbek/strings.po b/addons/pvr.hts/addon/resources/language/Uzbek/strings.po deleted file mode 100644 index 9eb7bd7b7..000000000 --- a/addons/pvr.hts/addon/resources/language/Uzbek/strings.po +++ /dev/null @@ -1,29 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/uz/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: uz\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30003" -msgid "Username" -msgstr "Foydalanuvchi nomi" - -msgctxt "#30004" -msgid "Password" -msgstr "Maxfiy so'z" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Ekran o'lchamlari" diff --git a/addons/pvr.hts/addon/resources/language/Vietnamese/strings.po b/addons/pvr.hts/addon/resources/language/Vietnamese/strings.po deleted file mode 100644 index f6a3e9a62..000000000 --- a/addons/pvr.hts/addon/resources/language/Vietnamese/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/vi/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: vi\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Tên miền hoặc địa chỉ IP của Tvheadend" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Cổng HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Cổng HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Tên truy cập" - -msgctxt "#30004" -msgid "Password" -msgstr "Mật khẩu" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Số giây tự ngắt kết nối" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Số giây tự ngắt chờ" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Thiết lập bộ chuyển mã của Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Thiết lập bộ chuyển mã" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Sử dụng bộ chuyển mã" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Bộ giải mã Audio" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Bộ giải mã Video" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Độ phân giải" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Đã ngắt kết nối từ '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Đã kết nối lại tới '%s'" diff --git a/addons/pvr.hts/addon/resources/language/Welsh/strings.po b/addons/pvr.hts/addon/resources/language/Welsh/strings.po deleted file mode 100644 index a4b069ce2..000000000 --- a/addons/pvr.hts/addon/resources/language/Welsh/strings.po +++ /dev/null @@ -1,77 +0,0 @@ -# Kodi Media Center language file -# Addon Name: Tvheadend HTSP Client -# Addon id: pvr.hts -# Addon Provider: Lars Op den Kamp, Team XBMC -msgid "" -msgstr "" -"Project-Id-Version: XBMC Main\n" -"Report-Msgid-Bugs-To: http://trac.xbmc.org/\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 (http://www.transifex.com/projects/p/xbmc-main/language/cy/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: cy\n" -"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;\n" - -msgctxt "#30000" -msgid "Tvheadend hostname or IP address" -msgstr "Enw gwesteiwr neu gyfeiriad IP Tvheadend" - -msgctxt "#30001" -msgid "HTTP port" -msgstr "Porth HTTP" - -msgctxt "#30002" -msgid "HTSP port" -msgstr "Porth HTSP" - -msgctxt "#30003" -msgid "Username" -msgstr "Enw defnyddiwr" - -msgctxt "#30004" -msgid "Password" -msgstr "Cyfrinair" - -msgctxt "#30006" -msgid "Connect timeout in seconds" -msgstr "Amser allan cysylltu mewn eiliadau" - -msgctxt "#30007" -msgid "Response timeout in seconds" -msgstr "Ymateb amser allan mewn eiliadau" - -msgctxt "#30100" -msgid "Tvheadend transcoding settings" -msgstr "Gosodiadau trawscodio Tvheadend" - -msgctxt "#30101" -msgid "Transcoding settings" -msgstr "Gosodiadau trawscodio" - -msgctxt "#30102" -msgid "Enable transcoding" -msgstr "Galluogi trawscodio" - -msgctxt "#30103" -msgid "Audio codec" -msgstr "Codec sain" - -msgctxt "#30104" -msgid "Video codec" -msgstr "Codec fideo" - -msgctxt "#30105" -msgid "Resolution" -msgstr "Cydraniad" - -msgctxt "#30500" -msgid "Disconnected from '%s'" -msgstr "Datgysylltwyd o '%s'" - -msgctxt "#30501" -msgid "Reconnected to '%s'" -msgstr "Ail gysylltwyd â '%s'" diff --git a/addons/pvr.hts/addon/resources/settings.xml b/addons/pvr.hts/addon/resources/settings.xml index 8ac80368d..db97a4fd6 100644 --- a/addons/pvr.hts/addon/resources/settings.xml +++ b/addons/pvr.hts/addon/resources/settings.xml @@ -1,15 +1,20 @@ - - - - - - - - - - - - + + + + + + + + + + + + + + + + + diff --git a/addons/pvr.hts/addon/resources/skins/Confluence/720p/DialogTranscode.xml b/addons/pvr.hts/addon/resources/skins/Confluence/720p/DialogTranscode.xml deleted file mode 100644 index 191b8f4cd..000000000 --- a/addons/pvr.hts/addon/resources/skins/Confluence/720p/DialogTranscode.xml +++ /dev/null @@ -1,170 +0,0 @@ - - 10 - - 1 - 240 - 100 - - dialogeffect - - - background image - 0 - 0 - 800 - 500 - DialogBack.png - - - Dialog Header image - 40 - 16 - 720 - 40 - dialogheader.png - - - header label - 40 - 20 - 720 - 30 - font13_title - - center - center - selected - black - - - Close Window button - 710 - 15 - 64 - 32 - - - - PreviousMenu - DialogCloseButton-focus.png - DialogCloseButton.png - 10 - 10 - 10 - 10 - system.getbool(input.enablemouse) - - - - Enable transcoding - 40 - 50 - 40 - 720 - - font13 - grey2 - white - button-nofocus.png - button-focus2.png - 10 - 10 - 1 - 11 - - - - Audio codec - 40 - 100 - 720 - 40 - font13 - grey2 - white - button-nofocus.png - button-focus2.png - - 11 - 11 - 10 - 12 - - - - Video codec - 40 - 150 - 720 - 40 - font13 - grey2 - white - button-nofocus.png - button-focus2.png - center - - 12 - 12 - 11 - 13 - - - - Resolution - 40 - 200 - 720 - 40 - font13 - grey2 - white - button-nofocus.png - button-focus2.png - center - - 13 - 13 - 12 - 1 - - - - 190 - 435 - - Ok Button - 0 - 0 - 200 - 40 - center - center - button-nofocus.png - button-focus.png - - font12_title - 13 - 2 - 2 - 10 - - - Cancel Button - 210 - 0 - 200 - 40 - center - center - button-nofocus.png - button-focus.png - - font12_title - 13 - 1 - 1 - 10 - - - - diff --git a/addons/pvr.hts/project/VS2010Express/pvrclient_tvheadend.vcxproj b/addons/pvr.hts/project/VS2010Express/pvrclient_tvheadend.vcxproj index fbd15b292..4a831e220 100644 --- a/addons/pvr.hts/project/VS2010Express/pvrclient_tvheadend.vcxproj +++ b/addons/pvr.hts/project/VS2010Express/pvrclient_tvheadend.vcxproj @@ -86,29 +86,29 @@ if errorlevel 1 exit 0 else exit %errorlevel% + + {00700e12-a63b-4e54-b962-4011a90584bd} + + + {fe4573f6-a794-4ad3-b37f-49e51f1140e6} + + + + - - - + + + + - - - - - - - - {00700e12-a63b-4e54-b962-4011a90584bd} - - - {fe4573f6-a794-4ad3-b37f-49e51f1140e6} - + + diff --git a/addons/pvr.hts/project/VS2010Express/pvrclient_tvheadend.vcxproj.filters b/addons/pvr.hts/project/VS2010Express/pvrclient_tvheadend.vcxproj.filters index 7876057ba..10bcf1034 100644 --- a/addons/pvr.hts/project/VS2010Express/pvrclient_tvheadend.vcxproj.filters +++ b/addons/pvr.hts/project/VS2010Express/pvrclient_tvheadend.vcxproj.filters @@ -15,45 +15,45 @@ - + Source Files - + Source Files - + Source Files - + Source Files - + + Source Files + + Source Files - + Source Files - - Header Files - - + Header Files - + Header Files - + Header Files Header Files - + Header Files - + Header Files diff --git a/addons/pvr.hts/src/AsyncState.cpp b/addons/pvr.hts/src/AsyncState.cpp new file mode 100644 index 000000000..223e7e237 --- /dev/null +++ b/addons/pvr.hts/src/AsyncState.cpp @@ -0,0 +1,59 @@ +/* + * 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 * 1000; +} + +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); +} diff --git a/addons/pvr.hts/src/AsyncState.h b/addons/pvr.hts/src/AsyncState.h new file mode 100644 index 000000000..ed9638bda --- /dev/null +++ b/addons/pvr.hts/src/AsyncState.h @@ -0,0 +1,86 @@ +/* + * 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 */ + diff --git a/addons/pvr.hts/src/CircBuffer.cpp b/addons/pvr.hts/src/CircBuffer.cpp index 376334248..74e38ddec 100644 --- a/addons/pvr.hts/src/CircBuffer.cpp +++ b/addons/pvr.hts/src/CircBuffer.cpp @@ -14,8 +14,7 @@ * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to - * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ @@ -39,7 +38,14 @@ void CCircBuffer::alloc(size_t size) { if (size > m_alloc) { m_alloc = size; - m_buffer = (unsigned char*) realloc(m_buffer, size); + + // don't allow memory to leak on realloc failure + unsigned char * buffer = (unsigned char*) realloc(m_buffer, size); + + if (!buffer) + ::free(m_buffer); + else + m_buffer = buffer; } m_size = size; reset(); @@ -80,7 +86,6 @@ size_t CCircBuffer::free(void) const ssize_t CCircBuffer::write(const unsigned char* data, size_t len) { - size_t pt1, pt2; if (m_size < 2) return -1; if (len > free()) @@ -88,6 +93,7 @@ ssize_t CCircBuffer::write(const unsigned char* data, size_t len) if (m_pin < m_pout) memcpy(m_buffer+m_pin, data, len); else { + size_t pt1, pt2; pt1 = m_size - m_pin; if (len < pt1) { pt1 = len; @@ -105,7 +111,6 @@ ssize_t CCircBuffer::write(const unsigned char* data, size_t len) ssize_t CCircBuffer::read(unsigned char* data, size_t len) { - size_t pt1, pt2; if (m_size < 2) return -1; if (len > avail()) @@ -113,6 +118,7 @@ ssize_t CCircBuffer::read(unsigned char* data, size_t len) if (m_pout < m_pin) memcpy(data, m_buffer+m_pout, len); else { + size_t pt1, pt2; pt1 = m_size - m_pout; if (len < pt1) { pt1 = len; diff --git a/addons/pvr.hts/src/CircBuffer.h b/addons/pvr.hts/src/CircBuffer.h index 490aece2a..80b99f796 100644 --- a/addons/pvr.hts/src/CircBuffer.h +++ b/addons/pvr.hts/src/CircBuffer.h @@ -16,8 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to - * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ diff --git a/addons/pvr.hts/src/GUIDialogTranscode.cpp b/addons/pvr.hts/src/GUIDialogTranscode.cpp deleted file mode 100644 index e459dcf3d..000000000 --- a/addons/pvr.hts/src/GUIDialogTranscode.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/* - * 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, 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#include "GUIDialogTranscode.h" -#include "libXBMC_gui.h" - -#define BUTTON_OK 1 -#define BUTTON_CANCEL 2 - -#define CONTROL_RADIO_BUTTON_TRANSCODE 10 -#define SPIN_CONTROL_AUDIO_CODEC 11 -#define SPIN_CONTROL_VIDEO_CODEC 12 -#define SPIN_CONTROL_RESOLUTION 13 - -CGUIDialogTranscode::CGUIDialogTranscode(const CodecVector &v) : - m_window(0), m_spinAudioCodec(0), m_spinVideoCodec(0), m_spinResolution(0), - m_radioTranscode(0), m_codecs(v) -{ - m_window = GUI->Window_create("DialogTranscode.xml", "Confluence", false, true); - m_window->m_cbhdl = this; - m_window->CBOnInit = OnInitCB; - m_window->CBOnFocus = OnFocusCB; - m_window->CBOnClick = OnClickCB; - m_window->CBOnAction = OnActionCB; -} - -CGUIDialogTranscode::~CGUIDialogTranscode() -{ - GUI->Window_destroy(m_window); -} - -bool CGUIDialogTranscode::OnInitCB(GUIHANDLE cbhdl) -{ - CGUIDialogTranscode* dialog = static_cast(cbhdl); - return dialog->OnInit(); -} - -bool CGUIDialogTranscode::OnClickCB(GUIHANDLE cbhdl, int controlId) -{ - CGUIDialogTranscode* dialog = static_cast(cbhdl); - return dialog->OnClick(controlId); -} - -bool CGUIDialogTranscode::OnFocusCB(GUIHANDLE cbhdl, int controlId) -{ - CGUIDialogTranscode* dialog = static_cast(cbhdl); - return dialog->OnFocus(controlId); -} - -bool CGUIDialogTranscode::OnActionCB(GUIHANDLE cbhdl, int actionId) -{ - CGUIDialogTranscode* dialog = static_cast(cbhdl); - return dialog->OnAction(actionId); -} - -bool CGUIDialogTranscode::Show() -{ - if (m_window) - return m_window->Show(); - - return false; -} - -void CGUIDialogTranscode::Close() -{ - if (m_window) - m_window->Close(); -} - -void CGUIDialogTranscode::DoModal() -{ - if (m_window) - m_window->DoModal(); -} - -bool CGUIDialogTranscode::OnInit() -{ - m_spinAudioCodec = GUI->Control_getSpin(m_window, SPIN_CONTROL_AUDIO_CODEC); - m_spinVideoCodec = GUI->Control_getSpin(m_window, SPIN_CONTROL_VIDEO_CODEC); - m_spinResolution = GUI->Control_getSpin(m_window, SPIN_CONTROL_RESOLUTION); - - m_radioTranscode = GUI->Control_getRadioButton(m_window, CONTROL_RADIO_BUTTON_TRANSCODE); - - m_spinAudioCodec->Clear(); - m_spinVideoCodec->Clear(); - m_spinResolution->Clear(); - - m_spinAudioCodec->AddLabel("Passthrough", XBMC_INVALID_CODEC_ID); - m_spinVideoCodec->AddLabel("Passthrough", XBMC_INVALID_CODEC_ID); - - int iSelectedAudio(0), iSelectedVideo(0); - for (unsigned int iPtr = 0; iPtr < m_codecs.size(); iPtr++) - { - if (m_codecs.at(iPtr).Codec().codec_type == XBMC_CODEC_TYPE_AUDIO) - { - m_spinAudioCodec->AddLabel(m_codecs.at(iPtr).Name().c_str(), iPtr); - if (m_codecs.at(iPtr).Codec().codec_id == g_audioCodec.Codec().codec_id) - iSelectedAudio = iPtr; - } - else if (m_codecs.at(iPtr).Codec().codec_type == XBMC_CODEC_TYPE_VIDEO) - { - m_spinVideoCodec->AddLabel(m_codecs.at(iPtr).Name().c_str(), iPtr); - if (m_codecs.at(iPtr).Codec().codec_id == g_videoCodec.Codec().codec_id) - iSelectedVideo = iPtr; - } - } - - m_spinResolution->AddLabel("192p", 192); - m_spinResolution->AddLabel("288p", 288); - m_spinResolution->AddLabel("384p", 384); - m_spinResolution->AddLabel("480p", 480); - m_spinResolution->AddLabel("576p", 576); - m_spinResolution->AddLabel("720p", 720); - - if (g_iResolution <= 192) - m_spinResolution->SetValue(192); - else if (g_iResolution <= 288) - m_spinResolution->SetValue(288); - else if (g_iResolution <= 384) - m_spinResolution->SetValue(384); - else if (g_iResolution <= 480) - m_spinResolution->SetValue(480); - else if (g_iResolution <= 576) - m_spinResolution->SetValue(576); - else - m_spinResolution->SetValue(720); - - m_radioTranscode->SetSelected(g_bTranscode); - m_spinAudioCodec->SetValue(iSelectedAudio); - m_spinVideoCodec->SetValue(iSelectedVideo); - - return true; -} - -bool CGUIDialogTranscode::OnClick(int controlId) -{ - if (controlId == BUTTON_CANCEL) - { - m_window->Close(); - GUI->Control_releaseSpin(m_spinAudioCodec); - GUI->Control_releaseSpin(m_spinVideoCodec); - GUI->Control_releaseSpin(m_spinResolution); - - GUI->Control_releaseRadioButton(m_radioTranscode); - } - else if (controlId == BUTTON_OK) - { - g_bTranscode = m_radioTranscode->IsSelected(); - g_iResolution = m_spinResolution->GetValue(); - g_audioCodec = m_codecs.at(m_spinAudioCodec->GetValue()); - g_videoCodec = m_codecs.at(m_spinVideoCodec->GetValue()); - - m_window->Close(); - - GUI->Control_releaseSpin(m_spinAudioCodec); - GUI->Control_releaseSpin(m_spinVideoCodec); - GUI->Control_releaseSpin(m_spinResolution); - - GUI->Control_releaseRadioButton(m_radioTranscode); - } - - return true; -} - -bool CGUIDialogTranscode::OnFocus(int controlId) -{ - return true; -} - -bool CGUIDialogTranscode::OnAction(int actionId) -{ - if (actionId == ADDON_ACTION_CLOSE_DIALOG - || actionId == ADDON_ACTION_PREVIOUS_MENU) - return OnClick(BUTTON_CANCEL); - else - return false; -} - diff --git a/addons/pvr.hts/src/GUIDialogTranscode.h b/addons/pvr.hts/src/GUIDialogTranscode.h deleted file mode 100644 index a2d205a47..000000000 --- a/addons/pvr.hts/src/GUIDialogTranscode.h +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once - -/* - * Copyright (C) 2005-2012 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, 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#include "client.h" -#include "HTSPTypes.h" - -class CGUIDialogTranscode -{ - -public: - CGUIDialogTranscode(const CodecVector&); - virtual ~CGUIDialogTranscode(); - - bool Show(); - void Close(); - void DoModal(); - -private: - bool OnClick(int controlId); - bool OnFocus(int controlId); - bool OnInit(); - bool OnAction(int actionId); - - static bool OnClickCB(GUIHANDLE cbhdl, int controlId); - static bool OnFocusCB(GUIHANDLE cbhdl, int controlId); - static bool OnInitCB(GUIHANDLE cbhdl); - static bool OnActionCB(GUIHANDLE cbhdl, int actionId); - - CAddonGUIWindow *m_window; - - CAddonGUISpinControl *m_spinAudioCodec; - CAddonGUISpinControl *m_spinVideoCodec; - CAddonGUISpinControl *m_spinResolution; - CAddonGUIRadioButton *m_radioTranscode; - - CodecVector m_codecs; -}; - diff --git a/addons/pvr.hts/src/HTSPConnection.cpp b/addons/pvr.hts/src/HTSPConnection.cpp index 8d2f66005..7a6ce0713 100644 --- a/addons/pvr.hts/src/HTSPConnection.cpp +++ b/addons/pvr.hts/src/HTSPConnection.cpp @@ -14,17 +14,14 @@ * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to - * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ -#include "HTSPConnection.h" #include "platform/threads/mutex.h" #include "platform/util/timeutils.h" #include "platform/sockets/tcp.h" -#include "client.h" extern "C" { #include "platform/util/atomic.h" @@ -32,708 +29,539 @@ extern "C" { #include "libhts/sha1.h" } +#include "Tvheadend.h" +#include "client.h" + using namespace std; using namespace ADDON; using namespace PLATFORM; -CHTSResult::CHTSResult(void) : - message(NULL), - status(PVR_ERROR_NO_ERROR) +/* + * HTSP Response objct + */ +CHTSPResponse::CHTSPResponse () + : m_flag(false), m_msg(NULL) { } -CHTSResult::~CHTSResult(void) +CHTSPResponse::~CHTSPResponse () { - if (message != NULL) - htsmsg_destroy(message); + if (m_msg) htsmsg_destroy(m_msg); + Set(NULL); // ensure signal is sent } -string CHTSResult::GetErrorMessage(void) +void CHTSPResponse::Set ( htsmsg_t *msg ) { - if (m_strError.empty()) - { - if (!message) - { - m_strError = "No response received"; - } - else - { - const char* error; - if((error = htsmsg_get_str(message, "error"))) - m_strError = error; - } - } - return m_strError; + m_msg = msg; + m_flag = true; + m_cond.Broadcast(); } -bool CHTSResult::IsError(void) +htsmsg_t *CHTSPResponse::Get ( CMutex &mutex, uint32_t timeout ) { - return !GetErrorMessage().empty(); + m_cond.Wait(mutex, m_flag, timeout); + htsmsg_t *r = m_msg; + m_msg = NULL; + m_flag = false; + return r; } -bool CHTSResult::NoAccess(void) +/* + * Registration thread + */ +CHTSPRegister::CHTSPRegister ( CHTSPConnection *conn ) + : m_conn(conn) { - uint32_t noaccess; - return (message && !htsmsg_get_u32(message, "noaccess", &noaccess) && noaccess); } -CHTSPConnection::CHTSPConnection(CHTSPConnectionCallback* callback) : - m_socket(new CTcpConnection(g_strHostname, g_iPortHTSP)), - m_challenge(NULL), - m_iChallengeLength(0), - m_iProtocol(0), - m_iPortnumber(g_iPortHTSP), - m_iConnectTimeout(g_iConnectTimeout * 1000), - m_strUsername(g_strUsername), - m_strPassword(g_strPassword), - m_strHostname(g_strHostname), - m_bIsConnected(false), - m_bTimeshiftSupport(false), - m_bTimeshiftSeekSupport(false), - m_bTranscodingSupport(false), - m_iQueueSize(1000), - m_callback(callback), - m_iReadTimeout(-1) +CHTSPRegister::~CHTSPRegister () { - m_reconnect = new CHTSPReconnect(this); + StopThread(0); } -CHTSPConnection::~CHTSPConnection() +void *CHTSPRegister::Process ( void ) { - // close the connection and stop the thread - Close(); + m_conn->Register(); + return NULL; +} + +/* + * HTSP Connection handler + */ - delete m_socket; - delete m_reconnect; +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) +{ } -const CStdString CHTSPConnection::GetWebURL (const char *fmt, ...) const +CHTSPConnection::~CHTSPConnection() { - CStdString url; - CStdString auth; + StopThread(-1); + Disconnect(); + StopThread(0); +} - /* Authentication */ - if (!g_strUsername.empty()) { - auth = g_strUsername; - if (!g_strPassword.empty()) - auth.AppendFormat(":%s", g_strPassword.c_str()); - auth += "@"; - } else { - auth = ""; - } +/* + * Info + */ - /* URL root */ - url.Format("http://%s%s:%i%s", auth.c_str(), g_strHostname.c_str(), g_iPortHTTP, m_strWebroot.c_str()); +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); - va_list args; - va_start(args, fmt); - url.AppendFormatV(fmt, args); - va_end(args); + CLockObject lock(m_mutex); + va_start(va, fmt); + url += m_webRoot; + url.AppendFormatV(fmt, va); + va_end(va); return url; } -void CHTSPConnection::SetReadTimeout(int iTimeout) +bool CHTSPConnection::WaitForConnection ( void ) { - CLockObject lock(m_mutex); - m_iReadTimeout = iTimeout; - m_readTimeout.Init(iTimeout); + if (!m_ready) { + tvhtrace("waiting for registration..."); + m_regCond.Wait(m_mutex, m_ready, tvh->GetSettings().iConnectTimeout * 1000); + } + return m_ready; } -bool CHTSPConnection::OpenSocket(void) +const char *CHTSPConnection::GetServerName ( void ) { + static CStdString str; CLockObject lock(m_mutex); - // already open - if (m_socket && m_socket->IsOpen()) - return true; - - // check if the socket could be created - if (!m_socket) - { - XBMC->Log(LOG_ERROR, "%s - failed to connect to the backend (couldn't create a socket)", __FUNCTION__); - return false; - } - - XBMC->Log(LOG_DEBUG, "%s - connecting to '%s', port '%d'", __FUNCTION__, m_strHostname.c_str(), m_iPortnumber); - - // try to open the socket - CTimeout timeout(m_iConnectTimeout); - while (!m_socket->IsOpen() && timeout.TimeLeft() > 0) - { - if (!m_socket->Open(timeout.TimeLeft())) - CEvent::Sleep(100); - } - - // check if the socket is open - if (!m_socket->IsOpen()) - { - XBMC->Log(LOG_ERROR, "%s - failed to connect to the backend (%s)", __FUNCTION__, m_socket->GetError().c_str()); - return false; - } - - // socket opened - m_bIsConnected = true; - XBMC->Log(LOG_DEBUG, "%s - connected to '%s', port '%d'", __FUNCTION__, m_strHostname.c_str(), m_iPortnumber); - return true; + str = m_serverName; + return str.c_str(); } -bool CHTSPConnection::Connect(void) +const char *CHTSPConnection::GetServerVersion ( void ) { - bool bFailed(false); - { - CLockObject lock(m_mutex); - - // already connected - if (m_bIsConnected) - return true; - - // open a socket - if (!OpenSocket()) - return false; - - // send the greeting, get the protocol version and capabilities - if (!SendGreeting()) - { - XBMC->Log(LOG_ERROR, "%s - failed to read greeting from the backend", __FUNCTION__); - m_socket->Close(); - return false; - } - - // check whether the proto is v2+ - if(m_iProtocol < 2) - { - XBMC->Log(LOG_ERROR, "%s - incompatible protocol version %d", __FUNCTION__, m_iProtocol); - m_socket->Close(); - return false; - } - - // create reader thread - if (!IsRunning() && !CreateThread(true)) - { - XBMC->Log(LOG_ERROR, "%s - failed to create data processing thread", __FUNCTION__); - bFailed = true; - } - - // send authentication - if (!bFailed && !Auth()) - { - XBMC->Log(LOG_ERROR, "%s - failed to authenticate", __FUNCTION__); - bFailed = true; - } - } - - if (bFailed) - Close(); - - // connected + static CStdString str; CLockObject lock(m_mutex); - m_connectEvent.Broadcast(); - return true; + str.Format("%s (HTSPv%d)", m_serverVersion.c_str(), m_htspVersion); + return str.c_str(); } -void CHTSPConnection::TriggerReconnect(void) +const char *CHTSPConnection::GetServerString ( void ) { - XBMC->Log(LOG_DEBUG, "reconnect triggered"); + static CStdString str; + tvheadend::Settings settings = tvh->GetSettings(); + CLockObject lock(m_mutex); - m_socket->Close(); - m_bIsConnected = false; + str.Format("%s:%d [%s]", settings.strHostname.c_str(), settings.iPortHTSP, + m_ready ? "connected" : "disconnected"); + return str.c_str(); } -void CHTSPConnection::Close() +bool CHTSPConnection::HasCapability(const std::string &capability) const { - // stop the reader thread - StopThread(); + return std::find(m_capabilities.begin(), m_capabilities.end(), capability) + != m_capabilities.end(); +} - // close the socket +/* + * Close the connection + */ +void CHTSPConnection::Disconnect ( void ) +{ CLockObject lock(m_mutex); - m_bIsConnected = false; - if(m_socket && m_socket->IsOpen()) + /* Close socket */ + if (m_socket) { + m_socket->Shutdown(); m_socket->Close(); - - // cleanup - if(m_challenge) - { - free(m_challenge); - m_challenge = NULL; - m_iChallengeLength = 0; } - for (deque::iterator it = m_queue.begin(); it != m_queue.end();) - delete *(it++); - m_queue.clear(); - - m_connectEvent.Broadcast(); + /* Signal all waiters and erase messages */ + m_messages.clear(); } -htsmsg_t* CHTSPConnection::ReadMessage(int iInitialTimeout /* = 10000 */, int iDatapacketTimeout /* = 10000 */) +/* + * Read message from socket + * + * Return false if an error occurs and the connection should be terminated + */ +bool CHTSPConnection::ReadMessage ( void ) { - void* buf; - uint32_t l; + uint8_t *buf; uint8_t lb[4]; - size_t bytes_read; + 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]; - // get the first queued message if any - if(m_queue.size()) + /* Read rest of packet */ + buf = (uint8_t*)malloc(len); + cnt = 0; + while (cnt < len) { - htsmsg_t* m = m_queue.front(); - m_queue.pop_front(); - return m; + r = m_socket->Read((char*)buf + cnt, len - cnt, tvh->GetSettings().iResponseTimeout * 1000); + if (r < 0) + { + tvherror("failed to read packet (%s)", + m_socket->GetError().c_str()); + free(buf); + return false; + } + cnt += r; + if (cnt < len) + printf("partial read\n"); } + /* Deserialize */ + if (!(msg = htsmsg_binary_deserialize(buf, len, buf))) { - CLockObject lock(m_mutex); - // check whether the socket is open - if (!m_socket || !m_socket->IsOpen()) - { - XBMC->Log(LOG_ERROR, "%s - not connected", __FUNCTION__); - return NULL; - } + /* Do not free buf here. Already done by htsmsg_binary_deserialize. */ + tvherror("failed to decode message"); + return false; + } - // read the size - if ((bytes_read = m_socket->Read(&lb, 4, iInitialTimeout)) != 4) + /* 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()) { - // timed out - if(m_socket->GetErrorNumber() == ETIMEDOUT) - { - // we did read something. try to finish the read - if (bytes_read > 0) - bytes_read += m_socket->Read(&lb + bytes_read, 4 - bytes_read, iDatapacketTimeout); - else - return NULL; - } - - // read error, close the connection - if (bytes_read != 4) - { - XBMC->Log(LOG_ERROR, "%s - failed to read packet size (%s)", __FUNCTION__, m_socket->GetError().c_str()); - TriggerReconnect(); - return NULL; - } + it->second->Set(msg); + return true; } + } - l = (lb[0] << 24) + (lb[1] << 16) + (lb[2] << 8) + lb[3]; - - // empty message - if(l == 0) - return htsmsg_create_map(); - - // read the data - buf = malloc(l); - if(m_socket->Read(buf, l, iDatapacketTimeout) != (ssize_t)l) - { - // failed to read (wrong size), close the connection - XBMC->Log(LOG_ERROR, "%s - failed to read packet (%s)", __FUNCTION__, m_socket->GetError().c_str()); - free(buf); - TriggerReconnect(); - return NULL; - } + /* 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 the data - return htsmsg_binary_deserialize(buf, l, buf); /* consumes 'buf' */ + return true; } -bool CHTSPConnection::TransmitMessage(htsmsg_t* m) +/* + * Send message to server + */ +bool CHTSPConnection::SendMessage0 ( const char *method, htsmsg_t *msg ) { - void* buf; - size_t len; + 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); - // check whether the socket is open - if (!m_socket || !m_socket->IsOpen()) - { - XBMC->Log(LOG_ERROR, "%s - not connected", __FUNCTION__); - htsmsg_destroy(m); + /* Serialise */ + e = htsmsg_binary_serialize(msg, &buf, &len, -1); + htsmsg_destroy(msg); + if (e < 0) return false; - } - // serialise the data - if(htsmsg_binary_serialize(m, &buf, &len, -1) < 0) + /* Send data */ + c = m_socket->Write(buf, len); + free(buf); + if (c != (ssize_t)len) { - htsmsg_destroy(m); + tvherror("failed to write (%s)", + m_socket->GetError().c_str()); + Disconnect(); return false; } - htsmsg_destroy(m); - // write the data - CLockObject lock(m_mutex); - ssize_t iWriteResult = m_socket->Write(buf, len); - if (iWriteResult != (ssize_t)len) - { - // failed to write, close the connection - XBMC->Log(LOG_ERROR, "%s - failed to write packet (%s)", __FUNCTION__, m_socket->GetError().c_str()); - free(buf); - TriggerReconnect(); - return false; - } - free(buf); return true; } -void CHTSPConnection::ReadResult(htsmsg_t *m, CHTSResult &result, const char* strAction /* = NULL */) +/* + * Send a message and wait for response + */ +htsmsg_t *CHTSPConnection::SendAndWait0 ( const char *method, htsmsg_t *msg, int iResponseTimeout ) { - // check whether we're connected - if (!IsConnected()) + 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)) { - htsmsg_destroy(m); - result.status = PVR_ERROR_SERVER_ERROR; - if (strAction) - XBMC->Log(LOG_ERROR, "%s - '%s' failed - not connected", __FUNCTION__, strAction); - return; + m_messages.erase(seq); + tvherror("failed to transmit"); + return NULL; } - // store in the message queue - result.status = PVR_ERROR_NO_ERROR; - uint32_t seq = HTSPNextSequenceNumber(); - - SMessage &message(m_messageQueue[seq]); - message.event = new CEvent; - message.msg = NULL; - - // transmit the message - htsmsg_add_u32(m, "seq", seq); - if(!TransmitMessage(m)) + /* Wait for response */ + msg = resp.Get(m_mutex, iResponseTimeout * 1000); + m_messages.erase(seq); + if (!msg) { - // command couldn't be sent - if (strAction) - XBMC->Log(LOG_ERROR, "%s - '%s' failed - failed to send command", __FUNCTION__, strAction); - else - XBMC->Log(LOG_ERROR, "%s - failed to send command", __FUNCTION__); - result.status = PVR_ERROR_SERVER_ERROR; + //XBMC->QueueNotification(QUEUE_ERROR, "Command %s failed: No response received", method); + tvherror("Command %s failed: No response received", method); + Disconnect(); + return NULL; } - else if(!message.event->Wait(g_iResponseTimeout * 1000)) + + /* Check result for errors and announce. */ + uint32_t noaccess; + if (!htsmsg_get_u32(msg, "noaccess", &noaccess) && noaccess) { - // no response - if (strAction) - XBMC->Log(LOG_ERROR, "%s - '%s' failed - request timed out after %d seconds", __FUNCTION__, strAction, g_iResponseTimeout); - else - XBMC->Log(LOG_ERROR, "%s - request timed out after %d seconds", __FUNCTION__, g_iResponseTimeout); - result.status = PVR_ERROR_SERVER_TIMEOUT; + // 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 { - // response received - result.message = message.msg; - - if (result.NoAccess()) - { - // access denied - if (strAction) - XBMC->Log(LOG_ERROR, "%s - '%s' failed - access denied", __FUNCTION__, strAction); - else - XBMC->Log(LOG_ERROR, "%s - command failed - access denied", __FUNCTION__); - XBMC->QueueNotification(QUEUE_ERROR, "Access denied"); - result.status = PVR_ERROR_REJECTED; - } - - if (result.IsError()) + const char* strError; + if(strError = htsmsg_get_str(msg, "error")) { - // server reported an error - string strError = result.GetErrorMessage(); - if (strAction) - XBMC->Log(LOG_ERROR, "%s - '%s' failed - %s", __FUNCTION__, strAction, strError.c_str()); - else - XBMC->Log(LOG_ERROR, "%s - command failed - %s", __FUNCTION__, strError.c_str()); - XBMC->QueueNotification(QUEUE_ERROR, "Command failed: %s", strError.c_str()); - result.status = PVR_ERROR_REJECTED; + //XBMC->QueueNotification(QUEUE_ERROR, "Command %s failed: %s", method, strError); + tvherror("Command %s failed: %s", method, strError); + htsmsg_destroy(msg); + return NULL; } } - // delete from the queue - { - CLockObject lock(m_mutex); - delete message.event; - m_messageQueue.erase(seq); - } + return msg; } -bool CHTSPConnection::ReadSuccess(htsmsg_t* m, const char* strAction /* = NULL */) +/* + * Send and wait for response + */ +htsmsg_t *CHTSPConnection::SendAndWait ( const char *method, htsmsg_t *msg, int iResponseTimeout ) { - CHTSResult result; - ReadResult(m, result, strAction); - return result.status == PVR_ERROR_NO_ERROR; + if (iResponseTimeout == -1) + iResponseTimeout = tvh->GetSettings().iResponseTimeout; + + if (!WaitForConnection()) + return NULL; + return SendAndWait0(method, msg, iResponseTimeout); } -bool CHTSPConnection::SendGreeting(void) +bool CHTSPConnection::SendHello ( void ) { - htsmsg_t *m, *cap; - htsmsg_field_t *f; - const char *server, *version, *webroot; - const void * chall = NULL; - size_t chall_len = 0; - int32_t proto = 0; - - // send hello - m = htsmsg_create_map(); - htsmsg_add_str(m, "method", "hello"); - htsmsg_add_str(m, "clientname", "XBMC Media Center"); - htsmsg_add_u32(m, "htspversion", 8); + /* Build message */ + htsmsg_t *msg = htsmsg_create_map(); + htsmsg_add_str(msg, "clientname", "XBMC Media Center"); + htsmsg_add_u32(msg, "htspversion", HTSP_API_VERSION); - CLockObject lock(m_mutex); - - // read welcome - if (!TransmitMessage(m)) - { - XBMC->Log(LOG_ERROR, "CHTSPConnection - %s - failed to transmit greeting", __FUNCTION__); + /* Send and Wait */ + if (!(msg = SendAndWait0("hello", msg))) return false; - } - - m = ReadMessage(g_iConnectTimeout * 1000, g_iConnectTimeout * 1000); - if (m == NULL || m->hm_data == NULL) - { - if (m) - htsmsg_destroy(m); - // no welcome received - XBMC->Log(LOG_ERROR, "CHTSPConnection - %s - failed get a reply after the greeting", __FUNCTION__); - return false; - } - - htsmsg_get_str(m, "method"); - htsmsg_get_s32(m, "htspversion", &proto); - server = htsmsg_get_str(m, "servername"); - version = htsmsg_get_str(m, "serverversion"); - htsmsg_get_bin(m, "challenge", &chall, &chall_len); - cap = htsmsg_get_list(m, "servercapability"); - webroot = htsmsg_get_str(m, "webroot"); - - // process capabilities - m_bTimeshiftSupport = false; - m_bTimeshiftSeekSupport = false; - m_bTranscodingSupport = false; - if (cap) + + /* 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) - { - if (!strcmp("timeshift", f->hmf_str)) - { - m_bTimeshiftSupport = true; - m_bTimeshiftSeekSupport = true; - } - else if (!strcmp("transcoding", f->hmf_str)) - m_bTranscodingSupport = true; - } + m_capabilities.push_back(f->hmf_str); } } - - m_strServerName = server; - m_strVersion = version; - m_iProtocol = proto; - m_strWebroot = webroot ? webroot : ""; - - if(chall && chall_len) - { - m_challenge = malloc(chall_len); - m_iChallengeLength = chall_len; - memcpy(m_challenge, chall, chall_len); - } - htsmsg_destroy(m); - - XBMC->Log(LOG_NOTICE, "CHTSPConnection - %s - connection opened to '%s %s', protocol v%d%s", __FUNCTION__, m_strServerName.c_str(), m_strVersion.c_str(), m_iProtocol, m_bTimeshiftSupport ? " (timeshift enabled)" : ""); - return true; -} - -bool CHTSPConnection::Auth(void) -{ - CLockObject lock(m_mutex); - // no username set, don't authenticate - if (m_strUsername.empty()) - { - XBMC->Log(LOG_DEBUG, "CHTSPConnection - %s - no username set. not authenticating", __FUNCTION__); - return true; - } - - htsmsg_t *m = htsmsg_create_map(); - htsmsg_add_str(m, "method" , "authenticate"); - htsmsg_add_str(m, "username", m_strUsername.c_str()); - - if(!m_strPassword.empty() && m_challenge) - { - XBMC->Log(LOG_DEBUG, "CHTSPConnection - %s - authenticating as user '%s' with a password", __FUNCTION__, m_strUsername.c_str()); - - struct HTSSHA1* shactx = (struct HTSSHA1*) malloc(hts_sha1_size); - uint8_t d[20]; - hts_sha1_init(shactx); - hts_sha1_update(shactx, (const uint8_t *) m_strPassword.c_str(), m_strPassword.length()); - hts_sha1_update(shactx, (const uint8_t *) m_challenge, m_iChallengeLength); - hts_sha1_final(shactx, d); - htsmsg_add_bin(m, "digest", d, 20); - free(shactx); - } - else - { - XBMC->Log(LOG_DEBUG, "CHTSPConnection - %s - authenticating as user '%s' without a password", __FUNCTION__, m_strUsername.c_str()); - } - - if (!TransmitMessage(m)) - { - XBMC->Log(LOG_ERROR, "CHTSPConnection - %s - failed to transmit auth command", __FUNCTION__); - XBMC->QueueNotification(QUEUE_ERROR, "Access denied"); - return false; - } - - CHTSResult result; - result.message = ReadMessage(g_iConnectTimeout * 1000, g_iConnectTimeout * 1000); - if (result.message == NULL) - { - XBMC->Log(LOG_ERROR, "CHTSPConnection - %s - failed to get a reply from the auth command", __FUNCTION__); - XBMC->QueueNotification(QUEUE_ERROR, "Access denied"); - return false; - } - else if (result.NoAccess()) - { - // access denied - XBMC->Log(LOG_ERROR, "%s - auth failed - access denied", __FUNCTION__); - XBMC->QueueNotification(QUEUE_ERROR, "Access denied"); - return false; - } - else if (result.IsError()) + + /* Authentication */ + htsmsg_get_bin(msg, "challenge", &chal, &chal_len); + if (chal && chal_len) { - // server reported an error - string strError = result.GetErrorMessage(); - XBMC->Log(LOG_ERROR, "%s - auth failed - %s", __FUNCTION__, strError.c_str()); - XBMC->QueueNotification(QUEUE_ERROR, "Access denied"); - return false; + m_challenge = malloc(chal_len); + m_challengeLen = chal_len; + memcpy(m_challenge, chal, chal_len); } + htsmsg_destroy(msg); + return true; } -bool CHTSPConnection::CheckConnection(uint32_t iTimeout) +bool CHTSPConnection::SendAuth + ( const CStdString &user, const CStdString &pass ) { - CLockObject lock(m_mutex); - if (IsConnected()) - return true; - - return m_connectEvent.Wait(m_mutex, m_bIsConnected, iTimeout); + 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); } -bool CHTSPConnection::IsConnected(void) -{ - CLockObject lock(m_mutex); - return m_bIsConnected && m_socket && m_socket->IsOpen(); -} - -bool CHTSPConnection::CanTimeshift(void) -{ - return m_bTimeshiftSupport; -} - -bool CHTSPConnection::CanSeekLiveStream(void) +/** + * Register the connection, hello+auth + */ +void CHTSPConnection::Register ( void ) { - return m_bTimeshiftSeekSupport; -} + CStdString user, pass; + user = tvh->GetSettings().strUsername; + pass = tvh->GetSettings().strPassword; -void* CHTSPConnection::Process(void) -{ - htsmsg_t* msg(NULL); - while (!IsStopped()) { - if (!IsConnected() && !m_reconnect->IsRunning()) - { - XBMC->Log(LOG_ERROR, "connection dropped, trying to restore"); - m_reconnect->CreateThread(true); + CLockObject lock(m_mutex); + + /* Send Greeting */ + tvhdebug("sending hello"); + if (!SendHello()) { + tvherror("failed to send hello"); + goto fail; } - else - { - // if there's anything in the buffer, read it - { - { - CLockObject lock(m_mutex); - msg = ReadMessage(5, g_iResponseTimeout * 1000); - } - if(msg == NULL || msg->hm_data == NULL) - { - if (msg) - htsmsg_destroy(msg); - - { - CLockObject lock(m_mutex); - if (!m_reconnect->IsRunning() && m_iReadTimeout > 0 && m_readTimeout.TimeLeft() == 0) - { - TriggerReconnect(); - continue; - } - } - - Sleep(5); - continue; - } - } - { - CLockObject lock(m_mutex); - if (!m_reconnect->IsRunning() && m_iReadTimeout > 0) - m_readTimeout.Init(m_iReadTimeout); - } + /* Send Auth */ + tvhdebug("sending auth"); + + if (!SendAuth(user, pass)) + goto fail; - // signal if 'seq' is set - uint32_t seq; - if(htsmsg_get_u32(msg, "seq", &seq) == 0) - { - CLockObject lock(m_mutex); - SMessages::iterator it = m_messageQueue.find(seq); - if(it != m_messageQueue.end()) - { - it->second.msg = msg; - it->second.event->Broadcast(); - continue; - } - } + /* Rebuild state */ + tvhdebug("rebuilding state"); + if (!tvh->Connected()) + goto fail; - // process the message - m_callback->ProcessMessage(msg); - htsmsg_destroy(msg); - } + tvhdebug("registered"); + m_ready = true; + m_regCond.Broadcast(); + return; } - m_reconnect->StopThread(); - - return NULL; + /* Rate limit retry */ +fail: + Sleep(5000); + Disconnect(); } -void* CHTSPReconnect::Process(void) +/* + * Main thread loop for connection and rx handling + */ +void* CHTSPConnection::Process ( void ) { - if (m_connection->m_callback) - m_connection->m_callback->OnConnectionDropped(); + static bool log = false; + static unsigned int retryAttempt = 0; + tvheadend::Settings settings = tvh->GetSettings(); - while (!m_connection->IsConnected() && !IsStopped()) + while (!IsStopped()) { - { - CLockObject lock(m_connection->m_mutex); - for (SMessages::iterator it = m_connection->m_messageQueue.begin(); it != m_connection->m_messageQueue.end(); it++) - it->second.event->Broadcast(); + CStdString host = settings.strHostname; + int port, timeout; + port = settings.iPortHTSP; + timeout = settings.iConnectTimeout * 1000; - m_connection->m_bIsConnected = false; - if(m_connection->m_challenge) - { - free(m_connection->m_challenge); - m_connection->m_challenge = NULL; - m_connection->m_iChallengeLength = 0; + /* Create socket (ensure mutex protection) */ + { + CLockObject lock(m_mutex); + if (m_socket) + delete m_socket; + tvh->Disconnected(); + if (!log) + tvhdebug("connecting to %s:%d", host.c_str(), port); + else + tvhtrace("connecting to %s:%d", host.c_str(), port); + log = true; + m_socket = new CTcpSocket(host.c_str(), port); + m_ready = false; + m_seq = 0; + if (m_challenge) { + free(m_challenge); + m_challenge = NULL; } } - if (m_connection->Connect()) + /* Connect */ + tvhtrace("waiting for connection..."); + if (!m_socket->Open(timeout)) { - if (m_connection->m_callback && m_connection->m_callback->OnConnectionRestored()) - { - m_connection->m_bIsConnected = true; - if (m_connection->m_iReadTimeout > 0) - m_connection->m_readTimeout.Init(m_connection->m_iReadTimeout); - XBMC->Log(LOG_DEBUG, "connection restored"); - } + /* Unable to connect, inform the user */ + 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 - { - m_connection->TriggerReconnect(); - Sleep(1000); - } + Sleep(timeout); + + continue; } - else + tvhdebug("connected"); + log = false; + retryAttempt = 0; + + /* Start connect thread */ + m_regThread.CreateThread(true); + + /* Receive loop */ + while (!IsStopped()) { - if (m_connection->m_callback) - m_connection->m_callback->OnConnectionDropped(); + if (!ReadMessage()) + { + break; + } } + + /* Stop connect thread (if not already) */ + m_regThread.StopThread(0); } + return NULL; } diff --git a/addons/pvr.hts/src/HTSPConnection.h b/addons/pvr.hts/src/HTSPConnection.h deleted file mode 100644 index d3ab4eca6..000000000 --- a/addons/pvr.hts/src/HTSPConnection.h +++ /dev/null @@ -1,151 +0,0 @@ -#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, 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#include "client.h" -#include "HTSPTypes.h" -#include "platform/threads/threads.h" - -extern "C" { -#include "libhts/net.h" -#include "libhts/htsmsg.h" -} - -namespace PLATFORM -{ - class CTcpConnection; -} - -class CHTSPConnectionCallback -{ -public: - CHTSPConnectionCallback(void) {} - virtual ~CHTSPConnectionCallback(void) {} - - virtual bool OnConnectionDropped(void) { return true; } - virtual bool OnConnectionRestored(void) { return true; } - virtual bool ProcessMessage(htsmsg* msg) = 0; -}; - -struct SMessage -{ - PLATFORM::CEvent* event; - htsmsg_t* msg; -}; -typedef std::map SMessages; - -class CHTSResult -{ -public: - CHTSResult(void); - ~CHTSResult(void); - - std::string GetErrorMessage(void); - bool IsError(void); - bool NoAccess(void); - - htsmsg* message; /*!< the response message */ - PVR_ERROR status; /*!< the return code */ - -private: - std::string m_strError; /*!< the error response */ -}; - -class CHTSPConnection; - -class CHTSPReconnect : public PLATFORM::CThread -{ -public: - CHTSPReconnect(CHTSPConnection* connection) : - m_connection(connection) {} - virtual ~CHTSPReconnect(void) {} - - void* Process(void); - -private: - CHTSPConnection* m_connection; -}; - -class CHTSPConnection : private PLATFORM::CThread -{ - friend class CHTSPReconnect; - -public: - CHTSPConnection(CHTSPConnectionCallback* callback); - ~CHTSPConnection(); - - bool Connect(void); - void Close(); - bool IsConnected(void); - bool CheckConnection(uint32_t iTimeout); - int GetProtocol() const { return m_iProtocol; } - const char *GetServerName() const { return m_strServerName.c_str(); } - const char *GetVersion() const { return m_strVersion.c_str(); } - const char *GetWebroot() const { return m_strWebroot.c_str(); } - const CStdString GetWebURL(const char *fmt, ...) const; - - bool TransmitMessage(htsmsg_t* m); - void ReadResult(htsmsg_t *m, CHTSResult &result, const char* strAction = NULL); - bool ReadSuccess(htsmsg_t* m, const char* strAction = NULL); - - bool CanTimeshift(void); - bool CanSeekLiveStream(void); - - bool CanTranscode(void) const { return m_bTranscodingSupport; } - void SetReadTimeout(int iTimeout); - void TriggerReconnect(void); - -private: - bool OpenSocket(void); - void* Process(void); - bool SendGreeting(void); - bool Auth(void); - htsmsg_t* ReadMessage(int iInitialTimeout = 1000, int iDatapacketTimeout = 1000); - - PLATFORM::CMutex m_mutex; - PLATFORM::CTcpConnection* m_socket; - void* m_challenge; - int m_iChallengeLength; - int m_iProtocol; - int m_iPortnumber; - int m_iConnectTimeout; - std::string m_strServerName; - std::string m_strUsername; - std::string m_strPassword; - std::string m_strVersion; - std::string m_strHostname; - std::string m_strWebroot; - bool m_bIsConnected; - bool m_bTimeshiftSupport; - bool m_bTimeshiftSeekSupport; - bool m_bTranscodingSupport; - - std::deque m_queue; - const unsigned int m_iQueueSize; - CHTSPConnectionCallback* m_callback; - PLATFORM::CCondition m_connectEvent; - SMessages m_messageQueue; - PLATFORM::CTimeout m_readTimeout; - int m_iReadTimeout; - CHTSPReconnect* m_reconnect; -}; diff --git a/addons/pvr.hts/src/HTSPData.cpp b/addons/pvr.hts/src/HTSPData.cpp deleted file mode 100644 index c15c2c41a..000000000 --- a/addons/pvr.hts/src/HTSPData.cpp +++ /dev/null @@ -1,1640 +0,0 @@ -/* - * 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, 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#include "HTSPData.h" -#include "HTSPDemux.h" -#include "platform/util/util.h" - -extern "C" { -#include "platform/util/atomic.h" -#include "libhts/htsmsg.h" -#include "libhts/htsmsg_binary.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; - -using namespace std; -using namespace ADDON; -using namespace PLATFORM; - -CHTSPData::CHTSPData() -{ - m_session = NULL; - m_bDisconnectWarningDisplayed = false; - m_bIsStarted = false; - m_recordingId = 0; - m_demux = NULL; - m_recordingBuf.alloc(1000000); -} - -CHTSPData::~CHTSPData() -{ - Close(); - delete m_session; -} - -bool CHTSPData::Open() -{ - if (!m_session) - m_session = new CHTSPConnection(this); - - CLockObject lock(m_mutex); - if(!m_session->Connect()) - { - /* failed to connect */ - return false; - } - - if (!m_demux) - m_demux = new CHTSPDemux(m_session); - - if(!SendEnableAsync()) - { - XBMC->Log(LOG_ERROR, "%s - couldn't send EnableAsync().", __FUNCTION__); - return false; - } - - return m_started.Wait(m_mutex, m_bIsStarted, g_iConnectTimeout * 1000); -} - -void CHTSPData::Close() -{ - CLockObject lock(m_mutex); - m_bIsStarted = false; - m_started.Broadcast(); - SAFE_DELETE(m_demux); - SAFE_DELETE(m_session); -} - -void CHTSPData::ReadResult(htsmsg_t *m, CHTSResult &result) -{ - if (!m_session || !m_session->IsConnected()) - { - htsmsg_destroy(m); - result.status = PVR_ERROR_SERVER_ERROR; - return; - } - - return m_session->ReadResult(m, result); -} - -bool CHTSPData::GetDriveSpace(long long *total, long long *used) -{ - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "getDiskSpace"); - - CHTSResult result; - ReadResult(msg, result); - if (result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_DEBUG, "%s - failed to get getDiskSpace", __FUNCTION__); - return false; - } - - int64_t freespace; - if (htsmsg_get_s64(result.message, "freediskspace", &freespace) != 0) - return false; - - int64_t totalspace; - if (htsmsg_get_s64(result.message, "totaldiskspace", &totalspace) != 0) - return false; - - *total = totalspace / 1024; - *used = (totalspace - freespace) / 1024; - return true; -} - -bool CHTSPData::GetBackendTime(time_t *utcTime, int *gmtOffset) -{ - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "getSysTime"); - - CHTSResult result; - ReadResult(msg, result); - if (result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_ERROR, "%s - failed to get sysTime", __FUNCTION__); - return false; - } - - unsigned int secs; - if (htsmsg_get_u32(result.message, "time", &secs) != 0) - return false; - - int offset; - if (htsmsg_get_s32(result.message, "timezone", &offset) != 0) - return false; - - XBMC->Log(LOG_DEBUG, "%s - tvheadend reported time=%u, timezone=%d, correction=%d" - , __FUNCTION__, secs, offset); - - *utcTime = secs; - *gmtOffset = offset; - - return true; -} - - -CodecVector CHTSPData::GetTranscodingCodecs(void) -{ - htsmsg_t *msg; - htsmsg_field_t *f; - CodecVector v; - CHTSResult result; - - msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "getCodecs"); - - ReadResult(msg, result); - if (result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_DEBUG, "%s - failed to getCodecs", __FUNCTION__); - return v; - } - - msg = htsmsg_get_list(result.message, "encoders"); - if(!msg) - { - XBMC->Log(LOG_DEBUG, "%s - failed to get encoders", __FUNCTION__); - return v; - } - - HTSMSG_FOREACH(f, msg) { - if (f->hmf_type != HMF_STR) - continue; - - CodecDescriptor codec = CodecDescriptor::GetCodecByName(f->hmf_str); - if (codec.Codec().codec_type != XBMC_CODEC_TYPE_UNKNOWN) - v.push_back(codec); - } - - return v; -} - -unsigned int CHTSPData::GetNumChannels() -{ - return GetChannels().size(); -} - -PVR_ERROR CHTSPData::GetChannels(ADDON_HANDLE handle, bool bRadio) -{ - SChannels channels = GetChannels(); - for(SChannels::iterator it = channels.begin(); it != channels.end(); ++it) - { - SChannel& channel = it->second; - if(bRadio != channel.radio) - continue; - - PVR_CHANNEL tag; - memset(&tag, 0 , sizeof(PVR_CHANNEL)); - - tag.iUniqueId = channel.id; - tag.bIsRadio = channel.radio; - tag.iChannelNumber = channel.num; - tag.iSubChannelNumber = channel.numMinor; - strncpy(tag.strChannelName, channel.name.c_str(), sizeof(tag.strChannelName) - 1); - tag.iEncryptionSystem = channel.caid; - strncpy(tag.strIconPath, channel.icon.c_str(), sizeof(tag.strIconPath) - 1); - tag.bIsHidden = false; - - PVR->TransferChannelEntry(handle, &tag); - } - - return PVR_ERROR_NO_ERROR; -} - -PVR_ERROR CHTSPData::GetEpg(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd) -{ - PVR_ERROR retVal = PVR_ERROR_NO_ERROR; - SChannels channels = GetChannels(); - - if (channels.find(channel.iUniqueId) != channels.end()) - { - - /* Full channel update */ - if (GetProtocol() >= 6) - { - retVal = GetEvents(handle, channel.iUniqueId, iEnd); - } - /* Event at a time */ - else - { - uint32_t eventId = channels[channel.iUniqueId].event; - if (eventId != 0) - { - do - { - retVal = GetEvent(handle, &eventId, iEnd); - } while(eventId && retVal == PVR_ERROR_NO_ERROR); - } - } - } - - return retVal; -} - -SRecordings CHTSPData::GetDVREntries(bool recorded, bool scheduled) -{ - CLockObject lock(m_mutex); - SRecordings recordings; - - for(SRecordings::const_iterator it = m_recordings.begin(); it != m_recordings.end(); ++it) - { - SRecording recording = it->second; - - if ((recorded && (recording.state == ST_COMPLETED || recording.state == ST_ABORTED || recording.state == ST_RECORDING)) || - (scheduled && (recording.state == ST_SCHEDULED || recording.state == ST_RECORDING))) - recordings[recording.id] = recording; - } - - return recordings; -} - -unsigned int CHTSPData::GetNumRecordings() -{ - SRecordings recordings = GetDVREntries(true, false); - return recordings.size(); -} - -PVR_ERROR CHTSPData::GetRecordings(ADDON_HANDLE handle) -{ - SRecordings recordings = GetDVREntries(true, false); - - for(SRecordings::const_iterator it = recordings.begin(); it != recordings.end(); ++it) - { - SRecording recording = it->second; - CStdString strStreamURL; - CStdString strRecordingId; - CStdString strDirectory = "/"; - std::string strChannelName = ""; - std::string strIconPath = ""; - - /* lock */ - { - CLockObject lock(m_mutex); - - /* determine channel name and icon */ - SChannels::const_iterator itr = m_channels.find(recording.channel); - if (itr != m_channels.end()) - { - strChannelName = itr->second.name; - strIconPath = itr->second.icon; - } - - /* HTSPv7+ - use HTSP */ - if (GetProtocol() >= 7) - strStreamURL = ""; - - /* HTSPv6- - use HTTP */ - else - strStreamURL = m_session->GetWebURL("/dvrfile/%i", recording.id); - } - - strRecordingId.Format("%i", recording.id); - - if (recording.path != "") - { - size_t idx = recording.path.rfind("/"); - if (idx == 0 || idx == std::string::npos) { - strDirectory = "/"; - } else { - strDirectory = recording.path.substr(0, idx); - if (strDirectory[0] != '/') - strDirectory = "/" + strDirectory; - } - } - - PVR_RECORDING tag; - memset(&tag, 0, sizeof(PVR_RECORDING)); - - strncpy(tag.strRecordingId, strRecordingId.c_str(), sizeof(tag.strRecordingId) - 1); - strncpy(tag.strTitle, recording.title.c_str(), sizeof(tag.strTitle) - 1); - strncpy(tag.strStreamURL, strStreamURL.c_str(), sizeof(tag.strStreamURL) - 1); - strncpy(tag.strDirectory, strDirectory.c_str(), sizeof(tag.strDirectory) - 1); - strncpy(tag.strPlot, recording.description.c_str(), sizeof(tag.strPlot) - 1); - strncpy(tag.strChannelName, strChannelName.c_str(), sizeof(tag.strChannelName) - 1); - strncpy(tag.strIconPath, strIconPath.c_str(), sizeof(tag.strIconPath) - 1); - tag.recordingTime = recording.start; - tag.iDuration = recording.stop - recording.start; - tag.iPriority = recording.priority; - tag.iLifetime = recording.retention; - - PVR->TransferRecordingEntry(handle, &tag); - } - - return PVR_ERROR_NO_ERROR; -} - -PVR_ERROR CHTSPData::DeleteRecording(const PVR_RECORDING &recording) -{ - XBMC->Log(LOG_DEBUG, "%s", __FUNCTION__); - - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "deleteDvrEntry"); - htsmsg_add_u32(msg, "id", atoi(recording.strRecordingId)); - - CHTSResult result; - ReadResult(msg, result); - if (result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_DEBUG, "%s - Failed to get deleteDvrEntry", __FUNCTION__); - return result.status; - } - - unsigned int success; - if (htsmsg_get_u32(result.message, "success", &success) != 0) - { - XBMC->Log(LOG_DEBUG, "%s - Failed to parse param", __FUNCTION__); - return PVR_ERROR_SERVER_ERROR; - } - - return success > 0 ? PVR_ERROR_NO_ERROR : PVR_ERROR_FAILED; -} - -unsigned int CHTSPData::GetNumTimers() -{ - SRecordings recordings = GetDVREntries(false, true); - return recordings.size(); -} - -unsigned int CHTSPData::GetNumChannelGroups(void) -{ - return m_tags.size(); -} - -PVR_ERROR CHTSPData::GetChannelGroups(ADDON_HANDLE handle) -{ - for(unsigned int iTagPtr = 0; iTagPtr < m_tags.size(); iTagPtr++) - { - if (!m_tags[iTagPtr].name.empty()) - { - PVR_CHANNEL_GROUP tag; - memset(&tag, 0 , sizeof(PVR_CHANNEL_GROUP)); - - tag.bIsRadio = false; - strncpy(tag.strGroupName, m_tags[iTagPtr].name.c_str(), sizeof(tag.strGroupName) - 1); - - PVR->TransferChannelGroup(handle, &tag); - } - } - - return PVR_ERROR_NO_ERROR; -} - -PVR_ERROR CHTSPData::GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group) -{ - XBMC->Log(LOG_DEBUG, "%s - group '%s'", __FUNCTION__, group.strGroupName); - - for(unsigned int iTagPtr = 0; iTagPtr < m_tags.size(); iTagPtr++) - { - if (m_tags[iTagPtr].name != group.strGroupName) - continue; - - SChannels channels = GetChannels(m_tags[iTagPtr].id); - - for(SChannels::iterator it = channels.begin(); it != channels.end(); ++it) - { - SChannel& channel = it->second; - if (channel.radio != group.bIsRadio) - continue; - - PVR_CHANNEL_GROUP_MEMBER tag; - memset(&tag,0 , sizeof(PVR_CHANNEL_GROUP_MEMBER)); - - strncpy(tag.strGroupName, group.strGroupName, sizeof(tag.strGroupName) - 1); - tag.iChannelUniqueId = channel.id; - tag.iChannelNumber = channel.num; - -#if HTSP_DEBUGGING - XBMC->Log(LOG_DEBUG, "%s - add channel %s (%d) to group '%s' channel number %d", - __FUNCTION__, channel.name.c_str(), tag.iChannelUniqueId, group.strGroupName, channel.num); -#endif - - PVR->TransferChannelGroupMember(handle, &tag); - } - } - - return PVR_ERROR_NO_ERROR; -} - -PVR_ERROR CHTSPData::GetTimers(ADDON_HANDLE handle) -{ - SRecordings recordings = GetDVREntries(false, true); - - for(SRecordings::const_iterator it = recordings.begin(); it != recordings.end(); ++it) - { - SRecording recording = it->second; - - PVR_TIMER tag; - memset(&tag, 0, sizeof(PVR_TIMER)); - - tag.iClientIndex = recording.id; - tag.iClientChannelUid = recording.channel; - tag.startTime = recording.start; - tag.endTime = recording.stop; - strncpy(tag.strTitle, recording.title.c_str(), sizeof(tag.strTitle) - 1); - strncpy(tag.strSummary, recording.description.c_str(), sizeof(tag.strSummary) - 1); - tag.state = (PVR_TIMER_STATE) recording.state; - tag.iPriority = recording.priority; - tag.iLifetime = recording.retention; - tag.bIsRepeating = false; // unused - tag.firstDay = 0; // unused - tag.iWeekdays = 0; // unused - tag.iEpgUid = 0; // unused - tag.iMarginStart = recording.startExtra; - tag.iMarginEnd = recording.stopExtra; - tag.iGenreType = 0; // unused - tag.iGenreSubType = 0; // unused - - PVR->TransferTimerEntry(handle, &tag); - } - - return PVR_ERROR_NO_ERROR; -} - -PVR_ERROR CHTSPData::DeleteTimer(const PVR_TIMER &timer, bool bForce) -{ - XBMC->Log(LOG_DEBUG, "%s", __FUNCTION__); - - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "cancelDvrEntry"); - htsmsg_add_u32(msg, "id", timer.iClientIndex); - - CHTSResult result; - ReadResult(msg, result); - if (result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_DEBUG, "%s - Failed to get cancelDvrEntry", __FUNCTION__); - return result.status; - } - - const char *strError = NULL; - if ((strError = htsmsg_get_str(result.message, "error"))) - { - XBMC->Log(LOG_DEBUG, "%s - Error deleting timer: '%s'", __FUNCTION__, strError); - return PVR_ERROR_SERVER_ERROR; - } - - unsigned int success; - if (htsmsg_get_u32(result.message, "success", &success) != 0) - { - XBMC->Log(LOG_DEBUG, "%s - Failed to parse param", __FUNCTION__); - return PVR_ERROR_SERVER_ERROR; - } - - return success > 0 ? PVR_ERROR_NO_ERROR : PVR_ERROR_FAILED; -} - -PVR_ERROR CHTSPData::AddTimer(const PVR_TIMER &timer) -{ - XBMC->Log(LOG_DEBUG, "%s - channelUid=%d title=%s epgid=%d", __FUNCTION__, timer.iClientChannelUid, timer.strTitle, timer.iEpgUid); - - time_t startTime = timer.startTime; - if (startTime <= 0) - { - int iGmtOffset; - GetBackendTime(&startTime, &iGmtOffset); - } - - dvr_prio_t prio = DVR_PRIO_UNIMPORTANT; - if (timer.iPriority <= 20) - prio = DVR_PRIO_UNIMPORTANT; - else if (timer.iPriority <= 40) - prio = DVR_PRIO_LOW; - else if (timer.iPriority <= 60) - prio = DVR_PRIO_NORMAL; - else if (timer.iPriority <= 80) - prio = DVR_PRIO_HIGH; - else - prio = DVR_PRIO_IMPORTANT; - - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "addDvrEntry"); - if ((GetProtocol() >= 6) && timer.iEpgUid > 0) - { - htsmsg_add_u32(msg, "eventId", timer.iEpgUid); - } - else - { - htsmsg_add_str(msg, "title", timer.strTitle); - htsmsg_add_u32(msg, "start", startTime); - htsmsg_add_u32(msg, "stop", timer.endTime); - htsmsg_add_u32(msg, "channelId", timer.iClientChannelUid); - htsmsg_add_str(msg, "description", timer.strSummary); - htsmsg_add_u32(msg, "eventId", -1); - } - - htsmsg_add_s64(msg, "startExtra", timer.iMarginStart); - htsmsg_add_s64(msg, "stopExtra", timer.iMarginEnd); - - if (GetProtocol() > 12) - htsmsg_add_u32(msg, "retention", timer.iLifetime); - - htsmsg_add_u32(msg, "priority", prio); - htsmsg_add_str(msg, "creator", "XBMC"); - - CHTSResult result; - ReadResult(msg, result); - if (result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_DEBUG, "%s - Failed to get addDvrEntry", __FUNCTION__); - return result.status; - } - - const char *strError = NULL; - if ((strError = htsmsg_get_str(result.message, "error"))) - { - XBMC->Log(LOG_DEBUG, "%s - Error adding timer: '%s'", __FUNCTION__, strError); - return PVR_ERROR_SERVER_ERROR; - } - - unsigned int success; - if (htsmsg_get_u32(result.message, "success", &success) != 0) - { - XBMC->Log(LOG_DEBUG, "%s - Failed to parse param", __FUNCTION__); - return PVR_ERROR_SERVER_ERROR; - } - - return success > 0 ? PVR_ERROR_NO_ERROR : PVR_ERROR_FAILED; -} - -PVR_ERROR CHTSPData::UpdateTimer(const PVR_TIMER &timer) -{ - XBMC->Log(LOG_DEBUG, "%s - channelUid=%d title=%s epgid=%d", __FUNCTION__, timer.iClientChannelUid, timer.strTitle, timer.iEpgUid); - - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "updateDvrEntry"); - htsmsg_add_u32(msg, "id", timer.iClientIndex); - htsmsg_add_str(msg, "title", timer.strTitle); - htsmsg_add_u32(msg, "start", timer.startTime); - htsmsg_add_u32(msg, "stop", timer.endTime); - htsmsg_add_s64(msg, "startExtra", timer.iMarginStart); - htsmsg_add_s64(msg, "stopExtra", timer.iMarginEnd); - - if (GetProtocol() > 12) - { - htsmsg_add_u32(msg, "retention", timer.iLifetime); - - /* Priority */ - dvr_prio_t prio = DVR_PRIO_UNIMPORTANT; - if (timer.iPriority <= 20) - prio = DVR_PRIO_UNIMPORTANT; - else if (timer.iPriority <= 40) - prio = DVR_PRIO_LOW; - else if (timer.iPriority <= 60) - prio = DVR_PRIO_NORMAL; - else if (timer.iPriority <= 80) - prio = DVR_PRIO_HIGH; - else - prio = DVR_PRIO_IMPORTANT; - - htsmsg_add_u32(msg, "priority", (int)prio); - } - - CHTSResult result; - ReadResult(msg, result); - if (result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_DEBUG, "%s - Failed to get updateDvrEntry", __FUNCTION__); - return result.status; - } - - unsigned int success; - if (htsmsg_get_u32(result.message, "success", &success) != 0) - { - XBMC->Log(LOG_DEBUG, "%s - Failed to parse param", __FUNCTION__); - return PVR_ERROR_SERVER_ERROR; - } - - return success > 0 ? PVR_ERROR_NO_ERROR : PVR_ERROR_FAILED; -} - -PVR_ERROR CHTSPData::RenameRecording(const PVR_RECORDING &recording, const char *strNewName) -{ - XBMC->Log(LOG_DEBUG, "%s - id=%s", __FUNCTION__, recording.strRecordingId); - - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "updateDvrEntry"); - htsmsg_add_u32(msg, "id", atoi(recording.strRecordingId)); - htsmsg_add_str(msg, "title", recording.strTitle); - - CHTSResult result; - ReadResult(msg, result); - if (result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_DEBUG, "%s - Failed to get updateDvrEntry", __FUNCTION__); - return result.status; - } - - unsigned int success; - if (htsmsg_get_u32(result.message, "success", &success) != 0) - { - XBMC->Log(LOG_DEBUG, "%s - Failed to parse param", __FUNCTION__); - return PVR_ERROR_SERVER_ERROR; - } - - if (success > 0 && m_bIsStarted) - PVR->TriggerRecordingUpdate(); - - return success > 0 ? PVR_ERROR_NO_ERROR : PVR_ERROR_FAILED; -} - - -bool CHTSPData::ProcessMessage(htsmsg* msg) -{ - const char* method; - if((method = htsmsg_get_str(msg, "method")) == NULL) - return true; - - CLockObject lock(m_mutex); - if (m_demux && m_demux->ProcessMessage(msg)) - { - // demux packet - } - else if(strstr(method, "channelAdd")) - ParseChannelUpdate(msg); - else if(strstr(method, "channelUpdate")) - ParseChannelUpdate(msg); - else if(strstr(method, "channelDelete")) - ParseChannelRemove(msg); - else if(strstr(method, "tagAdd")) - ParseTagUpdate(msg); - else if(strstr(method, "tagUpdate")) - ParseTagUpdate(msg); - else if(strstr(method, "tagDelete")) - ParseTagRemove(msg); - else if(strstr(method, "initialSyncCompleted")) - { - m_bIsStarted = true; - m_started.Broadcast(); - } - else if(strstr(method, "dvrEntryAdd")) - ParseDVREntryUpdate(msg); - else if(strstr(method, "dvrEntryUpdate")) - ParseDVREntryUpdate(msg); - else if(strstr(method, "dvrEntryDelete")) - ParseDVREntryDelete(msg); - else - XBMC->Log(LOG_DEBUG, "%s - Unmapped action recieved '%s'", __FUNCTION__, method); - return true; -} - -SChannels CHTSPData::GetChannels() -{ - return GetChannels(0); -} - -SChannels CHTSPData::GetChannels(int tag) -{ - CLockObject lock(m_mutex); - if(tag == 0) - return m_channels; - - STags::iterator it = m_tags.find(tag); - if(it == m_tags.end()) - { - SChannels channels; - return channels; - } - return GetChannels(it->second); -} - -SChannels CHTSPData::GetChannels(STag& tag) -{ - CLockObject lock(m_mutex); - SChannels channels; - - std::vector::iterator it; - for(it = tag.channels.begin(); it != tag.channels.end(); it++) - { - SChannels::iterator it2 = m_channels.find(*it); - if(it2 == m_channels.end()) - { - XBMC->Log(LOG_ERROR, "%s - tag points to unknown channel %d", __FUNCTION__, *it); - continue; - } - channels[*it] = it2->second; - } - return channels; -} - -STags CHTSPData::GetTags() -{ - CLockObject lock(m_mutex); - return m_tags; -} - -PVR_ERROR CHTSPData::GetEvent(ADDON_HANDLE handle, uint32_t *id, time_t stop) -{ - if(*id == 0) - { - return PVR_ERROR_UNKNOWN; - } - - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "getEvent"); - htsmsg_add_u32(msg, "eventId", *id); - - CHTSResult result; - ReadResult(msg, result); - if(result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_DEBUG, "%s - failed to get event %d", __FUNCTION__, id); - return result.status; - } - - if (ParseEvent(handle, result.message, id, stop)) - { - return PVR_ERROR_NO_ERROR; - } - - return PVR_ERROR_SERVER_ERROR; -} - -PVR_ERROR CHTSPData::GetEvents(ADDON_HANDLE handle, uint32_t cid, time_t stop) -{ - PVR_ERROR retVal = PVR_ERROR_NO_ERROR; - - if (cid == 0) - { - return PVR_ERROR_UNKNOWN; - } - - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "getEvents"); - htsmsg_add_u32(msg, "channelId", cid); - htsmsg_add_s64(msg, "maxTime", stop); - - CHTSResult result; - ReadResult(msg, result); - if(result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_DEBUG, "%s - failed to get events for %d", __FUNCTION__, cid); - return result.status; - } - - if (!(msg = htsmsg_get_list(result.message, "events"))) { - XBMC->Log(LOG_DEBUG, "%s - failed to get events for %d", __FUNCTION__, cid); - return PVR_ERROR_UNKNOWN; - } - - htsmsg_t *e; - htsmsg_field_t *f; - - unsigned int failedEvents = 0; - unsigned int goodEvents = 0; - - HTSMSG_FOREACH(f, msg) - { - if ((e = htsmsg_get_map_by_field(f))) - { - if (ParseEvent(handle, e, NULL, stop)) - goodEvents++; - else - failedEvents++; - } - } - - if (goodEvents == 0 && failedEvents > 0) - retVal = PVR_ERROR_SERVER_ERROR; - - return retVal; -} - -bool CHTSPData::SendEnableAsync() -{ - htsmsg_t *m = htsmsg_create_map(); - htsmsg_add_str(m, "method", "enableAsyncMetadata"); - return m_session->ReadSuccess(m, "enableAsyncMetadata"); -} - -void CHTSPData::ParseChannelRemove(htsmsg_t* msg) -{ - uint32_t id; - if(htsmsg_get_u32(msg, "channelId", &id)) - { - XBMC->Log(LOG_ERROR, "%s - malformed message received", __FUNCTION__); - htsmsg_print(msg); - return; - } - XBMC->Log(LOG_DEBUG, "%s - id:%u", __FUNCTION__, id); - - m_channels.erase(id); - - if (m_bIsStarted) - PVR->TriggerChannelUpdate(); -} - -void CHTSPData::ParseChannelUpdate(htsmsg_t* msg) -{ - bool bChannelChanged(false), bTagsChanged(false); - uint32_t iChannelId, iEventId = 0, iChannelNumber = 0, iSubChannelNumber = 0, iCaid = 0; - const char *strName, *strIconPath; - if(htsmsg_get_u32(msg, "channelId", &iChannelId)) - { - XBMC->Log(LOG_ERROR, "%s - malformed message received", __FUNCTION__); - htsmsg_print(msg); - return; - } - - SChannel &channel = m_channels[iChannelId]; - channel.id = iChannelId; - - if(htsmsg_get_u32(msg, "eventId", &iEventId) == 0) - channel.event = iEventId; - - if((strName = htsmsg_get_str(msg, "channelName"))) - { - if (channel.name != strName) - { - bChannelChanged = true; - channel.name = strName; - } - } - - if((strIconPath = htsmsg_get_str(msg, "channelIcon"))) - { - CStdString strIconURL; - - if (strIconPath[0] != '/' || strIconPath[0] == '\0') - strIconURL = strIconPath; - else - strIconURL = m_session->GetWebURL("%s", strIconPath); - - if (channel.icon != strIconURL) - { - bChannelChanged = true; - channel.icon = strIconURL; - } - } - - if(htsmsg_get_u32(msg, "channelNumber", &iChannelNumber) == 0) - { - int iNewChannelNumber = (iChannelNumber == 0) ? iChannelId + 1000 : iChannelNumber; - if (channel.num != iNewChannelNumber) - { - bChannelChanged = true; - channel.num = iNewChannelNumber; - } - } - - /* ATSC subchannel number */ - if (!htsmsg_get_u32(msg, "channelNumberMinor", &iSubChannelNumber)) - { - if (channel.numMinor != iSubChannelNumber) - { - bChannelChanged = true; - channel.numMinor = iSubChannelNumber; - } - } - - htsmsg_t *tags; - - if((tags = htsmsg_get_list(msg, "tags"))) - { - std::vector newTags; - htsmsg_field_t *f; - HTSMSG_FOREACH(f, tags) - { - if(f->hmf_type != HMF_S64) - continue; - newTags.push_back((int)f->hmf_s64); - } - - for (std::vector::const_iterator it = newTags.begin(); it != newTags.end(); it++) - { - if (std::find(channel.tags.begin(), channel.tags.end(), *it) == channel.tags.end()) - bTagsChanged = true; - } - for (std::vector::const_iterator it = channel.tags.begin(); it != channel.tags.end(); it++) - { - if (std::find(newTags.begin(), newTags.end(), *it) == newTags.end()) - bTagsChanged = true; - } - if (bTagsChanged) - channel.tags = newTags; - } - - htsmsg_t *services; - bool bIsRadio = channel.radio; - if((services = htsmsg_get_list(msg, "services"))) - { - htsmsg_field_t *f; - HTSMSG_FOREACH(f, services) - { - if(f->hmf_type != HMF_MAP) - continue; - - htsmsg_t *service = &f->hmf_msg; - const char *service_type = htsmsg_get_str(service, "type"); - if(service_type != NULL) - bIsRadio = !strcmp(service_type, "Radio"); - - if(!htsmsg_get_u32(service, "caid", &iCaid)) - { - if ((channel.caid != (int)iCaid)) - { - bChannelChanged = true; - channel.caid = (int) iCaid; - } - } - } - } - if (channel.radio != bIsRadio) - { - bChannelChanged = true; - channel.radio = bIsRadio; - } - -#if HTSP_DEBUGGING - XBMC->Log(LOG_DEBUG, "%s - id:%u, name:'%s', icon:'%s', event:%u", - __FUNCTION__, iChannelId, strName ? strName : "(null)", strIconPath ? strIconPath : "(null)", iEventId); -#endif - - if (m_bIsStarted) - { - if (bChannelChanged) - PVR->TriggerChannelUpdate(); - if (bTagsChanged) - PVR->TriggerChannelGroupsUpdate(); - } -} - -void CHTSPData::ParseDVREntryDelete(htsmsg_t* msg) -{ - uint32_t id; - - if(htsmsg_get_u32(msg, "id", &id)) - { - XBMC->Log(LOG_ERROR, "%s - malformed message received", __FUNCTION__); - htsmsg_print(msg); - return; - } - - XBMC->Log(LOG_DEBUG, "%s - Recording %i was deleted", __FUNCTION__, id); - - m_recordings.erase(id); - - if (m_bIsStarted) - { - PVR->TriggerTimerUpdate(); - PVR->TriggerRecordingUpdate(); - } -} - -void CHTSPData::ParseDVREntryUpdate(htsmsg_t* msg) -{ - SRecording recording; - const char *state; - int64_t startExtra, stopExtra; - uint32_t retention, priority; - - /* Required fields */ - if(htsmsg_get_u32(msg, "id", &recording.id) - || htsmsg_get_u32(msg, "channel", &recording.channel) - || htsmsg_get_u32(msg, "start", &recording.start) - || htsmsg_get_u32(msg, "stop", &recording.stop) - || (state = htsmsg_get_str(msg, "state")) == NULL) - { - XBMC->Log(LOG_ERROR, "%s - malformed message received", __FUNCTION__); - htsmsg_print(msg); - return; - } - - /* parse the dvr entry's state */ - if (strstr(state, "scheduled")) - recording.state = ST_SCHEDULED; - else if(strstr(state, "recording")) - recording.state = ST_RECORDING; - else if(strstr(state, "completed")) - recording.state = ST_COMPLETED; - else if(strstr(state, "invalid")) - recording.state = ST_INVALID; - - /* Optional fields */ - if(!htsmsg_get_s64(msg, "startExtra", &startExtra)) - recording.startExtra = startExtra; - - if(!htsmsg_get_s64(msg, "stopExtra", &stopExtra)) - recording.stopExtra = stopExtra; - - if(!htsmsg_get_u32(msg, "retention", &retention)) - recording.retention = retention; - - if(!htsmsg_get_u32(msg, "priority", &priority)) - { - switch (priority) - { - case DVR_PRIO_IMPORTANT: - recording.priority = 100; - break; - case DVR_PRIO_HIGH: - recording.priority = 75; - break; - case DVR_PRIO_NORMAL: - recording.priority = 50; - break; - case DVR_PRIO_LOW: - recording.priority = 25; - break; - case DVR_PRIO_UNIMPORTANT: - recording.priority = 0; - break; - default: - XBMC->Log(LOG_ERROR, "%s - malformed message received", __FUNCTION__); - htsmsg_print(msg); - return; - } - } - - const char* str; - if((str = htsmsg_get_str(msg, "title")) == NULL) - recording.title = ""; - else - recording.title = str; - - if((str = htsmsg_get_str(msg, "path")) == NULL) - recording.path = ""; - else - recording.path = str; - - if((str = htsmsg_get_str(msg, "description")) == NULL) - recording.description = ""; - else - recording.description = str; - - if((str = htsmsg_get_str(msg, "error")) == NULL) - recording.error = ""; - else - recording.error = str; - - // if the user has aborted the recording then the recording.error will be set to 300 by tvheadend - if (recording.error == "300") - { - recording.state = ST_ABORTED; - recording.error.clear(); - } - - // Missing file (hide) - else if (recording.error == "File missing") - { - recording.state = ST_INVALID; - recording.error.clear(); - } - - -#if HTSP_DEBUGGING - XBMC->Log(LOG_DEBUG, "%s - id:%u, state:'%s', title:'%s', description: '%s', error:'%s'" - , __FUNCTION__, recording.id, state, recording.title.c_str() - , recording.description.c_str(), recording.error.c_str()); -#endif - - m_recordings[recording.id] = recording; - - if (m_bIsStarted) - { - PVR->TriggerTimerUpdate(); - - if (recording.state == ST_RECORDING) - PVR->TriggerRecordingUpdate(); - } -} - -bool CHTSPData::ParseEvent(ADDON_HANDLE handle, htsmsg_t* msg, uint32_t *id, time_t end) -{ - uint32_t eventId, channelId, content, nextId, stars, age, start, stop; - int64_t aired; - const char *title, *subtitle, *desc, *summary, *image; - - /* Required fields */ - if( htsmsg_get_u32(msg, "eventId", &eventId) - || htsmsg_get_u32(msg, "channelId", &channelId) - || htsmsg_get_u32(msg, "start", &start) - || htsmsg_get_u32(msg, "stop" , &stop) - || (title = htsmsg_get_str(msg, "title")) == NULL - || (id && (*id != eventId))) - { - XBMC->Log(LOG_DEBUG, "%s - malformed event", __FUNCTION__); - htsmsg_print(msg); - return false; - } - - /* Optional fields */ - summary = htsmsg_get_str(msg, "summary"); - subtitle = htsmsg_get_str(msg, "subtitle"); - desc = htsmsg_get_str(msg, "description"); - image = htsmsg_get_str(msg, "image"); - content = htsmsg_get_u32_or_default(msg, "contentType", 0); - nextId = htsmsg_get_u32_or_default(msg, "nextEventId", 0); - stars = htsmsg_get_u32_or_default(msg, "starRating", 0); - age = htsmsg_get_u32_or_default(msg, "ageRating", 0); - htsmsg_get_s64(msg, "firstAired", &aired); - - /* Fix old genre spec */ - if (GetProtocol() < 6) - content = content << 4; - -#if HTSP_DEBUGGING - XBMC->Log(LOG_DEBUG, "%s - id:%u, chan_id:%u, title:'%s', genre_type:%u, genre_sub_type:%u, desc:'%s', start:%u, stop:%u, next:%u" - , __FUNCTION__ - , eventId - , channelId - , title - , content & 0xF0 - , content & 0x0F - , desc - , start - , stop - , nextId); -#endif - - /* Broadcast */ - EPG_TAG broadcast; - memset(&broadcast, 0, sizeof(EPG_TAG)); - - broadcast.iUniqueBroadcastId = eventId; - broadcast.strTitle = title; - broadcast.iChannelNumber = channelId; - broadcast.startTime = start; - broadcast.endTime = stop; - broadcast.strPlotOutline = summary ? summary : ""; - broadcast.strPlot = desc ? desc : ""; - broadcast.strIconPath = image ? image : ""; - broadcast.iGenreType = content & 0xF0; - broadcast.iGenreSubType = content & 0x0F; - broadcast.strGenreDescription = ""; // unused - broadcast.firstAired = (time_t) aired; - broadcast.iParentalRating = age; - broadcast.iStarRating = stars; - broadcast.bNotify = false; - broadcast.iSeriesNumber = htsmsg_get_u32_or_default(msg, "seasonNumber", 0); - broadcast.iEpisodeNumber = htsmsg_get_u32_or_default(msg, "episodeNumber", 0); - broadcast.iEpisodePartNumber = htsmsg_get_u32_or_default(msg, "partNumber", 0); - broadcast.strEpisodeName = subtitle ? subtitle : ""; - - /* Post to PVR */ - PVR->TransferEpgEntry(handle, &broadcast); - - /* Update next */ - if (id && ((time_t)stop < end)) - *id = nextId; - else if (id) - *id = 0; - - return true; -} - -void CHTSPData::ParseTagRemove(htsmsg_t* msg) -{ - uint32_t id; - if(htsmsg_get_u32(msg, "tagId", &id)) - { - XBMC->Log(LOG_ERROR, "%s - malformed message received", __FUNCTION__); - htsmsg_print(msg); - return; - } - XBMC->Log(LOG_DEBUG, "%s - id:%u", __FUNCTION__, id); - - m_tags.erase(id); - - if (m_bIsStarted) - PVR->TriggerChannelGroupsUpdate(); -} - -void CHTSPData::ParseTagUpdate(htsmsg_t* msg) -{ - uint32_t id; - const char *name, *icon; - if(htsmsg_get_u32(msg, "tagId", &id)) - { - XBMC->Log(LOG_ERROR, "%s - malformed message received", __FUNCTION__); - htsmsg_print(msg); - return; - } - STag &tag = m_tags[id]; - tag.id = id; - - if((icon = htsmsg_get_str(msg, "tagIcon"))) - tag.icon = icon; - - if((name = htsmsg_get_str(msg, "tagName"))) - tag.name = name; - - htsmsg_t *channels; - - if((channels = htsmsg_get_list(msg, "members"))) - { - tag.channels.clear(); - - htsmsg_field_t *f; - HTSMSG_FOREACH(f, channels) - { - if(f->hmf_type != HMF_S64) - continue; - tag.channels.push_back((int)f->hmf_s64); - } - } - -#if HTSP_DEBUGGING - XBMC->Log(LOG_DEBUG, "%s - id:%u, name:'%s', icon:'%s'" - , __FUNCTION__, id, name ? name : "(null)", icon ? icon : "(null)"); -#endif - - if (m_bIsStarted) - PVR->TriggerChannelGroupsUpdate(); -} - -bool CHTSPData::OpenRecordedStream(const PVR_RECORDING &recording) -{ - if (GetProtocol() < 7) return false; - - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "fileOpen"); - - CStdString strDvrPath; - strDvrPath.Format("dvr/%s", recording.strRecordingId); - htsmsg_add_str(msg, "file", strDvrPath.c_str()); - - CHTSResult result; - ReadResult(msg, result); - if (result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_DEBUG, "%s - failed to fileOpen", __FUNCTION__); - return false; - } - - uint32_t id; - if (htsmsg_get_u32(result.message, "id", &id)) - return false; - m_recordingId = id; - m_recordingOff = 0; - m_recordingBuf.reset(); - - return true; -} - -void CHTSPData::CloseRecordedStream(void) -{ - if (GetProtocol() < 7) return; - if (!m_recordingId) return; - - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "fileClose"); - htsmsg_add_u32(msg, "id", m_recordingId); - CHTSResult result; - ReadResult(msg, result); - if (result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_DEBUG, "%s - failed to fileClose", __FUNCTION__); - } - m_recordingId = 0; -} - -int CHTSPData::ReadRecordedStream(unsigned char *pBuffer, unsigned int iBufferSize) -{ - ssize_t ret; - if (GetProtocol() < 7) return 0; - if (!m_recordingId) return -1; - - /* Fetch data */ - if (m_recordingBuf.avail() <= iBufferSize) - { - const void *buf; - size_t len; - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "fileRead"); - htsmsg_add_u32(msg, "id", m_recordingId); - htsmsg_add_s64(msg, "size", m_recordingBuf.free()); - CHTSResult result; - ReadResult(msg, result); - if (result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_DEBUG, "%s - failed to fileRead", __FUNCTION__); - return -1; - } - if (htsmsg_get_bin(result.message, "data", &buf, &len)) { - XBMC->Log(LOG_DEBUG, "%s - failed fileRead no buffer", __FUNCTION__); - return -1; - } - ret = m_recordingBuf.write((unsigned char*)buf, len); - if (ret != (ssize_t)len) - { - XBMC->Log(LOG_ERROR, "%s - CircBuffer::write() partial %ld != %ld", __FUNCTION__, ret, len); - return -1; - } - } - - /* Read */ - ret = m_recordingBuf.read(pBuffer, iBufferSize); - m_recordingOff += ret; - return (int)ret; -} - -long long CHTSPData::SeekRecordedStream(long long iPosition, int iWhence /* = SEEK_SET */) -{ - if (GetProtocol() < 7) return 0; - if (!m_recordingId) return -1; - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "fileSeek"); - htsmsg_add_u32(msg, "id", m_recordingId); - htsmsg_add_s64(msg, "offset", iPosition); - if (iWhence == SEEK_CUR) - htsmsg_add_str(msg, "whence", "SEEK_CUR"); - else if (iWhence == SEEK_END) - htsmsg_add_str(msg, "whence", "SEEK_END"); - //else - // htsmsg_add_str(msg, "whence", SEEK_SET"); - // Note: last is default so no need to send - CHTSResult result; - ReadResult(msg, result); - if (result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_DEBUG, "%s - failed to fileSeek", __FUNCTION__); - return -1; - } - int64_t off; - if (htsmsg_get_s64(result.message, "offset", &off)) { - XBMC->Log(LOG_DEBUG, "%s - failed to fileSeek no offset", __FUNCTION__); - return -1; - } - m_recordingOff = off; - m_recordingBuf.reset(); - return m_recordingOff; -} - -long long CHTSPData::PositionRecordedStream(void) -{ - if (GetProtocol() < 7) return 0; - return m_recordingOff; -} - -long long CHTSPData::LengthRecordedStream(void) -{ - if (GetProtocol() < 7) return 0; - if (!m_recordingOff) return -1; - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "fileStat"); - htsmsg_add_u32(msg, "id", m_recordingId); - CHTSResult result; - ReadResult(msg, result); - if (result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_DEBUG, "%s - failed to fileStat", __FUNCTION__); - return -1; - } - int64_t size; - if (htsmsg_get_s64(result.message, "size", &size)) - { - XBMC->Log(LOG_DEBUG, "%s - failed to fileStat no size", __FUNCTION__); - return -1; - } - return size; -} - -bool CHTSPData::OnConnectionDropped(void) -{ - if (m_demux) - m_demux->OnConnectionDropped(); - m_bIsStarted = false; - if (m_connectionWarningTimeout.TimeLeft() == 0) - { - // don't show the warning more than once every 5 seconds - m_connectionWarningTimeout.Init(5000); - - CStdString strNotification(XBMC->GetLocalizedString(30500)); - XBMC->QueueNotification(QUEUE_ERROR, strNotification, GetServerName()); - } - return true; -} - -bool CHTSPData::OnConnectionRestored(void) -{ - // Clear cached data. They may be invalid due to changes on tvh side - // while connection was down (e.g. deleted timers). - m_channels.clear(); - m_tags.clear(); - m_recordings.clear(); - - if(!SendEnableAsync()) - return false; - - { - CLockObject lock(m_mutex); - if (!m_started.Wait(m_mutex, m_bIsStarted, g_iConnectTimeout * 1000)) - return false; - } - - PVR->TriggerChannelUpdate(); - PVR->TriggerChannelGroupsUpdate(); - PVR->TriggerRecordingUpdate(); - PVR->TriggerTimerUpdate(); - - if (m_demux) - m_demux->OnConnectionRestored(); - - CStdString strNotification(XBMC->GetLocalizedString(30501)); - XBMC->QueueNotification(QUEUE_INFO, strNotification, GetServerName()); - return true; -} - -bool CHTSPData::OpenLiveStream(const PVR_CHANNEL &channel) -{ - CloseLiveStream(); - - if (!IsConnected() || !m_demux) - return false; - - return m_demux->Open(channel); -} - -void CHTSPData::CloseLiveStream(void) -{ - if (m_demux) - m_demux->Close(); -} - -int CHTSPData::GetCurrentClientChannel(void) -{ - return m_demux ? - m_demux->CurrentChannel() : - -1; -} - -bool CHTSPData::SwitchChannel(const PVR_CHANNEL &channel) -{ - return m_demux ? - m_demux->SwitchChannel(channel) : - false; -} - -PVR_ERROR CHTSPData::GetStreamProperties(PVR_STREAM_PROPERTIES* pProperties) -{ - return m_demux && m_demux->GetStreamProperties(pProperties) ? - PVR_ERROR_NO_ERROR : - PVR_ERROR_SERVER_ERROR; -} - -PVR_ERROR CHTSPData::SignalStatus(PVR_SIGNAL_STATUS &signalStatus) -{ - return m_demux && m_demux->GetSignalStatus(signalStatus) ? - PVR_ERROR_NO_ERROR : - PVR_ERROR_SERVER_ERROR; -} - -void CHTSPData::DemuxAbort(void) -{ - if (m_demux) - m_demux->Abort(); -} - -void CHTSPData::DemuxFlush(void) -{ - if (m_demux) - m_demux->Flush(); -} - -DemuxPacket* CHTSPData::DemuxRead(void) -{ - return m_demux ? - m_demux->Read() : - NULL; -} - -bool CHTSPData::SeekTime(int time,bool backward,double *startpts) -{ - return m_demux && CanSeekLiveStream() ? - m_demux->SeekTime(time, backward, startpts) : - false; -} - -void CHTSPData::SetSpeed(int speed) -{ - if (m_demux && CanTimeshift()) - m_demux->SetSpeed(speed); -} - -PVR_ERROR CHTSPData::GetEdl(const PVR_RECORDING &recording, PVR_EDL_ENTRY entries[], int *size) -{ - if (GetProtocol() < 12) return PVR_ERROR_NOT_IMPLEMENTED; - - XBMC->Log(LOG_DEBUG, "%s - dvrEntryId:%s", __FUNCTION__, recording.strRecordingId); - - htsmsg_t *msg = htsmsg_create_map(); - htsmsg_add_str(msg, "method", "getDvrCutpoints"); - htsmsg_add_u32(msg, "id", atoi(recording.strRecordingId)); - - CHTSResult result; - ReadResult(msg, result); - if (result.status != PVR_ERROR_NO_ERROR) - { - XBMC->Log(LOG_ERROR, "%s - Failed to get EDL data.", __FUNCTION__); - return result.status; - } - - htsmsg_t *edlList = htsmsg_get_list(result.message, "cutpoints"); - if(!edlList) - { - XBMC->Log(LOG_DEBUG, "%s - No EDL list found.", __FUNCTION__); - *size = 0; - return PVR_ERROR_NO_ERROR; - } - - htsmsg_field_t *field; - int index = 0; - HTSMSG_FOREACH(field, edlList) - { - if(field->hmf_type != HMF_MAP) - continue; - - if(index < *size) - { - htsmsg_t *edl = &field->hmf_msg; - - // start and end are in milliseconds - unsigned int start, end, type; - - if (htsmsg_get_u32(edl, "start", &start) != 0 || - htsmsg_get_u32(edl, "end", &end) != 0 || - htsmsg_get_u32(edl, "type", &type) != 0) - { - continue; - } - - PVR_EDL_ENTRY entry; - entry.start = start; - entry.end = end; - - switch(type) - { - case DVR_ACTION_TYPE_CUT: - entry.type = PVR_EDL_TYPE_CUT; - break; - case DVR_ACTION_TYPE_MUTE: - entry.type = PVR_EDL_TYPE_MUTE; - break; - case DVR_ACTION_TYPE_SCENE: - entry.type = PVR_EDL_TYPE_SCENE; - break; - case DVR_ACTION_TYPE_COMBREAK: - entry.type = PVR_EDL_TYPE_COMBREAK; - break; - default: - entry.type = PVR_EDL_TYPE_COMBREAK; - break; - } - - XBMC->Log(LOG_DEBUG, "%s - EDL: start: %d, end: %d, action: %d", __FUNCTION__, entry.start, entry.end, entry.type); - - entries[index] = entry; - index++; - } - else - { - XBMC->Log(LOG_ERROR, "%s - Maximum number of EDL entries reached for recordingId: %s", __FUNCTION__, recording.strRecordingId); - break; - } - } - *size = index; - - return PVR_ERROR_NO_ERROR; -} - -double CHTSPData::DemuxGetTimeshiftTime(void) -{ - return m_demux ? - m_demux->GetTimeshiftTime() : - 0; -} diff --git a/addons/pvr.hts/src/HTSPData.h b/addons/pvr.hts/src/HTSPData.h deleted file mode 100644 index 717b76912..000000000 --- a/addons/pvr.hts/src/HTSPData.h +++ /dev/null @@ -1,132 +0,0 @@ -#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, 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#include "client.h" -#include "platform/threads/threads.h" -#include "HTSPConnection.h" -#include "CircBuffer.h" - -class CHTSPDemux; - -class CHTSPData : CHTSPConnectionCallback -{ -public: - CHTSPData(); - ~CHTSPData(); - - bool Open(); - void Close(); - bool IsConnected(void) const { return m_session->IsConnected(); } - - /*! - * @brief Send a message to the backend and read the result. - * @param message The message to send. - * @return The returned message or NULL if an error occured or nothing was received. - */ - void ReadResult(htsmsg_t *message, CHTSResult &result); - int GetProtocol(void) const { return m_session->GetProtocol(); } - const char * GetServerName(void) const { return m_session->GetServerName(); } - const char * GetVersion(void) const { return m_session->GetVersion(); } - bool CanTimeshift(void) const { return m_session->CanTimeshift(); } - bool CanSeekLiveStream(void) const { return m_session->CanSeekLiveStream(); } - - bool CanTranscode(void) const { return m_session->CanTranscode(); } - CodecVector GetTranscodingCodecs(void); - - bool GetDriveSpace(long long *total, long long *used); - bool GetBackendTime(time_t *utcTime, int *gmtOffset); - unsigned int GetNumChannels(void); - PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio); - PVR_ERROR GetEpg(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd); - unsigned int GetNumRecordings(); - PVR_ERROR GetRecordings(ADDON_HANDLE handle); - PVR_ERROR DeleteRecording(const PVR_RECORDING &recinfo); - PVR_ERROR AddTimer(const PVR_TIMER &timerinfo); - PVR_ERROR UpdateTimer(const PVR_TIMER &timerinfo); - PVR_ERROR RenameRecording(const PVR_RECORDING &recinfo, const char* newname); - unsigned int GetNumTimers(); - PVR_ERROR GetTimers(ADDON_HANDLE handle); - PVR_ERROR DeleteTimer(const PVR_TIMER &timerinfo, bool force); - unsigned int GetNumChannelGroups(void); - PVR_ERROR GetChannelGroups(ADDON_HANDLE handle); - PVR_ERROR GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group); - bool OpenRecordedStream(const PVR_RECORDING &recording); - void CloseRecordedStream(void); - int ReadRecordedStream(unsigned char *pBuffer, unsigned int iBufferSize); - long long SeekRecordedStream(long long iPosition, int iWhence /* = SEEK_SET */); - long long PositionRecordedStream(void); - long long LengthRecordedStream(void); - - bool OnConnectionDropped(void); - bool OnConnectionRestored(void); - bool ProcessMessage(htsmsg* msg); - - bool OpenLiveStream(const PVR_CHANNEL &channel); - void CloseLiveStream(void); - int GetCurrentClientChannel(void); - bool SwitchChannel(const PVR_CHANNEL &channel); - PVR_ERROR GetStreamProperties(PVR_STREAM_PROPERTIES* pProperties); - PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS &signalStatus); - void DemuxAbort(void); - void DemuxFlush(void); - DemuxPacket* DemuxRead(void); - bool SeekTime(int time,bool backward,double *startpts); - void SetSpeed(int speed); - PVR_ERROR GetEdl(const PVR_RECORDING &recinfo, PVR_EDL_ENTRY entries[], int *size); - double DemuxGetTimeshiftTime(void); - -private: - SChannels GetChannels(); - SChannels GetChannels(int tag); - SChannels GetChannels(STag &tag); - STags GetTags(); - PVR_ERROR GetEvent(ADDON_HANDLE handle, uint32_t *id, time_t stop); - PVR_ERROR GetEvents(ADDON_HANDLE handle, uint32_t cid, time_t stop); - bool SendEnableAsync(); - SRecordings GetDVREntries(bool recorded, bool scheduled); - - void ParseChannelRemove(htsmsg_t* msg); - void ParseChannelUpdate(htsmsg_t* msg); - void ParseDVREntryDelete(htsmsg_t* msg); - void ParseDVREntryUpdate(htsmsg_t* msg); - bool ParseEvent(ADDON_HANDLE handle, htsmsg_t* msg, uint32_t *id, time_t end); - void ParseTagRemove(htsmsg_t* msg); - void ParseTagUpdate(htsmsg_t* msg); - - CHTSPConnection * m_session; - bool m_bIsStarted; - PLATFORM::CCondition m_started; - PLATFORM::CMutex m_mutex; - SChannels m_channels; - STags m_tags; - SRecordings m_recordings; - int m_iReconnectRetries; - bool m_bDisconnectWarningDisplayed; - uint32_t m_recordingId; - int64_t m_recordingOff; - CCircBuffer m_recordingBuf; - CHTSPDemux* m_demux; - PLATFORM::CTimeout m_connectionWarningTimeout; -}; - diff --git a/addons/pvr.hts/src/HTSPDemux.cpp b/addons/pvr.hts/src/HTSPDemux.cpp deleted file mode 100644 index d6b2af2be..000000000 --- a/addons/pvr.hts/src/HTSPDemux.cpp +++ /dev/null @@ -1,669 +0,0 @@ -/* - * 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, 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#include "client.h" -#include "HTSPConnection.h" -#include "HTSPDemux.h" -#include - -#define READ_TIMEOUT_MS 20000 -#define STREAM_PROPS_TIMEOUT_MS 500 - -using namespace std; -using namespace ADDON; -using namespace PLATFORM; - -CHTSPDemux::CHTSPDemux(CHTSPConnection* connection) : - m_session(connection), - m_bIsRadio(false), - m_subs(0), - m_channel(0), - m_tag(0), - m_bIsOpen(false) -{ - m_seekEvent = new CEvent; - m_seekTime = -1; -} - -CHTSPDemux::~CHTSPDemux() -{ - Close(); -} - -bool CHTSPDemux::Open(const PVR_CHANNEL &channelinfo) -{ - m_channel = channelinfo.iUniqueId; - m_bIsRadio = channelinfo.bIsRadio; - m_bIsOpen = false; - - if(!m_session->CheckConnection(g_iConnectTimeout * 1000)) - return false; - - if(!SendSubscribe(++m_subs, m_channel)) - return false; - - return true; -} - -void CHTSPDemux::Close() -{ - if (m_session->IsConnected() && m_subs > 0) - SendUnsubscribe(m_subs); - m_subs = 0; -} - -void CHTSPDemux::SetSpeed(int speed) -{ - SendSpeed(m_subs, speed/10); -} - -bool CHTSPDemux::SeekTime(int time, bool backward, double *startpts) -{ - return SendSeek(m_subs, time, backward, startpts); -} - -bool CHTSPDemux::GetStreamProperties(PVR_STREAM_PROPERTIES* props) -{ - CLockObject lock(m_mutex); - if (!m_startedCondition.Wait(m_mutex, m_bIsOpen, STREAM_PROPS_TIMEOUT_MS)) - return false; - return m_streams.GetProperties(props); -} - -void CHTSPDemux::Abort() -{ - CLockObject lock(m_mutex); - m_streams.Clear(); -} - -void CHTSPDemux::Flush(void) -{ - DemuxPacket* pkt(NULL); - while (m_demuxPacketBuffer.Pop(pkt)) - PVR->FreeDemuxPacket(pkt); -} - -bool CHTSPDemux::ProcessMessage(htsmsg* msg) -{ - uint32_t subs; - const char *method = htsmsg_get_str(msg, "method"); - if (!method) - return true; - - if ( strcmp("subscriptionStart", method) == 0) - { - ParseSubscriptionStart(msg); - } - else if(htsmsg_get_u32(msg, "subscriptionId", &subs)) - { - // no subscription id set, ignore - return false; - } - else if (subs != m_subs) - { - // switching channels - return true; - } - else if(strcmp("subscriptionStop", method) == 0) - ParseSubscriptionStop(msg); - else if(strcmp("subscriptionStatus", method) == 0) - ParseSubscriptionStatus(msg); - else if(strcmp("subscriptionSkip" , method) == 0) - ParseSubscriptionSkip(msg); - else if(strcmp("subscriptionSpeed" , method) == 0) - ParseSubscriptionSpeed(msg); - else if(strcmp("queueStatus" , method) == 0) - ParseQueueStatus(msg); - else if(strcmp("signalStatus" , method) == 0) - ParseSignalStatus(msg); - else if(strcmp("timeshiftStatus" , method) == 0) - ParseTimeshiftStatus(msg); - else if(strcmp("muxpkt" , method) == 0) - ParseMuxPacket(msg); - else - { - // not a demux message - return false; - } - - return true; -} - -DemuxPacket* CHTSPDemux::Read() -{ - if (!m_session->CheckConnection(1000)) - return PVR->AllocateDemuxPacket(0); - - DemuxPacket* packet(NULL); - if (m_demuxPacketBuffer.Pop(packet, 100)) - return packet; - - return PVR->AllocateDemuxPacket(0); -} - -void CHTSPDemux::ParseMuxPacket(htsmsg_t *msg) -{ - uint32_t index, duration; - const void* bin; - size_t binlen; - int64_t ts; - - if(htsmsg_get_u32(msg, "stream" , &index) || - htsmsg_get_bin(msg, "payload", &bin, &binlen)) - { - XBMC->Log(LOG_ERROR, "%s - malformed message", __FUNCTION__); - return; - } - - DemuxPacket* pkt = PVR->AllocateDemuxPacket(binlen); - if (!pkt) - return; - memcpy(pkt->pData, bin, binlen); - - pkt->iSize = binlen; - - if(!htsmsg_get_u32(msg, "duration", &duration)) - pkt->duration = (double)duration * DVD_TIME_BASE / 1000000; - - if(!htsmsg_get_s64(msg, "dts", &ts)) - pkt->dts = (double)ts * DVD_TIME_BASE / 1000000; - else - pkt->dts = DVD_NOPTS_VALUE; - - if(!htsmsg_get_s64(msg, "pts", &ts)) - pkt->pts = (double)ts * DVD_TIME_BASE / 1000000; - else - pkt->pts = DVD_NOPTS_VALUE; - - pkt->iStreamId = m_streams.GetStreamId((unsigned int)index); - - // drop packets with an invalid stream id - if (pkt->iStreamId < 0) - { - PVR->FreeDemuxPacket(pkt); - return; - } - - m_demuxPacketBuffer.Push(pkt); -} - -bool CHTSPDemux::SwitchChannel(const PVR_CHANNEL &channelinfo) -{ - XBMC->Log(LOG_INFO, "%s - changing to channel '%s'", __FUNCTION__, channelinfo.strChannelName); - - if (!SendUnsubscribe(m_subs)) - XBMC->Log(LOG_ERROR, "%s - failed to unsubscribe from previous channel", __FUNCTION__); - - if (!SendSubscribe(++m_subs, channelinfo.iUniqueId)) - { - XBMC->Log(LOG_ERROR, "%s - failed to set channel", __FUNCTION__); - m_subs = 0; - } - else - { - m_channel = channelinfo.iUniqueId; - m_streams.Clear(); - - return true; - } - return false; -} - -bool CHTSPDemux::GetSignalStatus(PVR_SIGNAL_STATUS &qualityinfo) -{ - memset(&qualityinfo, 0, sizeof(qualityinfo)); - if (m_SourceInfo.si_adapter.empty() || m_Quality.fe_status.empty()) - return false; - - strncpy(qualityinfo.strAdapterName, m_SourceInfo.si_adapter.c_str(), sizeof(qualityinfo.strAdapterName)); - strncpy(qualityinfo.strAdapterStatus, m_Quality.fe_status.c_str(), sizeof(qualityinfo.strAdapterStatus)); - strncpy(qualityinfo.strServiceName, m_SourceInfo.si_service.c_str(), sizeof(qualityinfo.strServiceName)); - strncpy(qualityinfo.strProviderName, m_SourceInfo.si_provider.c_str(), sizeof(qualityinfo.strProviderName)); - strncpy(qualityinfo.strMuxName, m_SourceInfo.si_mux.c_str(), sizeof(qualityinfo.strMuxName)); - - qualityinfo.iSignal = (uint16_t)m_Quality.fe_signal; - qualityinfo.iSNR = (uint16_t)m_Quality.fe_snr; - qualityinfo.iBER = (uint32_t)m_Quality.fe_ber; - qualityinfo.iUNC = (uint32_t)m_Quality.fe_unc; - - return true; -} - -inline void HTSPResetDemuxStreamInfo(PVR_STREAM_PROPERTIES::PVR_STREAM &stream) -{ - memset(&stream, 0, sizeof(stream)); - stream.iIdentifier = -1; - stream.iCodecType = XBMC_CODEC_TYPE_UNKNOWN; - stream.iCodecId = XBMC_INVALID_CODEC_ID; -} - -inline void HTSPSetDemuxStreamInfoAudio(PVR_STREAM_PROPERTIES::PVR_STREAM &stream, htsmsg_t *msg) -{ - stream.iChannels = htsmsg_get_u32_or_default(msg, "channels" , 0); - stream.iSampleRate = htsmsg_get_u32_or_default(msg, "rate" , 0); -} - -inline void HTSPSetDemuxStreamInfoVideo(PVR_STREAM_PROPERTIES::PVR_STREAM &stream, htsmsg_t *msg) -{ - stream.iWidth = htsmsg_get_u32_or_default(msg, "width" , 0); - stream.iHeight = htsmsg_get_u32_or_default(msg, "height" , 0); - uint32_t den = htsmsg_get_u32_or_default(msg, "aspect_den", 1); - if(den) - stream.fAspect = (float)htsmsg_get_u32_or_default(msg, "aspect_num", 1) / den; - else - stream.fAspect = 0.0f; - uint32_t iDuration = htsmsg_get_u32_or_default(msg, "duration" , 0); - if (iDuration > 0) - { - stream.iFPSScale = iDuration; - stream.iFPSRate = DVD_TIME_BASE; - } -} - -inline void HTSPSetDemuxStreamInfoLanguage(PVR_STREAM_PROPERTIES::PVR_STREAM &stream, htsmsg_t *msg) -{ - if (const char *strLanguage = htsmsg_get_str(msg, "language")) - { - stream.strLanguage[0] = strLanguage[0]; - stream.strLanguage[1] = strLanguage[1]; - stream.strLanguage[2] = strLanguage[2]; - stream.strLanguage[3] = 0; - } -} - -void CHTSPDemux::ParseSubscriptionStart(htsmsg_t *m) -{ - vector newStreams; - - htsmsg_t *streams; - htsmsg_field_t *f; - uint32_t subs; - - if(htsmsg_get_u32(m, "subscriptionId", &subs)) - { - XBMC->Log(LOG_ERROR, "%s - invalid subscription id", __FUNCTION__); - return; - } - m_subs = subs; - - if((streams = htsmsg_get_list(m, "streams")) == NULL) - { - XBMC->Log(LOG_ERROR, "%s - malformed message", __FUNCTION__); - return; - } - - HTSMSG_FOREACH(f, streams) - { - uint32_t index; - const char* type; - htsmsg_t* sub; - - if (f->hmf_type != HMF_MAP) - continue; - - sub = &f->hmf_msg; - - if ((type = htsmsg_get_str(sub, "type")) == NULL) - continue; - - if (htsmsg_get_u32(sub, "index", &index)) - continue; - - bool bValidStream(true); - XbmcPvrStream newStream; - m_streams.GetStreamData(index, &newStream); - - CodecDescriptor codecId = CodecDescriptor::GetCodecByName(type); - if (codecId.Codec().codec_type != XBMC_CODEC_TYPE_UNKNOWN) - { - newStream.iCodecType = codecId.Codec().codec_type; - newStream.iCodecId = codecId.Codec().codec_id; - - if (codecId.Codec().codec_type == XBMC_CODEC_TYPE_SUBTITLE) - { - if (!strcmp(type, "DVBSUB")) - { - uint32_t composition_id = 0, ancillary_id = 0; - htsmsg_get_u32(sub, "composition_id", &composition_id); - htsmsg_get_u32(sub, "ancillary_id" , &ancillary_id); - newStream.iIdentifier = (composition_id & 0xffff) | ((ancillary_id & 0xffff) << 16); - } - HTSPSetDemuxStreamInfoLanguage(newStream, sub); - } - } - else - { - bValidStream = false; - } - - if (bValidStream) - { - XBMC->Log(LOG_DEBUG, "%s - id: %d, type: %s, codec: %u", __FUNCTION__, index, codecId.Name().c_str(), codecId.Codec().codec_id); - - newStream.iPhysicalId = index; - if (codecId.Codec().codec_type == XBMC_CODEC_TYPE_AUDIO) - { - HTSPSetDemuxStreamInfoAudio(newStream, sub); - HTSPSetDemuxStreamInfoLanguage(newStream, sub); - } - else if (codecId.Codec().codec_type == XBMC_CODEC_TYPE_VIDEO) - HTSPSetDemuxStreamInfoVideo(newStream, sub); - - newStreams.push_back(newStream); - } - else - { - XBMC->Log(LOG_DEBUG, "%s - id: %d, type: %s, ignored", __FUNCTION__, index, type); - } - } - - CLockObject lock(m_mutex); - m_streams.UpdateStreams(newStreams); - - DemuxPacket* pkt = PVR->AllocateDemuxPacket(0); - pkt->iStreamId = DMX_SPECIALID_STREAMCHANGE; - m_demuxPacketBuffer.Push(pkt); - - if (ParseSourceInfo(m)) - { - XBMC->Log(LOG_INFO, "%s - subscription started on adapter %s, mux %s, network %s, provider %s, service %s" - , __FUNCTION__, m_SourceInfo.si_adapter.c_str(), m_SourceInfo.si_mux.c_str(), - m_SourceInfo.si_network.c_str(), m_SourceInfo.si_provider.c_str(), - m_SourceInfo.si_service.c_str()); - } - else - { - XBMC->Log(LOG_INFO, "%s - subscription started on an unknown device", __FUNCTION__); - } - - m_bIsOpen = true; - m_startedCondition.Signal(); -} - -void CHTSPDemux::ParseSubscriptionStop(htsmsg_t *m) -{ - XBMC->Log(LOG_INFO, "%s - subscription ended on adapter %s", __FUNCTION__, m_SourceInfo.si_adapter.c_str()); - CLockObject lock(m_mutex); - m_streams.Clear(); - - /* reset the signal status */ - m_Quality.fe_status = ""; - m_Quality.fe_ber = -2; - m_Quality.fe_signal = -2; - m_Quality.fe_snr = -2; - m_Quality.fe_unc = -2; - - /* reset the source info */ - m_SourceInfo.si_adapter = ""; - m_SourceInfo.si_mux = ""; - m_SourceInfo.si_network = ""; - m_SourceInfo.si_provider = ""; - m_SourceInfo.si_service = ""; -} - -void CHTSPDemux::ParseSubscriptionStatus(htsmsg_t *m) -{ - const char* status; - status = htsmsg_get_str(m, "status"); - if(status == NULL) - m_Status = ""; - else - { - m_Status = status; - XBMC->Log(LOG_INFO, "%s - status = '%s'", __FUNCTION__, status); - XBMC->QueueNotification(QUEUE_INFO, status); - } -} - -void CHTSPDemux::ParseSubscriptionSkip(htsmsg_t *m) -{ - int64_t s64; - uint32_t u32; - if (!htsmsg_get_u32(m, "error", &u32) || - htsmsg_get_u32(m, "absolute", &u32) || - htsmsg_get_s64(m, "time", &s64)) { - m_seekTime = -1; - } else { - m_seekTime = (double)s64; - } - XBMC->Log(LOG_DEBUG, "HTSP::ParseSubscriptionSkip - skip = %lf\n", m_seekTime); - m_seekEvent->Broadcast(); -} - -void CHTSPDemux::ParseSubscriptionSpeed(htsmsg_t *m) -{ - uint32_t u32; - if (!htsmsg_get_u32(m, "speed", &u32)) { - XBMC->Log(LOG_INFO, "%s - speed = %u", __FUNCTION__, u32); - // TODO: need a way to pass this to player core - } -} - -bool CHTSPDemux::SendUnsubscribe(int subscription) -{ - XBMC->Log(LOG_INFO, "%s - unsubscribe from subscription %d", __FUNCTION__, subscription); - - htsmsg_t *m = htsmsg_create_map(); - htsmsg_add_str(m, "method" , "unsubscribe"); - htsmsg_add_s32(m, "subscriptionId", subscription); - bool bReturn = m_session->ReadSuccess(m, "unsubscribe from channel"); - m_session->SetReadTimeout(-1); - Flush(); - m_bIsOpen = false; - return bReturn; -} - -bool CHTSPDemux::SendSubscribe(int subscription, int channel) -{ - const char* audioCodec(NULL); - const char* videoCodec(NULL); - - XBMC->Log(LOG_INFO, "%s - subscribe to channel '%d', subscription %d", __FUNCTION__, channel, subscription); - - htsmsg_t *m = htsmsg_create_map(); - htsmsg_add_str(m, "method" , "subscribe"); - htsmsg_add_s32(m, "channelId" , channel); - htsmsg_add_s32(m, "subscriptionId" , subscription); - htsmsg_add_u32(m, "timeshiftPeriod", (uint32_t)~0); - - if(g_bTranscode) - { - audioCodec = g_audioCodec.Name().c_str() ? g_audioCodec.Name().c_str() : "UNKNOWN"; - videoCodec = g_videoCodec.Name().c_str() ? g_videoCodec.Name().c_str() : "UNKNOWN"; - htsmsg_add_u32(m, "maxResolution", g_iResolution); - htsmsg_add_str(m, "audioCodec" , audioCodec); - htsmsg_add_str(m, "videoCodec" , videoCodec); - } - - if (!m_session->ReadSuccess(m, "subscribe to channel")) - { - XBMC->Log(LOG_ERROR, "%s - failed to subscribe to channel %d, consider the connection dropped", __FUNCTION__, m_channel); - m_session->TriggerReconnect(); - return false; - } - - // TODO get this from the pvr api. hardcoded to 10 seconds now - m_session->SetReadTimeout(READ_TIMEOUT_MS); - Flush(); - - XBMC->Log(LOG_DEBUG, "%s - new subscription for channel %d (%d)", __FUNCTION__, m_channel, m_subs); - return true; -} - -bool CHTSPDemux::SendSpeed(int subscription, int speed) -{ - XBMC->Log(LOG_DEBUG, "%s(%d, %d)", __FUNCTION__, subscription, speed); - htsmsg_t *m = htsmsg_create_map(); - htsmsg_add_str(m, "method" , "subscriptionSpeed"); - htsmsg_add_s32(m, "subscriptionId", subscription); - htsmsg_add_s32(m, "speed" , speed); - if (m_session->ReadSuccess(m, "pause subscription")) - { - m_session->SetReadTimeout(speed == 0 ? -1 : READ_TIMEOUT_MS); - return true; - } - return false; -} - -bool CHTSPDemux::SendSeek(int subscription, int time, bool backward, double *startpts) -{ - htsmsg_t *m = htsmsg_create_map(); - int64_t seek; - - // Note: time is in MSEC not DVD_TIME_BASE, TVH requires 1MHz (us) input - seek = time * 1000; - XBMC->Log(LOG_DEBUG, "%s(time=%d, seek=%ld)", __FUNCTION__, time, seek); - - htsmsg_add_str(m, "method" , "subscriptionSkip"); - htsmsg_add_s32(m, "subscriptionId", subscription); - htsmsg_add_s64(m, "time" , seek); - htsmsg_add_u32(m, "absolute" , 1); - - if (!m_session->ReadSuccess(m, "seek subscription")) - return false; - - if (!m_seekEvent->Wait(g_iResponseTimeout * 1000)) - return false; - - if (m_seekTime < 0) - return false; - - // Note: return value is in DVD_TIME_BASE not MSEC - *startpts = m_seekTime * DVD_TIME_BASE / 1000000; - XBMC->Log(LOG_DEBUG, "%s(%ld) = %lf", __FUNCTION__, seek, *startpts); - return true; -} - -bool CHTSPDemux::ParseQueueStatus(htsmsg_t* msg) -{ - if(htsmsg_get_u32(msg, "packets", &m_QueueStatus.packets) - || htsmsg_get_u32(msg, "bytes", &m_QueueStatus.bytes) - || htsmsg_get_u32(msg, "Bdrops", &m_QueueStatus.bdrops) - || htsmsg_get_u32(msg, "Pdrops", &m_QueueStatus.pdrops) - || htsmsg_get_u32(msg, "Idrops", &m_QueueStatus.idrops)) - { - XBMC->Log(LOG_ERROR, "%s - malformed message received", __FUNCTION__); - htsmsg_print(msg); - return false; - } - - /* delay isn't always transmitted */ - if(htsmsg_get_u32(msg, "delay", &m_QueueStatus.delay)) - m_QueueStatus.delay = 0; - - return true; -} - -bool CHTSPDemux::ParseSignalStatus(htsmsg_t* msg) -{ - if(htsmsg_get_u32(msg, "feSNR", &m_Quality.fe_snr)) - m_Quality.fe_snr = -2; - - if(htsmsg_get_u32(msg, "feSignal", &m_Quality.fe_signal)) - m_Quality.fe_signal = -2; - - if(htsmsg_get_u32(msg, "feBER", &m_Quality.fe_ber)) - m_Quality.fe_ber = -2; - - if(htsmsg_get_u32(msg, "feUNC", &m_Quality.fe_unc)) - m_Quality.fe_unc = -2; - - const char* status; - if((status = htsmsg_get_str(msg, "feStatus"))) - m_Quality.fe_status = status; - else - m_Quality.fe_status = "(unknown)"; - - return true; -} - -bool CHTSPDemux::ParseTimeshiftStatus(htsmsg_t *msg) -{ - uint32_t u32; - int64_t s64; - - if (!htsmsg_get_u32(msg, "full", &u32)) - m_timeshiftStatus.full = (bool)u32; - if (!htsmsg_get_s64(msg, "shift", &s64)) - m_timeshiftStatus.shift = s64; - if (!htsmsg_get_s64(msg, "start", &s64)) - m_timeshiftStatus.start = s64; - if (!htsmsg_get_s64(msg, "end", &s64)) - m_timeshiftStatus.end = s64; - - return true; -} - -bool CHTSPDemux::ParseSourceInfo(htsmsg_t* msg) -{ - htsmsg_t *sourceinfo; - if((sourceinfo = htsmsg_get_map(msg, "sourceinfo")) == NULL) - { - XBMC->Log(LOG_ERROR, "%s - malformed message", __FUNCTION__); - return false; - } - - const char* str; - if((str = htsmsg_get_str(sourceinfo, "adapter")) == NULL) - m_SourceInfo.si_adapter = ""; - else - m_SourceInfo.si_adapter = str; - - if((str = htsmsg_get_str(sourceinfo, "mux")) == NULL) - m_SourceInfo.si_mux = ""; - else - m_SourceInfo.si_mux = str; - - if((str = htsmsg_get_str(sourceinfo, "network")) == NULL) - m_SourceInfo.si_network = ""; - else - m_SourceInfo.si_network = str; - - if((str = htsmsg_get_str(sourceinfo, "provider")) == NULL) - m_SourceInfo.si_provider = ""; - else - m_SourceInfo.si_provider = str; - - if((str = htsmsg_get_str(sourceinfo, "service")) == NULL) - m_SourceInfo.si_service = ""; - else - m_SourceInfo.si_service = str; - - return true; -} - -bool CHTSPDemux::OnConnectionRestored(void) -{ - if (m_subs == 0) - return true; - - SendUnsubscribe(m_subs); - - if (!SendSubscribe(++m_subs, m_channel)) - { - m_subs = 0; - XBMC->Log(LOG_ERROR, "%s - failed to subscribe to channel %d", __FUNCTION__, m_channel); - return false; - } - - return true; -} diff --git a/addons/pvr.hts/src/HTSPDemux.h b/addons/pvr.hts/src/HTSPDemux.h deleted file mode 100644 index 23cce81fe..000000000 --- a/addons/pvr.hts/src/HTSPDemux.h +++ /dev/null @@ -1,86 +0,0 @@ -#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, 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#include "client.h" -#include "HTSPConnection.h" -#include "platform/util/buffer.h" -#include "platform/threads/mutex.h" -#include "xbmc_stream_utils.hpp" - -class CHTSPDemux : public CHTSPConnectionCallback -{ -public: - CHTSPDemux(CHTSPConnection* connection); - ~CHTSPDemux(); - - bool Open(const PVR_CHANNEL &channelinfo); - void Close(); - bool GetStreamProperties(PVR_STREAM_PROPERTIES* props); - void Abort(); - DemuxPacket* Read(); - bool SwitchChannel(const PVR_CHANNEL &channelinfo); - int CurrentChannel() { return m_channel; } - double GetTimeshiftTime() const { return m_timeshiftStatus.shift; } - bool GetSignalStatus(PVR_SIGNAL_STATUS &qualityinfo); - bool SeekTime(int time, bool backward, double *startpts); - void SetSpeed(int speed); - bool OnConnectionRestored(void); - bool ProcessMessage(htsmsg* msg); - void Flush(void); - -private: - void ParseSubscriptionStart (htsmsg_t *m); - void ParseSubscriptionStop (htsmsg_t *m); - void ParseSubscriptionStatus(htsmsg_t *m); - void ParseSubscriptionSkip (htsmsg_t *m); - void ParseSubscriptionSpeed (htsmsg_t *m); - bool SendSubscribe (int subscription, int channel); - bool SendUnsubscribe(int subscription); - bool SendSpeed (int subscription, int speed); - bool SendSeek (int subscription, int time, bool backward, double *startpts); - void ParseMuxPacket(htsmsg_t *m); - bool ParseQueueStatus(htsmsg_t* msg); - bool ParseSignalStatus(htsmsg_t* msg); - bool ParseTimeshiftStatus(htsmsg_t* msg); - bool ParseSourceInfo(htsmsg_t* msg); - - CHTSPConnection* m_session; - bool m_bIsRadio; - unsigned m_subs; - int m_channel; - int m_tag; - std::string m_Status; - ADDON::XbmcStreamProperties m_streams; - SChannels m_channels; - SQueueStatus m_QueueStatus; - SQuality m_Quality; - STimeshiftStatus m_timeshiftStatus; - SSourceInfo m_SourceInfo; - PLATFORM::SyncedBuffer m_demuxPacketBuffer; - bool m_bIsOpen; - PLATFORM::CEvent* m_seekEvent; - double m_seekTime; - PLATFORM::CMutex m_mutex; - PLATFORM::CCondition m_startedCondition; -}; diff --git a/addons/pvr.hts/src/HTSPDemuxer.cpp b/addons/pvr.hts/src/HTSPDemuxer.cpp new file mode 100644 index 000000000..8db632e39 --- /dev/null +++ b/addons/pvr.hts/src/HTSPDemuxer.cpp @@ -0,0 +1,677 @@ +/* + * 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/util/timeutils.h" +#include "platform/sockets/tcp.h" + +extern "C" { +#include "platform/util/atomic.h" +#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 * 1000)) + { + 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); + + strncpy(sig.strAdapterName, m_sourceInfo.si_adapter.c_str(), + sizeof(sig.strAdapterName)); + strncpy(sig.strAdapterStatus, m_signalInfo.fe_status.c_str(), + sizeof(sig.strAdapterStatus)); + strncpy(sig.strServiceName, m_sourceInfo.si_service.c_str(), + sizeof(sig.strServiceName)); + strncpy(sig.strProviderName, m_sourceInfo.si_provider.c_str(), + sizeof(sig.strProviderName)); + strncpy(sig.strMuxName, m_sourceInfo.si_mux.c_str(), + sizeof(sig.strMuxName)); + + 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"); + 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"); + 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)); + } + + /* 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:"); + 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, "mux")) != NULL) + { + tvhtrace(" mux : %s", str); + m_sourceInfo.si_mux = 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; + } + 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; + + if (!htsmsg_get_u32(m, "full", &u32)) + m_timeshiftStatus.full = (bool)u32; + if (!htsmsg_get_s64(m, "shift", &s64)) + m_timeshiftStatus.shift = s64; + if (!htsmsg_get_s64(m, "start", &s64)) + m_timeshiftStatus.start = s64; + if (!htsmsg_get_s64(m, "end", &s64)) + m_timeshiftStatus.end = s64; + + tvhtrace("timeshiftStatus:"); + tvhtrace(" full : %d", m_timeshiftStatus.full); + tvhtrace(" shift : %lld", m_timeshiftStatus.shift); + tvhtrace(" start : %lld", m_timeshiftStatus.start); + tvhtrace(" end : %lld", m_timeshiftStatus.end); +} diff --git a/addons/pvr.hts/src/HTSPTypes.h b/addons/pvr.hts/src/HTSPTypes.h index 1e917c5eb..72e6783cf 100644 --- a/addons/pvr.hts/src/HTSPTypes.h +++ b/addons/pvr.hts/src/HTSPTypes.h @@ -16,8 +16,7 @@ * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to - * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ @@ -27,62 +26,85 @@ #include #include #include "platform/util/StdString.h" -#include "libXBMC_codec.h" #include "client.h" -#include "xbmc_codec_descriptor.hpp" -typedef std::vector CodecVector; +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, +}; struct STag { - int id; - std::string name; - std::string icon; - std::vector channels; + bool del; + uint32_t id; + std::string name; + std::string icon; + std::vector channels; STag() { Clear(); } void Clear() { + del = false; id = 0; name.clear(); icon.clear(); channels.clear(); } - bool BelongsTo(int channel) const + + inline bool operator==(const STag &right) { - return std::find(channels.begin(), channels.end(), channel) != channels.end(); + return id == right.id && name == right.name && + icon == right.icon && channels == right.channels; } + inline bool operator!=(const STag &right) + { + return !(*this == right); + } }; struct SChannel { - int id; + bool del; + uint32_t id; + uint32_t num; + uint32_t numMinor; + bool radio; + uint32_t caid; std::string name; std::string icon; - int event; - int num; - int numMinor; - bool radio; - int caid; - std::vector tags; SChannel() { Clear(); } void Clear() { + del = false; id = 0; - event = 0; num = 0; numMinor = 0; radio = false; caid = 0; name.clear(); icon.clear(); - tags.clear(); - } - bool MemberOf(int tag) const - { - return std::find(tags.begin(), tags.end(), tag) != tags.end(); } bool operator<(const SChannel &right) const { @@ -90,50 +112,20 @@ struct SChannel } }; -struct SEvent -{ - int id; - int next; - int chan_id; - - int content; - int start; - int stop; - std::string title; - std::string descs; - - SEvent() { Clear(); } - void Clear() - { - id = 0; - next = 0; - start = 0; - stop = 0; - title.clear(); - descs.clear(); - } -}; - -typedef enum recording_state { - ST_INVALID = 0, - ST_SCHEDULED = 1, - ST_RECORDING = 2, - ST_COMPLETED = 3, - ST_ABORTED = 4 -} ERecordingState; - struct SRecording { + bool del; uint32_t id; uint32_t channel; - uint32_t start; - uint32_t stop; + uint32_t eventId; + int64_t start; + int64_t stop; int64_t startExtra; int64_t stopExtra; std::string title; std::string path; std::string description; - ERecordingState state; + PVR_TIMER_STATE state; std::string error; uint32_t retention; uint32_t priority; @@ -141,16 +133,105 @@ struct SRecording SRecording() { Clear(); } void Clear() { - id = channel = start = stop = startExtra = stopExtra = 0; + del = false; + id = 0; + channel = 0; + eventId = 0; + start = 0; + stop = 0; + startExtra = 0; + stopExtra = 0; + + state = PVR_TIMER_STATE_ERROR; title.clear(); description.clear(); - state = ST_INVALID; error.clear(); - retention = 99; // xbmc default - 99 days - priority = 50; // xbmc default - "normal" + + 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; + uint32_t age; + time_t aired; + uint32_t season; + uint32_t episode; + uint32_t part; + std::string title; + std::string desc; + std::string summary; + std::string image; + uint32_t recordingId; + + SEvent() { Clear(); } + void Clear() + { + 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; + title.clear(); + desc.clear(); + summary.clear(); + image.clear(); + recordingId = 0; + } +}; + +typedef std::map SChannels; +typedef std::map STags; +typedef std::map SEvents; +typedef std::map SRecordings; + +struct SSchedule +{ + bool del; + uint32_t channel; + SEvents events; + + SSchedule() { Clear(); } + void Clear () + { + del = false; + channel = 0; + events.clear(); + } +}; + +typedef std::map SSchedules; + struct SQueueStatus { uint32_t packets; // Number of data packets in queue. @@ -178,7 +259,7 @@ struct STimeshiftStatus int64_t shift; int64_t start; int64_t end; - + STimeshiftStatus() { Clear(); } void Clear() { @@ -196,6 +277,16 @@ struct SQuality uint32_t fe_signal; uint32_t fe_ber; uint32_t fe_unc; + + SQuality() { Clear(); } + void Clear () + { + fe_status.clear(); + fe_snr = 0; + fe_signal = 0; + fe_ber = 0; + fe_unc = 0; + } }; struct SSourceInfo @@ -205,9 +296,56 @@ struct SSourceInfo std::string si_mux; std::string si_provider; std::string si_service; + + SSourceInfo() { Clear(); } + 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::map SChannels; -typedef std::map STags; -typedef std::map SEvents; -typedef std::map SRecordings; +typedef std::vector SHTSPEventList; + +class SSubscription +{ +public: + uint32_t subscriptionId; + uint32_t channelId; + int speed; + bool active; + + SSubscription() + { + speed = 1000; + active = false; + + static int previousId = 0; + subscriptionId = ++previousId; + } +}; diff --git a/addons/pvr.hts/src/HTSPVFS.cpp b/addons/pvr.hts/src/HTSPVFS.cpp new file mode 100644 index 000000000..07b78dbd2 --- /dev/null +++ b/addons/pvr.hts/src/HTSPVFS.cpp @@ -0,0 +1,286 @@ +/* + * 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" +#include "platform/util/timeutils.h" +#include "platform/sockets/tcp.h" + +extern "C" { +#include "platform/util/atomic.h" +#include "libhts/htsmsg_binary.h" +#include "libhts/sha1.h" +} + +#include "Tvheadend.h" +#include "client.h" + +using namespace std; +using namespace ADDON; +using namespace PLATFORM; + +CHTSPVFS::CHTSPVFS ( CHTSPConnection &conn ) + : m_conn(conn), m_path(""), m_fileId(0), m_offset(0) +{ + m_buffer.alloc(MAX_BUFFER_SIZE); +} + +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 ) +{ + CLockObject lock(m_conn.Mutex()); + + /* 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_buffer.reset(); + m_offset = 0; + m_fileId = 0; + m_path = ""; +} + +int CHTSPVFS::Read ( unsigned char *buf, unsigned int len ) +{ + ssize_t ret; + + /* Not opened */ + if (!m_fileId) + return -1; + + /* Fetch data */ + if (m_buffer.avail() <= len) + { + htsmsg_t *m; + const void *buf; + size_t len; + + /* Build */ + m = htsmsg_create_map(); + htsmsg_add_u32(m, "id", m_fileId); + htsmsg_add_s64(m, "size", m_buffer.free()); + + tvhtrace("vfs read id=%d size=%lld", + m_fileId, (long long)m_buffer.free()); + + /* Send */ + { + CLockObject lock(m_conn.Mutex()); + m = m_conn.SendAndWait("fileRead", m); + } + + if (m == NULL) + return -1; + + /* Process */ + if (htsmsg_get_bin(m, "data", &buf, &len)) + { + htsmsg_destroy(m); + tvherror("vfs fileRead malformed response"); + return -1; + } + + /* Store */ + if (m_buffer.write((unsigned char*)buf, len) != (ssize_t)len) + { + htsmsg_destroy(m); + tvherror("vfs partial buffer write"); + return -1; + } + htsmsg_destroy(m); + } + + /* Read */ + ret = m_buffer.read(buf, len); + m_offset += ret; + return (int)ret; +} + +long long CHTSPVFS::Seek ( long long pos, int whence ) +{ + CLockObject lock(m_conn.Mutex()); + if (m_fileId == 0) + return -1; + return SendFileSeek(pos, whence); +} + +long long CHTSPVFS::Tell ( void ) +{ + CLockObject lock(m_conn.Mutex()); + if (m_fileId == 0) + return -1; + return m_offset; +} + +long long CHTSPVFS::Size ( void ) +{ + int64_t ret = -1; + CLockObject lock(m_conn.Mutex()); + htsmsg_t *m; + + /* Build */ + m = htsmsg_create_map(); + htsmsg_add_u32(m, "id", m_fileId); + + tvhtrace("vfs stat id=%d", m_fileId); + + /* Send */ + if ((m = m_conn.SendAndWait("fileStat", m)) == NULL) + return -1; + + /* Process */ + if (htsmsg_get_s64(m, "size", &ret)) + tvherror("vfs fileStat malformed response"); + 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 */ + if (force) + m = m_conn.SendAndWait0("fileOpen", m); + else + m = m_conn.SendAndWait("fileOpen", m); + if (m == NULL) + return false; + + /* Get ID */ + htsmsg_get_u32(m, "id", &m_fileId); + htsmsg_destroy(m); + tvhtrace("vfs opened id=%d", m_fileId); + + /* Log */ + 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 */ + m = m_conn.SendAndWait("fileClose", m); + if (m) + htsmsg_destroy(m); + // Note: ignore the return; +} + +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 */ + if (force) + m = m_conn.SendAndWait0("fileSeek", m); + else + m = m_conn.SendAndWait("fileSeek", m); + if (m == NULL) + return false; + + /* Get new offset */ + if (htsmsg_get_s64(m, "offset", &ret)) + tvherror("vfs malformed fileSeek response"); + htsmsg_destroy(m); + + /* Update */ + if (ret >= 0) + { + tvhtrace("vfs seek offset=%lld", (long long)ret); + m_offset = ret; + m_buffer.reset(); + } + else + tvherror("vfs fileSeek failed"); + + return ret; +} diff --git a/addons/pvr.hts/src/Settings.h b/addons/pvr.hts/src/Settings.h new file mode 100644 index 000000000..61da57b18 --- /dev/null +++ b/addons/pvr.hts/src/Settings.h @@ -0,0 +1,40 @@ +#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; + }; + +} \ No newline at end of file diff --git a/addons/pvr.hts/src/Tvheadend.cpp b/addons/pvr.hts/src/Tvheadend.cpp new file mode 100644 index 000000000..2b48c8ca3 --- /dev/null +++ b/addons/pvr.hts/src/Tvheadend.cpp @@ -0,0 +1,1529 @@ +/* + * 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" + +extern "C" { +#include "platform/util/atomic.h" +#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(); + 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"); + return PVR_ERROR_SERVER_ERROR; +} + +CStdString CTvheadend::GetImageURL ( const char *str ) +{ + if (*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 ) +{ + if (!m_asyncState.WaitForState(ASYNC_DVR)) + return PVR_ERROR_FAILED; + + std::vector tags; + { + CLockObject lock(m_mutex); + STags::const_iterator it; + for (it = m_tags.begin(); it != m_tags.end(); ++it) + { + PVR_CHANNEL_GROUP tag; + memset(&tag, 0, sizeof(tag)); + + tag.bIsRadio = false; + strncpy(tag.strGroupName, it->second.name.c_str(), + sizeof(tag.strGroupName)); + 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; + STags::const_iterator tit = m_tags.begin(); + while (tit != m_tags.end()) + { + if (tit->second.name == group.strGroupName) + { + for (it = tit->second.channels.begin(); + it != tit->second.channels.end(); ++it) + { + if ((cit = m_channels.find(*it)) != m_channels.end()) + { + 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, 30)) == NULL) + return PVR_ERROR_SERVER_ERROR; + + /* Check for error */ + if (htsmsg_get_u32(m, "success", &u32)) + { + tvherror("failed to parse cancelDvrEntry response"); + } + 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("failed to parse updateDvrEntry response"); + } + + 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_NO_ERROR; + + 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)); + + strncpy(rec.strIconPath, cit->second.icon.c_str(), + sizeof(rec.strIconPath)); + } + + /* URL ( HTSP < v7 ) */ + // TODO: do I care! + + /* ID */ + snprintf(buf, sizeof(buf), "%i", rit->second.id); + strncpy(rec.strRecordingId, buf, sizeof(rec.strRecordingId)); + + /* Title */ + strncpy(rec.strTitle, rit->second.title.c_str(), sizeof(rec.strTitle)); + + /* Description */ + strncpy(rec.strPlot, rit->second.description.c_str(), sizeof(rec.strPlot)); + + /* 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)); + else + { + CStdString d = rit->second.path.substr(0, idx); + if (d[0] != '/') + d = "/" + d; + strncpy(rec.strDirectory, d.c_str(), sizeof(rec.strDirectory)); + } + } + + 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; + } + + /* Validate */ + if (!(list = htsmsg_get_list(m, "cutpoints"))) + { + tvherror("malformed getDvrCutpoints response"); + htsmsg_destroy(m); + return PVR_ERROR_FAILED; + } + + /* 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 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); + + PVR_ERROR e = SendDvrUpdate(m); + htsmsg_destroy(m); + return e; +} + +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; + + /* 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("failed to parse addDvrEntry response"); + } + 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); + } + + PVR_ERROR e = SendDvrUpdate(m); + htsmsg_destroy(m); + return e; +} + +/* ************************************************************************** + * 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.strIconPath = event.image.c_str(); + epg.iGenreType = event.content & 0xF0; + epg.iGenreSubType = event.content & 0x0F; + epg.firstAired = event.aired; + epg.iSeriesNumber = event.season; + epg.iEpisodeNumber = event.episode; + epg.iEpisodePartNumber = event.part; + + std::stringstream ss; + ss << event.recordingId; + const std::string recordingId = ss.str(); + epg.strRecordingId = recordingId.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"); + return PVR_ERROR_SERVER_ERROR; + } + HTSMSG_FOREACH(f, l) + { + SEvent event; + if (f->hmf_type == HMF_MAP) + { + if (ParseEvent(&f->hmf_msg, 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; + STags::iterator tit; + SChannels::iterator cit; + + /* 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.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) || + !strcmp("channelUpdate", method)) + ParseChannelUpdate(msg.m_msg); + else if (!strcmp("channelDelete", method)) + ParseChannelDelete(msg.m_msg); + + /* Tags */ + else if (!strcmp("tagAdd", method) || + !strcmp("tagUpdate", method)) + ParseTagUpdate(msg.m_msg); + else if (!strcmp("tagDelete", method)) + ParseTagDelete(msg.m_msg); + + /* Recordings */ + else if (!strcmp("dvrEntryAdd", method) || + !strcmp("dvrEntryUpdate", method)) + ParseRecordingUpdate(msg.m_msg); + else if (!strcmp("dvrEntryDelete", method)) + ParseRecordingDelete(msg.m_msg); + + /* EPG */ + else if (!strcmp("eventAdd", method) || + !strcmp("eventUpdate", method)) + ParseEventUpdate(msg.m_msg); + 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(); + STags::iterator tit = m_tags.begin(); + + /* Tags */ + update = false; + while (tit != m_tags.end()) + { + if (tit->second.del) + { + 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::ParseTagUpdate ( htsmsg_t *msg ) +{ + uint32_t u32; + const char *str; + htsmsg_t *list; + + /* Validate */ + if (htsmsg_get_u32(msg, "tagId", &u32)) + { + tvherror("malformed tagUpdate"); + return; + } + + /* Locate object */ + STag &existingTag = m_tags[u32]; + existingTag.del = false; + + /* Create new object */ + STag tag; + tag.id = u32; + + /* Name */ + if ((str = htsmsg_get_str(msg, "tagName")) != NULL) + tag.name = str; + + /* Icon */ + if ((str = htsmsg_get_str(msg, "tagIcon")) != NULL) + tag.icon = 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.channels.push_back((int)f->hmf_s64); + } + } + + /* Update */ + if (existingTag != tag) + { + existingTag = tag; + tvhdebug("tag updated id:%u, name:%s", + existingTag.id, existingTag.name.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"); + return; + } + tvhdebug("delete tag %u", u32); + + /* Erase */ + m_tags.erase(u32); + TriggerChannelGroupsUpdate(); +} + +void CTvheadend::ParseChannelUpdate ( htsmsg_t *msg ) +{ + bool update = false; + uint32_t u32; + const char *str; + htsmsg_t *list; + + /* Validate */ + if (htsmsg_get_u32(msg, "channelId", &u32)) + { + tvherror("malformed channelUpdate"); + 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); + + /* Channel number */ + if (!htsmsg_get_u32(msg, "channelNumber", &u32)) + { + if (!u32) u32 = GetNextUnnumberedChannelNumber(); + UPDATE(channel.num, u32); + } + 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 XBMC */ + 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 channelUpdate"); + return; + } + tvhdebug("delete channel %u", u32); + + /* Erase */ + m_channels.erase(u32); + TriggerChannelUpdate(); +} + +void CTvheadend::ParseRecordingUpdate ( htsmsg_t *msg ) +{ + 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) || + htsmsg_get_u32(msg, "channel", &channel) || + htsmsg_get_s64(msg, "start", &start) || + htsmsg_get_s64(msg, "stop", &stop) || + ((state = htsmsg_get_str(msg, "state")) == NULL)) + { + tvherror("malformed dvrEntryAdd/dvrEntryUpdate"); + return; + } + + /* Get entry */ + SRecording &rec = m_recordings[id]; + rec.id = id; + rec.del = false; + UPDATE(rec.channel, channel); + UPDATE(rec.start, start); + UPDATE(rec.stop, stop); + + /* Add optional fields */ + if (!htsmsg_get_u32(msg, "eventId", &eventId)) + { + UPDATE(rec.eventId, eventId); + } + + if (!htsmsg_get_s64(msg, "startExtra", &startExtra)) + { + UPDATE(rec.startExtra, startExtra); + } + + if (!htsmsg_get_s64(msg, "stopExtra", &stopExtra)) + { + UPDATE(rec.stopExtra, stopExtra); + } + + if (!htsmsg_get_u32(msg, "retention", &retention)) + { + UPDATE(rec.retention, retention); + } + + 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"); + return; + } + } + + /* 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); + } + + /* Info */ + 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); + } + + /* 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"); + return; + } + tvhdebug("delete recording %u", u32); + + /* Erase */ + m_recordings.erase(u32); + + /* Update */ + TriggerTimerUpdate(); + TriggerRecordingUpdate(); +} + +bool CTvheadend::ParseEvent ( htsmsg_t *msg, 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) || + htsmsg_get_u32(msg, "channelId", &channel) || + htsmsg_get_s64(msg, "start", &start) || + htsmsg_get_s64(msg, "stop", &stop) || + (str = htsmsg_get_str(msg, "title")) == NULL) + { + tvherror("malformed eventUpdate message"); + return false; + } + + evt.id = id; + evt.channel = channel; + evt.start = (time_t)start; + evt.stop = (time_t)stop; + evt.title = 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; + + /* 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::ParseEventUpdate ( htsmsg_t *msg ) +{ + bool update = false; + SEvent tmp; + + /* Parse */ + if (!ParseEvent(msg, 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.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 */ + 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"); + 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++; +} diff --git a/addons/pvr.hts/src/Tvheadend.h b/addons/pvr.hts/src/Tvheadend.h new file mode 100644 index 000000000..70d907e6a --- /dev/null +++ b/addons/pvr.hts/src/Tvheadend.h @@ -0,0 +1,550 @@ +#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 "xbmc_codec_types.h" +#include "xbmc_stream_utils.hpp" +#include "libXBMC_addon.h" +#include "CircBuffer.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_API_VERSION (12) +#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; } + +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; +}; + +/* + * 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; + CCircBuffer m_buffer; + int64_t m_offset; + + bool Open ( const PVR_RECORDING &rec ); + void Close ( void ); + int 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 ); + long long SendFileSeek ( int64_t pos, int whence, bool force = false ); + + static const int MAX_BUFFER_SIZE = 1000000; +}; + +/* + * 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() { + return m_settings; + }; + + PVR_ERROR GetDriveSpace ( long long *total, long long *used ); + + int GetTagCount ( void ); + PVR_ERROR GetTags ( ADDON_HANDLE handle ); + 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 GetEpg ( ADDON_HANDLE handle, const PVR_CHANNEL &chn, + time_t start, time_t end ); + +private: + uint32_t GetNextUnnumberedChannelNumber(); + + PLATFORM::CMutex m_mutex; + const tvheadend::Settings m_settings; + + CHTSPConnection m_conn; + CHTSPDemuxer m_dmx; + CHTSPVFS m_vfs; + + CHTSPMessageQueue m_queue; + + SChannels m_channels; + STags 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 ParseTagUpdate ( htsmsg_t *m ); + void ParseTagDelete ( htsmsg_t *m ); + void ParseChannelUpdate ( htsmsg_t *m ); + void ParseChannelDelete ( htsmsg_t *m ); + void ParseRecordingUpdate ( htsmsg_t *m ); + void ParseRecordingDelete ( htsmsg_t *m ); + void ParseEventUpdate ( htsmsg_t *m ); + void ParseEventDelete ( htsmsg_t *m ); + bool ParseEvent ( htsmsg_t *msg, 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 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(); + } + + /* + * 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 ) + { + PLATFORM::CLockObject lock(m_conn.Mutex()); + m_vfs.Close(); + } + inline int 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(); + } +}; diff --git a/addons/pvr.hts/src/client.cpp b/addons/pvr.hts/src/client.cpp index ee1b38ac6..31ce6ae52 100644 --- a/addons/pvr.hts/src/client.cpp +++ b/addons/pvr.hts/src/client.cpp @@ -14,172 +14,110 @@ * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to - * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "client.h" #include "xbmc_pvr_dll.h" -#include "HTSPData.h" -#include "HTSPDemux.h" -#include "GUIDialogTranscode.h" #include "platform/threads/mutex.h" #include "platform/util/atomic.h" #include "platform/util/util.h" +#include "Settings.h" +#include "Tvheadend.h" using namespace std; using namespace ADDON; using namespace PLATFORM; -bool m_bCreated = false; +/* ************************************************************************** + * Global variables + * *************************************************************************/ + +/* + * Client state + */ ADDON_STATUS m_CurStatus = ADDON_STATUS_UNKNOWN; -int g_iClientId = -1; -long g_iPacketSequence = 0; -/* User adjustable settings are saved here. - * Default values are defined inside client.h - * and exported to the other source files. +/* + * Global configuration */ -std::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; -bool g_bTranscode = DEFAULT_TRANSCODE; -CodecDescriptor g_audioCodec; -CodecDescriptor g_videoCodec; -int g_iResolution = DEFAULT_RESOLUTION; -std::string g_strUsername = ""; -std::string g_strPassword = ""; -std::string g_strUserPath = ""; -std::string g_strClientPath = ""; - -CHelper_libXBMC_addon *XBMC = NULL; -CHelper_libXBMC_codec *CODEC = NULL; -CHelper_libXBMC_pvr *PVR = NULL; -CHelper_libXBMC_gui *GUI = NULL; -PVR_MENUHOOK *menuHook = NULL; -CHTSPData * HTSPData = NULL; -CMutex g_seqMutex; - -uint32_t HTSPNextSequenceNumber(void) -{ - long lSequence = atomic_inc(&g_iPacketSequence); - - if ((uint32_t)lSequence != lSequence) - { - CLockObject lock(g_seqMutex); - if ((uint32_t)g_iPacketSequence != g_iPacketSequence) - g_iPacketSequence = 0; +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; - lSequence = atomic_inc(&g_iPacketSequence); - } +/* + * Global state + */ +CHelper_libXBMC_addon *XBMC = NULL; +CHelper_libXBMC_pvr *PVR = NULL; +CHelper_libXBMC_gui *GUI = NULL; +CHelper_libXBMC_codec *CODEC = NULL; +PVR_MENUHOOK *menuHook = NULL; +CTvheadend *tvh = NULL; - return (uint32_t)lSequence; -} +/* ************************************************************************** + * ADDON setup + * *************************************************************************/ extern "C" { void ADDON_ReadSettings(void) { - /* read setting "host" from settings.xml */ - char * buffer; - buffer = (char*) malloc (1024); - buffer[0] = 0; /* Set the end of string */ - - if (XBMC->GetSetting("host", buffer)) - g_strHostname = buffer; - else - g_strHostname = DEFAULT_HOST; - buffer[0] = 0; /* Set the end of string */ - - /* read setting "user" from settings.xml */ - if (XBMC->GetSetting("user", buffer)) - g_strUsername = buffer; - else - g_strUsername = ""; - buffer[0] = 0; /* Set the end of string */ - - /* read setting "pass" from settings.xml */ - if (XBMC->GetSetting("pass", buffer)) - g_strPassword = buffer; - else - g_strPassword = ""; - - /* read setting "htsp_port" from settings.xml */ - if (!XBMC->GetSetting("htsp_port", &g_iPortHTSP)) - g_iPortHTSP = DEFAULT_HTSP_PORT; +#define UPDATE_INT(var, key, def)\ + if (!XBMC->GetSetting(key, &var))\ + var = def; - /* read setting "http_port" from settings.xml */ - if (!XBMC->GetSetting("http_port", &g_iPortHTTP)) - g_iPortHTTP = DEFAULT_HTTP_PORT; +#define UPDATE_STR(var, key, tmp, def)\ + if (XBMC->GetSetting(key, tmp))\ + var = tmp;\ + else\ + var = def; - /* read setting "connect_timeout" from settings.xml */ - if (!XBMC->GetSetting("connect_timeout", &g_iConnectTimeout)) - g_iConnectTimeout = DEFAULT_CONNECT_TIMEOUT; + char buffer[1024]; - /* read setting "read_timeout" from settings.xml */ - if (!XBMC->GetSetting("response_timeout", &g_iResponseTimeout)) - g_iResponseTimeout = DEFAULT_RESPONSE_TIMEOUT; + /* 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_HTSP_PORT); + UPDATE_INT(g_iConnectTimeout, "connect_timeout", DEFAULT_CONNECT_TIMEOUT); + UPDATE_INT(g_iResponseTimeout, "response_timeout", DEFAULT_RESPONSE_TIMEOUT); - /* read setting "transcode" from settings.xml */ - if (!XBMC->GetSetting("transcode", &g_bTranscode)) - g_bTranscode = DEFAULT_TRANSCODE; + /* Data Transfer */ + UPDATE_INT(g_bAsyncEpg, "epg_async", false); - /* read setting "audio_codec_name" from settings.xml */ - if (XBMC->GetSetting("audio_codec_name", buffer)) - g_audioCodec = CodecDescriptor::GetCodecByName(buffer); - else - g_audioCodec = CodecDescriptor::GetCodecByName(DEFAULT_AUDIO_CODEC); + /* Debug */ + UPDATE_INT(g_bTraceDebug, "trace_debug", false); - /* read setting "video_codec_name" from settings.xml */ - if (XBMC->GetSetting("video_codec_name", buffer)) - g_videoCodec = CodecDescriptor::GetCodecByName(buffer); - else - g_videoCodec = CodecDescriptor::GetCodecByName(DEFAULT_VIDEO_CODEC); + /* TODO: Transcoding */ - /* read setting "resolution" from settings.xml */ - if (!XBMC->GetSetting("resolution", &g_iResolution)) - g_iResolution = DEFAULT_RESOLUTION; - - free(buffer); +#undef UPDATE_INT +#undef UPDATE_STR } -ADDON_STATUS ADDON_Create(void* hdl, void* props) +ADDON_STATUS ADDON_Create(void* hdl, void* _unused(props)) { - if (!hdl || !props) - return ADDON_STATUS_UNKNOWN; - - PVR_PROPERTIES* pvrprops = (PVR_PROPERTIES*)props; - - XBMC = new CHelper_libXBMC_addon; - if (!XBMC->RegisterMe(hdl)) - { - SAFE_DELETE(XBMC); - return ADDON_STATUS_PERMANENT_FAILURE; - } - - GUI = new CHelper_libXBMC_gui; - if (!GUI->RegisterMe(hdl)) - { - SAFE_DELETE(GUI); - SAFE_DELETE(XBMC); - return ADDON_STATUS_PERMANENT_FAILURE; - } - + if (!hdl) + return m_CurStatus; + + /* Instantiate helpers */ + XBMC = new CHelper_libXBMC_addon; + GUI = new CHelper_libXBMC_gui; CODEC = new CHelper_libXBMC_codec; - if (!CODEC->RegisterMe(hdl)) - { - SAFE_DELETE(CODEC); - SAFE_DELETE(GUI); - SAFE_DELETE(XBMC); - return ADDON_STATUS_PERMANENT_FAILURE; - } - - PVR = new CHelper_libXBMC_pvr; - if (!PVR->RegisterMe(hdl)) + PVR = new CHelper_libXBMC_pvr; + + if (!XBMC->RegisterMe(hdl) || !GUI->RegisterMe(hdl) || + !CODEC->RegisterMe(hdl) || !PVR->RegisterMe(hdl)) { SAFE_DELETE(PVR); SAFE_DELETE(CODEC); @@ -188,44 +126,45 @@ ADDON_STATUS ADDON_Create(void* hdl, void* props) return ADDON_STATUS_PERMANENT_FAILURE; } - XBMC->Log(LOG_DEBUG, "%s - Creating Tvheadend PVR-Client", __FUNCTION__); - - m_CurStatus = ADDON_STATUS_UNKNOWN; - g_strUserPath = pvrprops->strUserPath; - g_strClientPath = pvrprops->strClientPath; + tvhinfo("starting PVR client"); ADDON_ReadSettings(); - - HTSPData = new CHTSPData; - if (!HTSPData->Open()) - { - SAFE_DELETE(HTSPData); - SAFE_DELETE(CODEC); + + /* 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.iConnectTimeout = g_iConnectTimeout; + settings.iResponseTimeout = g_iResponseTimeout; + settings.bTraceDebug = g_bTraceDebug; + settings.bAsyncEpg = g_bAsyncEpg; + + tvh = new CTvheadend(settings); + tvh->Start(); + + /* Wait for connection */ + if (!tvh->WaitForConnection()) { + SAFE_DELETE(tvh); SAFE_DELETE(PVR); + SAFE_DELETE(CODEC); SAFE_DELETE(GUI); SAFE_DELETE(XBMC); - m_CurStatus = ADDON_STATUS_LOST_CONNECTION; - return m_CurStatus; - } - - if(HTSPData->CanTranscode()) - { - menuHook = new PVR_MENUHOOK(); - menuHook->category = PVR_MENUHOOK_ALL; - menuHook->iHookId = 1; - menuHook->iLocalizedStringId = 30100; - PVR->AddMenuHook(menuHook); + return ADDON_STATUS_LOST_CONNECTION; } - m_CurStatus = ADDON_STATUS_OK; - m_bCreated = true; + m_CurStatus = ADDON_STATUS_OK; return m_CurStatus; } ADDON_STATUS ADDON_GetStatus() { - /* check whether we're still connected */ - if (m_CurStatus == ADDON_STATUS_OK && !HTSPData->IsConnected()) + 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; @@ -233,14 +172,13 @@ ADDON_STATUS ADDON_GetStatus() void ADDON_Destroy() { - m_bCreated = false; - SAFE_DELETE(HTSPData); - SAFE_DELETE(CODEC); + CLockObject lock(g_mutex); + SAFE_DELETE(tvh); SAFE_DELETE(PVR); + SAFE_DELETE(CODEC); SAFE_DELETE(GUI); SAFE_DELETE(XBMC); SAFE_DELETE(menuHook); - m_CurStatus = ADDON_STATUS_UNKNOWN; } @@ -249,119 +187,58 @@ bool ADDON_HasSettings() return true; } -unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet) +unsigned int ADDON_GetSettings + (ADDON_StructSetting ***_unused(sSet)) { return 0; } -ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) +ADDON_STATUS ADDON_SetSetting + (const char *settingName, const void *settingValue) { - string str = settingName; - if (str == "host") - { - string tmp_sHostname; - XBMC->Log(LOG_INFO, "%s - Changed Setting 'host' from %s to %s", __FUNCTION__, g_strHostname.c_str(), (const char*) settingValue); - tmp_sHostname = g_strHostname; - g_strHostname = (const char*) settingValue; - if (tmp_sHostname != g_strHostname) - return ADDON_STATUS_NEED_RESTART; - } - else if (str == "user") - { - string tmp_sUsername = g_strUsername; - g_strUsername = (const char*) settingValue; - if (tmp_sUsername != g_strUsername) - { - XBMC->Log(LOG_INFO, "%s - Changed Setting 'user'", __FUNCTION__); - return ADDON_STATUS_NEED_RESTART; - } - } - else if (str == "pass") - { - string tmp_sPassword = g_strPassword; - g_strPassword = (const char*) settingValue; - if (tmp_sPassword != g_strPassword) - { - XBMC->Log(LOG_INFO, "%s - Changed Setting 'pass'", __FUNCTION__); - return ADDON_STATUS_NEED_RESTART; - } - } - else if (str == "htsp_port") - { - if (g_iPortHTSP != *(int*) settingValue) - { - XBMC->Log(LOG_INFO, "%s - Changed Setting 'htsp_port' from %u to %u", __FUNCTION__, g_iPortHTSP, *(int*) settingValue); - g_iPortHTSP = *(int*) settingValue; - return ADDON_STATUS_NEED_RESTART; - } - } - else if (str == "http_port") - { - if (g_iPortHTTP != *(int*) settingValue) - { - XBMC->Log(LOG_INFO, "%s - Changed Setting 'port' from %u to %u", __FUNCTION__, g_iPortHTTP, *(int*) settingValue); - g_iPortHTTP = *(int*) settingValue; - return ADDON_STATUS_NEED_RESTART; - } - } - else if (str == "connect_timeout") - { - int iNewValue = *(int*) settingValue + 1; - if (g_iConnectTimeout != iNewValue) - { - XBMC->Log(LOG_INFO, "%s - Changed Setting 'connect_timeout' from %u to %u", __FUNCTION__, g_iConnectTimeout, iNewValue); - g_iConnectTimeout = iNewValue; - return ADDON_STATUS_OK; - } - } - else if (str == "response_timeout") - { - int iNewValue = *(int*) settingValue + 1; - if (g_iResponseTimeout != iNewValue) - { - XBMC->Log(LOG_INFO, "%s - Changed Setting 'response_timeout' from %u to %u", __FUNCTION__, g_iResponseTimeout, iNewValue); - g_iResponseTimeout = iNewValue; - return ADDON_STATUS_OK; - } - } - else if (str == "transcode") - { - int bNewValue = *(bool*) settingValue; - XBMC->Log(LOG_INFO, "%s - Changed Setting 'transcode' from %u to %u", __FUNCTION__, g_bTranscode, bNewValue); - g_bTranscode = (bNewValue == 1); +#define UPDATE_STR(key, var)\ + if (!strcmp(settingName, key))\ + {\ + if (!strcmp(var.c_str(), (const char*)settingValue))\ + {\ + tvhdebug("update %s from '%s' to '%s'",\ + settingName, var.c_str(), settingValue);\ + return ADDON_STATUS_NEED_RESTART;\ + }\ + return ADDON_STATUS_OK;\ } - else if (str == "resolution") - { - int iNewValue = *(int*) settingValue + 1; - if (g_iResolution != iNewValue) - { - XBMC->Log(LOG_INFO, "%s - Changed Setting 'resolution' from %u to %u", __FUNCTION__, g_iResolution, iNewValue); - g_iResolution = iNewValue; - return ADDON_STATUS_OK; - } - } - else if (str == "video_codec_name") - { - string tmp_strCodecname = g_videoCodec.Name(); - if (tmp_strCodecname != (const char*) settingValue) - { - XBMC->Log(LOG_INFO, "%s - Changed Setting 'video_codec' from %s to %s", __FUNCTION__, tmp_strCodecname.c_str(), (const char*) settingValue); - g_videoCodec = CodecDescriptor::GetCodecByName((const char*) settingValue); - return ADDON_STATUS_OK; - } - } - else if (str == "audio_codec_name") - { - string tmp_strCodecname = g_audioCodec.Name(); - if (tmp_strCodecname != (const char*) settingValue) - { - XBMC->Log(LOG_INFO, "%s - Changed Setting 'audio_codec' from %s to %s", __FUNCTION__, tmp_strCodecname.c_str(), (const char*) settingValue); - g_audioCodec = CodecDescriptor::GetCodecByName((const char*) settingValue); - 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() @@ -372,13 +249,24 @@ void ADDON_FreeSettings() { } -void ADDON_Announce(const char *flag, const char *sender, const char *message, const void *data) +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")) + { + /* Wake - close connection (it'll most likely need remaking) */ + if (!strcmp("OnWake", message)) + tvh->Disconnect(); + } } -/*********************************************************** - * PVR Client AddOn specific public library functions - ***********************************************************/ +/* ************************************************************************** + * Versioning + * *************************************************************************/ const char* GetPVRAPIVersion(void) { @@ -392,17 +280,25 @@ const char* GetMininumPVRAPIVersion(void) return strMinApiVersion; } +#ifdef XBMC_GUI_API_VERSION const char* GetGUIAPIVersion(void) { static const char *strGuiApiVersion = XBMC_GUI_API_VERSION; return strGuiApiVersion; } +#endif +#ifdef XBMC_GUI_MIN_API_VERSION const char* GetMininumGUIAPIVersion(void) { static const char *strMinGuiApiVersion = XBMC_GUI_MIN_API_VERSION; return strMinGuiApiVersion; } +#endif + +/* ************************************************************************** + * Capabilities / Info + * *************************************************************************/ PVR_ERROR GetAddonCapabilities(PVR_ADDON_CAPABILITIES* pCapabilities) { @@ -416,355 +312,334 @@ PVR_ERROR GetAddonCapabilities(PVR_ADDON_CAPABILITIES* pCapabilities) pCapabilities->bHandlesDemuxing = true; pCapabilities->bSupportsRecordingFolders = true; pCapabilities->bSupportsRecordingEdl = true; + return PVR_ERROR_NO_ERROR; } const char *GetBackendName(void) { - static const char *strBackendName = HTSPData ? HTSPData->GetServerName() : "unknown"; - return strBackendName; + return tvh->GetServerName(); } const char *GetBackendVersion(void) { - static CStdString strBackendVersion; - if (HTSPData) - strBackendVersion.Format("%s (Protocol: %i)", HTSPData->GetVersion(), HTSPData->GetProtocol()); - return strBackendVersion.c_str(); + return tvh->GetServerVersion(); } const char *GetConnectionString(void) { - static CStdString strConnectionString; - if (HTSPData) - strConnectionString.Format("%s:%i%s", g_strHostname.c_str(), g_iPortHTSP, HTSPData->IsConnected() ? "" : " (Not connected!)"); - else - strConnectionString.Format("%s:%i (addon error!)", g_strHostname.c_str(), g_iPortHTSP); - return strConnectionString.c_str(); + return tvh->GetServerString(); } PVR_ERROR GetDriveSpace(long long *iTotal, long long *iUsed) { - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; + return tvh->GetDriveSpace(iTotal, iUsed); +} - if (HTSPData->GetDriveSpace(iTotal, iUsed)) - return PVR_ERROR_NO_ERROR; +/* ************************************************************************** + * GUI hooks + * *************************************************************************/ - return PVR_ERROR_SERVER_ERROR; +PVR_ERROR CallMenuHook + (const PVR_MENUHOOK &_unused(menuhook), + const PVR_MENUHOOK_DATA &_unused(data)) +{ + return PVR_ERROR_NO_ERROR; } -PVR_ERROR GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd) -{ - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; +/* ************************************************************************** + * Demuxer + * *************************************************************************/ - return HTSPData->GetEpg(handle, channel, iStart, iEnd); +bool CanPauseStream(void) +{ + return tvh->HasCapability("timeshift"); } -int GetChannelsAmount(void) +bool CanSeekStream(void) { - if (!HTSPData || !HTSPData->IsConnected()) - return 0; - - return HTSPData->GetNumChannels(); + return tvh->HasCapability("timeshift"); } -PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio) +bool OpenLiveStream(const PVR_CHANNEL &channel) { - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; - - return HTSPData->GetChannels(handle, bRadio); + return tvh->DemuxOpen(channel); } -int GetRecordingsAmount(void) +void CloseLiveStream(void) { - if (!HTSPData || !HTSPData->IsConnected()) - return 0; - - return HTSPData->GetNumRecordings(); + tvh->DemuxClose(); } -PVR_ERROR GetRecordings(ADDON_HANDLE handle) +bool SeekTime(int time,bool backward,double *startpts) { - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; - - return HTSPData->GetRecordings(handle); + return tvh->DemuxSeek(time, backward, startpts); } -PVR_ERROR DeleteRecording(const PVR_RECORDING &recording) +void SetSpeed(int speed) { - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; - - return HTSPData->DeleteRecording(recording); + tvh->DemuxSpeed(speed); } -PVR_ERROR RenameRecording(const PVR_RECORDING &recording) +int GetCurrentClientChannel(void) { - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; - - return HTSPData->RenameRecording(recording, recording.strTitle); + return -1; // XBMC doesn't even use this } -int GetTimersAmount(void) +bool SwitchChannel(const PVR_CHANNEL &channel) { - if (!HTSPData || !HTSPData->IsConnected()) - return 0; - - return HTSPData->GetNumTimers(); + return tvh->DemuxOpen(channel); } -PVR_ERROR GetTimers(ADDON_HANDLE handle) +PVR_ERROR GetStreamProperties(PVR_STREAM_PROPERTIES* pProperties) { - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; - - return HTSPData->GetTimers(handle); + return tvh->DemuxCurrentStreams(pProperties); } -PVR_ERROR AddTimer(const PVR_TIMER &timer) +PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS &signalStatus) { - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; - - return HTSPData->AddTimer(timer); + return tvh->DemuxCurrentSignal(signalStatus); } -PVR_ERROR DeleteTimer(const PVR_TIMER &timer, bool bForceDelete) +DemuxPacket* DemuxRead(void) { - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; - - return HTSPData->DeleteTimer(timer, bForceDelete); + return tvh->DemuxRead(); } -PVR_ERROR UpdateTimer(const PVR_TIMER &timer) +void DemuxAbort(void) { - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; - - return timer.state == PVR_TIMER_STATE_CANCELLED || timer.state == PVR_TIMER_STATE_ABORTED ? - HTSPData->DeleteTimer(timer, false) : - HTSPData->UpdateTimer(timer); + tvh->DemuxAbort(); } -bool OpenLiveStream(const PVR_CHANNEL &channel) +void DemuxReset(void) { - return HTSPData ? - HTSPData->OpenLiveStream(channel) : - false; } -void CloseLiveStream(void) +void DemuxFlush(void) { - if (HTSPData) - HTSPData->CloseLiveStream(); + tvh->DemuxFlush(); } -int GetCurrentClientChannel(void) +/* ************************************************************************** + * Channel Management + * *************************************************************************/ + +int GetChannelGroupsAmount(void) { - return HTSPData ? - HTSPData->GetCurrentClientChannel(): - -1; + return tvh->GetTagCount(); } -bool SwitchChannel(const PVR_CHANNEL &channel) +PVR_ERROR GetChannelGroups(ADDON_HANDLE handle, bool bRadio) { - return HTSPData ? - HTSPData->SwitchChannel(channel) : - false; + // tvheadend doesn't support separate groups for radio and TV + if (bRadio) + return PVR_ERROR_NO_ERROR; + + return tvh->GetTags(handle); } -PVR_ERROR GetStreamProperties(PVR_STREAM_PROPERTIES* pProperties) +PVR_ERROR GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group) { - return HTSPData ? - HTSPData->GetStreamProperties(pProperties) : - PVR_ERROR_SERVER_ERROR; + return tvh->GetTagMembers(handle, group); } -PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS &signalStatus) +int GetChannelsAmount(void) { - return HTSPData ? - HTSPData->SignalStatus(signalStatus) : - PVR_ERROR_SERVER_ERROR; + return tvh->GetChannelCount(); } -void DemuxAbort(void) +PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio) { - if (HTSPData) - HTSPData->DemuxAbort(); + return tvh->GetChannels(handle, bRadio); } -DemuxPacket* DemuxRead(void) +/* ************************************************************************** + * EPG + * *************************************************************************/ + +PVR_ERROR GetEPGForChannel + (ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd) { - return HTSPData ? - HTSPData->DemuxRead() : - NULL; + return tvh->GetEpg(handle, channel, iStart, iEnd); } -int GetChannelGroupsAmount(void) -{ - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; +/* ************************************************************************** + * Recording Management + * *************************************************************************/ - return HTSPData->GetNumChannelGroups(); +int GetRecordingsAmount(void) +{ + return tvh->GetRecordingCount(); } -PVR_ERROR GetChannelGroups(ADDON_HANDLE handle, bool bRadio) +PVR_ERROR GetRecordings(ADDON_HANDLE handle) { - /* tvheadend doesn't support separated groups, so we only support TV groups */ - if (bRadio) - return PVR_ERROR_NO_ERROR; - - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; - - return HTSPData->GetChannelGroups(handle); + return tvh->GetRecordings(handle); } -PVR_ERROR GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group) +PVR_ERROR GetRecordingEdl + (const PVR_RECORDING &rec, PVR_EDL_ENTRY edl[], int *num) { - /* tvheadend doesn't support separated groups, so we only support TV groups */ - if (group.bIsRadio) - return PVR_ERROR_NO_ERROR; + return tvh->GetRecordingEdl(rec, edl, num); +} - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; +PVR_ERROR DeleteRecording(const PVR_RECORDING &rec) +{ + return tvh->DeleteRecording(rec); +} - return HTSPData->GetChannelGroupMembers(handle, group); +PVR_ERROR RenameRecording(const PVR_RECORDING &rec) +{ + return tvh->RenameRecording(rec); } -PVR_ERROR CallMenuHook(const PVR_MENUHOOK &menuhook, const PVR_MENUHOOK_DATA &item) +int GetTimersAmount(void) { - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; + return tvh->GetTimerCount(); +} - if (!HTSPData->CanTranscode()) - return PVR_ERROR_REJECTED; +PVR_ERROR GetTimers(ADDON_HANDLE handle) +{ + return tvh->GetTimers(handle); +} - CodecVector v = HTSPData->GetTranscodingCodecs(); - CGUIDialogTranscode settings(v); +PVR_ERROR AddTimer(const PVR_TIMER &timer) +{ + return tvh->AddTimer(timer); +} - settings.DoModal(); +PVR_ERROR DeleteTimer(const PVR_TIMER &timer, bool bForceDelete) +{ + return tvh->DeleteTimer(timer, bForceDelete); +} - return PVR_ERROR_NO_ERROR; +PVR_ERROR UpdateTimer(const PVR_TIMER &timer) +{ + return tvh->UpdateTimer(timer); } + +/* ************************************************************************** + * Recording VFS + * *************************************************************************/ bool OpenRecordedStream(const PVR_RECORDING &recording) { - if (!HTSPData || !HTSPData->IsConnected()) - return false; - return HTSPData->OpenRecordedStream(recording); + return tvh->VfsOpen(recording); } void CloseRecordedStream(void) { - if (!HTSPData || !HTSPData->IsConnected()) - return; - HTSPData->CloseRecordedStream(); + tvh->VfsClose(); } int ReadRecordedStream(unsigned char *pBuffer, unsigned int iBufferSize) { - if (!HTSPData || !HTSPData->IsConnected()) - return -1; - return HTSPData->ReadRecordedStream(pBuffer, iBufferSize); + return tvh->VfsRead(pBuffer, iBufferSize); } long long SeekRecordedStream(long long iPosition, int iWhence /* = SEEK_SET */) { - if (!HTSPData || !HTSPData->IsConnected()) - return -1; - return HTSPData->SeekRecordedStream(iPosition, iWhence); + return tvh->VfsSeek(iPosition, iWhence); } long long PositionRecordedStream(void) { - if (!HTSPData || !HTSPData->IsConnected()) - return -1; - return HTSPData->PositionRecordedStream(); + return tvh->VfsTell(); } long long LengthRecordedStream(void) { - if (!HTSPData || !HTSPData->IsConnected()) - return -1; - return HTSPData->LengthRecordedStream(); + return tvh->VfsSize(); } -bool CanPauseStream(void) +/* ************************************************************************** + * Unused Functions + * *************************************************************************/ + +unsigned int GetChannelSwitchDelay(void) { return 0; } + +/* Recording History */ +PVR_ERROR SetRecordingPlayCount + (const PVR_RECORDING &_unused(recording), int _unused(count)) { - if (HTSPData) - return HTSPData->CanTimeshift(); - return false; + return PVR_ERROR_NOT_IMPLEMENTED; } - -bool CanSeekStream(void) +PVR_ERROR SetRecordingLastPlayedPosition + (const PVR_RECORDING &_unused(recording), int _unused(lastplayedposition)) { - if (HTSPData) - return HTSPData->CanSeekLiveStream(); - return false; + return PVR_ERROR_NOT_IMPLEMENTED; } - -bool SeekTime(int time,bool backward,double *startpts) +int GetRecordingLastPlayedPosition(const PVR_RECORDING &_unused(recording)) { - return HTSPData ? - HTSPData->SeekTime(time, backward, startpts) : - false; + return -1; } -void SetSpeed(int speed) +/* Channel Management */ +PVR_ERROR DialogChannelScan(void) { - if(HTSPData) - HTSPData->SetSpeed(speed); + return PVR_ERROR_NOT_IMPLEMENTED; } - -void DemuxFlush(void) +PVR_ERROR DeleteChannel(const PVR_CHANNEL &_unused(channel)) { - if (HTSPData) - HTSPData->DemuxFlush(); + return PVR_ERROR_NOT_IMPLEMENTED; } - -PVR_ERROR GetRecordingEdl(const PVR_RECORDING &recording, PVR_EDL_ENTRY entries[], int *size) -{ - if (!HTSPData || !HTSPData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; - - return HTSPData->GetEdl(recording, &*entries, size); +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 DialogChannelSettings(const PVR_CHANNEL &_unused(channel)) +{ + return PVR_ERROR_NOT_IMPLEMENTED; +} +PVR_ERROR DialogAddChannel(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() { - int seconds = 0; - - if (HTSPData) - seconds = HTSPData->DemuxGetTimeshiftTime() / 1000000; - - return (time(NULL) - seconds); -} - -/** UNUSED API FUNCTIONS */ -PVR_ERROR DialogChannelScan(void) { return PVR_ERROR_NOT_IMPLEMENTED; } -PVR_ERROR DeleteChannel(const PVR_CHANNEL &channel) { return PVR_ERROR_NOT_IMPLEMENTED; } -PVR_ERROR RenameChannel(const PVR_CHANNEL &channel) { return PVR_ERROR_NOT_IMPLEMENTED; } -PVR_ERROR MoveChannel(const PVR_CHANNEL &channel) { return PVR_ERROR_NOT_IMPLEMENTED; } -PVR_ERROR DialogChannelSettings(const PVR_CHANNEL &channel) { return PVR_ERROR_NOT_IMPLEMENTED; } -PVR_ERROR DialogAddChannel(const PVR_CHANNEL &channel) { return PVR_ERROR_NOT_IMPLEMENTED; } -void DemuxReset(void) {} -int ReadLiveStream(unsigned char *pBuffer, unsigned int iBufferSize) { return 0; } -long long SeekLiveStream(long long iPosition, int iWhence /* = SEEK_SET */) { return -1; } -long long PositionLiveStream(void) { return -1; } -long long LengthLiveStream(void) { return -1; } -const char * GetLiveStreamURL(const PVR_CHANNEL &channel) { return ""; } -PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING &recording, int count) { return PVR_ERROR_NOT_IMPLEMENTED; } -PVR_ERROR SetRecordingLastPlayedPosition(const PVR_RECORDING &recording, int lastplayedposition) { return PVR_ERROR_NOT_IMPLEMENTED; } -int GetRecordingLastPlayedPosition(const PVR_RECORDING &recording) { return -1; } -unsigned int GetChannelSwitchDelay(void) { return 0; } -void PauseStream(bool bPaused) {} -time_t GetBufferTimeStart() { return 0; } -time_t GetBufferTimeEnd() { return 0; } + // 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 ""; } diff --git a/addons/pvr.hts/src/client.h b/addons/pvr.hts/src/client.h index f54cc61e0..3423236c8 100644 --- a/addons/pvr.hts/src/client.h +++ b/addons/pvr.hts/src/client.h @@ -15,50 +15,28 @@ * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to - * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA + * 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 "libXBMC_addon.h" -#include "libXBMC_codec.h" #include "libXBMC_pvr.h" #include "libXBMC_gui.h" +#include "libXBMC_codec.h" -extern ADDON::CHelper_libXBMC_addon* XBMC; -extern CHelper_libXBMC_codec* CODEC; -extern CHelper_libXBMC_pvr* PVR; -extern CHelper_libXBMC_gui* GUI; - -#include "HTSPTypes.h" +extern ADDON::CHelper_libXBMC_addon* XBMC; +extern CHelper_libXBMC_pvr* PVR; +extern CHelper_libXBMC_gui* GUI; +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 6 -#define DEFAULT_RESPONSE_TIMEOUT 4 -#define DEFAULT_VIDEO_CODEC "H264" -#define DEFAULT_AUDIO_CODEC "UNKNOWN" -#define DEFAULT_RESOLUTION 480 -#define DEFAULT_TRANSCODE false -#define HTSP_DEBUGGING 0 - -extern bool m_bCreated; -extern std::string g_strHostname; -extern int g_iPortHTSP; -extern int g_iPortHTTP; -extern std::string g_strUsername; -extern std::string g_strPassword; -extern int g_iConnectTimeout; -extern int g_iResponseTimeout; -extern bool g_bShowTimerNotifications; -extern std::string g_szUserPath; -extern std::string g_szClientPath; -extern bool g_bTranscode; -extern CodecDescriptor g_audioCodec; -extern CodecDescriptor g_videoCodec; -extern int g_iResolution; +#define DEFAULT_CONNECT_TIMEOUT 10 +#define DEFAULT_RESPONSE_TIMEOUT 5 -uint32_t HTSPNextSequenceNumber(void); +class CTvheadend; +extern CTvheadend *tvh;