diff -Nru kodi-pvr-vuplus-2.4.12/CMakeLists.txt kodi-pvr-vuplus-3.15.0/CMakeLists.txt --- kodi-pvr-vuplus-2.4.12/CMakeLists.txt 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/CMakeLists.txt 2018-11-18 11:16:20.000000000 +0000 @@ -17,7 +17,67 @@ ${KODI_INCLUDE_DIR}) set(VUPLUS_SOURCES src/client.cpp - src/VuData.cpp) + src/Enigma2.cpp + src/enigma2/Admin.cpp + src/enigma2/Channels.cpp + src/enigma2/ChannelGroups.cpp + src/enigma2/Epg.cpp + src/enigma2/RecordingReader.cpp + src/enigma2/Recordings.cpp + src/enigma2/Settings.cpp + src/enigma2/StreamReader.cpp + src/enigma2/Timers.cpp + src/enigma2/TimeshiftBuffer.cpp + src/enigma2/data/AutoTimer.cpp + src/enigma2/data/BaseEntry.cpp + src/enigma2/data/Channel.cpp + src/enigma2/data/ChannelGroup.cpp + src/enigma2/data/EpgEntry.cpp + src/enigma2/data/RecordingEntry.cpp + src/enigma2/data/Timer.cpp + src/enigma2/extract/EpgEntryExtractor.cpp + src/enigma2/extract/GenreIdMapper.cpp + src/enigma2/extract/GenreRytecTextMapper.cpp + src/enigma2/extract/ShowInfoExtractor.cpp + src/enigma2/utilities/CurlFile.cpp + src/enigma2/utilities/FileUtils.cpp + src/enigma2/utilities/Logger.cpp + src/enigma2/utilities/WebUtils.cpp) + +set(VUPLUS_HEADERS src/client.h + src/Enigma2.h + src/enigma2/Admin.h + src/enigma2/Channels.h + src/enigma2/ChannelGroups.h + src/enigma2/Epg.h + src/enigma2/IStreamReader.h + src/enigma2/RecordingReader.h + src/enigma2/Recordings.h + src/enigma2/Settings.h + src/enigma2/StreamReader.h + src/enigma2/Timers.h + src/enigma2/TimeshiftBuffer.h + src/enigma2/data/AutoTimer.h + src/enigma2/data/BaseEntry.h + src/enigma2/data/Channel.h + src/enigma2/data/ChannelGroup.h + src/enigma2/data/EpgEntry.h + src/enigma2/data/RecordingEntry.h + src/enigma2/data/Timer.h + src/enigma2/extract/IExtractor.h + src/enigma2/extract/EpgEntryExtractor.h + src/enigma2/extract/EpisodeSeasonPattern.h + src/enigma2/extract/GenreIdMapper.h + src/enigma2/extract/GenreRytecTextMapper.h + src/enigma2/extract/ShowInfoExtractor.h + src/enigma2/utilities/CurlFile.h + src/enigma2/utilities/DeviceInfo.h + src/enigma2/utilities/DeviceSettings.h + src/enigma2/utilities/LocalizedString.h + src/enigma2/utilities/UpdateState.h + src/enigma2/utilities/FileUtils.h + src/enigma2/utilities/Logger.h + src/enigma2/utilities/WebUtils.h) set(DEPLIBS ${kodiplatform_LIBRARIES} ${p8-platform_LIBRARIES} diff -Nru kodi-pvr-vuplus-2.4.12/debian/changelog kodi-pvr-vuplus-3.15.0/debian/changelog --- kodi-pvr-vuplus-2.4.12/debian/changelog 2017-10-26 19:51:01.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/debian/changelog 2018-11-21 13:16:02.000000000 +0000 @@ -1,117 +1,7 @@ -kodi-pvr-vuplus (2.4.12-1~xenial) xenial; urgency=low +kodi-pvr-vuplus (3.15.0-1~xenial) xenial; urgency=low [ kodi ] * autogenerated dummy changelog - [ wsnipex ] - * v2.4.12 - backport: Fixed timer recording margins to Krypton v2.4.9 - - updated language files from Transifex v2.4.8 - updated language - files from Transifex v2.4.7 - streaming always use anonymous http - connection, regardless of the "Use https" setting v2.4.6 - updated - language files from Transifex v2.4.5 - Updated to PVR addon API - v5.2.1 v2.4.4 - updated language files from Transifex v2.4.3 - - updated language files from Transifex v2.4.2 - updated language - files from Transifex v2.4.1 - updated language files from Transifex - v2.4.0 - Cmake: rename find_package kodi to Kodi v2.3.1 - Fix - includes v2.3.0 - Updated to PVR addon API v5.2.0 v2.2.0 - Updated - to PVR addon API v5.1.0 v2.1.0 - Updated to PVR addon API v5.0.0 - v2.0.1 - updated language files from Transifex v2.0.0 - Initial Kodi - Krypton version. v1.11.9 - updated language files from Transifex - v1.11.8 - updated language files from Transifex v1.11.7 - updated - language files from Transifex 1.11.6 - Updated to PVR API v4.1.0 - 1.11.5 - Updated to PVR API v4.0.0 1.11.4 - Updated to PVR API - v3.0.0 (API 1.9.7 compatibility mode) 1.11.3 - Updated to PVR API - v2.1.0 - Automatically fill in platform and library name 1.11.2 - - Debian packaging: fix library install path - Miscellaneous backend - fixes 1.11.1 - Updated to API v2.0.0 1.11.0 - Updated to API v1.9.7 - v1.10.5 - updated language files from Transifex 1.10.4 - Updated to - use new libplatform-dev 1.10.3 - Updated to API v1.9.6 1.10.2 - - Updated to API v1.9.5 1.10.1 - Updated to API v1.9.4 1.9.23 - - updated language files from Transifex 1.9.22 - updated language - files from Transifex - minor changes to conform with C++11 1.9.21 - - added getBackendHostname function 1.9.20 - updated language files - from Transifex 1.9.19 - change library name to Kodi 1.9.18 - fixed - deadlock when activating the addon on some darwin (osx, ios) - runtimes 1.9.17 - updated language files from Transifex 1.9.16 - - updated language files from Transifex 1.9.15 - updated to API v1.9.2 - 1.9.14 - remove: implementation for lastplayedposition (XBMC handles - this now) - remove: loading of channel data from HDD - change: - handling of EPG - add: error message if username or password contain - the @-sign 1.9.13 - sync with PVR API v1.9.1 1.9.12 - updated - language files from Transifex 1.9.11 - updated language files from - Transifex 1.9.10 - updated language files from Transifex 1.9.9 - add - timeshift buffer functions 1.8.8 - sync with PVR API v1.8.0 1.7.8 - - fix: typo in settings.xml 1.7.7 - Bump after PVR API version bump - 1.6.7 - add: support for /virtual) recording folders - add: support - for fetching picons from the webinterface - add: support for - recording icons 1.6.6 - updated language files from Transifex 1.6.5 - - updated language files from Transifex 1.6.4 - New version number by - Team XBMC 0.3.5: - fix: URL encoding in timer-add operations 0.3.4: - - fix: several crashes on win32 due to missing locks / invalid memory - access - fix: do not report connection problems when there is an - empty TV-channel bouquet 0.3.3: - add: support for storing the last - played positions for recordings. These will be stored in the file - recordings.xml - fix: if the webinterface cannot be loaded, - deactivate the addon 0.3.2: - fix: continue to load channels even if - we do not have any radio channels 0.3.1: - change: remove XMLParser - - change: add enigma2 to the displayname 0.3.0: - change: remove curl - dependancy - change: adjust to new PVR API 0.2.8: - add: option to - only fetch one TV bouquet which can be specified via the addon - settings 0.2.7: - fix: fix incorrect escape character for & (use - '&' instead of '"'). Thx to 'hani' for pointing this out. - 0.2.6: - cosmetic: remove unnecessary '/' in recording-stream url - - cosmetic: inprove log output - change: get the proper device info - from the reveiver box instead of just setting dummy values - change: - change the buildzip.bat to include version string in the name of the - zip-file - change: introduce a version string for the channeldata - xml file so that we can invalidate old channeldata files if - necessary 0.2.5: - fix: cleanup the service reference in the - streaming url 0.2.4 - fix: put username & password into the - streaming url 0.2.3 - fix: put username & password into recording- - url 0.2.2: - fix: escape xml entities in the stream-url before - saving to channeldata.xml - fix: fetch the version string from - configure.in not the ChangeLog (thanks to 'trans') - fix: rename - changelog in addon-directory to changelog.txt 0.2.1: - fix: encode - the stream-url properly. Please remove your channeldata.xml file - after updating - change: add proper version string to the addon.xml - generated by buildzip.bat (thanks to 'trans') 0.2.0: - change: - Complete rework of timer handling. Now it will only show - notifications for changed items - fix: Update / Add / Delete Timers. - Note that the timer names in the XBMC are sometimes not updated - properly (in the dialog it is OK) - fix: Instant Recordings do now - work again - fix: timer status is now shown correctly (completed, - recording, disabled) - fix: enabling / disabling timers do now work - - change: removed "show completed timers" option (they are now always - be shown) - add: added buildzip.bat & xbmc-addon-vuplus.sln (thanks - to 'trans') - fix: Channel numbering / incorrect picons due to the - change introduced in 0.1.15 0.1.15 - fix: when using the channeldata- - store option not all channel groups (bouquets) were loaded due to a - nulled counter variable 0.1.14 - change: change .gitignores and copy - current changelog into the addon folder. This will enable the user - to view the changelog in the addon settings window 0.1.13 - add: - option to set deepstandby powerstate on the DVB box on PVR-addon - shutdown - fix: error in settings.xml, causing crashes on linux - 0.1.12 - add: support to specify the folder for storing recordings - 0.1.11 - fix: some unicode string errors in german language file - - change: add categories to addon settings 0.1.10 - add: support for - using only the recording path currently active on the DVB box 0.1.9 - - change: add addon icon (copyied from the openelec guys, thanks!) - - fix: win32 release target (thanks to 'trans' for patch) 0.1.8 - - change: fetch the recording locations and use these locations when - querying the recordings - fix: Stop update thread when destroying - the PVR addon - fixes shutdown issues 0.1.7 - fix: Copy & Paste - error 0.1.6 - fix: Change the logic to determine the picon file name - from the service reference. 0.1.5 - fix: Fix access violation errors - on windows (thanks to 'trans' for finding the correct compiler / - linker settings) - fix: do not return out of scope local variable - for the streaming URL - fix: remove the last '_' character from the - filename (if applicable). Should finally fix the picon path errors. - 0.1.4 - fix: limit length of the service reference part of the Icon- - Path to 30 characters. - fix: Escape "&", "<" and ">" characters in - XML channeldata file. - add: support to disable all bouquet or - channel updates 0.1.3 - fix: order of timerlist cleanup and - timerlist updates 0.1.2 - add: support for storing channel data into - a file 0.1.1 - fix: URLEncode the service reference when fetching - EPG 0.1.0 - Iniital Version + -- Cristiano A. Silva Mon, 23 Feb 2015 15:56:31 +0000 - -- wsnipex Thu, 26 Oct 2017 21:51:01 +0200 diff -Nru kodi-pvr-vuplus-2.4.12/debian/changelog.tmp kodi-pvr-vuplus-3.15.0/debian/changelog.tmp --- kodi-pvr-vuplus-2.4.12/debian/changelog.tmp 2017-10-26 19:50:31.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/debian/changelog.tmp 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -kodi-pvr-vuplus (2.4.12-1~#DIST#) #DIST#; urgency=low - - [ kodi ] - * autogenerated dummy changelog - - -- Cristiano A. Silva Mon, 23 Feb 2015 15:56:31 +0000 - diff -Nru kodi-pvr-vuplus-2.4.12/debian/control kodi-pvr-vuplus-3.15.0/debian/control --- kodi-pvr-vuplus-2.4.12/debian/control 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/debian/control 2018-11-05 17:50:27.000000000 +0000 @@ -1,7 +1,7 @@ Source: kodi-pvr-vuplus Priority: extra Maintainer: Cristiano A. Silva -Build-Depends: debhelper (>= 9.0.0), cmake, libtinyxml-dev, kodi-pvr-dev, +Build-Depends: debhelper (>= 9.0.0), cmake, libtinyxml-dev, libkodiplatform-dev (>= 16.0.0), kodi-addon-dev Standards-Version: 3.9.4 Section: libs diff -Nru kodi-pvr-vuplus-2.4.12/debian/kodi-pvr-vuplus.install kodi-pvr-vuplus-3.15.0/debian/kodi-pvr-vuplus.install --- kodi-pvr-vuplus-2.4.12/debian/kodi-pvr-vuplus.install 2017-10-26 19:50:31.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/debian/kodi-pvr-vuplus.install 2018-11-05 17:50:27.000000000 +0000 @@ -1,2 +1,2 @@ -usr/lib -usr/share +usr/lib/* +usr/share/* diff -Nru kodi-pvr-vuplus-2.4.12/Jenkinsfile kodi-pvr-vuplus-3.15.0/Jenkinsfile --- kodi-pvr-vuplus-2.4.12/Jenkinsfile 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/Jenkinsfile 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1 @@ +buildPlugin() diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/addon.xml.in kodi-pvr-vuplus-3.15.0/pvr.vuplus/addon.xml.in --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/addon.xml.in 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/addon.xml.in 2018-11-18 11:16:20.000000000 +0000 @@ -1,20 +1,17 @@ - - - - + version="3.15.0" + name="Enigma2 Client" + provider-name="Joerg Dembski and Ross Nicholson"> + @ADDON_DEPENDS@ Kodi se voorprogram vir VU+ / Enigma2 gebasseerde 'set-top' bokse Kodi's frontend for VU+ / Enigma2 based settop boxes - Kodi клиент за тунери базирани на VU+ / Enigma2 + Клиент за устройства, базирани на VU+ / Enigma2 Frontal de Kodi per als descodificadors basats en VU+/Enigma2 Rozhraní Kodi pro přijímače založené na VU+ nebo Enigma2 Blaen Kodi ar gyfer blychau teledu VU+ / Enigma2 @@ -22,7 +19,7 @@ Kodi Oberfläche für VU+ / Enigma2-basierte Settop-Boxen Frontend του Kodi για αποκωδικοποιητές (settop box) τύπου VU+ / Enigma2 Kodi's frontend for VU+ / Enigma2 based settop boxes - Kodi's frontend for VU+ / Enigma2 based settop boxes + Kodi's frontend for Enigma2 based set-top boxes Kodi's frontend for VU+ / Enigma2 based settop boxes Kodi's frontend for VU+ / Enigma2 based settop boxes Kodi frontend para decodificadores equipados con VU+/Enigma2 @@ -66,7 +63,7 @@ 給以VU+ / Enigma2開發的機上盒所使用的Kodi前端 VU+ voorprogram; ondersteun stroom van Lewendige TV & Opnames, EPG, Tydhouers. VU+ frontend; supporting streaming of Live TV & Recordings, EPG, Timers. - VU+ клиент. Поддържа поточна телевизия и записване, електронен програмен справочник и броячи. + Клиент за „VU+“. Поддържа телевизия на живо и записване, електронен програмен справочник и броячи. Frontal de VU+; és compatible amb les transmissions en línia de TV en directe i enregistraments, guia electrònica de programació (EPG) i temporitzadors. Rozhraní VU+; podporuje streamování živého vysílání a nahrávání, televizní program, časovače. Blaen VU+; cynnal ffrydio Teledu Byw, Recordio, Amserlenni, Amseryddion @@ -74,7 +71,7 @@ VU+ -Oberfläche; Unterstützt Live TV & Aufnahmen, EPG und Timer. Frontend για το VU+. Υποστηρίζει ροές Live TV & Εγγραφές, EPG, Χρονοδιακόπτες. VU+ frontend; supporting streaming of Live TV & Recordings, EPG, Timers. - VU+ frontend; supporting streaming of Live TV & Recordings, EPG, Timers. + Enigma2 frontend - supporting streaming of Live TV & Recordings, EPG, Timers, Autotimers. For documentation visit: https://github.com/kodi-pvr/pvr.vuplus/blob/master/README.md VU+ frontend; supporting streaming of Live TV & Recordings, EPG, Timers. VU+ frontend; supporting streaming of Live TV & Recordings, EPG, Timers. VU+ frontend; soporta TV en vivo, grabaciones, guía de programación (GEP) y temporizadores. @@ -82,7 +79,7 @@ VU+ frontend; Soportando transmisión de TV en directo y grabaciones, EPG, Temporizadores. VU+ liides. Toetab telekanalite striimimist ja salvestamist ning elektroonilist saatekava. VU+-asiakasohjelma. Tukee suorien tv-lähetysten ja tallennusten katsomista, ohjelmaopasta ja ohjelmien ajastamista. - Frontal VU+, prenant en charge la diffusion en continu des télés en direct & les enregistrements, le GÉP et les minuteries. + Frontal VU+, prenant en charge la diffusion en continu des télés en direct et les enregistrements, le GÉP et les minuteries Interface logicielle pour enregistreur VU+. Gère la diffusion et les enregistrements de la TV en direct, le guide électronique des programmes TV et les programmations. Interface VU+; soporta TV en directo, gravacións, Guía de programación e temporizadores. לקוח טלוויזיה חיה של VU+. תומך בהזרמת שידורים חיים והקלטות, הצגת לוח שידורים ותזמון הקלטות. @@ -98,7 +95,7 @@ VU+ интерфејс;подржува стриминг на Live TV & Recordings, EPG, Timers. Bahagian hadapan VU+; menyokong penstirman Langsung & Rakaman, EPG, Pemasa TV VU+grenseflate; støtter strømming av direkte-TV og opptak, EPG, tidsur. - VU+ frontend; ondersteunt het streamen van LiveTV & Opnames, EPG, Timers + VU+ frontend; ondersteunt het streamen van Live-TV & opnames, EPG, timers Klient telewizji dla VU+ obsługuje transmisję kanałów radiowych i telewizyjnych, nagrywanie i harmonogram nagrań oraz funkcje przewodnika telewizyjnego. VU+ frontend; suporta streaming de TV Ao Vivo e Gravações, EPG, agendamentos. Interface VU+ ; suporta transmissão e gravação de TV em direto, EPG e temporizadores. @@ -120,7 +117,7 @@ This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. Тази програма е нестабилна! Авторите не носят отговорност за неуспешно записване, некоректни броячи, пропиляно време и други нежелани ефекти. Això és programari inestable! Els autors no són de cap manera responsables dels enregistraments que han fallat, temporitzadors incorrectes, hores perdudes, o qualssevol altres efectes no desitjats.. - Tento software není stabilní! Autoři nejsou žádným způsobem zodpovědní za neúspěšná nahrávání, chybné časovače, ztracený čas nebo jakékoliv jiné nežádoucí výsledky... + Tento software není stabilní! Autoři nejsou žádným způsobem zodpovědní za neúspěšná nahrávání, chybné časovače, ztracený čas nebo jakékoliv jiné nežádoucí výsledky… Mae hwn yn feddalwedd ansad! Nid yw'r awduron yn gyfrifol mewn unrhyw ffordd am fethu recordio, amseru gwallus, oriau wedi eu gwastraffu nac effeithiau anymunol eraill. Dette er ustabil software! Ophavsmændene er på ingen måde ansvarlige for mislykkede optagelser, ukorrekte timere, spildte timer, eller andre uønskede konsekvenser.. Dies ist instabile Software! Die Autoren sind in keiner Weise verantwortlich für fehlgeschlagene Aufnahmen, falsche Timer, verschwendete Zeit oder andere ungewünschte Effekte. @@ -133,9 +130,9 @@ ¡Este es un software inestable! Los autores no son de ninguna manera responsables de las grabaciones fallidas o incorrectas, las temporizadores perdidas, ni otros efectos no deseables.. ¡Esto es software inestable! Los autores no son de ninguna manera responsables por grabaciones fallidas, temporizadores incorrectos, horas perdidas o cualquier otro efecto no deseado... See on ebastabiilne tarkvara! Autorid ei ole kuidagi moodi vastutavad nurjunud salvestiste, ebaõige aegrelee, raisatud tundide ega muude soovimatute asjade eest. - Software hau beta bertsioan dago! Egilea ez da arduratzen grabaketa erroretaz, kronometro erroreak, hordu galduak edo beste edozein ondorio ezerosotaz + Software hau ezegonkorra da! Egilea ez da arduratzen grabazio-erroreetaz, kronometro-erroreetaz, ordu galduetaz edo beste edozein ondorio ezerosoetaz. Tämä on epävakaa ohjelma! Sen tekijät eivät ole millään muotoa vastuussa epäonnistuneista tallennuksista, virheellisistä ajastuksista, haaskatusta ajasta, verenpaineen noususta tai mistään muusta epäsuotuisasta vaikutuksesta. - Ce logiciel est instable! Les auteurs ne sont aucunement responsables des enregistrements défaillants, des minuteries erronées, des heures perdues ou tout autre effet indésirable. + Ce logiciel est instable ! Les auteurs ne sont aucunement responsables des enregistrements défaillants, des minuteries erronées, des heures perdues ou tout autre effet indésirable. Logiciel en cours d'élaboration ! Les auteurs ne sont en aucun cas responsables de l'échec des enregistrements, programmations défectueuses, temps perdu ou autres effets indésirables. Software non estable, os autores non se fan responsábeis dos erros na gravacións, temporizadores incorrectos, e outros efectos non desexados. זוהי איננה הרחבה יציבה! המפתחים אינם אחראים על כשלון בניגון, זמנים שגויים במדריך השידורים, שעות מבוזבזות או כל תופעה לא רצויה אחרת. @@ -177,5 +174,28 @@ 这是不稳定版的软件!作者不对录像失败、错误定时造成时间浪费或其它不良影响负责。 這是測試版軟體!其原創作者並無法對於以下情況負責,包含:錄影失敗,不正確的定時設定,多餘時數,或任何產生的其它不良影響... @PLATFORM@ + +v3.15.0 +- Added: Support for Radio Groups +- Added: Create unique list of channels instead of a copy of each channel per group, fixes #101 +- Fixed: hdd free space is wrong, fixes #122 +- Added: Device Settings - AutoTimer and Padding +- Added: PowerstateMode on exit, fixes #128 +- Fixed: Store timer state on update, fixes #131 +- Fixed: Updates not occuring at specified time and immediate update on timer event, fixes #130 +- Added: Support different update modes for timers and recordings, fixes #125 + +v3.14.0 +- Added: Externalised season/episode and genre config to allow users support other formats/languages, closes #118 +- Added: Server OpenWebIf version now reported by addon + +v3.13.0 +- Added: New setting to enable streaming over HTTPS +- Added: New setting to enable authentication for streaming + +v3.12.6 +- Fixed: Windows build fix +- Fixed: tsbuffer.ts never got deleted, fixes #115 + diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/changelog.txt kodi-pvr-vuplus-3.15.0/pvr.vuplus/changelog.txt --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/changelog.txt 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/changelog.txt 2018-11-18 11:16:20.000000000 +0000 @@ -1,20 +1,167 @@ -v2.4.12 -- backport: Fixed timer recording margins to Krypton +v3.15.0 +- Added: Support for Radio Groups +- Added: Create unique list of channels instead of a copy of each channel per group, fixes #101 +- Fixed: hdd free space is wrong, fixes #122 +- Added: Device Settings - AutoTimer and Padding +- Added: PowerstateMode on exit, fixes #128 +- Fixed: Store timer state on update, fixes #131 +- Fixed: Updates not occuring at specified time and immediate update on timer event, fixes #130 +- Added: Support different update modes for timers and recordings, fixes #125 -v2.4.9 -- updated language files from Transifex +v3.14.1 +- Added: updated language files from Transifex -v2.4.8 -- updated language files from Transifex +v3.14.0 +- Added: Externalised season/episode and genre config to allow users support other formats/languages, closes #118 +- Added: Server OpenWebIf version now reported by addon + +v3.13.0 +- Added: New setting to enable streaming over HTTPS +- Added: New setting to enable authentication for streaming + +v3.12.6 +- Fixed: Windows build fix +- Fixed: tsbuffer.ts never got deleted, fixes #115 + +v3.12.5 +- Fixed: Large refactor for code organisation +- Fixed: Disk space, only for mounts configured for recordings - Requires OpenWebIf 1.3.5, fixes #112 + +v3.12.4 +- Fixed: Used space instead of free space in GetDriveSpace - fixes #109 +- Added: Genre id support from OTA feeds - Requires OpenWebIf 1.3.5 + +v3.12.3 +- Fixed: Refactoring - Changed Directory structure, split out classes and added getters/setters #102 +- Fixed: Updated readme without VU+ entries - Courtesy of Hedda +- Fixed: New temporary icon + +v3.12.2 +- Fixed: Refactoring - Conventions: includes, namesapce naming, public private order in class definition +- Fixed: GetInitialEPGForGroup called for each CHANNEL while initial EPG Update - #86 + +v3.12.1 +- Added: New setting for Prepending outline to plot +- Added: New setting for stream read chunk size +- Fixed: cosmetic error when recordings folder is empty #10 +- Fixed: Rename "VuPlus" PVR client addon to Enigma2 or something else for Kodi? #28 + +v3.12.0 +- Added: Extracting Genre and Season/Episode numbers for EPG entries and recordings +- Added: Updated Readme +- Fixed: Minimum version now 1.3.0 to use autotimers + +v3.11.3 +- Added: New settings to allow feature switches for generating repeating timers and autotimers +- Added: Config guide to Readme +- Fixed: Missing channel or more than one channel in timers/autotimers + +v3.11.2 +- Fixed: Previous version picon fix turned into an option to use picons.eu file format + +v3.11.1 +- Fixed: Not able to select duplicate with titles and all descs +- Fixed: Online icons path processing incorrect for some channels + +v3.11.0 +- Added: Autotimer support +- Added: Generate ReadOnly Timers for Repeating Timer Rules +- Added: GetDriveSpace + +v3.10.1 +- Cleaned up settings screen +- Fix: Timer tags no longer removed on timer update + +v3.10.0 +- Added: Recorded Streams support +- Added: PVR API 5.0.0: iChannelUid in recordings +- Added: PVR API 5.1.0: Support channel type in recordings + +v3.9.0 +- Added: Timer Types Support, now supports Manual Once, Manual Repeating and EPG Once + +v3.8.0 +- Added: timeshift support +- Signal Status support +- Fixed recording duration bug and cleaned up split string code + +v3.7.3 +- Translation update from Transifex + +v3.7.2 +- Translation update from Transifex + +v3.7.1 +- Updated to PVR addon API v5.10.1 + +v3.7.0 +- Updated to PVR addon API v5.10.0 + +v3.6.3 +- Updated to PVR addon API v5.9.0 + +v3.6.0 +- Updated to PVR addon API v5.8.0 + +v3.5.6 +- Fix string replace syntax + +v3.5.5 +- Remove StdString usage + +v3.5.2 +- Fixed timer recording margins + +v3.5.1 +- Updated language files from Transifex + +v3.5.0 +- Updated to PVR addon API v5.7.0 + +v3.4.1 +- Removed incomplete implementation of channel playback via live input stream. Addon claimed to support it, but actually didn't. +- Restored channel playback via stream URL. This is what the addon actually implements. + +v3.4.0 +- Updated to PVR addon API v5.6.0 + +v3.3.2 +- added option to keep the folder structure from STB + +v3.3.1 +- added option to request the streaming-URL from openWebif and thus eliminating the need to configure the streaming port + +v3.3.0 +- Updated to PVR addon API v5.5.0 + +v3.2.0 +- Updated to PVR addon API v5.4.0 + +v3.1.0 +- Updated to PVR addon API v5.3.0 + +v3.0.6 +- remove of never used addon interface function + +v3.0.5 +- update Debian package control +- PVR addon callback way changes + +v3.0.4 +- removed old no more needed version functions + +v3.0.3 +- set dependency versions automatic during build +- removed never used kodi to addon functions -v2.4.7 +v3.0.2 - streaming always use anonymous http connection, regardless of the "Use https" setting -v2.4.6 +v3.0.1 - updated language files from Transifex -v2.4.5 -- Updated to PVR addon API v5.2.1 +v3.0.0 +- Initial Kodi v18 version v2.4.4 - updated language files from Transifex Binary files /tmp/tmpkY6JOA/dV7v9hEOko/kodi-pvr-vuplus-2.4.12/pvr.vuplus/icon.png and /tmp/tmpkY6JOA/Y7LnmWnZdf/kodi-pvr-vuplus-3.15.0/pvr.vuplus/icon.png differ diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/data/genres/genreIdMappings/AU-SAT.xml kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/data/genres/genreIdMappings/AU-SAT.xml --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/data/genres/genreIdMappings/AU-SAT.xml 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/data/genres/genreIdMappings/AU-SAT.xml 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,282 @@ + + + + AU-SAT + + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x20 + 0x20 + 0x20 + 0x20 + 0x20 + 0x20 + 0x20 + 0x20 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x51 + 0x30 + 0x30 + 0x50 + 0x33 + 0x30 + 0x50 + 0x30 + 0x00 + 0x30 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x12 + 0x12 + 0x16 + 0x13 + 0x14 + 0x11 + 0x10 + 0x10 + 0x60 + 0x00 + 0x60 + 0x00 + 0x60 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x40 + 0x40 + 0x40 + 0x43 + 0x40 + 0x40 + 0x40 + 0x40 + 0x40 + 0x49 + 0x40 + 0x40 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + + \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-IT.xml kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-IT.xml --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-IT.xml 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-IT.xml 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,282 @@ + + + + Sky-IT + + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x15 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x31 + 0x33 + 0x30 + 0x30 + 0x30 + 0x30 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x40 + 0x40 + 0x44 + 0x47 + 0x40 + 0x40 + 0x40 + 0x40 + 0x40 + 0x40 + 0x46 + 0x40 + 0x40 + 0x40 + 0x4A + 0x40 + 0x40 + 0x40 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x10 + 0x17 + 0x14 + 0x16 + 0x12 + 0x10 + 0x12 + 0x14 + 0x13 + 0x12 + 0x10 + 0x12 + 0x12 + 0x10 + 0x11 + 0x10 + 0x10 + 0x10 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x60 + 0x60 + 0x60 + 0x60 + 0x60 + 0x60 + 0x60 + 0x60 + 0x60 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x60 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x30 + 0x30 + 0x30 + 0x30 + 0x00 + 0x30 + 0x30 + 0x18 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + + \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-NZ.xml kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-NZ.xml --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-NZ.xml 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-NZ.xml 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,282 @@ + + + + Sky-NZ + + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x10 + 0x11 + 0x12 + 0x13 + 0x14 + 0x10 + 0x16 + 0x17 + 0x17 + 0x10 + 0x13 + 0x17 + 0x17 + 0x17 + 0x12 + 0x10 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x20 + 0x21 + 0x22 + 0x23 + 0x24 + 0x90 + 0x23 + 0x90 + 0x20 + 0x91 + 0x73 + 0x92 + 0x76 + 0x94 + 0x90 + 0x20 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x30 + 0x31 + 0x33 + 0x33 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x30 + 0x31 + 0x30 + 0x33 + 0x32 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x40 + 0x41 + 0x42 + 0x43 + 0x44 + 0x45 + 0x46 + 0x47 + 0x48 + 0x49 + 0x4A + 0x4B + 0x45 + 0x40 + 0x40 + 0x40 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x50 + 0x51 + 0x52 + 0x53 + 0x54 + 0x55 + 0x50 + 0x50 + 0x54 + 0x55 + 0x50 + 0x50 + 0x50 + 0x50 + 0x50 + 0x50 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x60 + 0x61 + 0x62 + 0x63 + 0x64 + 0x65 + 0x66 + 0x60 + 0x60 + 0x60 + 0x60 + 0x60 + 0x60 + 0x60 + 0x60 + 0x60 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x70 + 0x71 + 0x72 + 0x73 + 0x74 + 0x75 + 0x76 + 0x77 + 0x78 + 0x79 + 0x7A + 0x7B + 0x00 + 0x00 + 0x00 + 0x70 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + + \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-UK.xml kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-UK.xml --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-UK.xml 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-UK.xml 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,282 @@ + + + + Sky-UK + + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0xA6 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x50 + 0x55 + 0x50 + 0x50 + 0x54 + 0x51 + 0x54 + 0x50 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x10 + 0x12 + 0x14 + 0x11 + 0x10 + 0x31 + 0x13 + 0x15 + 0x10 + 0x33 + 0xA5 + 0x90 + 0x7B + 0xA7 + 0xA1 + 0x10 + 0x70 + 0xA0 + 0xA0 + 0x22 + 0x10 + 0x24 + 0xA0 + 0xA3 + 0x75 + 0x66 + 0x65 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x60 + 0x62 + 0x63 + 0x60 + 0x64 + 0x65 + 0x61 + 0x60 + 0x60 + 0x60 + 0x60 + 0x60 + 0x60 + 0x00 + 0x00 + 0x00 + 0x60 + 0x00 + 0x00 + 0x00 + 0x00 + 0x60 + 0x60 + 0x60 + 0x60 + 0x60 + 0x60 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x20 + 0x20 + 0x20 + 0x20 + 0x83 + 0x90 + 0x20 + 0x80 + 0x20 + 0x20 + 0x20 + 0x20 + 0x20 + 0x20 + 0x20 + 0x20 + 0x20 + 0x20 + 0x20 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x10 + 0x12 + 0x10 + 0x10 + 0x14 + 0x10 + 0x10 + 0x10 + 0x13 + 0x11 + 0x13 + 0x16 + 0x10 + 0x10 + 0x12 + 0x17 + 0x13 + 0x18 + 0x12 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x40 + 0x45 + 0x46 + 0x45 + 0x45 + 0x40 + 0x45 + 0x40 + 0x43 + 0x40 + 0x45 + 0x47 + 0x4A + 0x45 + 0x4A + 0x49 + 0x40 + 0x44 + 0x4B + 0x40 + 0x40 + 0x40 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x00 + + \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/data/genres/genreRytecTextMappings/Rytec-UK-Ireland.xml kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/data/genres/genreRytecTextMappings/Rytec-UK-Ireland.xml --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/data/genres/genreRytecTextMappings/Rytec-UK-Ireland.xml 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/data/genres/genreRytecTextMappings/Rytec-UK-Ireland.xml 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,141 @@ + + + + Rytec UK/Ireland + + + General Movie/Drama + Film + Animated Movie/Drama + Thriller + Detective/Thriller + Action + Adventure + Adventure/War + Western + Gangster + Fantasy + Science Fiction + Family + Sitcom + Comedy + TV Drama. Comedy + Drama + Soap/Melodrama/Folkloric + TV Drama + TV Drama. Melodrama + TV Drama. Factual + TV Drama. Crime + TV Drama. Period + Medical Drama + Romance + Crime drama + Historical/Period Drama + Police/Crime Drama + + + News + General News/Current Affairs + Documentary + Documentary. News + Discussion. News + + + Series + Show + Vets/Pets + Wildlife + Property + General Show/Game Show + Game Show + Challenge/Reality Show + Show. Variety Show + Variety Show + Entertainment + Miscellaneous + Talk Show + Show. Talk Show + + + Sport + Live/Sport + General Sports + Football. Sports + Martial Sports + Martial Sports. Sports + Wrestling + + + Children + Educational/Schools Programmes + Animation + Cartoons/Puppets + + + Music + General Music/Ballet/Dance + Music. Folk + Musical + + + General Arts/Culture + Arts/Culture + Arts/Culture. Fine Arts + Religion + + + Social/Political + Social/Political. Famous People + + + Education + Educational + History" + Factual" + General Education/Science/Factual Topics + Science + Educational. Nature + Environment + Technology + Computers/Internet/Gaming + + + Leisure + Leisure. Lifestyle + Travel + Health + Leisure. Health + Medicine/Health + Cookery + Leisure. Cooking + Leisure. Shopping + Advertisement/Shopping + Consumer + + + + Factual Crime + + \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/data/genres/kodiDvbGenres.xml kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/data/genres/kodiDvbGenres.xml --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/data/genres/kodiDvbGenres.xml 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/data/genres/kodiDvbGenres.xml 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,140 @@ + + + + Rytec UK/Ireland + + + + Undefined + + General Movie/Drama + Detective/Thriller + Adventure/Western/War + Science Fiction/Fantasy/Horror + Comedy + Soap/Melodrama/Folkloric + Romance + Serious/Classical/Religious/Historical Movie/Drama + Adult Movie/Drama + + + News/Current Affairs + News/Weather Report + News Magazine + Documentary + Discussion/Interview/Debate + + + Show/Game Show + Game Show/Quiz/Contest + Variety Show + Talk Show + + + Sports + Special Event + Sport Magazine + Football + Tennis/Squash + Team Sports + Athletics + Motor Sport + Water Sport + Winter Sports + Equestrian + Martial Sports + + + Children's/Youth Programmes + Pre-school Children's Programmes + Entertainment Programmes for 6 to 14 + Entertainment Programmes for 10 to 16 + Informational/Educational/School Programme + Cartoons/Puppets + + + Music/Ballet/Dance + Rock/Pop + Serious/Classical Music + Folk/Traditional Music + Jazz + Musical/Opera + Ballet + + + Arts/Culture + Performing Arts + Fine Arts + Religion + Popular Culture/Traditional Arts + Literature + Film/Cinema + Experimental Film/Video + Broadcasting/Press + New Media + Arts/Culture Magazines + Fashion + + + Social/Political/Economics + Magazines/Reports/Documentary + Economics/Social Advisory + Remarkable People + + + Education/Science/Factual + Nature/Animals/Environment + Technology/Natural Sciences + Medicine/Physiology/Psychology + Foreign Countries/Expeditions + Social/Spiritual Sciences + Further Education + Languages + + + Leisure/Hobbies + Tourism/Travel + Handicraft + Motoring + Fitness & Health + Cooking + Advertisement/Shopping + Gardening + + + Special Characteristics + Original Language + Black & White + Unpublished + Live Broadcast + + + Drama + Detective/Thriller + Adventure/Western/War + Science Fiction/Fantasy/Horror + + Comedy + Soap/Melodrama/Folkloric + Romance + Serious/ClassicalReligion/Historical + Adult + + \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/data/showInfo/English-ShowInfo.xml kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/data/showInfo/English-ShowInfo.xml --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/data/showInfo/English-ShowInfo.xml 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/data/showInfo/English-ShowInfo.xml 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,53 @@ + + + + English Show Info + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.af_za/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.af_za/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.af_za/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.af_za/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: af_ZA\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ gasheernaam of IP adres" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Stroom Poort" - msgctxt "#30003" msgid "Username" msgstr "Gebruikersnaam" @@ -32,37 +24,33 @@ msgid "Password" msgstr "Wagwoord" +msgctxt "#30005" +msgid "Connection" +msgstr "Konneksie" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikone" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Reaksie tydverstreke in sekondes" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Ikoon Pad" +msgctxt "#30009" +msgid "Update Interval" +msgstr "Opdateer Interval" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Opdateer Interval in minute" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatiese Tydhouerlys Skoonmaak" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Webkoppelvlak Poort" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap voor kanaal verander (d.w.s. vir Enkel Stemmer bokse)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Vouer vir kanaal data" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Kyk vir boeket opdaterings" +msgid "Update interval" +msgstr "Opdateer interval" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +84,109 @@ msgid "Recording folder on the receiver" msgstr "Opname vouer op die ontvanger" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Stuur Diep Bystand bevel" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Gaan haal slegs een TV boeket" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Boeket" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Gaan haal picons vanaf webkoppelvlak" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Gebruik Secure HTTP (HTTPS)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Stel outomatiese konfigurasie in staat vir lewendige strome" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Behou gids struktuur vir rekords" + +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30035" +msgid "Use picons.eu file format" +msgstr "Gebruik picons.eu lêer formaat" + +msgctxt "#30042" +msgid "Never" +msgstr "Nooit" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Slegs in EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Slegs in opnames" + +msgctxt "#30045" +msgid "Always" +msgstr "Altyd" + +msgctxt "#30051" +msgid "Login" +msgstr "Teken in" + +msgctxt "#30052" +msgid "Misc" +msgstr "Diverse" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Tydskuif" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Tydskuif buffer pad" + +msgctxt "#30063" +msgid "Off" +msgstr "Af" + +msgctxt "#30064" +msgid "On playback" +msgstr "Met terugspeel" + +msgctxt "#30065" +msgid "On pause" +msgstr "Met pouseer" + +msgctxt "#30070" +msgid "Recordings & Timers" +msgstr "Opnames & Tydhouers" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Opnames" + +msgctxt "#30072" +msgid "Timers" +msgstr "Tydhouers" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Outomaties" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Een keer (Geskeduleer deur gids-gebaseerde tydhouer reël)" + +msgctxt "#30421" +msgid "One time (Scheduled by repeating timer rule)" +msgstr "Een keer (Geskeduleer deur herhalende tydhouer reël)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Nie in staat gestel" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Neem op as EPG titel verskil" + +msgctxt "#30432" +msgid "Record if EPG title and short description differs" +msgstr "Neem op as EPG titel en kort beskrywing verskil" + +msgctxt "#30433" +msgid "Record if EPG title and all descriptions differ" +msgstr "Neem op as EPG titel en alle beskrywings verskil" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +195,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Geherkonnekteer aan '%s'" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Tydskuif buffer pad bestaan nie" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.am_et/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.am_et/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.am_et/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.am_et/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -24,14 +24,18 @@ msgid "Password" msgstr "የመግቢያ ቃል" +msgctxt "#30005" +msgid "Connection" +msgstr "ግንኙነት " + +msgctxt "#30006" +msgid "Icons" +msgstr "ምልክቶች " + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "መመለሻ ጊዜ በ ሰከንዶች" -msgctxt "#30008" -msgid "Icon Path" -msgstr "የ ምልክት መንገድ" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "የ ማሻሻያ እረፍት በ ደቂቆች" @@ -40,6 +44,10 @@ msgid "Folder for channeldata" msgstr "ፎልደር ለ ጣቢያዎች ዳታ " +msgctxt "#30015" +msgid "Update interval" +msgstr "የ ማሻሻያ ክፍተት" + msgctxt "#30016" msgid "Check for channel updates" msgstr "የ ጣቢያ ማሻሻያ መፈለጊያ" @@ -64,6 +72,38 @@ msgid "Recordings / Timer" msgstr "የ መቅረጫ / ሰአት" +msgctxt "#30042" +msgid "Never" +msgstr "በፍጹም " + +msgctxt "#30045" +msgid "Always" +msgstr "ሁልጊዜ" + +msgctxt "#30051" +msgid "Login" +msgstr "መግቢያ" + +msgctxt "#30052" +msgid "Misc" +msgstr "የተለያዩ " + +msgctxt "#30063" +msgid "Off" +msgstr "ማጥፊያ " + +msgctxt "#30071" +msgid "Recordings" +msgstr "መቅረጫ " + +msgctxt "#30072" +msgid "Timers" +msgstr "መቁጠሪያ" + +msgctxt "#30430" +msgid "Disabled" +msgstr "ተሰናክሏል " + msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "ግንኙነት ተቋርጧል ከ '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ar_sa/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ar_sa/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ar_sa/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ar_sa/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -24,6 +24,10 @@ msgid "Password" msgstr "كلمة المرور" +msgctxt "#30006" +msgid "Icons" +msgstr "رموز" + msgctxt "#30018" msgid "General" msgstr "عام" @@ -40,6 +44,30 @@ msgid "HTTP" msgstr "HTTP" +msgctxt "#30042" +msgid "Never" +msgstr "أبداً" + +msgctxt "#30045" +msgid "Always" +msgstr "دائما" + +msgctxt "#30051" +msgid "Login" +msgstr "تسجيل الدخول" + +msgctxt "#30063" +msgid "Off" +msgstr "تعطيل" + +msgctxt "#30071" +msgid "Recordings" +msgstr "التسجيلات" + +msgctxt "#30430" +msgid "Disabled" +msgstr "معطلة" + msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "قطع الاتصال من '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.az_az/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.az_az/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.az_az/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.az_az/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,6 +16,14 @@ "Language: az_AZ\n" "Plural-Forms: nplurals=1; plural=0;\n" +msgctxt "#30005" +msgid "Connection" +msgstr "Qoşulma" + +msgctxt "#30006" +msgid "Icons" +msgstr "Piktoqramlar" + msgctxt "#30018" msgid "General" msgstr "Ümumi" @@ -23,3 +31,7 @@ msgctxt "#30019" msgid "Channels" msgstr "Kanallar" + +msgctxt "#30045" +msgid "Always" +msgstr "Həmişə" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.be_by/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.be_by/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.be_by/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.be_by/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: be_BY\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ hostname or IP address" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Streaming Port" - msgctxt "#30003" msgid "Username" msgstr "Username" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Пароль" +msgctxt "#30005" +msgid "Connection" +msgstr "Злучэньне" + +msgctxt "#30006" +msgid "Icons" +msgstr "Значкі" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Response timeout in seconds" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Icon Path" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Update Interval in minutes" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatic Timerlist Cleanup" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Webinterface Port" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap before channelswitch (i.e. for Single Tuner boxes)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Folder for channeldata" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Check for bouquett updates" +msgid "Update interval" +msgstr "Прамежак паміж абнаўленнямі" msgctxt "#30016" msgid "Check for channel updates" @@ -96,17 +80,37 @@ msgid "Recording folder on the receiver" msgstr "Recording folder on the receiver" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Send DeepStandby-Command" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Fetch only one TV bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" +msgctxt "#30042" +msgid "Never" +msgstr "Ніколі" + +msgctxt "#30045" +msgid "Always" +msgstr "Заўжды" + +msgctxt "#30051" +msgid "Login" +msgstr "Login" + +msgctxt "#30063" +msgid "Off" +msgstr "Не" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Recordings" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Аўтаматычна " + +msgctxt "#30430" +msgid "Disabled" +msgstr "Забаронена" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.bg_bg/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.bg_bg/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.bg_bg/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.bg_bg/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: bg_BG\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ хост или IP адрес" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Порт за поточно излъчване" - msgctxt "#30003" msgid "Username" msgstr "Потребител" @@ -32,45 +24,41 @@ msgid "Password" msgstr "Парола" +msgctxt "#30005" +msgid "Connection" +msgstr "Връзка" + +msgctxt "#30006" +msgid "Icons" +msgstr "Иконки" + msgctxt "#30007" msgid "Response timeout in seconds" -msgstr "Време на изчакване на отговор (секунди)" +msgstr "Време на изчакване за отговор (секунди)" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Път до иконите" +msgctxt "#30009" +msgid "Update Interval" +msgstr "Интервал на обновяване" msgctxt "#30010" msgid "Update Interval in minutes" -msgstr "Интервал за обновяване в минути" - -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Автоматично почистване на броячите" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Порт на уеб интерфейса" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Нулиране преди превключване на канал (за едно-тунерни устройства)" +msgstr "Интервал на обновяване (минути)" msgctxt "#30014" msgid "Folder for channeldata" -msgstr "Папка за данните на канала" +msgstr "Папка за данните на каналите" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Провери за обновявания на букетите" +msgid "Update interval" +msgstr "Интервал на обновление" msgctxt "#30016" msgid "Check for channel updates" -msgstr "Проверявай за обновяване на каналите" +msgstr "Проверка за промени по каналите" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" -msgstr "Ползвай само за запис на зададения в DVB път" +msgstr "Използване само на текущия път за запис на устройствата" msgctxt "#30018" msgid "General" @@ -96,30 +84,118 @@ msgid "Recording folder on the receiver" msgstr "Папка за записите на приемника" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Изпращай DeepStandby команда" - msgctxt "#30025" msgid "Fetch only one TV bouquet" -msgstr "Избери само един ТВ букет" +msgstr "Извличане само на един ТВ букет" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "ТВ букет" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Взимай логото на канала от уеб интерфейса" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Ползвай защитена HTTP (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Автоматична настройка на потоците на живо" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Запазване на структурата на папките за записите" + +msgctxt "#30032" +msgid "EPG" +msgstr "Справочник" + +msgctxt "#30035" +msgid "Use picons.eu file format" +msgstr "Използване на файловия форма на picons.eu" + +msgctxt "#30042" +msgid "Never" +msgstr "Никога" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Само в справочника" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Само в записите" + +msgctxt "#30045" +msgid "Always" +msgstr "Винаги" + +msgctxt "#30051" +msgid "Login" +msgstr "Влизане" + +msgctxt "#30052" +msgid "Misc" +msgstr "Разни" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Изместване във времето" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Път до буфера за изместване във времето" + +msgctxt "#30063" +msgid "Off" +msgstr "Изкл." + +msgctxt "#30064" +msgid "On playback" +msgstr "При възпроизвеждане" + +msgctxt "#30065" +msgid "On pause" +msgstr "На пауза" + +msgctxt "#30070" +msgid "Recordings & Timers" +msgstr "Записи и броячи" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Записи" + +msgctxt "#30072" +msgid "Timers" +msgstr " Броячи" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Автоматично" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Еднократен (насрочено чрез правило на брояч)" + +msgctxt "#30421" +msgid "One time (Scheduled by repeating timer rule)" +msgstr "Еднократен (насрочено чрез правило на повтарящ се брояч)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Изключено" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Запис само, ако заглавието в справочника е различно" + +msgctxt "#30432" +msgid "Record if EPG title and short description differs" +msgstr "Запис само, ако заглавието и краткото описание в справочника са различни" + +msgctxt "#30433" +msgid "Record if EPG title and all descriptions differ" +msgstr "Запис само, ако заглавието и всички описания в справочника са различни" msgctxt "#30500" msgid "Disconnected from '%s'" -msgstr "Изключен от '%s'" +msgstr "Връзката с „%s“ се разпадна" msgctxt "#30501" msgid "Reconnected to '%s'" -msgstr "Повторно свързан с '%s'" +msgstr "Отново има връзка с „%s“" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Пътят до буфера за изместване във времето не съществува" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.bs_ba/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.bs_ba/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.bs_ba/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.bs_ba/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -24,6 +24,10 @@ msgid "Password" msgstr "Lozinka" +msgctxt "#30006" +msgid "Icons" +msgstr "Ikone" + msgctxt "#30018" msgid "General" msgstr "Opšte" @@ -35,3 +39,23 @@ msgctxt "#30021" msgid "HTTP" msgstr "HTTP" + +msgctxt "#30042" +msgid "Never" +msgstr "Nikada" + +msgctxt "#30045" +msgid "Always" +msgstr "Uvijek" + +msgctxt "#30063" +msgid "Off" +msgstr "Isklj." + +msgctxt "#30071" +msgid "Recordings" +msgstr "Snimci" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Onemogućeno" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ca_es/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ca_es/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ca_es/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ca_es/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: ca_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Nom d'amfitrió o IP de VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Port de la transmissió en línia" - msgctxt "#30003" msgid "Username" msgstr "Nom d'usuari" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Contrasenya" +msgctxt "#30005" +msgid "Connection" +msgstr "Connexió" + +msgctxt "#30006" +msgid "Icons" +msgstr "Icones" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Temps d'expiració de la resposta en segons" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Camí a la icona" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Interval d'actualització en minuts" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Neteja automàtica de Timerlist" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Port de la interfície web" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap abans de canviar de canal (és a dir, per a les caixes amb solament un sintonitzador)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Carpeta pel canal de dades" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Comprova si hi ha actualitzacions del paquet de TV" +msgid "Update interval" +msgstr "Interval d'actualització" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,73 @@ msgid "Recording folder on the receiver" msgstr "Carpeta d'enregistrament en el receptor" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Enviar ordre DeepStandby" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Obté només un paquet de TV" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "Paquet TV" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Obté els picons des de la interfície web" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Utilitza HTTP segur (https)" +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30042" +msgid "Never" +msgstr "Mai" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Solament a l'EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Solament als enregistraments" + +msgctxt "#30045" +msgid "Always" +msgstr "Sempre" + +msgctxt "#30051" +msgid "Login" +msgstr "Autenticació" + +msgctxt "#30052" +msgid "Misc" +msgstr "Altres" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Salts en el temps" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Camí a la memòria intermèdia dels salts en el temps" + +msgctxt "#30063" +msgid "Off" +msgstr "Apagat" + +msgctxt "#30064" +msgid "On playback" +msgstr "Amb la reproducció" + +msgctxt "#30065" +msgid "On pause" +msgstr "Amb la pausa" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Enregistraments" + +msgctxt "#30072" +msgid "Timers" +msgstr "Temporitzadors" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automàtic" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Inhabilitat" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.cs_cz/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.cs_cz/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.cs_cz/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.cs_cz/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: cs_CZ\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Název hostitele nebo adresa IP VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Port streamování" - msgctxt "#30003" msgid "Username" msgstr "Uživatelské jméno" @@ -32,37 +24,33 @@ msgid "Password" msgstr "Heslo" +msgctxt "#30005" +msgid "Connection" +msgstr "Spojení" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikony" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Časový limit odpovědi v sekundách" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Cesta k ikonám" +msgctxt "#30009" +msgid "Update Interval" +msgstr "Interval aktualizace" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Interval aktualizace v minutách" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatické čištění seznamu časovačů" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Port webového rozhraní" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Přepnout před přepnutím kanálu (např. pro jednotunerové přijímače)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Složka pro data kanálů" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Kontrolovat aktualizace skupin oblíbených programů" +msgid "Update interval" +msgstr "Interval aktualizace" msgctxt "#30016" msgid "Check for channel updates" @@ -96,30 +84,122 @@ msgid "Recording folder on the receiver" msgstr "Složka s nahrávkami na přijímači" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Odeslat příkaz úsporného uspání" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Načíst pouze jednu skupinu oblíbených programů" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "Skupina oblíbených programů" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Načíst pikony z webového rozhraní" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Použít zabezpečené HTTP (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Povolit automatickou konfiguraci pro živé datové proudy" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Zachovat strukturu složky pro nahrávky" + +msgctxt "#30032" +msgid "EPG" +msgstr "Televizní program" + +msgctxt "#30035" +msgid "Use picons.eu file format" +msgstr "Používat formát souboru picons.eu" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Streamování" + +msgctxt "#30042" +msgid "Never" +msgstr "Nikdy" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Pouze v televizním programu" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Pouze v nahrávkách" + +msgctxt "#30045" +msgid "Always" +msgstr "Vždy" + +msgctxt "#30051" +msgid "Login" +msgstr "Přihlášení" + +msgctxt "#30052" +msgid "Misc" +msgstr "Různé" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Časový posun" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Popis umístění vyrovnávací paměti časového posunu" + +msgctxt "#30063" +msgid "Off" +msgstr "Vypnout" + +msgctxt "#30064" +msgid "On playback" +msgstr "Při přehrávání" + +msgctxt "#30065" +msgid "On pause" +msgstr "Při pozastavení" + +msgctxt "#30070" +msgid "Recordings & Timers" +msgstr "Nahrávky a časovače" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Nahrávky" + +msgctxt "#30072" +msgid "Timers" +msgstr "Časovače" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatické" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Jednou (naplánováno pravidlem časovače)" + +msgctxt "#30421" +msgid "One time (Scheduled by repeating timer rule)" +msgstr "Jednou (Naplánováno opakujícím se pravidlem časovače)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Zakázáno" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Nahrávat, pokud se liší název televizního programu" + +msgctxt "#30432" +msgid "Record if EPG title and short description differs" +msgstr "Nahrávat, pokud se liší název a krátký popis televizního programu" + +msgctxt "#30433" +msgid "Record if EPG title and all descriptions differ" +msgstr "Nahrávat, pokud se liší název a všechny popisy televizního programu" msgctxt "#30500" msgid "Disconnected from '%s'" -msgstr "Odpojeno od '%s'" +msgstr "Odpojeno od „%s“" msgctxt "#30501" msgid "Reconnected to '%s'" -msgstr "Znovu připojeno k '%s'" +msgstr "Znovu připojeno k „%s“" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Popisované umístění pro vyrovnávací paměť časového posunu neexistuje" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.cy_gb/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.cy_gb/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.cy_gb/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.cy_gb/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: cy_GB\n" "Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Enw gwesteiwr neu gyfeiriad IP VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Porth Ffrydio" - msgctxt "#30003" msgid "Username" msgstr "Enw defnyddiwr" @@ -32,38 +24,26 @@ msgid "Password" msgstr "Cyfrinair" +msgctxt "#30005" +msgid "Connection" +msgstr "Cysylltiad" + +msgctxt "#30006" +msgid "Icons" +msgstr "Eiconau" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Ymateb amser allan mewn eiliadau" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Llwybr Eiconau" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Cyfnod diweddaru mewn munudau" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Glanhau Amserlen yn Awtomatig" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Porth Rhyngwyneb Gwe" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Sapio cyn newid sianel (h.y. ar gyfer blychau Tiwniwr Unigol)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Ffolder ar gyfer data sianel" -msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Gwirio am ddiweddariad bouquett" - msgctxt "#30016" msgid "Check for channel updates" msgstr "Gwirio am ddiweddariad sianeli" @@ -96,25 +76,45 @@ msgid "Recording folder on the receiver" msgstr "Ffolder recordio ar y derbynnydd" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Anfon DeepStandby-Command" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Estyn dim ond un bouquet Teledu" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Estyn piconau o'r rhyngwyneb gwe" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Defnyddiwch HTTP (https) Diogel" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Galluogi ffurfweddu awtomatig ar gyfer ffrydio'n fyw" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Cadw strwythur y ffolderi ar gyfer recordiadau" + +msgctxt "#30042" +msgid "Never" +msgstr "Byth" + +msgctxt "#30045" +msgid "Always" +msgstr "Bob tro" + +msgctxt "#30051" +msgid "Login" +msgstr "Mewngofnodi" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Llwybr byffro Symud Amser" + +msgctxt "#30063" +msgid "Off" +msgstr "Diffodd" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Recordiadau" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Analluogwyd" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.da_dk/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.da_dk/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.da_dk/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.da_dk/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: da_DK\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ værtsnavn eller IP-adresse" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Streamport" - msgctxt "#30003" msgid "Username" msgstr "Brugernavn" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Adgangskode" +msgctxt "#30005" +msgid "Connection" +msgstr "Forbindelse" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikoner" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Tidsfrist for tilbagemelding i sekunder" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Ikon-sti" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Opdateringsinterval i minutter" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatisk oprydning af Timerliste" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Web-grænsefladeport" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap før kanalskift (fx. for enkelttuner-bokse)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Mappe til kanaldata" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Søg efter buketopdateringer" +msgid "Update interval" +msgstr "Opdateringsinterval" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,73 @@ msgid "Recording folder on the receiver" msgstr "Optagelsesmappe på modtageren" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Send \"DeepStandby\" kommando" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Hent kun én TV-buket" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-buket" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Hent picons fra webinterfacet" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Brug sikker HTTP (https)" +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Streaming" + +msgctxt "#30042" +msgid "Never" +msgstr "Aldrig" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Kun i EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Kun i optagelser" + +msgctxt "#30045" +msgid "Always" +msgstr "Altid" + +msgctxt "#30051" +msgid "Login" +msgstr "Brugernavn" + +msgctxt "#30052" +msgid "Misc" +msgstr "Diverse" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Tidsforskydning" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Stien til tidsforskydningsbuffer" + +msgctxt "#30063" +msgid "Off" +msgstr "Fra" + +msgctxt "#30065" +msgid "On pause" +msgstr "Sat på pause" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Optagelser" + +msgctxt "#30072" +msgid "Timers" +msgstr "Timeroptagelser" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatisk" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Deaktiveret" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.de_de/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.de_de/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.de_de/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.de_de/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: de_DE\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ Hostname oder IP-Adresse" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Streaming Port" - msgctxt "#30003" msgid "Username" msgstr "Benutzername" @@ -32,37 +24,33 @@ msgid "Password" msgstr "Passwort" +msgctxt "#30005" +msgid "Connection" +msgstr "Verbindung" + +msgctxt "#30006" +msgid "Icons" +msgstr "Symbole" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Antwortzeitüberschreitung in Sekunden" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Icon-Pfad" +msgctxt "#30009" +msgid "Update Interval" +msgstr "Aktualisierungsintervall" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Aktualisierungsintervall in Minuten" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Entferne abgeschlossene Timer automatisch" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Weboberfläche Port" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Umschalten auf Receiver (z.B. bei SingleTuner Receivern)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Speicherort für Kanaldaten" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Überprüfe auf Bouquettaktualisierungen" +msgid "Update interval" +msgstr "Aktualisierungsintervall" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +84,113 @@ msgid "Recording folder on the receiver" msgstr "Aufnahmeverzeichnis auf dem Receiver" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Sende DeepStandby-Befehl" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Lade nur ein TV-Bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Lade Picons aus der Weboberfläche" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Sicheres HTTP (https) verwenden" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Aktiviere die Autokonfiguration für Liveübertragungen" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Behalte die Ordnerstruktur für Einträge" + +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30035" +msgid "Use picons.eu file format" +msgstr "Picons.eu Dateiformat verwenden" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Streaming" + +msgctxt "#30042" +msgid "Never" +msgstr "Nie" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Nur im EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Nur in Aufnahmen" + +msgctxt "#30045" +msgid "Always" +msgstr "Immer" + +msgctxt "#30051" +msgid "Login" +msgstr "Anmeldung" + +msgctxt "#30052" +msgid "Misc" +msgstr "verschiedenes" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Timeshift" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Timeshift Puffer-Pfad" + +msgctxt "#30063" +msgid "Off" +msgstr "Inaktiv" + +msgctxt "#30064" +msgid "On playback" +msgstr "Beim Abspielen" + +msgctxt "#30065" +msgid "On pause" +msgstr "Während der Pause" + +msgctxt "#30070" +msgid "Recordings & Timers" +msgstr "Aufnahmen & Timer" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Aufnahmen" + +msgctxt "#30072" +msgid "Timers" +msgstr "Timer" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatisch" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Einmalig (geplant nach guide-basierter Zeitregel)" + +msgctxt "#30421" +msgid "One time (Scheduled by repeating timer rule)" +msgstr "Einmalig (geplant durch Wiederholung der Timerregel)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Ausschalten" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Aufnahme bei abweichenden EPG-Titel" + +msgctxt "#30432" +msgid "Record if EPG title and short description differs" +msgstr "Aufnahme, wenn EPG-Titel und Kurzbeschreibung voneinander abweichen." + +msgctxt "#30433" +msgid "Record if EPG title and all descriptions differ" +msgstr "Aufnahme, wenn EPG-Titel und alle Beschreibung voneinander abweichen." msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +199,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Verbindung zu '%s' wiederhergestellt" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Pfad für den Zeitversatz Puffer existiert nicht" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.el_gr/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.el_gr/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.el_gr/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.el_gr/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: el_GR\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Όνομα Υπολογιστή ή διεύθυνση IP του VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Θύρα Ροής" - msgctxt "#30003" msgid "Username" msgstr "Όνομα χρήστη" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Κωδικός πρόσβασης" +msgctxt "#30005" +msgid "Connection" +msgstr "Σύνδεση" + +msgctxt "#30006" +msgid "Icons" +msgstr "Εικονίδια" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Χρόνος απόκρισης σε δευτερόλεπτα" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Διαδρομή Εικονιδίου" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Διάστημα Ενημέρωσης σε λεπτά" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Εκκαθάριση Αυτόματης Λίστας Χρονοδιακοπτών" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Θύρα Διεπαφής Ιστού" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap πριν την αλλαγή καναλιού (π.χ. για αποκωδικοποιητές Single Tuner)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Φάκελος για δεδομένα καναλιών" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Έλεγχος για ενημερώσεις μπουκέτων" +msgid "Update interval" +msgstr "Διάστημα ενημέρωσης " msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,61 @@ msgid "Recording folder on the receiver" msgstr "Φάκελος εγγραφών στο δέκτη" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Αποστολή Εντολής DeepStandby" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Λήψη μόνο ενός μπουκέτου TV" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "Μπουκέτο TV" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Λήψη εικονιδίων από τη διεπαφή ιστού" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Χρήση Ασφαλούς HTTP (https)" +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30042" +msgid "Never" +msgstr "Ποτέ" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Μόνο στο EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Μόνο στις εγγραφές" + +msgctxt "#30045" +msgid "Always" +msgstr "Πάντα" + +msgctxt "#30051" +msgid "Login" +msgstr "Σύνδεση" + +msgctxt "#30052" +msgid "Misc" +msgstr "Διάφορα" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Timeshift" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Διαδρομή προσωρινής αποθήκευσης Timeshift" + +msgctxt "#30063" +msgid "Off" +msgstr "Ανενεργή" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Εγγραφές" + +msgctxt "#30072" +msgid "Timers" +msgstr "Χρονοδιακόπτες" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Ανενεργή" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.en_au/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.en_au/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.en_au/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.en_au/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: en_AU\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ hostname or IP address" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Streaming Port" - msgctxt "#30003" msgid "Username" msgstr "Username" @@ -32,38 +24,26 @@ msgid "Password" msgstr "Password" +msgctxt "#30005" +msgid "Connection" +msgstr "Connection" + +msgctxt "#30006" +msgid "Icons" +msgstr "Icons" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Response timeout in seconds" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Icon Path" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Update Interval in minutes" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatic Timerlist Cleanup" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Webinterface Port" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap before channelswitch (i.e. for Single Tuner boxes)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Folder for channeldata" -msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Check for bouquett updates" - msgctxt "#30016" msgid "Check for channel updates" msgstr "Check for channel updates" @@ -96,25 +76,37 @@ msgid "Recording folder on the receiver" msgstr "Recording folder on the receiver" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Send DeepStandby-Command" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Fetch only one TV bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Fetch picons from webinterface" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Use Secure HTTP (https)" +msgctxt "#30042" +msgid "Never" +msgstr "Never" + +msgctxt "#30045" +msgid "Always" +msgstr "Always" + +msgctxt "#30051" +msgid "Login" +msgstr "Login" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Timeshift buffer path" + +msgctxt "#30063" +msgid "Off" +msgstr "Off" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Recordings" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Disabled" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.en_gb/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.en_gb/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.en_gb/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.en_gb/strings.po 2018-11-18 11:16:20.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -19,13 +19,13 @@ #settings labels msgctxt "#30000" -msgid "VU+ hostname or IP address" +msgid "Enigma2 hostname or IP address" msgstr "" #empty string with id 30001 msgctxt "#30002" -msgid "Streaming Port" +msgid "Streaming port" msgstr "" msgctxt "#30003" @@ -36,32 +36,40 @@ msgid "Password" msgstr "" -#empty strings from id 30005 to 30006 +msgctxt "#30005" +msgid "Connection" +msgstr "" + +msgctxt "#30006" +msgid "Icons" +msgstr "" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "" msgctxt "#30008" -msgid "Icon Path" +msgid "Icon path" msgstr "" -#empty string with id 30009 +msgctxt "#30009" +msgid "Update Interval" +msgstr "" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "" msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" +msgid "Automatic timerlist cleanup" msgstr "" msgctxt "#30012" -msgid "Webinterface Port" +msgid "Web interface port" msgstr "" msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" +msgid "Zap before channelswitch (i.e. for single tuner boxes)" msgstr "" msgctxt "#30014" @@ -69,7 +77,7 @@ msgstr "" msgctxt "#30015" -msgid "Check for bouquett updates" +msgid "Update interval" msgstr "" msgctxt "#30016" @@ -105,26 +113,356 @@ msgstr "" msgctxt "#30024" -msgid "Send DeepStandby-Command" +msgid "Send powerstate mode on addon exit" msgstr "" msgctxt "#30025" -msgid "Fetch only one TV bouquet" +msgid "TV bouquet fetch mode" msgstr "" msgctxt "#30026" -msgid "TV-Bouquet" +msgid "TV bouquet" msgstr "" msgctxt "#30027" -msgid "Fetch picons from webinterface" +msgid "Fetch picons from web interface" msgstr "" msgctxt "#30028" -msgid "Use Secure HTTP (https)" +msgid "Use secure HTTP (https)" +msgstr "" + +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "" + +msgctxt "#30031" +msgid "Seasons and Episodes" +msgstr "" + +msgctxt "#30032" +msgid "EPG" +msgstr "" + +msgctxt "#30033" +msgid "Extract season, episode and year info where possible" +msgstr "" + +msgctxt "#30034" +msgid "Enable autotimers" +msgstr "" + +msgctxt "#30035" +msgid "Use picons.eu file format" +msgstr "" + +msgctxt "#30036" +msgid "Enable generate repeat timers" +msgstr "" + +msgctxt "#30037" +msgid "Log missing genre text mappings" +msgstr "" + +msgctxt "#30038" +msgid "Web Interface" +msgstr "" + +msgctxt "#30039" +msgid "Streaming" +msgstr "" + +msgctxt "#30040" +msgid "Put outline (e.g. sub-title) before plot" +msgstr "" + +msgctxt "#30041" +msgid "Stream read chunk size" +msgstr "" + +msgctxt "#30042" +msgid "Never" +msgstr "" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "" + +msgctxt "#30045" +msgid "Always" +msgstr "" + +msgctxt "#30046" +msgid "Extract show info file" +msgstr "" + +msgctxt "#30047" +msgid "Rytec genre text Mappings" +msgstr "" + +msgctxt "#30048" +msgid "Enable Rytec genre text mappings" +msgstr "" + +msgctxt "#30049" +msgid "Rytec genre text mappings file" +msgstr "" + +msgctxt "#30050" +msgid "Custom live TV timeout (0 to use default)" +msgstr "" + +msgctxt "#30051" +msgid "Login" +msgstr "" + +msgctxt "#30052" +msgid "Misc" +msgstr "" + +msgctxt "#30053" +msgid "Genre ID Mappings" +msgstr "" + +msgctxt "#30054" +msgid "Enable genre ID Mappings" +msgstr "" + +msgctxt "#30055" +msgid "Genre ID mappings file" +msgstr "" + +msgctxt "#30056" +msgid "TV" +msgstr "" + +msgctxt "#30057" +msgid "Radio" +msgstr "" + +msgctxt "#30058" +msgid "Radio bouquet fetch mode" +msgstr "" + +msgctxt "#30059" +msgid "Radio bouquet" +msgstr "" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "" + +msgctxt "#30061" +msgid "Enable timeshift" +msgstr "" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "" + +msgctxt "#30063" +msgid "Off" +msgstr "" + +msgctxt "#30064" +msgid "On playback" +msgstr "" + +msgctxt "#30065" +msgid "On pause" +msgstr "" + +msgctxt "#30066" +msgid "Use secure HTTP (https) for streams" +msgstr "" + +msgctxt "#30067" +msgid "Use login for streams" +msgstr "" + +msgctxt "#30068" +msgid "Fetch TV favourites bouquet" +msgstr "" + +msgctxt "#30069" +msgid "Fetch radio favourites bouquet" msgstr "" -#empty strings from id 30029 to 30499 +msgctxt "#30070" +msgid "Recordings & Timers" +msgstr "" + +msgctxt "#30071" +msgid "Recordings" +msgstr "" + +msgctxt "#30072" +msgid "Timers" +msgstr "" + +msgctxt "#30073" +msgid "Number of repeat timers to generate" +msgstr "" + +msgctxt "#30074" +msgid "All bouquets" +msgstr "" + +msgctxt "#30075" +msgid "Only one bouquet" +msgstr "" + +msgctxt "#30076" +msgid "As first bouquet" +msgstr "" + +msgctxt "#30077" +msgid "As last bouquet" +msgstr "" + +msgctxt "#30078" +msgid "Favourites group" +msgstr "" + +msgctxt "#30079" +msgid "Favourites (TV)" +msgstr "" + +msgctxt "#30080" +msgid "Favourites (Radio)" +msgstr "" + +msgctxt "#30081" +msgid "unknown" +msgstr "" + +msgctxt "#30082" +msgid " (Not connected!)" +msgstr "" + +msgctxt "#30083" +msgid "addon error" +msgstr "" + +msgctxt "#30084" +msgid "Enigma2 Media Server" +msgstr "" + +msgctxt "#30085" +msgid "OK" +msgstr "" + +msgctxt "#30086" +msgid "Backend" +msgstr "" + +msgctxt "#30087" +msgid "Recording Padding" +msgstr "" + +msgctxt "#30088" +msgid "Global start padding" +msgstr "" + +msgctxt "#30089" +msgid "Global end padding" +msgstr "" + +msgctxt "#30090" +msgid "Device Info" +msgstr "" + +msgctxt "#30091" +msgid "WebIf version" +msgstr "" + +msgctxt "#30092" +msgid "AutoTimer tag in timer tags" +msgstr "" + +msgctxt "#30093" +msgid "AutoTimer name in timer tags" +msgstr "" + +msgctxt "#30094" +msgid "N/A" +msgstr "" + +msgctxt "#30095" +msgid "True" +msgstr "" + +msgctxt "#30096" +msgid "False" +msgstr "" + +msgctxt "#30097" +msgid "Standby" +msgstr "" + +msgctxt "#30098" +msgid "Deep standby" +msgstr "" + +msgctxt "#30099" +msgid "Wakeup, then standby" +msgstr "" + +msgctxt "#30100" +msgid "Update mode" +msgstr "" + +msgctxt "#30101" +msgid "Timers and recordings" +msgstr "" + +msgctxt "#30102" +msgid "Timers only" +msgstr "" + +#empty strings from id 30103 to 30409 + +msgctxt "#30410" +msgid "Automatic" +msgstr "" + +#empty strings from id 30411 to 30419 + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "" + +msgctxt "#30421" +msgid "One time (Scheduled by repeating timer rule)" +msgstr "" + +#empty strings from id 30422 to 30429 + +msgctxt "#30430" +msgid "Disabled" +msgstr "" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "" + +msgctxt "#30432" +msgid "Record if EPG title and short description differs" +msgstr "" + +msgctxt "#30433" +msgid "Record if EPG title and all descriptions differ" +msgstr "" + +#empty strings from id 30434 to 30499 #notifications msgctxt "#30500" @@ -134,3 +472,9 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "" + +#empty strings from id 30502 to 30513 + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.en_nz/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.en_nz/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.en_nz/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.en_nz/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: en_NZ\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ hostname or IP address" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Streaming Port" - msgctxt "#30003" msgid "Username" msgstr "Username" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Password" +msgctxt "#30005" +msgid "Connection" +msgstr "Connection" + +msgctxt "#30006" +msgid "Icons" +msgstr "Icons" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Response timeout in seconds" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Icon Path" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Update Interval in minutes" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatic Timerlist Cleanup" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Webinterface Port" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap before channelswitch (i.e. for Single Tuner boxes)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Folder for channeldata" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Check for bouquet updates" +msgid "Update interval" +msgstr "Update interval" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,77 @@ msgid "Recording folder on the receiver" msgstr "Recording folder on the receiver" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Send DeepStandby-Command" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Fetch only one TV bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Fetch picons from webinterface" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Use Secure HTTP (https)" +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Streaming" + +msgctxt "#30042" +msgid "Never" +msgstr "Never" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "In EPG only" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "In recordings only" + +msgctxt "#30045" +msgid "Always" +msgstr "Always" + +msgctxt "#30051" +msgid "Login" +msgstr "Login" + +msgctxt "#30052" +msgid "Misc" +msgstr "Misc" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Timeshift" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Timeshift buffer path" + +msgctxt "#30063" +msgid "Off" +msgstr "Off" + +msgctxt "#30064" +msgid "On playback" +msgstr "On playback" + +msgctxt "#30065" +msgid "On pause" +msgstr "On pause" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Recordings" + +msgctxt "#30072" +msgid "Timers" +msgstr "Timers" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatic" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Disabled" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.en_us/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.en_us/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.en_us/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.en_us/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: en_US\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ hostname or IP address" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Streaming Port" - msgctxt "#30003" msgid "Username" msgstr "Username" @@ -32,37 +24,33 @@ msgid "Password" msgstr "Password" +msgctxt "#30005" +msgid "Connection" +msgstr "Connection" + +msgctxt "#30006" +msgid "Icons" +msgstr "Icons" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Response timeout in seconds" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Icon Path" +msgctxt "#30009" +msgid "Update Interval" +msgstr "Update Interval" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Update Interval in minutes" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatic Timerlist Cleanup" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Webinterface Port" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap before channelswitch (i.e. for Single Tuner boxes)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Folder for channeldata" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Check for bouquet updates" +msgid "Update interval" +msgstr "Update interval" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +84,109 @@ msgid "Recording folder on the receiver" msgstr "Recording folder on the receiver" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Send DeepStandby-Command" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Fetch only one TV bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Fetch picons from webinterface" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Use Secure HTTP (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Enable automatic configuration for live streams" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Keep folder structure for records" + +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30035" +msgid "Use picons.eu file format" +msgstr "Use picons.eu file format" + +msgctxt "#30042" +msgid "Never" +msgstr "Never" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "In EPG only" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "In recordings only" + +msgctxt "#30045" +msgid "Always" +msgstr "Always" + +msgctxt "#30051" +msgid "Login" +msgstr "Login" + +msgctxt "#30052" +msgid "Misc" +msgstr "Misc" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Timeshift" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Timeshift buffer path" + +msgctxt "#30063" +msgid "Off" +msgstr "Off" + +msgctxt "#30064" +msgid "On playback" +msgstr "On playback" + +msgctxt "#30065" +msgid "On pause" +msgstr "On pause" + +msgctxt "#30070" +msgid "Recordings & Timers" +msgstr "Recordings & Timers" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Recordings" + +msgctxt "#30072" +msgid "Timers" +msgstr "Timers" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatic" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "One time (Scheduled by guide-based timer rule)" + +msgctxt "#30421" +msgid "One time (Scheduled by repeating timer rule)" +msgstr "One time (Scheduled by repeating timer rule)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Disabled" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Record if EPG title differs" + +msgctxt "#30432" +msgid "Record if EPG title and short description differs" +msgstr "Record if EPG title and short description differs" + +msgctxt "#30433" +msgid "Record if EPG title and all descriptions differ" +msgstr "Record if EPG title and all descriptions differ" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +195,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Reconnected to '%s'" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Timeshift buffer path does not exist" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.eo/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.eo/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.eo/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.eo/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -27,3 +27,15 @@ msgctxt "#30018" msgid "General" msgstr "Generalo" + +msgctxt "#30042" +msgid "Never" +msgstr "Never" + +msgctxt "#30063" +msgid "Off" +msgstr "Off" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Disabled" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.es_ar/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.es_ar/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.es_ar/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.es_ar/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: es_AR\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Nombre o dirección IP de VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Puerto streaming" - msgctxt "#30003" msgid "Username" msgstr "Usuario" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Contraseña" +msgctxt "#30005" +msgid "Connection" +msgstr "Conexión" + +msgctxt "#30006" +msgid "Icons" +msgstr "Iconos" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Tiempo de espera de respuesta en segundos" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Ruta del icono" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Intervalo de actualización en minutos" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Limpieza automática de Timerlist" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Puerto interface web" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap antes de cambiar de canal (es decir, para las cajas de solo un sintonizador)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Carpeta para canales" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Buscar actualizaciones de bouquett" +msgid "Update interval" +msgstr "Intervalo de actualización" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,57 @@ msgid "Recording folder on the receiver" msgstr "Carpeta de grabaciones en el receptor" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Envíe el comando DeepStandby" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Buscar sólo TV bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Obtener picons de la interfaz web" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Usar HTTP seguro (https)" +msgctxt "#30042" +msgid "Never" +msgstr "Nunca" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Sólo en EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Sólo en grabaciones" + +msgctxt "#30045" +msgid "Always" +msgstr "Siempre" + +msgctxt "#30051" +msgid "Login" +msgstr "Ingresar" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Timeshift" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Ruta del buffer de Timeshift" + +msgctxt "#30063" +msgid "Off" +msgstr "Desactivado" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Grabaciones" + +msgctxt "#30072" +msgid "Timers" +msgstr "Temporizadores" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automático" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Deshabilitado" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.es_es/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.es_es/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.es_es/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.es_es/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: es_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Nombre o dirección IP de VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Puerto streaming" - msgctxt "#30003" msgid "Username" msgstr "Usuario" @@ -32,37 +24,33 @@ msgid "Password" msgstr "Contraseña" +msgctxt "#30005" +msgid "Connection" +msgstr "Conexión" + +msgctxt "#30006" +msgid "Icons" +msgstr "Iconos" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Tiempo de espera de respuesta en segundos" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Ruta del icono" +msgctxt "#30009" +msgid "Update Interval" +msgstr "Intervalo de Actualización" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Intervalo de actualización en minutos" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Limpieza automática de temporizadores" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Puerto interface web" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap antes de cambiar de canal (es decir, para las cajas de solo un sintonizador)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Carpeta para canales" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Buscar actualizaciones de bouquett" +msgid "Update interval" +msgstr "Intervalo de actualización" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +84,113 @@ msgid "Recording folder on the receiver" msgstr "Carpeta de grabaciones en el receptor" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Enviar comando DeepStandby" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Buscar sólo un bouquet de TV" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "Bouquet de TV" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Obtener picons de la interfaz web" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Usar HTTP seguro (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Actviar configuración automática para emisiones en directo" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Mantener estructura de carpetas para las grabaciones" + +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30035" +msgid "Use picons.eu file format" +msgstr "Usar formato de archivo picons.eu" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Streaming" + +msgctxt "#30042" +msgid "Never" +msgstr "Nunca" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Solo con EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Solo gravaciones" + +msgctxt "#30045" +msgid "Always" +msgstr "Siempre" + +msgctxt "#30051" +msgid "Login" +msgstr "Inicio de sesión" + +msgctxt "#30052" +msgid "Misc" +msgstr "Otros" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Timeshift" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Ruta del buffer de Timeshift" + +msgctxt "#30063" +msgid "Off" +msgstr "Desactivado" + +msgctxt "#30064" +msgid "On playback" +msgstr "Reproduciendo" + +msgctxt "#30065" +msgid "On pause" +msgstr "Pausado" + +msgctxt "#30070" +msgid "Recordings & Timers" +msgstr "Grabaciones y Programaciones" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Grabaciones" + +msgctxt "#30072" +msgid "Timers" +msgstr "Programaciones" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automático" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Una vez (Programado por una regla basada en la guía)" + +msgctxt "#30421" +msgid "One time (Scheduled by repeating timer rule)" +msgstr "Una vez (Programada para repetir por regla de tiempo)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Desactivado" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Grabar si el título en EPG difiere" + +msgctxt "#30432" +msgid "Record if EPG title and short description differs" +msgstr "Grabar aunque el título y la descripción corta en EPG difiera" + +msgctxt "#30433" +msgid "Record if EPG title and all descriptions differ" +msgstr "Grabar aunque el título y cualquier descripción en EPG difiera" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +199,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Reconectado a '%s'" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "La ruta para el buffer de timeshift no existe" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.es_mx/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.es_mx/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.es_mx/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.es_mx/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: es_MX\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Nombre de host o dirección IP VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Puerto de transmisión" - msgctxt "#30003" msgid "Username" msgstr "Usuario" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Contraseña" +msgctxt "#30005" +msgid "Connection" +msgstr "Conexión" + +msgctxt "#30006" +msgid "Icons" +msgstr "Iconos" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Tiempo de respuesta en segundos" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Ruta del icono" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Intervalo de actualización en minutos" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Limpieza automática de la lista de temporizadores" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Puerto interface web" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap antes del conmutador de canales (ej., para las cajas de sintonizador simple)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Carpeta de datos de canal" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Revise las actualizaciones de bouquet" +msgid "Update interval" +msgstr "Intervalo de actualización." msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,73 @@ msgid "Recording folder on the receiver" msgstr "Carpeta de grabación en el receptor" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Enviar comando DeepStandby" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Obtener sólo un ramo de TV" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Obtener iconos de la interfaz web" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Use HTTP seguro (https)" +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30042" +msgid "Never" +msgstr "Nunca" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Sólo en EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "solo en grabaciones" + +msgctxt "#30045" +msgid "Always" +msgstr "Siempre" + +msgctxt "#30051" +msgid "Login" +msgstr "iniciar sesión" + +msgctxt "#30052" +msgid "Misc" +msgstr "Misc" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Cambio de hora" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Ruta del buffer de TimeShift" + +msgctxt "#30063" +msgid "Off" +msgstr "apagado" + +msgctxt "#30064" +msgid "On playback" +msgstr "En reproducción" + +msgctxt "#30065" +msgid "On pause" +msgstr "En pausa" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Grabaciones" + +msgctxt "#30072" +msgid "Timers" +msgstr "Temporizadores" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automático" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Deshabilitado" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.et_ee/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.et_ee/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.et_ee/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.et_ee/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: et_EE\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ hosti nimi või IP aadress" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Voo port" - msgctxt "#30003" msgid "Username" msgstr "Kasutajanimi" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Salasõna" +msgctxt "#30005" +msgid "Connection" +msgstr "Ühendus" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikoonid" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Vastuse aegumine sekundites" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Ikooni asukoht" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Uuendamise intervall minutites" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Ajamõõtja loendi automaatne puhastus" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Veebiliidese port" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Enne kanali vahetamist kustutage (nt üksiktuunerite puhul)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Kanali info kaust" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Kontrollige kanalite uuendusi" +msgid "Update interval" +msgstr "Uuendamise vahemik" msgctxt "#30016" msgid "Check for channel updates" @@ -96,6 +80,38 @@ msgid "Recording folder on the receiver" msgstr "Salvestus kaust vastuvõtjas" +msgctxt "#30042" +msgid "Never" +msgstr "Mitte kunagi" + +msgctxt "#30045" +msgid "Always" +msgstr "Alati" + +msgctxt "#30051" +msgid "Login" +msgstr "Logi sisse" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Ajanihke puhverduse rada" + +msgctxt "#30063" +msgid "Off" +msgstr "Väljas" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Salvestused" + +msgctxt "#30072" +msgid "Timers" +msgstr "Taimerid" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Keelatud" + msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "'%s' lahti ühendatud" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.eu_es/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.eu_es/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.eu_es/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.eu_es/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -24,9 +24,13 @@ msgid "Password" msgstr "Pasahitza" -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Webinterface-aren Portua" +msgctxt "#30006" +msgid "Icons" +msgstr "Ikonoak" + +msgctxt "#30015" +msgid "Update interval" +msgstr "Eguneraketa denbora-tartea" msgctxt "#30018" msgid "General" @@ -43,3 +47,39 @@ msgctxt "#30021" msgid "HTTP" msgstr "HTTP" + +msgctxt "#30042" +msgid "Never" +msgstr "Inoiz ez" + +msgctxt "#30045" +msgid "Always" +msgstr "Beti" + +msgctxt "#30051" +msgid "Login" +msgstr "Hasi saioa" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Denbora aldaketa" + +msgctxt "#30063" +msgid "Off" +msgstr "Desgaituta" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Grabazioak" + +msgctxt "#30072" +msgid "Timers" +msgstr "Programazioak" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatikoa" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Desgaituta" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.fa_af/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.fa_af/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.fa_af/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.fa_af/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -24,6 +24,10 @@ msgid "Password" msgstr "کلمه عبور" +msgctxt "#30005" +msgid "Connection" +msgstr "اتصال" + msgctxt "#30018" msgid "General" msgstr "عمومی" @@ -31,3 +35,19 @@ msgctxt "#30020" msgid "Advanced" msgstr "پیشرفته" + +msgctxt "#30042" +msgid "Never" +msgstr "هرگز" + +msgctxt "#30045" +msgid "Always" +msgstr "همیشه" + +msgctxt "#30063" +msgid "Off" +msgstr "خاموش" + +msgctxt "#30430" +msgid "Disabled" +msgstr "غیرفعال" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.fa_ir/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.fa_ir/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.fa_ir/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.fa_ir/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -24,6 +24,10 @@ msgid "Password" msgstr "رمز عبور" +msgctxt "#30006" +msgid "Icons" +msgstr "آیکون" + msgctxt "#30018" msgid "General" msgstr "عمومی" @@ -39,3 +43,27 @@ msgctxt "#30021" msgid "HTTP" msgstr "HTTP" + +msgctxt "#30042" +msgid "Never" +msgstr "هرگز" + +msgctxt "#30045" +msgid "Always" +msgstr "همیشه" + +msgctxt "#30051" +msgid "Login" +msgstr "ورود" + +msgctxt "#30063" +msgid "Off" +msgstr "خاموش" + +msgctxt "#30071" +msgid "Recordings" +msgstr "ضبط شده ها" + +msgctxt "#30430" +msgid "Disabled" +msgstr "غیر فعال" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.fi_fi/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.fi_fi/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.fi_fi/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.fi_fi/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: fi_FI\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+-isäntänimi tai ip-osoite" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Suoratoistoportti" - msgctxt "#30003" msgid "Username" msgstr "Käyttäjänimi" @@ -32,37 +24,33 @@ msgid "Password" msgstr "Salasana" +msgctxt "#30005" +msgid "Connection" +msgstr "Yhteys" + +msgctxt "#30006" +msgid "Icons" +msgstr "Logot" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Vastauksen aikakatkaisu sekunneissa" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Kanavalogojen polku" +msgctxt "#30009" +msgid "Update Interval" +msgstr "Päivitysväli" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Päivitysväli minuuteissa" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automaattinen ajastuslistan siivous" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Web-käyttöliittymän portti" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Lähetä vaihtokäsky ennen kanavan vaihtamista (yhden virittimen bokseille)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Kanavadatan kansio" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Tarkista kanavaryhmien päivitykset" +msgid "Update interval" +msgstr "Päivitysväli" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +84,109 @@ msgid "Recording folder on the receiver" msgstr "Vastaanottimen tallennuskansio" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Lähetä syväunikomento" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Nouda vain yksi kanavaryhmä" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "Kanavaryhmän nimi" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Nouda kanavalogot web-käyttöliittymästä" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Käytä suojattua HTTP:tä (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Käytä tv-lähetysten automaattiasetuksia" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Säilytä tallenteiden kansiorakenne" + +msgctxt "#30032" +msgid "EPG" +msgstr "Ohjelmaopas" + +msgctxt "#30035" +msgid "Use picons.eu file format" +msgstr "Käytä picons.eu:n tiedostomuotoa" + +msgctxt "#30042" +msgid "Never" +msgstr "Ei koskaan" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Vain ohjelmaoppaassa" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Vain tallenteissa" + +msgctxt "#30045" +msgid "Always" +msgstr "Aina" + +msgctxt "#30051" +msgid "Login" +msgstr "Käyttäjätunnus" + +msgctxt "#30052" +msgid "Misc" +msgstr "Muut" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Ajansiirto" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Ajansiirtopuskurin polku" + +msgctxt "#30063" +msgid "Off" +msgstr "Pois päältä" + +msgctxt "#30064" +msgid "On playback" +msgstr "Toiston aikana" + +msgctxt "#30065" +msgid "On pause" +msgstr "Tauon aikana" + +msgctxt "#30070" +msgid "Recordings & Timers" +msgstr "Ajastus ja tallennus" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Tallenteet" + +msgctxt "#30072" +msgid "Timers" +msgstr "Ajastukset" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automaattinen" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Kerran (luotu ajastussäännöllä)" + +msgctxt "#30421" +msgid "One time (Scheduled by repeating timer rule)" +msgstr "Kerran (luotu ajastussäännöllä)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Ei käytössä" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Tallenna, jos on eri ohjelmanimi" + +msgctxt "#30432" +msgid "Record if EPG title and short description differs" +msgstr "Tallenna, jos ohjelman nimi ja jakso eroavat" + +msgctxt "#30433" +msgid "Record if EPG title and all descriptions differ" +msgstr "Tallenna, jos ohjelman nimi, jakso ja juoni eroavat" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +195,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Yhdistetty palvelimeen '%s'" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Ajansiirtopuskurin polkua ei ole olemassa" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.fo_fo/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.fo_fo/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.fo_fo/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.fo_fo/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -24,6 +24,10 @@ msgid "Password" msgstr "Loyniorð" +msgctxt "#30006" +msgid "Icons" +msgstr "Ímyndir" + msgctxt "#30018" msgid "General" msgstr "Vanligt" @@ -31,3 +35,23 @@ msgctxt "#30019" msgid "Channels" msgstr "Rás" + +msgctxt "#30042" +msgid "Never" +msgstr "Ongantíð" + +msgctxt "#30045" +msgid "Always" +msgstr "Altíð" + +msgctxt "#30063" +msgid "Off" +msgstr "Sløkk" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Upptøkur" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Sløkt" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.fr_ca/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.fr_ca/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.fr_ca/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.fr_ca/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,53 +16,41 @@ "Language: fr_CA\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Nom d'hôte ou adresse IP de VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Port de diffusion en continu" - msgctxt "#30003" msgid "Username" -msgstr "Nom d'utilisateur" +msgstr "Nom d’utilisateur" msgctxt "#30004" msgid "Password" msgstr "Mot de passe" +msgctxt "#30005" +msgid "Connection" +msgstr "Connexion" + +msgctxt "#30006" +msgid "Icons" +msgstr "Icônes" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Temporisation de réponse en secondes" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Chemin des icônes" +msgctxt "#30009" +msgid "Update Interval" +msgstr "Intervalle de mise à jour" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Intervalle de mise à jour en minutes" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Nettoyage automatique de la liste des minuteries" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Port de l'interface Web" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Passer les chaînes avant le changement effectif (c.-à-d. pour les boîtiers syntoniseurs simples)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Dossier des données de chaînes" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Vérifier les mises à jour du bouquet numérique" +msgid "Update interval" +msgstr "Intervalle de mise à jour" msgctxt "#30016" msgid "Check for channel updates" @@ -70,7 +58,7 @@ msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" -msgstr "Utiliser seulement le chemin d'enregistrement actuel du boîtier DVB" +msgstr "Utiliser seulement le chemin d’enregistrement actuel du boîtier DVB" msgctxt "#30018" msgid "General" @@ -94,27 +82,115 @@ msgctxt "#30023" msgid "Recording folder on the receiver" -msgstr "Dossier d'enregistrement du récepteur" - -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Envoyer la commande deepstandby" +msgstr "Dossier d’enregistrement du récepteur" msgctxt "#30025" msgid "Fetch only one TV bouquet" -msgstr "Ne récupérer qu'un bouquet télé" +msgstr "Ne récupérer qu’un bouquet télé" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "Bouquet télé" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Récupérer les icônes de l'interface Web" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Utiliser le HTTP sécurisé (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Activer la configuration automatique des diffusions en direct" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Conserver la structure de dossier pour les enregistrements" + +msgctxt "#30032" +msgid "EPG" +msgstr "GÉP" + +msgctxt "#30035" +msgid "Use picons.eu file format" +msgstr "Utiliser le format de fichier picons.eu" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Diffusion en continu" + +msgctxt "#30042" +msgid "Never" +msgstr "Jamais" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Dans le GÉP seulement" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Dans les enregistrements seulement" + +msgctxt "#30045" +msgid "Always" +msgstr "Toujours" + +msgctxt "#30051" +msgid "Login" +msgstr "Connexion" + +msgctxt "#30052" +msgid "Misc" +msgstr "Divers" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Décalage temporel" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Chemin du tampon de décalage temporel" + +msgctxt "#30063" +msgid "Off" +msgstr "Arrêt" + +msgctxt "#30064" +msgid "On playback" +msgstr "Lecture" + +msgctxt "#30065" +msgid "On pause" +msgstr "Pause" + +msgctxt "#30070" +msgid "Recordings & Timers" +msgstr "Enregistrements et minuteries" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Enregistrements" + +msgctxt "#30072" +msgid "Timers" +msgstr "Minuteries" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatiques" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Une fois (planifiée par une règle de minuterie d’après le guide)" + +msgctxt "#30421" +msgid "One time (Scheduled by repeating timer rule)" +msgstr "Une fois (planifiée par la règle de la minuterie de répétition) " + +msgctxt "#30430" +msgid "Disabled" +msgstr "Désactivées" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Enregistrer si le titre du GÉP diffère" + +msgctxt "#30432" +msgid "Record if EPG title and short description differs" +msgstr "Enregistrer si le titre et la description courte du GÉP diffèrent" + +msgctxt "#30433" +msgid "Record if EPG title and all descriptions differ" +msgstr "Enregistrer si le titre et toutes les descriptions du GÉP diffèrent" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +199,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Se reconnecter à « %s »" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Le chemin du tampon de décalage temporel n’existe pas" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.fr_fr/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.fr_fr/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.fr_fr/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.fr_fr/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: fr_FR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Nom d'hôte VU+ ou adresse IP" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Port du flux de diffusion" - msgctxt "#30003" msgid "Username" msgstr "Nom d'utilisateur" @@ -32,37 +24,33 @@ msgid "Password" msgstr "Mot de passe" +msgctxt "#30005" +msgid "Connection" +msgstr "Connexion" + +msgctxt "#30006" +msgid "Icons" +msgstr "Icônes" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Temporisation de réponse en secondes" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Chemin d'accès de l'icône" +msgctxt "#30009" +msgid "Update Interval" +msgstr "Intervalle de mise à jour" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Intervalle de mise à jour en minutes" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Nettoyage automatique de la liste de programmation" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Port de l'interface Web" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zapper avant le changement de chaîne (par ex. pour les appareils à tuner unique)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Dossier des données de chaîne" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Vérifier les mises à jour des bouquets" +msgid "Update interval" +msgstr "Intervalle de mise à jour" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +84,113 @@ msgid "Recording folder on the receiver" msgstr "Dossier d'enregistrement du récepteur" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Envoyer la commande de mise en veille profonde (DeepStandby)" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Ne rapporter qu'un bouquet TV" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "Bouquet TV" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Récupérer les icônes de l'interface Web " - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Utiliser le HTTP sécurisé (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Activer la configuration automatique pour les flux en direct" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Conserver l'arborescence de dossiers pour les enregistrements" + +msgctxt "#30032" +msgid "EPG" +msgstr "Guide électronique des programmes TV" + +msgctxt "#30035" +msgid "Use picons.eu file format" +msgstr "Utiliser le format de fichier picons.eu" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Diffusion par flux" + +msgctxt "#30042" +msgid "Never" +msgstr "Jamais" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Dans le guide des programmes seulement" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Dans les enregistrements seulement" + +msgctxt "#30045" +msgid "Always" +msgstr "Toujours" + +msgctxt "#30051" +msgid "Login" +msgstr "Identification" + +msgctxt "#30052" +msgid "Misc" +msgstr "Divers" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Différé" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Chemin du tampon pour le différé" + +msgctxt "#30063" +msgid "Off" +msgstr "Non" + +msgctxt "#30064" +msgid "On playback" +msgstr "En lecture" + +msgctxt "#30065" +msgid "On pause" +msgstr "En pause" + +msgctxt "#30070" +msgid "Recordings & Timers" +msgstr "Enregistrements et programmation" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Enregistrements" + +msgctxt "#30072" +msgid "Timers" +msgstr "Programmations" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatique" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Une fois (planifiée par une règle de programmation du guide)" + +msgctxt "#30421" +msgid "One time (Scheduled by repeating timer rule)" +msgstr "Une fois (planifiée par une règle de programmation répétée)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Désactivé" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Enregistrer si le titre du guide (EPG) diffère" + +msgctxt "#30432" +msgid "Record if EPG title and short description differs" +msgstr "Enregistrer si le titre et la description courte du guide (EPG) diffèrent" + +msgctxt "#30433" +msgid "Record if EPG title and all descriptions differ" +msgstr "Enregistrer si le titre et toutes les descriptions du guide (EPG) diffèrent" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +199,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Reconnecté à « %s »" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Le chemin du tampon pour le différé n'existe pas" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.gl_es/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.gl_es/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.gl_es/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.gl_es/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: gl_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Nome de host ou enderezo IP de VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Porto de transmisión" - msgctxt "#30003" msgid "Username" msgstr "Nome de usuario" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Contrasinal" +msgctxt "#30005" +msgid "Connection" +msgstr "Conexión" + +msgctxt "#30006" +msgid "Icons" +msgstr "Iconas" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Tempo de espera da resposta en segundos" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Camiño da icona" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Intervalo de actualización en minutos" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Limpeza automática da Timerlist" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Porto da interface web" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap antes de trocar de canle (útil para caixas cun só sintonizador)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Cartafol para channeldata" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Verificar actualizacións de bouquett" +msgid "Update interval" +msgstr "Intervalo de actualización" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,73 @@ msgid "Recording folder on the receiver" msgstr "Cartafol de gravacións no receptor" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Enviar comando de Standby profundo" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Obter só un TV bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Obter picons da interface web" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Usar HTTP Seguro (https)" +msgctxt "#30032" +msgid "EPG" +msgstr "Guía" + +msgctxt "#30042" +msgid "Never" +msgstr "Nunca" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Só na Guía" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Só nas gravacións" + +msgctxt "#30045" +msgid "Always" +msgstr "Sempre" + +msgctxt "#30051" +msgid "Login" +msgstr "Usuario" + +msgctxt "#30052" +msgid "Misc" +msgstr "Miscelánea" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Timeshift" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Ruta do búfer do Timeshift" + +msgctxt "#30063" +msgid "Off" +msgstr "Apagado" + +msgctxt "#30064" +msgid "On playback" +msgstr "En reprodución" + +msgctxt "#30065" +msgid "On pause" +msgstr "En Pausa" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Gravacións" + +msgctxt "#30072" +msgid "Timers" +msgstr "Temporizadores" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automático" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Desactivado" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.he_il/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.he_il/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.he_il/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.he_il/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: he_IL\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "שם מארח או כתובת IP" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "פורט הזרמה" - msgctxt "#30003" msgid "Username" msgstr "שם משתמש" @@ -32,37 +24,29 @@ msgid "Password" msgstr "סיסמה" +msgctxt "#30005" +msgid "Connection" +msgstr "חיבור" + +msgctxt "#30006" +msgid "Icons" +msgstr "סמלים" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "זמן המתנה מירבי לתגובה בשניות" -msgctxt "#30008" -msgid "Icon Path" -msgstr "נתיב סמלי ערוצים" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "מרווח זמני עדכונים בדקות" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "ניקוי רשימת תזמונים אוטומטית" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "פורט ממשק רשת" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "העבר ערוץ במכשיר לפני העברה ב־Kodi (מכשיר בעל מקלט בודד)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "תיקיית נתוני ערוצים" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "חיפוש עדכוני סל ערוצים" +msgid "Update interval" +msgstr "מרווח זמני עדכונים" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,81 @@ msgid "Recording folder on the receiver" msgstr "תיקיית הקלטות בשרת אחורי" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "שלח פקודת שינה עמוקה" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "משוך סל ערוצים יחיד בלבד" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "סל ערוצים" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "משוך סמלי ערוצים מממשק הדפדפן" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "השתמש ב־HTTP מאובטח (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "הפעל תצורה אוטומטית עבור הזרמת שידורים חיים" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "שמור על מבנה התיקיות עבור הרשומות" + +msgctxt "#30032" +msgid "EPG" +msgstr "לוח שידורים" + +msgctxt "#30042" +msgid "Never" +msgstr "אף פעם" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "בלוח שידורים בלבד" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "בהקלטות בלבד" + +msgctxt "#30045" +msgid "Always" +msgstr "תמיד" + +msgctxt "#30051" +msgid "Login" +msgstr "שם משתמש" + +msgctxt "#30052" +msgid "Misc" +msgstr "שונות" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "הסט זמן" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "נתיב חוצץ טיימשיפט" + +msgctxt "#30063" +msgid "Off" +msgstr "כבוי" + +msgctxt "#30064" +msgid "On playback" +msgstr "עם נגינה" + +msgctxt "#30065" +msgid "On pause" +msgstr "עם השהיה" + +msgctxt "#30071" +msgid "Recordings" +msgstr "הקלטות" + +msgctxt "#30072" +msgid "Timers" +msgstr "תזמונים" + +msgctxt "#30410" +msgid "Automatic" +msgstr "אוטומטי" + +msgctxt "#30430" +msgid "Disabled" +msgstr "מנוטרל" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.hi_in/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.hi_in/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.hi_in/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.hi_in/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -20,6 +20,10 @@ msgid "Username" msgstr "उपयोगकर्ता नाम" +msgctxt "#30006" +msgid "Icons" +msgstr "प्रतीक" + msgctxt "#30018" msgid "General" msgstr "सामान्य" @@ -27,3 +31,11 @@ msgctxt "#30020" msgid "Advanced" msgstr "उन्नत" + +msgctxt "#30063" +msgid "Off" +msgstr "से" + +msgctxt "#30430" +msgid "Disabled" +msgstr "विकलांग" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.hr_hr/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.hr_hr/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.hr_hr/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.hr_hr/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: hr_HR\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ naziv računala ili IP adresa" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Ulaz stremanja" - msgctxt "#30003" msgid "Username" msgstr "Korisničko ime" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Lozinka" +msgctxt "#30005" +msgid "Connection" +msgstr "Povezivanje" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikone" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Vrijeme odaziva u sekundama" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Putanja ikone" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Interval osvježavanja u minutama" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatsko čišćenje popisa zadanih snimanja" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Ulaz web sučelja" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Isključi prije promjene programa (za uređaje s jednim prijemnikom)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Mapa za podatke programa" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Provjeri nadopune buketa" +msgid "Update interval" +msgstr "Razdoblje nadopune" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,77 @@ msgid "Recording folder on the receiver" msgstr "Mapa snimanja na prijemniku" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Pošalji naredbu duboke pripravnosti" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Dohvati samo jedan TV buket" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV buket" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Dohvati ikone iz web sučelja" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Koristi sigurni HTTP (https)" +msgctxt "#30032" +msgid "EPG" +msgstr "EPG vodič" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Streamanje" + +msgctxt "#30042" +msgid "Never" +msgstr "Nikada" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Samo u EPG-u" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Samo u snimkama" + +msgctxt "#30045" +msgid "Always" +msgstr "Uvijek" + +msgctxt "#30051" +msgid "Login" +msgstr "Prijava" + +msgctxt "#30052" +msgid "Misc" +msgstr "Ostalo" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Vremensko premotavanje" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Putanja međuspremnika premotavanja u vremenu" + +msgctxt "#30063" +msgid "Off" +msgstr "Isključeno" + +msgctxt "#30064" +msgid "On playback" +msgstr "Pri reprodukciji" + +msgctxt "#30065" +msgid "On pause" +msgstr "Pri pauzi" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Snimke" + +msgctxt "#30072" +msgid "Timers" +msgstr "Snimanja" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatski" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Onemogućeno" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.hu_hu/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.hu_hu/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.hu_hu/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.hu_hu/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: hu_HU\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ Kiszolgálónév vagy IP cím" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Sugárzási port" - msgctxt "#30003" msgid "Username" msgstr "Felhasználónév" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Jelszó" +msgctxt "#30005" +msgid "Connection" +msgstr "Kapcsolat" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikon" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Válasz időkorlát másodpercben" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Csatornaikonok elérési útvonala" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Frissítési intervallum percben" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Időzítő lista automatikus tisztítása" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Web-kezelőfelület port" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Áthangolás csatornaváltás elött (Egytuneres boxoknál)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Csatornaadat mappa" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Csatonalista frissítés keresése" +msgid "Update interval" +msgstr "Frissítési intervallum" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,85 @@ msgid "Recording folder on the receiver" msgstr "Felvételi mappa a vevőn" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "DeepStandby parancs küldése" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Csak egy csatornalista letöltése" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-csatorna-csoport" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Webes ikonok használata" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Titkosított HTTP haszálata (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Automatikus konfigurálás engedélyezése élő adásokhoz" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Felvételek mappaszerkezetének megtartása" + +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Adatfolyam" + +msgctxt "#30042" +msgid "Never" +msgstr "Soha" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "csak az EPG-ben" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Csak a felvételekben" + +msgctxt "#30045" +msgid "Always" +msgstr "Mindig" + +msgctxt "#30051" +msgid "Login" +msgstr "Bejelentkezés" + +msgctxt "#30052" +msgid "Misc" +msgstr "Egyéb" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Csúsztatott felvétel" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Csúsztatott élőkép tároló útvonala" + +msgctxt "#30063" +msgid "Off" +msgstr "Ki" + +msgctxt "#30064" +msgid "On playback" +msgstr "Lejátszáskor" + +msgctxt "#30065" +msgid "On pause" +msgstr "Szüneteltetéskor" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Felvételek" + +msgctxt "#30072" +msgid "Timers" +msgstr "Időzítők" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatikus" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Letiltva" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.hy_am/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.hy_am/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.hy_am/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.hy_am/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -20,6 +20,18 @@ msgid "Password" msgstr "Գաղտնաբառ" +msgctxt "#30006" +msgid "Icons" +msgstr "Նշաններ" + msgctxt "#30018" msgid "General" msgstr "Գլխավոր" + +msgctxt "#30051" +msgid "Login" +msgstr "Մուտք" + +msgctxt "#30063" +msgid "Off" +msgstr "Անջատել" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.id_id/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.id_id/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.id_id/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.id_id/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: id_ID\n" "Plural-Forms: nplurals=1; plural=0;\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Hostname atau alamat IP VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Port pengaliran" - msgctxt "#30003" msgid "Username" msgstr "NamaPengguna" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Password" +msgctxt "#30005" +msgid "Connection" +msgstr "Koneksi" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikon" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Timeout response dalam deti" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Path Ikon" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Interval update dalam menit" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Pembersihan TImerlist secara otomatis" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Port antar-muka web" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Matikan sebelum pindah kanal (Contohnya untuk Tuner tunggal)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Folder untuk data kanal" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Cek untuk pemuktahiran buket" +msgid "Update interval" +msgstr "Interval update" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,57 @@ msgid "Recording folder on the receiver" msgstr "Folder rekaman di penerima" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Kirim perintah DeepStandby-Command" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Hanya ambil satu buket TV" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "Buket TV" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Ambil picons dan antarmuka web" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Gunakan Secure HTTP (https)" +msgctxt "#30032" +msgid "EPG" +msgstr "EPG " + +msgctxt "#30042" +msgid "Never" +msgstr "Tidak Pernah" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "di EPG saja" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Di perekaman saja" + +msgctxt "#30045" +msgid "Always" +msgstr "Selalu" + +msgctxt "#30051" +msgid "Login" +msgstr "Masuk" + +msgctxt "#30052" +msgid "Misc" +msgstr "Misc" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Pergeseran waktu" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Path penyangga Timeshift" + +msgctxt "#30063" +msgid "Off" +msgstr "Matikan" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Perekaman" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Non Aktif" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.is_is/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.is_is/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.is_is/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.is_is/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: is_IS\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Nafn eða IP vistfang VU+ hýsingar" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Gátt streymis" - msgctxt "#30003" msgid "Username" msgstr "Notandanafn" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Lykilorð" +msgctxt "#30005" +msgid "Connection" +msgstr "Tenging" + +msgctxt "#30006" +msgid "Icons" +msgstr "Tákn" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Tímatakmörk svartíma í sekúndum" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Slóð táknmynda" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Uppfærslutími í mínútum" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Sjálfvirk hreinsun á tímatökulista" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Gátt vefviðmóts" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Bið á milli rásaskipta (þ.e. fyrir box með einum móttakara)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Mappa fyrir rásargögn" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Athuga með uppfærslur knippa" +msgid "Update interval" +msgstr "Bið milli uppfærslna" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,93 @@ msgid "Recording folder on the receiver" msgstr "Upptökumappa á móttakaranum" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Senda DjúpurSvefn-skipun" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Sækja aðeins eitt sjónvarpsknippi" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "Sjónvarps-knippi" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Sækja 'picon' frá vefviðmóti" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Nota öruggara HTTP (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Virkja sjálfvirka uppsetningu á beinu streymi" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Halda möppuskipulagi fyrir plötur" + +msgctxt "#30032" +msgid "EPG" +msgstr "Rafrænn EPG-sjónvarpsvísir" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Streymi" + +msgctxt "#30042" +msgid "Never" +msgstr "Aldrei" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Aðeins í rafrænum EPG-dagskrárvísum" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Aðeins í upptökum" + +msgctxt "#30045" +msgid "Always" +msgstr "Alltaf" + +msgctxt "#30051" +msgid "Login" +msgstr "Innskrá" + +msgctxt "#30052" +msgid "Misc" +msgstr "Ýmislegt" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Tímaflakk" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Slóð á biðminni tímahliðrunar" + +msgctxt "#30063" +msgid "Off" +msgstr "Slökkt" + +msgctxt "#30064" +msgid "On playback" +msgstr "Við afspilun" + +msgctxt "#30065" +msgid "On pause" +msgstr "Við bið" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Upptökur" + +msgctxt "#30072" +msgid "Timers" +msgstr "Tímatökur" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Sjálfvirkt" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Eins-skiptis (sett á með tímatökureglu frá dagsrárvísi)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Óvirkt" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Taka upp ef titill í EPG-dagskrárvísi er öðruvísi" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +175,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Tengdur við '%s'" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Slóð á biðminni tímahliðrunar er ekki til" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.it_it/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.it_it/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.it_it/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.it_it/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: it_IT\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Nome host o indirizzo IP VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Porta per lo streaming" - msgctxt "#30003" msgid "Username" msgstr "Nome utente" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Password" +msgctxt "#30005" +msgid "Connection" +msgstr "Connessione" + +msgctxt "#30006" +msgid "Icons" +msgstr "Icone" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Timeout di risposta in secondi" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Percorso dell'icona" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Intervallo di aggiornamento in minuti" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Pulizia automatica della lista dei timer" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Porta dell'interfaccia web" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap prima del cambio canale (ad es: per i dispositivi con sintonizzatore singolo)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Cartella per i dati dei canali" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Controlla aggiornamenti dei bouquet" +msgid "Update interval" +msgstr "Intervallo aggiornamento" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,81 @@ msgid "Recording folder on the receiver" msgstr "Cartella per le registrazioni del ricevitore" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Invia comando di DeepStandby" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Prendi un solo bouquet TV" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "Bouquet TV" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Raccogli picons dall'interfaccia web" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Utilizza HTTP Sicuro (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Abilita configurazione automatica per trasmissioni in diretta" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Mantieni la struttura delle cartelle per i record" + +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30042" +msgid "Never" +msgstr "Mai" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Solo in EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Solo in registrazione" + +msgctxt "#30045" +msgid "Always" +msgstr "Sempre" + +msgctxt "#30051" +msgid "Login" +msgstr "Login" + +msgctxt "#30052" +msgid "Misc" +msgstr "Varie" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Timeshift" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Path per il buffer del timeshift" + +msgctxt "#30063" +msgid "Off" +msgstr "Off" + +msgctxt "#30064" +msgid "On playback" +msgstr "In riproduzione" + +msgctxt "#30065" +msgid "On pause" +msgstr "In pausa" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Registrazioni" + +msgctxt "#30072" +msgid "Timers" +msgstr "Timer" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatico" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Disabilitato" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ja_jp/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ja_jp/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ja_jp/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ja_jp/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: ja_JP\n" "Plural-Forms: nplurals=1; plural=0;\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ のホスト名または IPアドレス" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "ストリーミングのポート番号" - msgctxt "#30003" msgid "Username" msgstr "ユーザー名" @@ -32,37 +24,29 @@ msgid "Password" msgstr "パスワード" +msgctxt "#30005" +msgid "Connection" +msgstr "接続" + +msgctxt "#30006" +msgid "Icons" +msgstr "アイコン" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "レスポンスのタイムアウト (秒)" -msgctxt "#30008" -msgid "Icon Path" -msgstr "アイコンのパス" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "更新間隔 (分)" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "タイマーリストの自動クリーンアップ" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Web インターフェースのポート番号" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "チャンネル切り替えの前にザッピングする (つまり、シングルチューナーボックス用)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "チャンネルデータのフォルダー" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "ブーケの更新を確認" +msgid "Update interval" +msgstr "更新間隔" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,41 @@ msgid "Recording folder on the receiver" msgstr "レシーバーの録画フォルダー" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "ディープスタンバイコマンドを送る" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "ひとつのTV ブーケのみ取得" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-ブーケ" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "ウェブインターフェースからpiconを取得" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Secure HTTP (https) を使用する" +msgctxt "#30042" +msgid "Never" +msgstr "使用しない" + +msgctxt "#30045" +msgid "Always" +msgstr "常に" + +msgctxt "#30051" +msgid "Login" +msgstr "ログイン" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "タイムシフト用バッファのパス" + +msgctxt "#30063" +msgid "Off" +msgstr "オフ" + +msgctxt "#30071" +msgid "Recordings" +msgstr "録音" + +msgctxt "#30072" +msgid "Timers" +msgstr "タイマー" + +msgctxt "#30430" +msgid "Disabled" +msgstr "無効" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ko_kr/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ko_kr/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ko_kr/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ko_kr/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: ko_KR\n" "Plural-Forms: nplurals=1; plural=0;\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ 호스트네임 또는 IP 주소" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "스트리밍 포트" - msgctxt "#30003" msgid "Username" msgstr "사용자명" @@ -32,37 +24,29 @@ msgid "Password" msgstr "비밀번호" +msgctxt "#30005" +msgid "Connection" +msgstr "연결" + +msgctxt "#30006" +msgid "Icons" +msgstr "아이콘" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "응답 제한시간 (초)" -msgctxt "#30008" -msgid "Icon Path" -msgstr "아이콘 경로" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "업데이트 주기 (분)" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "타임시프트 자동 정리" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "웹인터페이스 포트" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "채널변경전 삭제 (Single Tuner boxes등을 위해)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "채널 데이터 폴더" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "묶음 업데이트 확인" +msgid "Update interval" +msgstr "업데이트 주기" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,69 @@ msgid "Recording folder on the receiver" msgstr "리시버 녹화 폴더" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "DeepStandby-Command 보내기" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "하나의 TV 묶음만 가져오기" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV 묶음" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "웹인터페이스로 부터 아이콘들을 가져옴" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "암호화된 HTTP (https) 사용" +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30039" +msgid "Streaming" +msgstr "스트리밍" + +msgctxt "#30042" +msgid "Never" +msgstr "사용 안 함" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "EPG에서만" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "녹화 중에만" + +msgctxt "#30045" +msgid "Always" +msgstr "항상" + +msgctxt "#30051" +msgid "Login" +msgstr "로그인" + +msgctxt "#30052" +msgid "Misc" +msgstr "기타" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "타임시프트" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "타임시프트 버퍼 경로" + +msgctxt "#30063" +msgid "Off" +msgstr "끔" + +msgctxt "#30071" +msgid "Recordings" +msgstr "녹화" + +msgctxt "#30072" +msgid "Timers" +msgstr "녹화 예약" + +msgctxt "#30410" +msgid "Automatic" +msgstr "자동" + +msgctxt "#30430" +msgid "Disabled" +msgstr "사용 안 함" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.lt_lt/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.lt_lt/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.lt_lt/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.lt_lt/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: lt_LT\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ kompiuterio vardas arba IP adresas" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Srauto prievadas" - msgctxt "#30003" msgid "Username" msgstr "Vartotojo vardas" @@ -32,37 +24,33 @@ msgid "Password" msgstr "Slaptažodis" +msgctxt "#30005" +msgid "Connection" +msgstr "Prijungimas" + +msgctxt "#30006" +msgid "Icons" +msgstr "Piktogramos" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Reakcijos laikas, sekundėmis" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Piktogramos kelias" +msgctxt "#30009" +msgid "Update Interval" +msgstr "Atnaujinimo intervalas" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Naujinimo intervalas minutėmis" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatinis 'Laikmačio Sąrašo' valymas" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Web sąsajos prievadas" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap before channelswitch (i.e. for Single Tuner boxes)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Aplankas kanalo duomenims" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Patikrinkite paketo atnaujinimus" +msgid "Update interval" +msgstr "Atnaujinimo intervalas" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +84,113 @@ msgid "Recording folder on the receiver" msgstr "Įrašymo aplankas į imtuvą" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Siųsti 'Gilus budėjimo režimas' - Komandą" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Išrinkta tik viena TV plokštė" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Plokštė" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Įkelti 'picons' iš interneto sąsajos" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Naudoti saugų HTTP (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Įjungti automatinę vaizdo transliacijų konfigūraciją" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Išlaikyti aplanko struktūrą įrašams" + +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30035" +msgid "Use picons.eu file format" +msgstr "Naudoti picons.eu failo formatą" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Transliuojama" + +msgctxt "#30042" +msgid "Never" +msgstr "Niekada" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Tik EPG lange" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Tik įrašymuose" + +msgctxt "#30045" +msgid "Always" +msgstr "Visada" + +msgctxt "#30051" +msgid "Login" +msgstr "Prisijungimo vardas" + +msgctxt "#30052" +msgid "Misc" +msgstr "Įvairūs" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Laiko poslinkis" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Laiko poslinkio buferio kelias" + +msgctxt "#30063" +msgid "Off" +msgstr "Išjungta" + +msgctxt "#30064" +msgid "On playback" +msgstr "Atkuriant" + +msgctxt "#30065" +msgid "On pause" +msgstr "Pristabdžius" + +msgctxt "#30070" +msgid "Recordings & Timers" +msgstr "Įrašai ir laikmačiai" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Įrašai" + +msgctxt "#30072" +msgid "Timers" +msgstr "Laikmačiai" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatiškai" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Vieną kartą (suplanuota gidu paremtos laikmačio taisyklės)" + +msgctxt "#30421" +msgid "One time (Scheduled by repeating timer rule)" +msgstr "Vienkartinis (suplanuotas pasikartojančio laikmačio taisyklės)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Atjungta" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Įrašyti, jei skiriasi EPG pavadinimas" + +msgctxt "#30432" +msgid "Record if EPG title and short description differs" +msgstr "Įrašyti jei EPG pavadinimas ir trumpas aprašymas skiriasi" + +msgctxt "#30433" +msgid "Record if EPG title and all descriptions differ" +msgstr "Įrašyti jei EPG pavadinimas ir visi aprašymai skiriasi" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +199,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Prijungtas prie '%s'" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Laiko poslinkio buferio kelias neegzistuoja" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.lv_lv/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.lv_lv/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.lv_lv/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.lv_lv/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: lv_LV\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ saimniekvārds vai IP adrese" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Straumēšanas ports" - msgctxt "#30003" msgid "Username" msgstr "LIetotājs" @@ -32,38 +24,26 @@ msgid "Password" msgstr "Parole" +msgctxt "#30005" +msgid "Connection" +msgstr "Pieslēgums" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikonas" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Atbildes noilgums sekundēs" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Ikonu ceļš" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Atjaunināšanas intervāls minūtēs" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automātiska taimersaraksta uzkopšana" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Tīmekļa saskarnes ports" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Pārslēgt pirms kanāla pārslēgšanās (piem., viena uztvērēja pierīcēm)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Mape kanāldatiem" -msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Pārbaudīt buķetes atjauninājumus" - msgctxt "#30016" msgid "Check for channel updates" msgstr "Pārbaudīt kanāla atjauninājumus" @@ -96,25 +76,45 @@ msgid "Recording folder on the receiver" msgstr "Ierakstīšanas mape atskaņotājā" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Sūtīt \"dziļas gatavības\" komandu" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Iegūt tikai vienu TV buķeti" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-buķete" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Iegūt pikonas no tīmeklā saskarnes" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Izmantot drošo HTTP (https)" +msgctxt "#30042" +msgid "Never" +msgstr "Nekad" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Tikai EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Tikai ierakstos" + +msgctxt "#30045" +msgid "Always" +msgstr "Vienmēr" + +msgctxt "#30051" +msgid "Login" +msgstr "Pieteikšanās" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Laika nobīdes bufera ceļš" + +msgctxt "#30063" +msgid "Off" +msgstr "Izslēgts" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Ieraksti" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Izslēgts" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.mi/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.mi/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.mi/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.mi/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -24,6 +24,10 @@ msgid "Password" msgstr "Kupuhipa" +msgctxt "#30006" +msgid "Icons" +msgstr "Ata" + msgctxt "#30018" msgid "General" msgstr "Āhuawhānui" @@ -39,3 +43,23 @@ msgctxt "#30021" msgid "HTTP" msgstr "HTTP" + +msgctxt "#30042" +msgid "Never" +msgstr "Kore rawa" + +msgctxt "#30045" +msgid "Always" +msgstr "Tonu" + +msgctxt "#30063" +msgid "Off" +msgstr "Weto" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Ngā pūhopu" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Kua mono" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.mk_mk/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.mk_mk/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.mk_mk/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.mk_mk/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: mk_MK\n" "Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ hostname или IP адреса" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Streaming Port" - msgctxt "#30003" msgid "Username" msgstr "Корисничко име" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Лозинка" +msgctxt "#30005" +msgid "Connection" +msgstr "Конекција" + +msgctxt "#30006" +msgid "Icons" +msgstr "Икони" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Response timeout in seconds" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Патека за икони" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Интервал на надградби во минути" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatic Timerlist Cleanup" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Webinterface Port" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap before channelswitch (i.e. for Single Tuner boxes)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Папки за channeldata" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Провери дали има нови пакети" +msgid "Update interval" +msgstr "Период на освежување" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,49 @@ msgid "Recording folder on the receiver" msgstr "Папка за снимање на ресиверот" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Испрати Наредба за DeepStandby" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Превземи само еден TV пакет" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "ТВ-Пакет" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Превземи икони од интернет" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Користи Secure HTTP (https)" +msgctxt "#30042" +msgid "Never" +msgstr "Никогаш" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Само во EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Само во снимките" + +msgctxt "#30045" +msgid "Always" +msgstr "Секогаш" + +msgctxt "#30051" +msgid "Login" +msgstr "Најави се" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Пат за Timeshift buffer-от" + +msgctxt "#30063" +msgid "Off" +msgstr "Искл." + +msgctxt "#30071" +msgid "Recordings" +msgstr "Снимки" + +msgctxt "#30072" +msgid "Timers" +msgstr "Бројачи" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Исклучено" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ml_in/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ml_in/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ml_in/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ml_in/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.mn_mn/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.mn_mn/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.mn_mn/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.mn_mn/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -40,6 +40,22 @@ msgid "HTTP" msgstr "HTTP" +msgctxt "#30063" +msgid "Off" +msgstr "Хаах" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Бичлэгүүд" + +msgctxt "#30072" +msgid "Timers" +msgstr "Цагалбарууд" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Идвэхгүй болсон" + msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "'%s'-с салгагдлаа" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ms_my/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ms_my/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ms_my/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ms_my/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: ms_MY\n" "Plural-Forms: nplurals=1; plural=0;\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Nama hos atau alamat IP VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Port Penstriman" - msgctxt "#30003" msgid "Username" msgstr "Nama Pengguna" @@ -32,37 +24,33 @@ msgid "Password" msgstr "Kata Laluan" +msgctxt "#30005" +msgid "Connection" +msgstr "Sambungan" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikon" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Had masa tamat respons dalam saat" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Laluan Ikon" +msgctxt "#30009" +msgid "Update Interval" +msgstr "Kemaskini Sela" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Sela kemaskini dalam minit" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Pembersihan Senarai Pemasa Berautomatik" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Port " - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap sebelum tukar saluran (cth. Kotak Penala Tunggal)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Folder untuk data saluran" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Semak unutk kemaskini bouquett" +msgid "Update interval" +msgstr "Kemaskini sela" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +84,109 @@ msgid "Recording folder on the receiver" msgstr "Folder rakaman pada penerima" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Hantar " - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Hanya hantar satu TV bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Dapatkan picons dari " - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Guna HTTP Selamat (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Benarkan konfigurasi automatik untuk strim langsung" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Kekalkan struktur folder untuk rekod" + +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30035" +msgid "Use picons.eu file format" +msgstr "Guna format fail picons.eu" + +msgctxt "#30042" +msgid "Never" +msgstr "Tidak sesekali" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Dalam EPG sahaja" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Hanya dalam rakaman" + +msgctxt "#30045" +msgid "Always" +msgstr "Sentiasa" + +msgctxt "#30051" +msgid "Login" +msgstr "Daftar Masuk" + +msgctxt "#30052" +msgid "Misc" +msgstr "Pelbagai" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Anjak Masa" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Laluan penimbal Anjak Masa" + +msgctxt "#30063" +msgid "Off" +msgstr "Mati" + +msgctxt "#30064" +msgid "On playback" +msgstr "Ketika main balik" + +msgctxt "#30065" +msgid "On pause" +msgstr "Ketika dijeda" + +msgctxt "#30070" +msgid "Recordings & Timers" +msgstr "Rakaman & Pemasa" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Rakaman" + +msgctxt "#30072" +msgid "Timers" +msgstr "Pemasa" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatik" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Sekali (Dijadulakan mengikut peraturan pemasa berasaskan-panduan)" + +msgctxt "#30421" +msgid "One time (Scheduled by repeating timer rule)" +msgstr "Sekali (Dijadualkan mengikut peraturan pemasa ulang)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Dilumpuhkan" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Rakam jika tajuk EPG berbeza" + +msgctxt "#30432" +msgid "Record if EPG title and short description differs" +msgstr "Rakam jika tajuk EPG dan keterangan pendek berlainan" + +msgctxt "#30433" +msgid "Record if EPG title and all descriptions differ" +msgstr "Rakam jika tajuk EPG dan semua keterangan berlainan" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +195,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Bersambung semula dengan '%s'" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Laluan penimbal anjak masa tidak wujud" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.mt_mt/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.mt_mt/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.mt_mt/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.mt_mt/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -24,13 +24,17 @@ msgid "Password" msgstr "Sigriet" +msgctxt "#30006" +msgid "Icons" +msgstr "Ajkons" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Kemm iddum tistenna riposta f'sekondi" -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Port tal-webinterface" +msgctxt "#30015" +msgid "Update interval" +msgstr "Il-ħin bejn l-aġġornamenti" msgctxt "#30018" msgid "General" @@ -47,3 +51,35 @@ msgctxt "#30021" msgid "HTTP" msgstr "HTTP" + +msgctxt "#30042" +msgid "Never" +msgstr "Qatt" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Fl-EPG biss" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Fir-rekordings biss" + +msgctxt "#30045" +msgid "Always" +msgstr "Dejjem" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Il-Buffer path tat-timeshift" + +msgctxt "#30063" +msgid "Off" +msgstr "Xejn" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Recordings" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Mhux attiv" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.my_mm/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.my_mm/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.my_mm/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.my_mm/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -24,6 +24,14 @@ msgid "Password" msgstr "စကားဝှက်" +msgctxt "#30005" +msgid "Connection" +msgstr "ကွန်နက်ရှင်" + +msgctxt "#30006" +msgid "Icons" +msgstr "Icons" + msgctxt "#30018" msgid "General" msgstr "ယေဘုယျ" @@ -35,3 +43,27 @@ msgctxt "#30020" msgid "Advanced" msgstr "အဆင့်မြင့်သော" + +msgctxt "#30042" +msgid "Never" +msgstr "ဘယ်တော့မှ" + +msgctxt "#30045" +msgid "Always" +msgstr "အမြဲတမ်း" + +msgctxt "#30051" +msgid "Login" +msgstr "ဝင်ရန်" + +msgctxt "#30063" +msgid "Off" +msgstr "ပိတ်" + +msgctxt "#30071" +msgid "Recordings" +msgstr "အသံသွင်းခြင်း" + +msgctxt "#30430" +msgid "Disabled" +msgstr "ပိတ်ထားမည်" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.nb_no/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.nb_no/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.nb_no/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.nb_no/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: nb_NO\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ vertsnavn eller IP adresse" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Stream Port" - msgctxt "#30003" msgid "Username" msgstr "Brukernavn" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Passord" +msgctxt "#30005" +msgid "Connection" +msgstr "Tilkobling" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikoner" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Svar timeout i sekunder" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Sti til ikoner" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Oppdateringsinterval i minutter" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatisk opprydding av tidsursliste" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Webgrensesnitt Port" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Bytt før kanalbytte (f.eks. for Single Tuner bokser)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Mappe for kanaldata" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Søk etter bouquett oppdateringer" +msgid "Update interval" +msgstr "Oppdateringsintervall" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,81 @@ msgid "Recording folder on the receiver" msgstr "Opptaksmappe på mottaker" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Send kommandoen DeepStandby" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Hen kun en TV bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Hent piconer fra nettgrensesnittet" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Bruk Sikker HTTP (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Skru på automatisk oppsett for sanntids-strømmer" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Behold mappestruktur for opptak" + +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30042" +msgid "Never" +msgstr "Aldri" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Kun i EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Kun i opptak" + +msgctxt "#30045" +msgid "Always" +msgstr "Alltid" + +msgctxt "#30051" +msgid "Login" +msgstr "Innlogging" + +msgctxt "#30052" +msgid "Misc" +msgstr "Diverse" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Tdsforskyvning" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Sti for tidsforskyvningbuffer" + +msgctxt "#30063" +msgid "Off" +msgstr "Av" + +msgctxt "#30064" +msgid "On playback" +msgstr "Ved avspilling" + +msgctxt "#30065" +msgid "On pause" +msgstr "På pause" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Opptak" + +msgctxt "#30072" +msgid "Timers" +msgstr "Tidsur" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatisk" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Deaktivert" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.nl_nl/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.nl_nl/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.nl_nl/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.nl_nl/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: nl_NL\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ hostnaam of IP-adres" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Streamingpoort" - msgctxt "#30003" msgid "Username" msgstr "Gebruikersnaam" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Wachtwoord" +msgctxt "#30005" +msgid "Connection" +msgstr "Verbinding" + +msgctxt "#30006" +msgid "Icons" +msgstr "Iconen" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Antwoordtimeout in seconden" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Icoonpad" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Update-interval in minuten" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatische opschoning van timers" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Webinterfacepoort" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap voor kanaalwisseling (bv. bij enkelvoudige tuners)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Map voor kanaaldata" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Controleer bouquetupdates" +msgid "Update interval" +msgstr "Updatefrequentie" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,93 @@ msgid "Recording folder on the receiver" msgstr "Opnamemap op de ontvanger" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Stuur DeepStandby-commando" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Haal slechts 1 TV-bouquet op" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Haal picons op van de webinterface" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Gebruik beveiligde HTTP (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Activeer automatische configuratie voor live streams" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Behoud folder structuur voor opnamen" + +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Streaming" + +msgctxt "#30042" +msgid "Never" +msgstr "Nooit" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Alleen in EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Alleen in opnames" + +msgctxt "#30045" +msgid "Always" +msgstr "Altijd" + +msgctxt "#30051" +msgid "Login" +msgstr "Gebruikersnaam" + +msgctxt "#30052" +msgid "Misc" +msgstr " Divers" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Timeshift" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Tijdsprong bufferlocatie" + +msgctxt "#30063" +msgid "Off" +msgstr "Uit" + +msgctxt "#30064" +msgid "On playback" +msgstr "Tijdens afspelen" + +msgctxt "#30065" +msgid "On pause" +msgstr "tijdens Pauze" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Opnames" + +msgctxt "#30072" +msgid "Timers" +msgstr "Timers" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatisch" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Eenmalig (ingesteld door gidsgebaseerde tijdregel)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Uitgeschakeld" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Opname indien EPG-titel afwijkt" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +175,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Verbinding met '%s' hersteld" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Tijdshift-bufferpad bestaat niet" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.pl_pl/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.pl_pl/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.pl_pl/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.pl_pl/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: pl_PL\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Nazwa lub adres serwera" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Port transmisji" - msgctxt "#30003" msgid "Username" msgstr "Użytkownik" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Hasło" +msgctxt "#30005" +msgid "Connection" +msgstr "Połączenie" + +msgctxt "#30006" +msgid "Icons" +msgstr "Plakaty" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Limit czasu odpowiedzi w sekundach" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Folder z ikonami" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Częstotliwość aktualizacji w minutach" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatyczne czyszczenie harmonogramu nagrań" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Port interfejsu webowego" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Przełączaj na dany kanał (np. dla dekoderów z jednym tunerem)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Folder danych kanałów" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Sprawdzaj aktualizacje bukietów" +msgid "Update interval" +msgstr "Częstotliwość aktualizacji" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,93 @@ msgid "Recording folder on the receiver" msgstr "Folder nagrywania na dekoderze" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Wysyłaj polecenie głębokiego czuwania" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Pobieraj tylko jeden bukiet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "Bukiet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Pobieraj loga kanałów przez interfejs webowy" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Używaj zabezpieczonego HTTP (HTTPS)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Konfiguruj transmisje na żywo automatycznie" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Zachowuj strukturę folderów nagrań" + +msgctxt "#30032" +msgid "EPG" +msgstr "Przewodnik" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Strumieniowanie" + +msgctxt "#30042" +msgid "Never" +msgstr "Nigdy" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "W przewodniku" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "W nagraniach" + +msgctxt "#30045" +msgid "Always" +msgstr "Zawsze" + +msgctxt "#30051" +msgid "Login" +msgstr "Użytkownik" + +msgctxt "#30052" +msgid "Misc" +msgstr "Dodatkowe" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Przesunięcie czasowe" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Folderu bufora przesunięcia czasowego" + +msgctxt "#30063" +msgid "Off" +msgstr "Nieaktywne" + +msgctxt "#30064" +msgid "On playback" +msgstr "Po rozpoczęciu odtwarzania" + +msgctxt "#30065" +msgid "On pause" +msgstr "Po wstrzymaniu odtwarzania" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Nagrania" + +msgctxt "#30072" +msgid "Timers" +msgstr "Zadania" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automat" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Jednorazowo (zaplanowane przez regułę bazująca na przewodniku)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Nieaktywny" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Nagrywaj, gdy tytuł w przewodniku się różni" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -122,4 +174,8 @@ msgctxt "#30501" msgid "Reconnected to '%s'" -msgstr "Ponownie połączono z '%s'" +msgstr "Połączono ponownie z '%s'" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Folderu bufora przesunięcia czasowego nie istnieje" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.pt_br/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.pt_br/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.pt_br/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.pt_br/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: pt_BR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Hostname VU+ ou endereço IP" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Porta de Streaming" - msgctxt "#30003" msgid "Username" msgstr "Nome do usuário" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Senha" +msgctxt "#30005" +msgid "Connection" +msgstr "Conexão" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ícones" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Tempo limite para resposta em segundos" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Caminho do ícone" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Intervalo de atualizações em minutos" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Limpar Timerlist automaticamente" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Porta da Interface Web" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zapear antes de trocar canal (isto é, para conversores com sintonizador único)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Pasta para dados dos canais" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Verificar atualizações de bouquett" +msgid "Update interval" +msgstr "Intervalo de atualização" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,85 @@ msgid "Recording folder on the receiver" msgstr "Pasta de gravações no receptor" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Enviar comando de Standby Profundo" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Buscar apenas um TV bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Buscar picons da webinterface" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Usar HTTP com segurança (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Ativar configuração automática para streams ao vivo" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Mantenha estrutura da pasta para gravações" + +msgctxt "#30032" +msgid "EPG" +msgstr "Guia" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Streaming" + +msgctxt "#30042" +msgid "Never" +msgstr "Nunca" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Somente no EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Somente em gravações" + +msgctxt "#30045" +msgid "Always" +msgstr "Sempre" + +msgctxt "#30051" +msgid "Login" +msgstr "Login" + +msgctxt "#30052" +msgid "Misc" +msgstr "Misc" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Mudança de horário" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Caminho do buffer de gravação" + +msgctxt "#30063" +msgid "Off" +msgstr "Desligado" + +msgctxt "#30064" +msgid "On playback" +msgstr "Na reprodução" + +msgctxt "#30065" +msgid "On pause" +msgstr "Na pausa" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Gravações" + +msgctxt "#30072" +msgid "Timers" +msgstr "Agendamentos" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automático" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Desabilitado" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.pt_pt/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.pt_pt/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.pt_pt/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.pt_pt/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: pt_PT\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Nome ou endereço IP do servidor VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Porta de transmissão" - msgctxt "#30003" msgid "Username" msgstr "Nome de utilizador" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Palavra-passe" +msgctxt "#30005" +msgid "Connection" +msgstr "Ligação" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ícones" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Tempo limite para resposta (segundos)" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Caminho do ícone" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Intervalo de atualização (minutos)" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Limpeza automática da Timerlist" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Porta da interface web" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap antes de mudar de canal (útil para caixas só com um sintonizador)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Pasta para dados do canais" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Procurar atualizações do bouquett" +msgid "Update interval" +msgstr "Intervalo de atualização " msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,73 @@ msgid "Recording folder on the receiver" msgstr "Pasta de gravação no recetor" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Enviar comando de DeepStandby" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Obter apenas um TV bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Obter ícones da interface web" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Utilizar HTTP seguro (https)" +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30042" +msgid "Never" +msgstr "Nunca" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Apenas em EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Apenas em gravações" + +msgctxt "#30045" +msgid "Always" +msgstr "Sempre" + +msgctxt "#30051" +msgid "Login" +msgstr "Iniciar sessão" + +msgctxt "#30052" +msgid "Misc" +msgstr "Outras" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Ver Mais Tarde" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Localização do buffer para 'Ver Mais Tarde'" + +msgctxt "#30063" +msgid "Off" +msgstr "Desligado" + +msgctxt "#30064" +msgid "On playback" +msgstr "Ao reproduzir" + +msgctxt "#30065" +msgid "On pause" +msgstr "Ao pausar" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Gravações" + +msgctxt "#30072" +msgid "Timers" +msgstr "Temporizadores" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automático" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Desativado" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ro_ro/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ro_ro/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ro_ro/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ro_ro/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: ro_RO\n" "Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ hostname sau IP address" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Portul de streaming" - msgctxt "#30003" msgid "Username" msgstr "Utilizator" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Parolă" +msgctxt "#30005" +msgid "Connection" +msgstr "Conexiune" + +msgctxt "#30006" +msgid "Icons" +msgstr "Imagini" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Expirare timp conexiune în secunde" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Adresa pictogramei " - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Intervalul de actualizare în minute" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Ștergere automata a listelor de înregistrare programată" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Portul interfaței web" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zap înainte de schimbarea canalului (ex. pentru decodoarele cu un singur tuner)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Dosarul pentru informațiile canalelor" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Verifică actualizarea buchetului" +msgid "Update interval" +msgstr "Interval actualizare" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,77 @@ msgid "Recording folder on the receiver" msgstr "Dosarul de înregistrari în decodor" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Trimite comandă - DeepStandby" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Adună date doar pentru un buchet TV" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Descarcă picons direct din interfața web" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Folosește HTTP sigur (https)" +msgctxt "#30032" +msgid "EPG" +msgstr "Ghid program electronic" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Difuzare în flux" + +msgctxt "#30042" +msgid "Never" +msgstr "Niciodată" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Doar în ghidul tv" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Doar în înregistrări" + +msgctxt "#30045" +msgid "Always" +msgstr "Întotdeauna" + +msgctxt "#30051" +msgid "Login" +msgstr "Autentificare" + +msgctxt "#30052" +msgid "Misc" +msgstr "Diverse" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Decalaj temporal" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Calea buffer-ului de înregistrare" + +msgctxt "#30063" +msgid "Off" +msgstr "Oprită" + +msgctxt "#30064" +msgid "On playback" +msgstr "La redare" + +msgctxt "#30065" +msgid "On pause" +msgstr "La pauzare" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Înregistrări" + +msgctxt "#30072" +msgid "Timers" +msgstr "Cronometre" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automat" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Dezactivat" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ru_ru/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ru_ru/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ru_ru/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ru_ru/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: ru_RU\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Имя VU+ хоста или IP-адрес" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Порт видео-потока" - msgctxt "#30003" msgid "Username" msgstr "Пользователь" @@ -32,37 +24,33 @@ msgid "Password" msgstr "Пароль" +msgctxt "#30005" +msgid "Connection" +msgstr "Соединение" + +msgctxt "#30006" +msgid "Icons" +msgstr "Значки" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Тайм-аут отклика в секундах" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Путь к значкам" +msgctxt "#30009" +msgid "Update Interval" +msgstr "Интервал обновления" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Интервал обновления в минутах" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Авто-очистка таймеров" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Порт веб-интерфейса" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Сброс перед переключением канала (для одно-тюнерных устройств)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Папка для данных о каналах" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Проверять обновления букетов" +msgid "Update interval" +msgstr "Интервал обновления" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +84,109 @@ msgid "Recording folder on the receiver" msgstr "Папка для записей на ресивере" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Послать команду DeepStandby" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Выбрать только один букет" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-букет" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Брать лого каналов из вебинтерфейса" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Использовать защищенный HTTP протокол (https) " +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Включить автоматическую настройку для прямых трансляций" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Хранить структуру папок для записей" + +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30035" +msgid "Use picons.eu file format" +msgstr "Использовать файлы в формате picons.eu" + +msgctxt "#30042" +msgid "Never" +msgstr "Никогда" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Только в EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Только в записях" + +msgctxt "#30045" +msgid "Always" +msgstr "Всегда" + +msgctxt "#30051" +msgid "Login" +msgstr "Логин" + +msgctxt "#30052" +msgid "Misc" +msgstr "Разное" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Таймшифт" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Путь к буферу таймшифт" + +msgctxt "#30063" +msgid "Off" +msgstr "Выкл." + +msgctxt "#30064" +msgid "On playback" +msgstr "Воспроизводится" + +msgctxt "#30065" +msgid "On pause" +msgstr "На паузе" + +msgctxt "#30070" +msgid "Recordings & Timers" +msgstr "Запись и планирование" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Записи" + +msgctxt "#30072" +msgid "Timers" +msgstr "Таймеры" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Автоматически" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Единоразово (по расписанию планировщика на основе руководства)" + +msgctxt "#30421" +msgid "One time (Scheduled by repeating timer rule)" +msgstr "Единоразово (по расписанию на основе правил планировщика)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Откл." + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Записывать, даже если название телепередачи не совпадает" + +msgctxt "#30432" +msgid "Record if EPG title and short description differs" +msgstr "Записывать, даже если не совпадает название и краткое описание телепередачи" + +msgctxt "#30433" +msgid "Record if EPG title and all descriptions differ" +msgstr "Записывать, даже если не совпадает название и описание телепередачи" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +195,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Подключено к '%s'" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Отсутствует путь для буферизации отложенного просмотра" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.si_lk/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.si_lk/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.si_lk/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.si_lk/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -24,6 +24,10 @@ msgid "Password" msgstr "මුරපදය" +msgctxt "#30006" +msgid "Icons" +msgstr "සුරුවම් " + msgctxt "#30018" msgid "General" msgstr "සාමාන්‍ය" @@ -35,3 +39,23 @@ msgctxt "#30021" msgid "HTTP" msgstr "HTTP" + +msgctxt "#30042" +msgid "Never" +msgstr "කිසි විටෙකත් නැති " + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "කාල සාරු අවරෝධක පෙත" + +msgctxt "#30063" +msgid "Off" +msgstr "වහනවා" + +msgctxt "#30071" +msgid "Recordings" +msgstr "පටිගතකිරීම්" + +msgctxt "#30430" +msgid "Disabled" +msgstr "අක්‍රිය කර ඇත." diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.sk_sk/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.sk_sk/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.sk_sk/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.sk_sk/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: sk_SK\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Sieťový názov VU+ zariadenia (názov hostiteľa) alebo IP adresa" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Port pre streamovanie" - msgctxt "#30003" msgid "Username" msgstr "Užívateľské meno" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Heslo" +msgctxt "#30005" +msgid "Connection" +msgstr "Pripojenie" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikony" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Časový limit pre odozvu v sekundách" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Cesta k ikonám" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Interval aktualizácie v minútach" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatické čistenie zoznamu časovačov" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Port pre webové rozhranie" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Vypnúť zobrazenie aktuálneho kanálu pred prepnutím (napr. pre jednotunerové prijímače)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Priečinok pre dáta kanálov" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Kontrolovať dostupnosť aktualizácií obľúbených skupín programov" +msgid "Update interval" +msgstr "Doba aktualizácie" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,89 @@ msgid "Recording folder on the receiver" msgstr "Priečinok pre nahrávky v prijímači" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Posielať príkaz pre uspanie prijímača" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Vyvolať len jednu obľúbenú skupinu TV programov" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "Obľúbená skupina TV programov" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Získať logá TV staníc z webového rozhrania" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Použiť Secure HTTP (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Povoliť automatickú konfiguráciu pre živé streamy" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Zachovať pri nahrávkach štruktúru priečinkov" + +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30042" +msgid "Never" +msgstr "Nikdy" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Iba v EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Iba v nahrávkach" + +msgctxt "#30045" +msgid "Always" +msgstr "Vždy" + +msgctxt "#30051" +msgid "Login" +msgstr "Prihlasovavie meno" + +msgctxt "#30052" +msgid "Misc" +msgstr "Rôzne" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Časový posun" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Cesta k zásobníku časového posunu" + +msgctxt "#30063" +msgid "Off" +msgstr "Vypnuté" + +msgctxt "#30064" +msgid "On playback" +msgstr "Pri prehrávaní" + +msgctxt "#30065" +msgid "On pause" +msgstr "Pri pozastavení" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Nahrávky" + +msgctxt "#30072" +msgid "Timers" +msgstr "Časovače" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automaticky" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "Jednorazovo (naplánované pravidlom časovača TV programu)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Zakázané" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Nahrávať, ak sa titul v EPG odlišuje" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +171,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Opätovne pripojený k '%s'" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Cesta k zásobníku časového posunu neexistuje" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.sl_si/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.sl_si/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.sl_si/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.sl_si/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: sl_SI\n" "Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Ime gostitelja ali IP strežnika VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Vrata za pretakanje" - msgctxt "#30003" msgid "Username" msgstr "Uporabniško ime" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Geslo" +msgctxt "#30005" +msgid "Connection" +msgstr "Povezava" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikone" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Čas preteka odgovora v sekundah" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Pot ikon" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Interval posodabljanja v minutah" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Samodejno čiščenje seznama časovnikov" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Vrata spletnega vmesnika" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zamenjaj program tudi na sprejemniku" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Mapa za podatke o programih" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Preveri za posodobitve skupin" +msgid "Update interval" +msgstr "Interval posodabljanja" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,69 @@ msgid "Recording folder on the receiver" msgstr "Mapa snemanja na sprejemniku" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Pošlji ukaz za prehod v stanje pripravljenosti" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Prenesi le eno skupino" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "Skupina programov" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Prenesi ikone s spletnega vmesnika" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Uporabi varen HTTP (https)" +msgctxt "#30032" +msgid "EPG" +msgstr "EPV" + +msgctxt "#30042" +msgid "Never" +msgstr "Nikoli" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Samo v EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Samo v posnetkih" + +msgctxt "#30045" +msgid "Always" +msgstr "Vedno" + +msgctxt "#30051" +msgid "Login" +msgstr "Prijava" + +msgctxt "#30052" +msgid "Misc" +msgstr "Razno" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Časovni zamik" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Pot medpomnenja časovnega zamika" + +msgctxt "#30063" +msgid "Off" +msgstr "Izključeno" + +msgctxt "#30064" +msgid "On playback" +msgstr "Ob predvajanju" + +msgctxt "#30065" +msgid "On pause" +msgstr "Ob prekinitvi" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Posnetki" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Samodejno" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Onemogočeno" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.sq_al/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.sq_al/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.sq_al/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.sq_al/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: sq_AL\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ hostname ose adresa IP" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Porti i transmetimit" - msgctxt "#30003" msgid "Username" msgstr "Emër-përdoruesi" @@ -32,38 +24,22 @@ msgid "Password" msgstr "Fjalëkalimi" +msgctxt "#30006" +msgid "Icons" +msgstr "Ikona" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Timeout i përgjigjjes në eskonda" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Vendndodhja e ikonave" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Interval i aktualizimit në minuta" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Pastrimi i Orarit automatikisht" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Webinterface porti" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Parashikimi i kanaleve para ndrimit tëi një kanali (p.sh. për aparate me Single Tuner )" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Rregjistri për informacionet të kanaleve" -msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Shikoni për aktualizime të buketit" - msgctxt "#30016" msgid "Check for channel updates" msgstr "Shikoni për aktualizime të kanaleve" @@ -96,21 +72,29 @@ msgid "Recording folder on the receiver" msgstr "Regjistër i regjistrimeve në resiverin" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Dërgo komand DeepStandby" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Shkarko vetëm një TV buket" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Buket" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Tërhiqni pikon'at nga webinterface" +msgctxt "#30042" +msgid "Never" +msgstr "Kurrë" + +msgctxt "#30045" +msgid "Always" +msgstr "Gjithnjë" + +msgctxt "#30063" +msgid "Off" +msgstr "Hequr" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Rregjistrime" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Deaktivuar" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.sr_rs/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.sr_rs/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.sr_rs/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.sr_rs/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "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 "VU+ hostname or IP address" -msgstr "VU+ hostname или IP адреса" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Порт за Стримовање" - msgctxt "#30003" msgid "Username" msgstr "Корисничко име" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Лозинка" +msgctxt "#30005" +msgid "Connection" +msgstr "Веза" + +msgctxt "#30006" +msgid "Icons" +msgstr "Иконе" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Истек времена за одзив у секундама" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Путања Икона" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Интервал ажурирања у минутима" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Аутоматско Чишћење Листе Тајмера" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Порт Web интерфејса" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Искључи пре промене програма (нпр. за кутије са једним пријемником)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Фасцикла за податке канала" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Провери за bouquett новије верзије" +msgid "Update interval" +msgstr "Интервал ажурирања" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,77 @@ msgid "Recording folder on the receiver" msgstr "Фасцикла за снимање на пријемнику" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Пошаљи Команду Дубоке Приправности" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Преузми само један ТВ bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "ТВ-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Преузми picons од web интерфејса" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Користи Сигурни HTTP (https)" +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Стримовање" + +msgctxt "#30042" +msgid "Never" +msgstr "Никада" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Само у EPG-у" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Само у снимцима" + +msgctxt "#30045" +msgid "Always" +msgstr "Увек" + +msgctxt "#30051" +msgid "Login" +msgstr "Пријава" + +msgctxt "#30052" +msgid "Misc" +msgstr "Остало" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Померај времена" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Путања међумеморије помераја времена" + +msgctxt "#30063" +msgid "Off" +msgstr "Искључено" + +msgctxt "#30064" +msgid "On playback" +msgstr "При започињању репродукције" + +msgctxt "#30065" +msgid "On pause" +msgstr "При паузирању" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Снимци" + +msgctxt "#30072" +msgid "Timers" +msgstr "Тајмери" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Аутоматски" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Онемогућено" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.sr_rs@latin/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.sr_rs@latin/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.sr_rs@latin/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.sr_rs@latin/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: sr_RS@latin\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ hostname ili IP adresa" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Port za Strimovanje" - msgctxt "#30003" msgid "Username" msgstr "Korisničko ime" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Lozinka" +msgctxt "#30005" +msgid "Connection" +msgstr "Veza" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikone" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Istek vremena za odziv u sekundama" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Putanja Ikona" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Interval ažuriranja u minutima" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatsko Čišćenje Liste Tajmera" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Port Web interfejsa" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Isključi pre promene programa (npr. za kutije sa jednim prijemnikom)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Fascikla za podatke kanala" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Proveri za bouquett novije verzije" +msgid "Update interval" +msgstr "Interval ažuriranja" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,77 @@ msgid "Recording folder on the receiver" msgstr "Fascikla za snimanje na prijemniku" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Pošalji Komandu Duboke Pripravnosti" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Preuzmi samo jedan TV bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Preuzmi picons od web interfejsa" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Koristi Sigurni HTTP (https)" +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Strimovanje" + +msgctxt "#30042" +msgid "Never" +msgstr "Nikada" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Samo u EPG-u" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Samo u snimcima" + +msgctxt "#30045" +msgid "Always" +msgstr "Uvek" + +msgctxt "#30051" +msgid "Login" +msgstr "Prijava" + +msgctxt "#30052" +msgid "Misc" +msgstr "Ostalo" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Pomeraj vremena" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Putanja međumemorije pomeraja vremena" + +msgctxt "#30063" +msgid "Off" +msgstr "Isključeno" + +msgctxt "#30064" +msgid "On playback" +msgstr "Pri započinjanju reprodukcije" + +msgctxt "#30065" +msgid "On pause" +msgstr "Pri pauziranju" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Snimci" + +msgctxt "#30072" +msgid "Timers" +msgstr "Tajmeri" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatski" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Onemogućeno" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.sv_se/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.sv_se/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.sv_se/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.sv_se/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: sv_SE\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ värdnamn eller IP-adress" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Strömningsport" - msgctxt "#30003" msgid "Username" msgstr "Användarnamn" @@ -32,37 +24,33 @@ msgid "Password" msgstr "Lösenord" +msgctxt "#30005" +msgid "Connection" +msgstr "Anslutning" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikoner" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Anslutningstimeout i sekunder" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Ikonsökväg" +msgctxt "#30009" +msgid "Update Interval" +msgstr "Uppdatera intervall" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Uppdateringsintervall i minuter" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Automatisk timerlistsrensning" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Webbgränssnittsport" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Zappa före kanalbyte (för enkeltuner boxar)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Mapp för kanaldata" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Sök efter bukett-uppdateringar" +msgid "Update interval" +msgstr "Uppdateringsintervall" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +84,113 @@ msgid "Recording folder on the receiver" msgstr "Inspelningsmapp på mottagaren" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Skicka djupstandby-kommando" - msgctxt "#30025" msgid "Fetch only one TV bouquet" -msgstr "Hämta endast en TV-bukett" +msgstr "Hämta endast en tv-bukett" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-bukett" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Använd picons från webinterfacet" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Använd Säker HTTP (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Aktivera automatisk konfiguration för direktsända strömmar" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Behåll mappstruktur för inspelningar" + +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30035" +msgid "Use picons.eu file format" +msgstr "Använd picons.eu filformat" + +msgctxt "#30039" +msgid "Streaming" +msgstr "Strömmning" + +msgctxt "#30042" +msgid "Never" +msgstr "Aldrig" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Endast i EPGn" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Endast i inspelningar" + +msgctxt "#30045" +msgid "Always" +msgstr "Alltid" + +msgctxt "#30051" +msgid "Login" +msgstr "Logga in" + +msgctxt "#30052" +msgid "Misc" +msgstr "Övrigt" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Tidsskifte" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Buffertsökväg för Timeshift " + +msgctxt "#30063" +msgid "Off" +msgstr "Av" + +msgctxt "#30064" +msgid "On playback" +msgstr "Vid uppspelning" + +msgctxt "#30065" +msgid "On pause" +msgstr "Vid paus" + +msgctxt "#30070" +msgid "Recordings & Timers" +msgstr "Inspelningar & Timers" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Inspelningar" + +msgctxt "#30072" +msgid "Timers" +msgstr "Timers" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Automatisk" + +msgctxt "#30420" +msgid "One time (Scheduled by guide-based timer rule)" +msgstr "En gång (Schemalags av guide-baserad tidsregel)" + +msgctxt "#30421" +msgid "One time (Scheduled by repeating timer rule)" +msgstr "En gång (Schemalagd av den upprepade timerregeln)" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Av" + +msgctxt "#30431" +msgid "Record if EPG title differs" +msgstr "Spela in om EPG-titeln skiljer sig" + +msgctxt "#30432" +msgid "Record if EPG title and short description differs" +msgstr "Spela in om EPG-titeln och den korta beskrivningen skiljer sig åt" + +msgctxt "#30433" +msgid "Record if EPG title and all descriptions differ" +msgstr "Spela in om EPG-titeln och alla beskrivningar skiljer sig åt" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +199,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Återansluten till '%s'" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "Sökvägen för Tidsskifte-buffert existerar inte" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.szl/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.szl/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.szl/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.szl/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: szl\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Miano lebo adresa ôd serwera" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Port szpricowaniŏ" - msgctxt "#30003" msgid "Username" msgstr "Miano ôd używŏcza" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Hasło" +msgctxt "#30005" +msgid "Connection" +msgstr "Skuplowanie" + +msgctxt "#30006" +msgid "Icons" +msgstr "Ikōny" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Czas na ôdpowiydź w sekundach" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Cesta do folderu z ikōnami" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Frekwyncyjŏ aktualizacyje we minutach" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Autōmatyczne pucowanie harmonogramu nagrań" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Port interfejsu necowygo" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Szaltruj na dany kanał (bp. dlŏ dekoderōw z jednym tunerym)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Folder datōw kanałōw" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Wybaduj aktualizacyje puketōw" +msgid "Update interval" +msgstr "Interwał ôdnŏwianiŏ" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,65 @@ msgid "Recording folder on the receiver" msgstr "Folder nagrowaniŏ na dekoderze" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Posyłej nakŏzanie głymbokigo wachowaniŏ" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Sebiyrej ino jedyn puket" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "Puket" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Sebiyrej loga kanałōw bez interfejs necowy" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Używej bezpieczōnygo HTTP (HTTPS)" +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30042" +msgid "Never" +msgstr "nigdy" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Ino w EPG" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Ino w nagraniach" + +msgctxt "#30045" +msgid "Always" +msgstr "dycki" + +msgctxt "#30051" +msgid "Login" +msgstr "Wloguj" + +msgctxt "#30052" +msgid "Misc" +msgstr "Roztōmajte" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Timeshift" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Cesta bufora timeshift" + +msgctxt "#30063" +msgid "Off" +msgstr "Zastawiōne" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Spamiyntania" + +msgctxt "#30072" +msgid "Timers" +msgstr "Auftragi" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Autōmat" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Zastawiōne" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ta_in/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ta_in/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.ta_in/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.ta_in/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -24,6 +24,14 @@ msgid "Password" msgstr "அடையாளச் சொல்" +msgctxt "#30006" +msgid "Icons" +msgstr "சின்னங்கள்" + +msgctxt "#30015" +msgid "Update interval" +msgstr "இடைவேளையை மெருகேற்று" + msgctxt "#30018" msgid "General" msgstr "பொதுவானது" @@ -39,3 +47,27 @@ msgctxt "#30021" msgid "HTTP" msgstr "HTTP" + +msgctxt "#30042" +msgid "Never" +msgstr "ஒருபோதும் இல்லை" + +msgctxt "#30045" +msgid "Always" +msgstr "எப்போதும்" + +msgctxt "#30051" +msgid "Login" +msgstr "புகுபதிகை" + +msgctxt "#30063" +msgid "Off" +msgstr "நிறுத்து" + +msgctxt "#30071" +msgid "Recordings" +msgstr "பதிவகள்" + +msgctxt "#30430" +msgid "Disabled" +msgstr "முடக்கப்பட்டன" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.te_in/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.te_in/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.te_in/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.te_in/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.tg_tj/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.tg_tj/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.tg_tj/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.tg_tj/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -24,6 +24,10 @@ msgid "Password" msgstr "Парол" +msgctxt "#30006" +msgid "Icons" +msgstr "Нишонаҳо" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Хотимаи вақти посух дар сонияҳо" @@ -44,6 +48,30 @@ msgid "HTTP" msgstr "HTTP" +msgctxt "#30042" +msgid "Never" +msgstr "Ҳеҷ гоҳ" + +msgctxt "#30045" +msgid "Always" +msgstr "Ҳамеша" + +msgctxt "#30051" +msgid "Login" +msgstr "Вуруд" + +msgctxt "#30063" +msgid "Off" +msgstr "Хомӯш" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Сабтҳо" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Ғайрифаъол" + msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Пайваст бо '%s' қатъ шудааст" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.th_th/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.th_th/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.th_th/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.th_th/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,10 +16,6 @@ "Language: th_TH\n" "Plural-Forms: nplurals=1; plural=0;\n" -msgctxt "#30002" -msgid "Streaming Port" -msgstr "พอร์ตการสตรีมมิ่ง" - msgctxt "#30003" msgid "Username" msgstr "ชื่อผู้ใช้" @@ -28,9 +24,17 @@ msgid "Password" msgstr "รหัสผ่าน" -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "พอร์ต Webinterface" +msgctxt "#30005" +msgid "Connection" +msgstr "การเชื่อมต่อ" + +msgctxt "#30006" +msgid "Icons" +msgstr "ไอคอน" + +msgctxt "#30015" +msgid "Update interval" +msgstr "ช่วงเวลาการปรับปรุง" msgctxt "#30018" msgid "General" @@ -47,3 +51,47 @@ msgctxt "#30021" msgid "HTTP" msgstr "HTTP" + +msgctxt "#30042" +msgid "Never" +msgstr "ไม่เลย" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "ใน EPG เท่านั้น" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "ในการบันทึกเท่านั้น" + +msgctxt "#30045" +msgid "Always" +msgstr "เสมอ" + +msgctxt "#30051" +msgid "Login" +msgstr "ลงชื่อเข้าใช้" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "เส้นทางบัฟเฟอร์ของ Timeshift" + +msgctxt "#30063" +msgid "Off" +msgstr "ปิด" + +msgctxt "#30071" +msgid "Recordings" +msgstr "กำลังบันทึก" + +msgctxt "#30072" +msgid "Timers" +msgstr "ตั้งเวลา" + +msgctxt "#30410" +msgid "Automatic" +msgstr "อัตโนมัติ" + +msgctxt "#30430" +msgid "Disabled" +msgstr "ปิดการใช้งาน" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.tr_tr/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.tr_tr/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.tr_tr/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.tr_tr/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: tr_TR\n" "Plural-Forms: nplurals=1; plural=0;\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ ana bilgisayar adı veya IP adresi" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Yayın Portu" - msgctxt "#30003" msgid "Username" msgstr "Kullanıcı adı" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Parola" +msgctxt "#30005" +msgid "Connection" +msgstr "Bağlantı" + +msgctxt "#30006" +msgid "Icons" +msgstr "Simgeler" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Saniye cinsinden yanıt zaman aşımı süresi" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Simge Yolu" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Güncelleme aralığı dakikası" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Otomatik Zamanlayıcı Listesi Temizleme" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Web arayüzü Portu" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Kanal değişiminden önce değiştir (örn. Tek Alıcılı kutular)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Kanal verisi için klasör" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "bouquett güncellemelerini denetle" +msgid "Update interval" +msgstr "Güncelleme aralığı" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,65 @@ msgid "Recording folder on the receiver" msgstr "Alıcıdaki kayıt klasörü" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Derin Hazırda Beklet komutu yolla" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Sadece tek TV destesi getir" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV Destesi" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Picon'ları web arayüzünden getir" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Güvenli HTTP kullan (https)" +msgctxt "#30032" +msgid "EPG" +msgstr "Elektronik Program Rehberi" + +msgctxt "#30042" +msgid "Never" +msgstr "Asla" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Sadece EPG içinde" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "Sadece kayıtlarda" + +msgctxt "#30045" +msgid "Always" +msgstr "Her zaman" + +msgctxt "#30051" +msgid "Login" +msgstr "Oturum Aç" + +msgctxt "#30052" +msgid "Misc" +msgstr "Çeşitli" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Zaman Kaydırma" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Zaman kaydırma arabellek yolu" + +msgctxt "#30063" +msgid "Off" +msgstr "Kapalı" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Kayıtlar" + +msgctxt "#30072" +msgid "Timers" +msgstr "Zamanlayıcılar" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Otomatik" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Devre dışı" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.uk_ua/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.uk_ua/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.uk_ua/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.uk_ua/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: uk_UA\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Сервер VU+ або адреса IP" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Порт потоку" - msgctxt "#30003" msgid "Username" msgstr "Ім'я користувача" @@ -32,37 +24,29 @@ msgid "Password" msgstr "Пароль" +msgctxt "#30005" +msgid "Connection" +msgstr "Зв’язок" + +msgctxt "#30006" +msgid "Icons" +msgstr "Піктограми" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Затримка відклику в секундах" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Шлях до іконки" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Інтервал оновлення в хвилинах" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Автоматичне очищення списку таймерів" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Порт веб-інтерфейсу" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Схопити сигнал перед переключенням каналу (тобто для одного тюнера)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Тека для даних каналів" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Перевірка на букетне оновлення " +msgid "Update interval" +msgstr "Інтервал оновлень" msgctxt "#30016" msgid "Check for channel updates" @@ -96,21 +80,69 @@ msgid "Recording folder on the receiver" msgstr "Тека записів на ресівері" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Вислати команду глибокої зупинки" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Отримати тільки один TV bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Отримати пікони з веб-інтерфейсу" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "Увімкнути автоматичну конфігурацію для прямих трансляцій" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "Зберігати структуру папок для записів" + +msgctxt "#30032" +msgid "EPG" +msgstr "EPG" + +msgctxt "#30042" +msgid "Never" +msgstr "Ніколи" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "Тільки в EPG" + +msgctxt "#30045" +msgid "Always" +msgstr "Завжди" + +msgctxt "#30051" +msgid "Login" +msgstr " Логін" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "Зрушення в часі" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Шлях до буферу зсуву у часі" + +msgctxt "#30063" +msgid "Off" +msgstr "Вимкн." + +msgctxt "#30064" +msgid "On playback" +msgstr "Під час відтворення" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Записи" + +msgctxt "#30072" +msgid "Timers" +msgstr "Таймери" + +msgctxt "#30410" +msgid "Automatic" +msgstr "Автоматично" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Вимкн." msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.uz_uz/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.uz_uz/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.uz_uz/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.uz_uz/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -24,6 +24,10 @@ msgid "Password" msgstr "Maxfiy so'z" +msgctxt "#30006" +msgid "Icons" +msgstr "Nishonchalar" + msgctxt "#30018" msgid "General" msgstr "Umumiy" @@ -35,3 +39,19 @@ msgctxt "#30021" msgid "HTTP" msgstr "HTTP" + +msgctxt "#30042" +msgid "Never" +msgstr "Hech qachon" + +msgctxt "#30045" +msgid "Always" +msgstr "Doim" + +msgctxt "#30051" +msgid "Login" +msgstr "Kirish" + +msgctxt "#30063" +msgid "Off" +msgstr "O'chirilgan" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.vi_vn/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.vi_vn/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.vi_vn/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.vi_vn/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: vi_VN\n" "Plural-Forms: nplurals=1; plural=0;\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "Tên miền hoặc địa chỉ IP của VU+" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "Cổng Streaming" - msgctxt "#30003" msgid "Username" msgstr "Tên truy cập" @@ -32,38 +24,26 @@ msgid "Password" msgstr "Mật khẩu" +msgctxt "#30005" +msgid "Connection" +msgstr "Kết nối" + +msgctxt "#30006" +msgid "Icons" +msgstr "Biểu tượng" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Số giây tự ngắt chờ kết nối" -msgctxt "#30008" -msgid "Icon Path" -msgstr "Đường dẫn biểu tượng" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Số phút tự cập nhật lại" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "Tự động xoá danh sách hẹn giờ" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Cổng Webinterface" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "Tắt trước khi chuyển kênh (ví dụ cho các Single Tuner box)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "Thư mục đặt dữ liệu cho kênh" -msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "Kiểm tra cập nhật bouquett" - msgctxt "#30016" msgid "Check for channel updates" msgstr "Kiểm tra cập nhật kênh" @@ -96,25 +76,37 @@ msgid "Recording folder on the receiver" msgstr "Thư mục lưu trên thiết bị" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "Gửi lệnh Chế Độ Chờ" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "Chỉ lấy một TV bouquet" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "TV-Bouquet" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "Lấy các hình icon từ mạng" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "Sử dụng an toàn HTTP (https)" +msgctxt "#30042" +msgid "Never" +msgstr "Không bao giờ" + +msgctxt "#30045" +msgid "Always" +msgstr "Luôn luôn" + +msgctxt "#30051" +msgid "Login" +msgstr "Đăng nhập" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "Đường dẫn bộ đệm Timeshift" + +msgctxt "#30063" +msgid "Off" +msgstr "Tắt" + +msgctxt "#30071" +msgid "Recordings" +msgstr "Các bản ghi" + +msgctxt "#30430" +msgid "Disabled" +msgstr "Đã tắt" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.zh_cn/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.zh_cn/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.zh_cn/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.zh_cn/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+ 主机名或 IP 地址" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "流媒体端口" - msgctxt "#30003" msgid "Username" msgstr "用户名" @@ -32,37 +24,29 @@ msgid "Password" msgstr "密码" +msgctxt "#30005" +msgid "Connection" +msgstr "连接" + +msgctxt "#30006" +msgid "Icons" +msgstr "图标" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "响应超时(秒)" -msgctxt "#30008" -msgid "Icon Path" -msgstr "图标路径" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "更新间隔(分)" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "自动清除定时器列表" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Web 界面端口" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "频道切换前清屏(如单调谐器机顶盒)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "频道数据文件夹" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "检查频道组更新" +msgid "Update interval" +msgstr "更新间隔" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,81 @@ msgid "Recording folder on the receiver" msgstr "接收器上的录像文件夹" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "发送 DeepStandby 命令" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "仅获取一个电视频道组" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "电视频道组" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "从 Web 界面获取 picons" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "使用安全连接(https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "启用直播流自动设置" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "保留录像文件夹结构" + +msgctxt "#30032" +msgid "EPG" +msgstr "电子节目单" + +msgctxt "#30042" +msgid "Never" +msgstr "从不" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "仅电子节目单中" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "仅录像中" + +msgctxt "#30045" +msgid "Always" +msgstr "总是" + +msgctxt "#30051" +msgid "Login" +msgstr "登录" + +msgctxt "#30052" +msgid "Misc" +msgstr "杂项" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "时光平移" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "时光平移缓存路径" + +msgctxt "#30063" +msgid "Off" +msgstr "关" + +msgctxt "#30064" +msgid "On playback" +msgstr "播放中" + +msgctxt "#30065" +msgid "On pause" +msgstr "暂停中" + +msgctxt "#30071" +msgid "Recordings" +msgstr "录像" + +msgctxt "#30072" +msgid "Timers" +msgstr "定时器" + +msgctxt "#30410" +msgid "Automatic" +msgstr "自动" + +msgctxt "#30430" +msgid "Disabled" +msgstr "已禁用" msgctxt "#30500" msgid "Disconnected from '%s'" @@ -123,3 +163,7 @@ msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "重新连接到“%s”" + +msgctxt "#30514" +msgid "Timeshift buffer path does not exist" +msgstr "TimeShift缓存路径不存在" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.zh_tw/strings.po kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.zh_tw/strings.po --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/language/resource.language.zh_tw/strings.po 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/language/resource.language.zh_tw/strings.po 2018-11-05 17:50:27.000000000 +0000 @@ -1,11 +1,11 @@ # Kodi Media Center language file -# Addon Name: VU+ / Enigma2 Client +# Addon Name: Enigma2 Client # Addon id: pvr.vuplus -# Addon Provider: Joerg Dembski +# Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" -"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" @@ -16,14 +16,6 @@ "Language: zh_TW\n" "Plural-Forms: nplurals=1; plural=0;\n" -msgctxt "#30000" -msgid "VU+ hostname or IP address" -msgstr "VU+主機名稱或IP位址" - -msgctxt "#30002" -msgid "Streaming Port" -msgstr "串流連接埠" - msgctxt "#30003" msgid "Username" msgstr "帳號" @@ -32,37 +24,29 @@ msgid "Password" msgstr "密碼" +msgctxt "#30005" +msgid "Connection" +msgstr "連接" + +msgctxt "#30006" +msgid "Icons" +msgstr "圖示" + msgctxt "#30007" msgid "Response timeout in seconds" msgstr "回應逾時 (秒)" -msgctxt "#30008" -msgid "Icon Path" -msgstr "圖示路徑" - msgctxt "#30010" msgid "Update Interval in minutes" msgstr "更新頻率 (分)" -msgctxt "#30011" -msgid "Automatic Timerlist Cleanup" -msgstr "自動清除定時器清單" - -msgctxt "#30012" -msgid "Webinterface Port" -msgstr "Web介面端口" - -msgctxt "#30013" -msgid "Zap before channelswitch (i.e. for Single Tuner boxes)" -msgstr "頻道切換前修正 (i.e.針對單頻電視盒)" - msgctxt "#30014" msgid "Folder for channeldata" msgstr "channeldata的資料夾" msgctxt "#30015" -msgid "Check for bouquett updates" -msgstr "檢查節目群組更新" +msgid "Update interval" +msgstr "更新間隔" msgctxt "#30016" msgid "Check for channel updates" @@ -96,25 +80,81 @@ msgid "Recording folder on the receiver" msgstr "接收器上的錄影資料夾" -msgctxt "#30024" -msgid "Send DeepStandby-Command" -msgstr "傳送 DeepStandby-Command" - msgctxt "#30025" msgid "Fetch only one TV bouquet" msgstr "只取單一電視節目群組" -msgctxt "#30026" -msgid "TV-Bouquet" -msgstr "電視節目群組" - -msgctxt "#30027" -msgid "Fetch picons from webinterface" -msgstr "從Web界面獲取picons" - -msgctxt "#30028" -msgid "Use Secure HTTP (https)" -msgstr "使用安全協定 (https)" +msgctxt "#30029" +msgid "Enable automatic configuration for live streams" +msgstr "開啟即時串流的自動配置" + +msgctxt "#30030" +msgid "Keep folder structure for records" +msgstr "保留錄影的資料夾架構" + +msgctxt "#30032" +msgid "EPG" +msgstr "電子節目表" + +msgctxt "#30042" +msgid "Never" +msgstr "永不" + +msgctxt "#30043" +msgid "In EPG only" +msgstr "僅限有在電子節目表中的" + +msgctxt "#30044" +msgid "In recordings only" +msgstr "僅限有在錄影檔中的" + +msgctxt "#30045" +msgid "Always" +msgstr "總是" + +msgctxt "#30051" +msgid "Login" +msgstr "登入" + +msgctxt "#30052" +msgid "Misc" +msgstr "雜項" + +msgctxt "#30060" +msgid "Timeshift" +msgstr "時間平移" + +msgctxt "#30062" +msgid "Timeshift buffer path" +msgstr "時間平移緩衝路徑" + +msgctxt "#30063" +msgid "Off" +msgstr "關閉" + +msgctxt "#30064" +msgid "On playback" +msgstr "當播放中" + +msgctxt "#30065" +msgid "On pause" +msgstr "當暫停中" + +msgctxt "#30071" +msgid "Recordings" +msgstr "錄影檔" + +msgctxt "#30072" +msgid "Timers" +msgstr "定時" + +msgctxt "#30410" +msgid "Automatic" +msgstr "自動" + +msgctxt "#30430" +msgid "Disabled" +msgstr "關閉" msgctxt "#30500" msgid "Disconnected from '%s'" diff -Nru kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/settings.xml kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/settings.xml --- kodi-pvr-vuplus-2.4.12/pvr.vuplus/resources/settings.xml 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/pvr.vuplus/resources/settings.xml 2018-11-21 13:14:33.000000000 +0000 @@ -1,30 +1,530 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +
+ + + + + + 0 + 127.0.0.1 + + + + 0 + 80 + + 1 + 1 + 65535 + + + + + 0 + false + + + + + + 0 + + + true + + + + + 0 + + + true + + + true + + + + + + 0 + false + + + + 0 + 8001 + + 1 + 1 + 65535 + + + false + + + + + 0 + false + + false + + + + + 0 + false + + false + + + + + + + + + + + 0 + true + + + + 0 + false + + true + + + + + 0 + + + true + true + + + false + + + 657 + + + + + + + 0 + 2 + + 1 + 1 + 1440 + + + true + 14044 + + + + 0 + 0 + + + + + + + + + + + + + + + + 0 + false + + + + + + 0 + 0 + + + + + + + + + + + 0 + + + true + + + 1 + + + + + 0 + 0 + + + + + + + + + + + 0 + 1 + + + + + + + + + 0 + 2 + + + + + + + + + + + 0 + + + true + + + 1 + + + + + 0 + 0 + + + + + + + + + + + 0 + 1 + + + + + + + + + + + + + 0 + false + + + + 0 + special://userdata/addon_data/pvr.vuplus/showInfo/English-ShowInfo.xml + + false + false + + + true + + + 1033 + + + + + + 0 + false + + + + 0 + special://userdata/addon_data/pvr.vuplus/genres/genreIdMappings/Sky-UK.xml + + false + false + + + true + + + 1033 + + + + + + 0 + false + + + + 0 + special://userdata/addon_data/pvr.vuplus/genres/genreRytecTextMappings/Rytec-UK-Ireland.xml + + false + false + + + true + + + 1033 + + + + 0 + false + + true + + + + + + + + + + + 0 + + + true + + + + + 0 + false + + + + 0 + false + + + + + + + 0 + true + + + + 0 + 1 + + 1 + 1 + 10 + + + true + + + + + 0 + true + + + + 0 + false + + + + + + + + + + 0 + 0 + + + + + + + + + + + 0 + + + true + true + + + 0 + + + 657 + + + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + 0 + 1 + 60 + + + true + 14045 + + + + 0 + 0 + + 0 + 4 + 128 + + + true + 14049 + + + + + + + + +
diff -Nru kodi-pvr-vuplus-2.4.12/README.md kodi-pvr-vuplus-3.15.0/README.md --- kodi-pvr-vuplus-2.4.12/README.md 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/README.md 2018-11-18 11:16:20.000000000 +0000 @@ -1,8 +1,12 @@ [![Build Status](https://travis-ci.org/kodi-pvr/pvr.vuplus.svg?branch=master)](https://travis-ci.org/kodi-pvr/pvr.vuplus) [![Coverity Scan Build Status](https://scan.coverity.com/projects/5120/badge.svg)](https://scan.coverity.com/projects/5120) -# VuPlus PVR -VuPlus PVR client addon for [Kodi] (http://kodi.tv) +Enigma2 is a open source TV-receiver/DVR platform which Linux-based firmware (OS images) can be loaded onto many Linux-based set-top boxes (satellite, terrestrial, cable or a combination of these) from different manufacturers. + +This addon leverage the OpenWebIf project: (https://github.com/E2OpenPlugins/e2openplugin-OpenWebif) + +# Enigma2 PVR +VuPlus PVR client addon for [Kodi] (https://kodi.tv) ## Build instructions @@ -11,10 +15,150 @@ 1. `git clone https://github.com/xbmc/xbmc.git` 2. `git clone https://github.com/kodi-pvr/pvr.vuplus.git` 3. `cd pvr.vuplus && mkdir build && cd build` -4. `cmake -DADDONS_TO_BUILD=pvr.vuplus -DADDON_SRC_PREFIX=../.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=../../xbmc/addons -DPACKAGE_ZIP=1 ../../xbmc/project/cmake/addons` +4. `cmake -DADDONS_TO_BUILD=pvr.vuplus -DADDON_SRC_PREFIX=../.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=../../xbmc/addons -DPACKAGE_ZIP=1 ../../xbmc/cmake/addons` 5. `make` ##### Useful links -* [Kodi's PVR user support] (http://forum.kodi.tv/forumdisplay.php?fid=167) -* [Kodi's PVR development support] (http://forum.kodi.tv/forumdisplay.php?fid=136) +* [Kodi's PVR user support] (https://forum.kodi.tv/forumdisplay.php?fid=167) +* [Kodi's PVR development support] (https://forum.kodi.tv/forumdisplay.php?fid=136) + +## Configuring the addon + +### Connection +Within this tab the connection options need to be configured before it can be successfully enabled. + +* **Enigma2 hostname or IP address**: The IP address or hostname of your enigma2 based set-top box. +* **Web interface port**: The port used to connect to the web interface +* **Use secure HTTP (https)**: Use https to connect to the web interface +* **Username**: If the webinterface of the set-top box is protected with a username / password combination this needs to be set in this option. +* **Password**: If the webinterface of the set-top box is protected with a username / password combination this needs to be set in this option. +* **Enable automatic configuration for live streams**: When enabled the stream URL will be read from an M3U file. When disabled it is constructed based on the filename. +* **Streaming port**: This option defines the streaming port the set-top box uses to stream live tv. The default is 8001 which should be fine if the user did not define a custom port within the webinterface. +Webinterface Port: This option defines the port that should be used to access the webinterface of the set-top box. +* **Use secure HTTP (https) for streams**: Use https to connect to streams +* **Use login for streams**: Use the login username and password for streams + +### General +Within this tab general options are configured. + +* **Fetch picons from web interface**: Fetch the picons straight from the Enigma 2 set-top box. +* **Use picons.eu file formate**: Assume all picons files fetched from the set-top box start with `1_1_1_` and end with `_0_0_0` +* **Icon path**: In order to have Kodi display channel logos you have to copy the picons from your set-top box onto your OpenELEC machine. You then need to specify this path in this property. +* **Update interval**: As the set-top box can also be used to modify timers, delete recordings etc. and the set-top box does not notify the Kodi installation, the addon needs to regularly check for updates (new channels, new/changed/deletes timers, deleted recordings, etc.) This property defines how often the addon checks for updates. +* **Update mode**: The mode used when the update interval is reached. Note that if there is any timer change detected a recordings update will always occur regardless of the update mode. Choose from one of the following two modes: + - `Timers and Recordings` - Update all timers and recordings. + - `Timers only` - Only update the timers. + +### Channels +Within this tab options that refer to channel data can be set. When changing bouquets you may need to clear the channel cache to the settings to take effect. You can do this by going to the following in Kodi settings: `Settings->PVR & Live TV->General->Clear cache`. + +* **Zap before channelswitch (i.e. for Single Tuner boxes)**: When using the addon with a single tuner box it may be necessary that the addon needs to be able to zap to another channel on the set-top box. If this option is enabled each channel switch in Kodi will also result in a channel switch on the set-top box. Please note that "allow channel switching" needs to be enabled in the webinterface on the set-top box. +* **TV bouquet fetch mode**: Choose from one of the following three modes: + - `All bouquets` - Fetch all TV bouquets from the set-top box. + - `Only one bouquet` - Only fetch the bouquet specified in the next option + - `Favourites group` - Only fetch the system bouquet for TV favourites. +* **TV bouquet**: If the previous option has been has been set to `Only one bouquet` you need to specify the TV bouquet to be fetched from the set-top box. Please not that this is the bouquet-name as shown on the set-top box (i.e. "Favourites (TV)"). This setting is case-sensitive. +* **Fetch TV favourites bouquet**: If the fetch mode is `All bouquets` or `Only one bouquet` depending on your Enigma2 image you may need to explicitly fetch favourites if you require them. The options are: + - `Disabled` - Don't explicitly fetch TV favourites. + - `As first bouquet` - Explicitly fetch them as the first bouquet. + - `As last bouquet` - Explicitly fetch them as the last bouquet. +* **Radio bouquet fetch mode**: Choose from one of the following three modes: + - `All bouquets` - Fetch all Radio bouquets from the set-top box. + - `Only one bouquet` - Only fetch the bouquet specified in the next option + - `Favourites group` - Only fetch the system bouquet for Radio favourites. +* **Radio bouquet**: If the previous option has been has been set to `Only one bouquet` you need to specify the Radio bouquet to be fetched from the set-top box. Please not that this is the bouquet-name as shown on the set-top box (i.e. "Favourites (Radio)"). This setting is case-sensitive. +* **Fetch Radio favourites bouquet**: If the fetch mode is `All bouquets` or `Only one bouquet` depending on your Enigma2 image you may need to explicitly fetch favourites if you require them. The options are: + - `Disabled` - Don't explicitly fetch Radio favourites. + - `As first bouquet` - Explicitly fetch them as the first bouquet. + - `As last bouquet` - Explicitly fetch them as the last bouquet. + +### EPG +Within this tab options that refer to EPG data can be set. Excluding logging missing genre text mappings all other options will require clearing the EPG cache to take effect. This can be done by going to `Settings->PVR & Live TV->Guide->Clear cache` in Kodi after the addon restarts. + +Information on customising the extraction and mapper configs can be found in the next section of the README. + +* **Extract season, episode and year info where possible**: Check the description fields in the EPG data and attempt to extract season, episode and year info where possible. +* **Extract show info file**: The config used to extract season, episode and year information. The default file is `English-ShowInfo.xml`. +* **Enable genre ID mappings**: If the genre IDs sent with EPG data from your set-top box are not using the DVB standard, map from these to the DVB standard IDs. Sky UK for instance uses OpenTV, in that case without this option set the genre colouring and text would be incorrect in Kodi. +* **Genre ID mappings file**: The config used to map set-top box EPG genre IDs to DVB standard IDs. The default file is `Sky-UK.xml`. +* **Enable Rytec genre text mappings**: If you use Rytec XMLTV EPG data this option can be used to map the text genres to DVB standard IDs. +* **Rytec genre text mappings file**: The config used to map Rytec Genre Text to DVB IDs. The default file is `Rytec-UK-Ireland.xml`. +* **Log missing genre text mappings**: If you would like missing genre mappings to be logged so you can report them enable this option. Note: any genres found that don't have a mapping will still be extracted and sent to Kodi as strings. Currently genres are extracted by looking for text between square brackets, e.g. [TV Drama], or for major, minor genres using a dot (.) to separate [TV Drama. Soap Opera] + +### Recordings & Timers + +* **Recording folder on receiver**: Per default the addon does not specify the recording folder in newly created timers, so the default set in the set-top box will be used. If you want to specify a different folder (i.e. because you want all recordings scheduled via Kodi to be stored in a separate folder), then you need to set this option. +* **Use only the DVB boxes' current recording path**: If this option is not set the addon will fetch all available recordings from all configured paths from the set-top box. If this option is set then it will only list recordings that are stored within the "current recording path" on the set-top box. +* **Keep folder structure for records**: If enabled do not specify a recording folder, when disabled (defaut), check if the recording is in it's own folder or in the root of the recording path +* **Enable generate repeat timers**: Repeat timers will display as timer rules. Enabling this will make Kodi generate regular timers to match the repeat timer rules so the UI can show what's scheduled and currently recording for each repeat timer. +* **Number of repeat timers to generate**: The number of Kodi PVR timers to generate. +* **Enable autotimers**: When this is enabled there are some settings required on the set-top box to enable linking of AutoTimers (Timer Rules) to Timers in the Kodi UI. The addon attempts to set these automatically on boot. To set manually on the set-top box enable the following options (note that this feature supports OpenWebIf 1.3.x and higher): + 1. Hit `Menu` on the remote and go to `Timers->AutoTimers` + 2. Hit `Menu` again and then select `6 Setup` + 3. Set the following to option to `yes` + * `Include "AutoTimer" in tags` + * `Include AutoTimer name in tags` +* **Automatic timerlist cleanup**: If this option is set then the addon will send the command to delete completed timers from the set-top box after each update interval. + +### Timeshift +* **Enable timeshift**: What timeshift option do you want: + - `Disabled` - No timeshifting + - `On Pause` - Timeshifting starts when a live stream is paused. E.g. you want to continue from where you were at after pausing. + - `On Playback` - Timeshifting starts when a live stream is opened. E.g. You can go to any point in the stream since it was opened. +* **Timeshift buffer path**: The path used to store the timeshoft buffer. The default is the addon data folder in userdata + +### Advanced +Within this tab more uncommon and advanced options can be configured. + +* **Put outline (e.g. sub-title) before plot**: By default plot outline (short description on Enigma2) is not displayed in the UI. Can be + displayed in EPG, Recordings or both. After changing this option you will need to clear the EPG cache `Settings->PVR & Live TV->Guide->Clear cache` for it to take effect. +* **Send powerstate mode on addon exit**: If this option is set to a value other than `DISABLED` then the addon will send a Powerstate command to the set-top box when Kodi will be closed (or the addon will be deactivated). + - `Disabled` - No command sent when the addon exits + - `Standby` - Send the standby command on exit + - `Deep standby` - Send the deep standby command on exit. Note, the set-top box will not respond to Kodi after this command is sent. + - `Wakeup, then standby` - Similar to standby but first sends a wakeup command. Can be useful if you want to ensure all streams have stopped. Note: if you use CEC this could cause your TV to wake. +* **Custom live TV timeout (0 to use default)**: The timemout to use when trying to read live streams +* **Stream read chunk size**: The chunk size used by Kodi for streams. Default 0 to leave it to Kodi to decide. + +## Customising Config Files + +The various config files allow users to create their own, making it possible to support other languages and formats. Each different type of config file is detailed below. Best way to learn about them is to read the config files themselves. Each contains details of how the config file works. + +All of the files listed below are overwritten each time the addon starts. Therefore if you are customising files please create new copies with different file names. Note: that only the files below are overwritten any new files you create will not be touched. + +After adding and selecting new config files you will need to clear the EPG cache `Settings->PVR & Live TV->Guide->Clear cache` for it to take effect. + +If you would like to support other formats/languages please raise an issue at the github project https://github.com/kodi-pvr/pvr.vuplus, where you can either create a PR or request your new configs be shipped with the addon. + +There is one config file located here: `userdata/addon_data/pvr.vuplus/genres/kodiDvbGenres.xml`. This simply contains the DVB genre IDs that Kodi supports. Can be a useful reference if creating your own configs. This file is also overwritten each time the addon restarts. + +### Season, Episode and Year Show Info + +Config files are located in the `userdata/addon_data/pvr.vuplus/showInfo` folder. + +The following files are currently available with the addon: + - `English-ShowInfo.xml` + +Note: the config file can contain as many pattern matches as are required. So if you need to support multiple languages in a single file that is possible. However there must be at least one pattern and at least one pattern. Proficiency in regular exressions is required! + +### Genre ID Mappings + +Config files are located in the `userdata/addon_data/pvr.vuplus/genres/genreIdMappings` folder. + +The following files are currently available with the addon: + - `AU-SAT.xml` + - `Sky-IT.xml` + - `Sky-NZ.xml` + - `Sky-UK.xml` + +Note: that each source genre ID can be mapped to a DVB ID. However multiple source IDs can be mapped to the same DVB ID. Therefore there are exactly 256 elements in each file as a genre ID is 8 bits. All values are in Hex. The first fours bits are the genreType in Kodi PVR and the last four bits are the genreSubType. + +### Rytec Genre Text Mappings + +Config files are located in the `userdata/addon_data/pvr.vuplus/genres/genreRytecTextMappings` folder. + +The following files are currently available with the addon: + - `Rytec-UK-Ireland.xml` + +Note: the config file can contain as many mappings as is required. Currently genres are extracted by looking for text between square brackets, e.g. [TV Drama], or for major, minor genres using a dot (.) to separate [TV Drama. Soap Opera]. The config file maps the text to a kodi DVB genre ID. If the full text cannot be matched it attempts to match just the major genre, i.e. "TV Drama" in the previous example. If a mapping cannot be found the text between the brackets will be used instead. However there will be no colouring in the Kodi EPG in this case. \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/client.cpp kodi-pvr-vuplus-3.15.0/src/client.cpp --- kodi-pvr-vuplus-2.4.12/src/client.cpp 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/client.cpp 2018-11-18 11:16:20.000000000 +0000 @@ -21,135 +21,42 @@ */ #include "client.h" -#include "xbmc_pvr_dll.h" + #include -#include "VuData.h" + +#include "Enigma2.h" +#include "enigma2/RecordingReader.h" +#include "enigma2/Settings.h" +#include "enigma2/StreamReader.h" +#include "enigma2/TimeshiftBuffer.h" +#include "enigma2/utilities/LocalizedString.h" +#include "enigma2/utilities/Logger.h" + #include "p8-platform/util/util.h" +#include +#include "xbmc_pvr_dll.h" -using namespace std; using namespace ADDON; - -bool m_bCreated = false; -ADDON_STATUS m_CurStatus = ADDON_STATUS_UNKNOWN; -//int g_iClientId = -1; - -/* User adjustable settings are saved here. - * Default values are defined inside client.h - * and exported to the other source files. - */ -std::string g_strHostname = DEFAULT_HOST; -int g_iConnectTimeout = DEFAULT_CONNECT_TIMEOUT; -int g_iPortStream = DEFAULT_STREAM_PORT; -int g_iPortWeb = DEFAULT_WEB_PORT; -int g_iUpdateInterval = DEFAULT_UPDATE_INTERVAL; -std::string g_strUsername = ""; -std::string g_strRecordingPath = ""; -std::string g_strPassword = ""; -std::string g_szUserPath = ""; -std::string g_strIconPath = ""; -bool g_bAutomaticTimerlistCleanup = false; -bool g_bZap = false; -bool g_bOnlyCurrentLocation = false; -bool g_bSetPowerstate = false; -bool g_bOnlyOneGroup = false; -bool g_bOnlinePicons = true; -bool g_bUseSecureHTTP = false; -std::string g_strOneGroup = ""; -std::string g_szClientPath = ""; - -CHelper_libXBMC_addon *XBMC = NULL; -CHelper_libXBMC_pvr *PVR = NULL; -Vu *VuData = NULL; +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::utilities; + +bool m_created = false; +ADDON_STATUS m_currentStatus = ADDON_STATUS_UNKNOWN; +IStreamReader *streamReader = nullptr; +int m_streamReadChunkSize = 64; +RecordingReader *recordingReader = nullptr; +Settings &settings = Settings::GetInstance(); + +CHelper_libXBMC_addon *XBMC = nullptr; +CHelper_libXBMC_pvr *PVR = nullptr; +Enigma2 *enigma = nullptr; 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 "recordingpath" from settings.xml */ - if (XBMC->GetSetting("recordingpath", buffer)) - g_strRecordingPath = buffer; - else - g_strRecordingPath = ""; - 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 "use_secure" from settings.xml */ - if (!XBMC->GetSetting("use_secure", &g_bUseSecureHTTP)) - g_bUseSecureHTTP = false; - - /* read setting "streamport" from settings.xml */ - if (!XBMC->GetSetting("streamport", &g_iPortStream)) - g_iPortStream = DEFAULT_STREAM_PORT; - - /* read setting "webport" from settings.xml */ - if (!XBMC->GetSetting("webport", &g_iPortWeb)) - g_iPortWeb = DEFAULT_WEB_PORT; - - /* read setting "onlinepicons" from settings.xml */ - if (!XBMC->GetSetting("onlinepicons", &g_bOnlinePicons)) - g_bOnlinePicons = true; - - /* read setting "onlycurrent" from settings.xml */ - if (!XBMC->GetSetting("onlycurrent", &g_bOnlyCurrentLocation)) - g_bOnlyCurrentLocation = false; - - /* read setting "setpowerstate" from settings.xml */ - if (!XBMC->GetSetting("setpowerstate", &g_bSetPowerstate)) - g_bSetPowerstate = false; - - /* read setting "zap" from settings.xml */ - if (!XBMC->GetSetting("zap", &g_bZap)) - g_bZap = false; - - /* read setting "onlyonegroup" from settings.xml */ - if (!XBMC->GetSetting("onlyonegroup", &g_bOnlyOneGroup)) - g_bOnlyOneGroup = false; - - /* read setting "onegroup" from settings.xml */ - if (XBMC->GetSetting("onegroup", buffer)) - g_strOneGroup = buffer; - else - g_strOneGroup = ""; - - /* read setting "timerlistcleanup" from settings.xml */ - if (!XBMC->GetSetting("timerlistcleanup", &g_bAutomaticTimerlistCleanup)) - g_bAutomaticTimerlistCleanup = false; - - /* read setting "updateint" from settings.xml */ - if (!XBMC->GetSetting("updateint", &g_iUpdateInterval)) - g_iConnectTimeout = DEFAULT_UPDATE_INTERVAL; - - /* read setting "iconpath" from settings.xml */ - if (XBMC->GetSetting("iconpath", buffer)) - g_strIconPath = buffer; - else - g_strIconPath = ""; - - free (buffer); -} +/*************************************************************************** + * Addon Calls + **************************************************************************/ ADDON_STATUS ADDON_Create(void* hdl, void* props) { @@ -173,129 +80,93 @@ return ADDON_STATUS_PERMANENT_FAILURE; } - XBMC->Log(LOG_DEBUG, "%s - Creating VU+ PVR-Client", __FUNCTION__); + Logger::Log(LEVEL_DEBUG, "%s - Creating VU+ PVR-Client", __FUNCTION__); + + m_currentStatus = ADDON_STATUS_UNKNOWN; + + /* Configure the logger */ + Logger::GetInstance().SetImplementation([](LogLevel level, const char *message) + { + /* Convert the log level */ + addon_log_t addonLevel; + + switch (level) + { + case LogLevel::LEVEL_ERROR: + addonLevel = addon_log_t::LOG_ERROR; + break; + case LogLevel::LEVEL_INFO: + addonLevel = addon_log_t::LOG_INFO; + break; + case LogLevel::LEVEL_NOTICE: + addonLevel = addon_log_t::LOG_NOTICE; + break; + default: + addonLevel = addon_log_t::LOG_DEBUG; + } + + /* Don't log trace messages unless told so */ + //if (level == LogLevel::LEVEL_TRACE && !Settings::GetInstance().GetTraceDebug()) + //return; + + XBMC->Log(addonLevel, "%s", message); + }); + + Logger::GetInstance().SetPrefix("pvr.vuplus"); - m_CurStatus = ADDON_STATUS_UNKNOWN; - //g_iClientId = pvrprops->iClientId; //removed from Frodo PVR API - g_szUserPath = pvrprops->strUserPath; - g_szClientPath = pvrprops->strClientPath; + Logger::Log(LogLevel::LEVEL_INFO, "%s starting PVR client...", __FUNCTION__); - ADDON_ReadSettings(); + settings.ReadFromAddon(); - VuData = new Vu; - if (!VuData->Open()) + enigma = new Enigma2(); + if (!enigma->Open()) { - SAFE_DELETE(VuData); + SAFE_DELETE(enigma); SAFE_DELETE(PVR); SAFE_DELETE(XBMC); - m_CurStatus = ADDON_STATUS_LOST_CONNECTION; - return m_CurStatus; + m_currentStatus = ADDON_STATUS_LOST_CONNECTION; + return m_currentStatus; } - m_CurStatus = ADDON_STATUS_OK; - m_bCreated = true; - return m_CurStatus; + m_currentStatus = ADDON_STATUS_OK; + m_created = true; + return m_currentStatus; } ADDON_STATUS ADDON_GetStatus() { /* check whether we're still connected */ - if (m_CurStatus == ADDON_STATUS_OK && !VuData->IsConnected()) - m_CurStatus = ADDON_STATUS_LOST_CONNECTION; + if (m_currentStatus == ADDON_STATUS_OK && !enigma->IsConnected()) + m_currentStatus = ADDON_STATUS_LOST_CONNECTION; - return m_CurStatus; + return m_currentStatus; } void ADDON_Destroy() { - if (m_bCreated) + if (m_created) { - m_bCreated = false; + m_created = false; } - if (VuData) + if (enigma) { - VuData->SendPowerstate(); + enigma->SendPowerstate(); } - SAFE_DELETE(VuData); + SAFE_DELETE(enigma); SAFE_DELETE(PVR); SAFE_DELETE(XBMC); - m_CurStatus = ADDON_STATUS_UNKNOWN; -} - -bool ADDON_HasSettings() -{ - return true; -} - -unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet) -{ - return 0; + m_currentStatus = ADDON_STATUS_UNKNOWN; } 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 == "streamport") - { - int iNewValue = *(int*) settingValue + 1; - if (g_iPortStream != iNewValue) - { - XBMC->Log(LOG_INFO, "%s - Changed Setting 'streamport' from %u to %u", __FUNCTION__, g_iPortStream, iNewValue); - g_iPortStream = iNewValue; - return ADDON_STATUS_OK; - } - } - else if (str == "webport") - { - int iNewValue = *(int*) settingValue + 1; - if (g_iPortWeb != iNewValue) - { - XBMC->Log(LOG_INFO, "%s - Changed Setting 'webport' from %u to %u", __FUNCTION__, g_iPortWeb, iNewValue); - g_iPortWeb = iNewValue; - return ADDON_STATUS_OK; - } - } - return ADDON_STATUS_OK; -} + if (!XBMC || !enigma) + return ADDON_STATUS_OK; -void ADDON_Stop() -{ -} - -void ADDON_FreeSettings() -{ + return settings.SetValue(settingName, settingValue); } /*********************************************************** @@ -318,28 +189,6 @@ { } -const char* GetPVRAPIVersion(void) -{ - static const char *strApiVersion = XBMC_PVR_API_VERSION; - return strApiVersion; -} - -const char* GetMininumPVRAPIVersion(void) -{ - static const char *strMinApiVersion = XBMC_PVR_MIN_API_VERSION; - return strMinApiVersion; -} - -const char* GetGUIAPIVersion(void) -{ - return ""; // GUI API not used -} - -const char* GetMininumGUIAPIVersion(void) -{ - return ""; // GUI API not used -} - PVR_ERROR GetAddonCapabilities(PVR_ADDON_CAPABILITIES* pCapabilities) { pCapabilities->bSupportsEPG = true; @@ -353,249 +202,382 @@ pCapabilities->bHandlesInputStream = true; pCapabilities->bHandlesDemuxing = false; pCapabilities->bSupportsLastPlayedPosition = false; + pCapabilities->bSupportsRecordingsRename = false; + pCapabilities->bSupportsRecordingsLifetimeChange = false; + pCapabilities->bSupportsDescrambleInfo = false; return PVR_ERROR_NO_ERROR; } const char *GetBackendName(void) { - static const char *strBackendName = VuData ? VuData->GetServerName() : "unknown"; - return strBackendName; + static const char *backendName = enigma ? enigma->GetServerName() : LocalizedString(60081).c_str(); //unknown + return backendName; } const char *GetBackendVersion(void) { - static const char *strBackendVersion = "UNKNOWN"; - return strBackendVersion; + static const char *backendVersion = enigma ? enigma->GetServerVersion() : LocalizedString(60081).c_str(); //unknown + return backendVersion; } -static CStdString strConnectionString; +static std::string connectionString; const char *GetConnectionString(void) { - if (VuData) - strConnectionString.Format("%s%s", g_strHostname.c_str(), VuData->IsConnected() ? "" : " (Not connected!)"); + if (enigma) + connectionString = StringUtils::Format("%s%s", settings.GetHostname().c_str(), enigma->IsConnected() ? "" : LocalizedString(60082).c_str()); // (Not connected!) else - strConnectionString.Format("%s (addon error!)", g_strHostname.c_str()); - return strConnectionString.c_str(); + connectionString = StringUtils::Format("%s (%s!)", settings.GetHostname().c_str(), LocalizedString(60083).c_str()); //addon error + return connectionString.c_str(); } const char *GetBackendHostname(void) { - return g_strHostname.c_str(); + return settings.GetHostname().c_str(); } PVR_ERROR GetDriveSpace(long long *iTotal, long long *iUsed) { - return PVR_ERROR_SERVER_ERROR; + return enigma->GetDriveSpace(iTotal, iUsed); +} + + +PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS &signalStatus) +{ + // the RS api doesn't provide information about signal quality (yet) + + PVR_STRCPY(signalStatus.strAdapterName, LocalizedString(60084).c_str()); //Enigma2 Media Server + PVR_STRCPY(signalStatus.strAdapterStatus, LocalizedString(60085).c_str()); //OK + return PVR_ERROR_NO_ERROR; +} + + +/*************************************************************************** + * ChannelGroups + **************************************************************************/ + +int GetChannelGroupsAmount(void) +{ + if (!enigma || !enigma->IsConnected()) + return PVR_ERROR_SERVER_ERROR; + + return enigma->GetNumChannelGroups(); +} + +PVR_ERROR GetChannelGroups(ADDON_HANDLE handle, bool bRadio) +{ + if (!enigma || !enigma->IsConnected()) + return PVR_ERROR_SERVER_ERROR; + + return enigma->GetChannelGroups(handle, bRadio); } +PVR_ERROR GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group) +{ + if (!enigma || !enigma->IsConnected()) + return PVR_ERROR_SERVER_ERROR; + + return enigma->GetChannelGroupMembers(handle, group); +} + +/*************************************************************************** + * EPG and Channels + **************************************************************************/ + PVR_ERROR GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd) { - if (!VuData || !VuData->IsConnected()) + if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; - return VuData->GetEPGForChannel(handle, channel, iStart, iEnd); + return enigma->GetEPGForChannel(handle, channel, iStart, iEnd); } int GetChannelsAmount(void) { - if (!VuData || !VuData->IsConnected()) + if (!enigma || !enigma->IsConnected()) return 0; - return VuData->GetChannelsAmount(); + return enigma->GetChannelsAmount(); } PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio) { - if (!VuData || !VuData->IsConnected()) + if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; - return VuData->GetChannels(handle, bRadio); + return enigma->GetChannels(handle, bRadio); } -int GetRecordingsAmount(bool deleted) +/*************************************************************************** + * Live Streams + **************************************************************************/ + +PVR_ERROR GetStreamReadChunkSize(int* chunksize) { - if (!VuData || !VuData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; + if (!chunksize) + return PVR_ERROR_INVALID_PARAMETERS; + int size = settings.GetStreamReadChunkSizeKb(); + if (!size) + return PVR_ERROR_NOT_IMPLEMENTED; + *chunksize = settings.GetStreamReadChunkSizeKb() * 1024; + return PVR_ERROR_NO_ERROR; +} - return VuData->GetRecordingsAmount(); +/* live stream functions */ +bool OpenLiveStream(const PVR_CHANNEL &channel) +{ + if (!enigma || !enigma->IsConnected()) + return false; + + if (!enigma->OpenLiveStream(channel)) + return false; + + /* queue a warning if the timeshift buffer path does not exist */ + if (settings.GetTimeshift() != Timeshift::OFF + && !settings.IsTimeshiftBufferPathValid()) + XBMC->QueueNotification(QUEUE_ERROR, LocalizedString(30514).c_str()); + + std::string streamURL = enigma->GetLiveStreamURL(channel); + streamReader = new StreamReader(streamURL, settings.GetReadTimeoutSecs()); + if (settings.GetTimeshift() == Timeshift::ON_PLAYBACK) + streamReader = new TimeshiftBuffer(streamReader, settings.GetTimeshiftBufferPath(), settings.GetReadTimeoutSecs()); + + return streamReader->Start(); } -PVR_ERROR GetRecordings(ADDON_HANDLE handle, bool deleted) +void CloseLiveStream(void) { - if (!VuData || !VuData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; + enigma->CloseLiveStream(); + SAFE_DELETE(streamReader); +} - return VuData->GetRecordings(handle); +bool IsRealTimeStream() +{ + return (streamReader) ? streamReader->IsRealTime() : false; } -PVR_ERROR DeleteRecording(const PVR_RECORDING &recording) +bool CanPauseStream(void) { - if (!VuData || !VuData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; + if (!enigma) + return false; + + if (settings.GetTimeshift() != Timeshift::OFF && streamReader) + return (streamReader->IsTimeshifting() || settings.IsTimeshiftBufferPathValid()); - return VuData->DeleteRecording(recording); + return false; } -PVR_ERROR RenameRecording(const PVR_RECORDING &recording) +bool CanSeekStream(void) { - return PVR_ERROR_NOT_IMPLEMENTED; + if (!enigma) + return false; + + return (settings.GetTimeshift() != Timeshift::OFF); } -PVR_ERROR GetTimerTypes(PVR_TIMER_TYPE types[], int *size) +int ReadLiveStream(unsigned char *buffer, unsigned int size) +{ + return (streamReader) ? streamReader->ReadData(buffer, size) : 0; +} + +long long SeekLiveStream(long long position, int whence) +{ + return (streamReader) ? streamReader->Seek(position, whence) : -1; +} + +long long LengthLiveStream(void) { - /* TODO: Implement this to get support for the timer features introduced with PVR API 1.9.7 */ + return (streamReader) ? streamReader->Length() : -1; +} + +bool IsTimeshifting(void) +{ + return (streamReader && streamReader->IsTimeshifting()); +} + +PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES *times) +{ + if (!times) + return PVR_ERROR_INVALID_PARAMETERS; + if (streamReader) + { + times->startTime = streamReader->TimeStart(); + times->ptsStart = 0; + times->ptsBegin = 0; + times->ptsEnd = (!streamReader->IsTimeshifting()) ? 0 + : (streamReader->TimeEnd() - streamReader->TimeStart()) * DVD_TIME_BASE; + + return PVR_ERROR_NO_ERROR; + } return PVR_ERROR_NOT_IMPLEMENTED; } -int GetTimersAmount(void) +void PauseStream(bool paused) { - if (!VuData || !VuData->IsConnected()) - return 0; + if (!enigma) + return; - return VuData->GetTimersAmount(); + /* start timeshift on pause */ + if (paused && settings.GetTimeshift() == Timeshift::ON_PAUSE + && streamReader && !streamReader->IsTimeshifting() + && settings.IsTimeshiftBufferPathValid()) + { + streamReader = new TimeshiftBuffer(streamReader, settings.GetTimeshiftBufferPath(), settings.GetReadTimeoutSecs()); + (void)streamReader->Start(); + } } -PVR_ERROR GetTimers(ADDON_HANDLE handle) +/*************************************************************************** + * Recordings + **************************************************************************/ + +int GetRecordingsAmount(bool deleted) { - if (!VuData || !VuData->IsConnected()) + if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; - /* TODO: Change implementation to get support for the timer features introduced with PVR API 1.9.7 */ - return VuData->GetTimers(handle); + return enigma->GetRecordingsAmount(); } -PVR_ERROR AddTimer(const PVR_TIMER &timer) +PVR_ERROR GetRecordings(ADDON_HANDLE handle, bool deleted) { - if (!VuData || !VuData->IsConnected()) + if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; - return VuData->AddTimer(timer); + return enigma->GetRecordings(handle); } -PVR_ERROR DeleteTimer(const PVR_TIMER &timer, bool bForceDelete) +PVR_ERROR DeleteRecording(const PVR_RECORDING &recording) { - if (!VuData || !VuData->IsConnected()) + if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; - return VuData->DeleteTimer(timer); + return enigma->DeleteRecording(recording); } -PVR_ERROR UpdateTimer(const PVR_TIMER &timer) +/*************************************************************************** + * Recording Streams + **************************************************************************/ + +bool OpenRecordedStream(const PVR_RECORDING &recording) { - if (!VuData || !VuData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; + if (recordingReader) + SAFE_DELETE(recordingReader); + recordingReader = enigma->OpenRecordedStream(recording); + return recordingReader->Start(); +} - return VuData->UpdateTimer(timer); +void CloseRecordedStream(void) +{ + if (recordingReader) + SAFE_DELETE(recordingReader); } -bool SwitchChannel(const PVR_CHANNEL &channel) +int ReadRecordedStream(unsigned char *buffer, unsigned int size) { - if (!VuData || !VuData->IsConnected()) - return false; + if (!recordingReader) + return 0; - return VuData->SwitchChannel(channel); + return recordingReader->ReadData(buffer, size); } -int GetChannelGroupsAmount(void) +long long SeekRecordedStream(long long position, int whence) { - if (!VuData || !VuData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; + if (!recordingReader) + return 0; - return VuData->GetNumChannelGroups(); + return recordingReader->Seek(position, whence); } -PVR_ERROR GetChannelGroups(ADDON_HANDLE handle, bool bRadio) +long long LengthRecordedStream(void) { - if (bRadio) - return PVR_ERROR_NO_ERROR; + if (!recordingReader) + return -1; - if (!VuData || !VuData->IsConnected()) - return PVR_ERROR_SERVER_ERROR; + return recordingReader->Length(); +} - return VuData->GetChannelGroups(handle); +/*************************************************************************** + * Timers + **************************************************************************/ + +PVR_ERROR GetTimerTypes(PVR_TIMER_TYPE types[], int *size) +{ + *size = 0; + if (enigma && enigma->IsConnected()) + enigma->GetTimerTypes(types, size); + return PVR_ERROR_NO_ERROR; } -PVR_ERROR GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group) +int GetTimersAmount(void) { - if (group.bIsRadio) - return PVR_ERROR_NO_ERROR; + if (!enigma || !enigma->IsConnected()) + return 0; + + return enigma->GetTimersAmount(); +} - if (!VuData || !VuData->IsConnected()) +PVR_ERROR GetTimers(ADDON_HANDLE handle) +{ + if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; - return VuData->GetChannelGroupMembers(handle, group); + return enigma->GetTimers(handle); } -void CloseLiveStream(void) -{ - VuData->CloseLiveStream(); -}; - -bool OpenLiveStream(const PVR_CHANNEL &channel) -{ - if (!VuData || !VuData->IsConnected()) - return false; +PVR_ERROR AddTimer(const PVR_TIMER &timer) +{ + if (!enigma || !enigma->IsConnected()) + return PVR_ERROR_SERVER_ERROR; - return VuData->OpenLiveStream(channel); + return enigma->AddTimer(timer); } -const char * GetLiveStreamURL(const PVR_CHANNEL &channel) -{ - if (!VuData || !VuData->IsConnected()) - return ""; +PVR_ERROR DeleteTimer(const PVR_TIMER &timer, bool bForceDelete) +{ + if (!enigma || !enigma->IsConnected()) + return PVR_ERROR_SERVER_ERROR; - return VuData->GetLiveStreamURL(channel); -} -PVR_ERROR SetRecordingLastPlayedPosition(const PVR_RECORDING &recording, int lastplayedposition) -{ - return PVR_ERROR_NOT_IMPLEMENTED; + return enigma->DeleteTimer(timer); } -int GetRecordingLastPlayedPosition(const PVR_RECORDING &recording) -{ - return PVR_ERROR_NOT_IMPLEMENTED; +PVR_ERROR UpdateTimer(const PVR_TIMER &timer) +{ + if (!enigma || !enigma->IsConnected()) + return PVR_ERROR_SERVER_ERROR; + + return enigma->UpdateTimer(timer); } /** UNUSED API FUNCTIONS */ -PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS &signalStatus) { return PVR_ERROR_NO_ERROR; } PVR_ERROR GetStreamProperties(PVR_STREAM_PROPERTIES* pProperties) { return PVR_ERROR_NOT_IMPLEMENTED; } +PVR_ERROR GetChannelStreamProperties(const PVR_CHANNEL*, PVR_NAMED_VALUE*, unsigned int*) { return PVR_ERROR_NOT_IMPLEMENTED; } void DemuxAbort(void) { return; } -DemuxPacket* DemuxRead(void) { return NULL; } +DemuxPacket* DemuxRead(void) { return nullptr; } PVR_ERROR OpenDialogChannelScan(void) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR CallMenuHook(const PVR_MENUHOOK &menuhook, const PVR_MENUHOOK_DATA &item) { 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 OpenDialogChannelSettings(const PVR_CHANNEL &channel) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR OpenDialogChannelAdd(const PVR_CHANNEL &channel) { return PVR_ERROR_NOT_IMPLEMENTED; } -bool OpenRecordedStream(const PVR_RECORDING &recording) { return false; } -void CloseRecordedStream(void) {} -int ReadRecordedStream(unsigned char *pBuffer, unsigned int iBufferSize) { return 0; } -long long SeekRecordedStream(long long iPosition, int iWhence /* = SEEK_SET */) { return 0; } -long long PositionRecordedStream(void) { return -1; } -long long LengthRecordedStream(void) { return 0; } +PVR_ERROR GetRecordingStreamProperties(const PVR_RECORDING* recording, PVR_NAMED_VALUE* properties, unsigned int* iPropertiesCount) { return PVR_ERROR_NOT_IMPLEMENTED; } void DemuxReset(void) {} void DemuxFlush(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; } +PVR_ERROR RenameRecording(const PVR_RECORDING &recording) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING &recording, int count) { return PVR_ERROR_NOT_IMPLEMENTED; } -PVR_ERROR GetRecordingEdl(const PVR_RECORDING&, PVR_EDL_ENTRY[], int*) { return PVR_ERROR_NOT_IMPLEMENTED; }; -unsigned int GetChannelSwitchDelay(void) { return 0; } -void PauseStream(bool bPaused) {} -bool CanPauseStream(void) { return false; } -bool CanSeekStream(void) { return false; } +PVR_ERROR SetRecordingLastPlayedPosition(const PVR_RECORDING &recording, int lastplayedposition) { return PVR_ERROR_NOT_IMPLEMENTED; } +int GetRecordingLastPlayedPosition(const PVR_RECORDING &recording) { return PVR_ERROR_NOT_IMPLEMENTED; } +PVR_ERROR GetRecordingEdl(const PVR_RECORDING&, PVR_EDL_ENTRY[], int*) { return PVR_ERROR_NOT_IMPLEMENTED; } bool SeekTime(double,bool,double*) { return false; } void SetSpeed(int) {}; -bool IsTimeshifting(void) { return false; } -time_t GetPlayingTime() { return 0; } -time_t GetBufferTimeStart() { return 0; } -time_t GetBufferTimeEnd() { return 0; } -bool IsRealTimeStream() { return true; } PVR_ERROR UndeleteRecording(const PVR_RECORDING& recording) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR DeleteAllRecordingsFromTrash() { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR SetEPGTimeFrame(int) { return PVR_ERROR_NOT_IMPLEMENTED; } +PVR_ERROR GetDescrambleInfo(PVR_DESCRAMBLE_INFO*) { return PVR_ERROR_NOT_IMPLEMENTED; } +PVR_ERROR SetRecordingLifetime(const PVR_RECORDING*) { return PVR_ERROR_NOT_IMPLEMENTED; } +PVR_ERROR IsEPGTagRecordable(const EPG_TAG*, bool*) { return PVR_ERROR_NOT_IMPLEMENTED; } +PVR_ERROR IsEPGTagPlayable(const EPG_TAG*, bool*) { return PVR_ERROR_NOT_IMPLEMENTED; } +PVR_ERROR GetEPGTagStreamProperties(const EPG_TAG*, PVR_NAMED_VALUE*, unsigned int*) { return PVR_ERROR_NOT_IMPLEMENTED; } +PVR_ERROR GetEPGTagEdl(const EPG_TAG* epgTag, PVR_EDL_ENTRY edl[], int *size) { return PVR_ERROR_NOT_IMPLEMENTED; } } diff -Nru kodi-pvr-vuplus-2.4.12/src/client.h kodi-pvr-vuplus-3.15.0/src/client.h --- kodi-pvr-vuplus-2.4.12/src/client.h 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/client.h 2018-11-05 17:50:27.000000000 +0000 @@ -24,34 +24,10 @@ #include "libXBMC_addon.h" #include "libXBMC_pvr.h" -#define DEFAULT_HOST "127.0.0.1" -#define DEFAULT_CONNECT_TIMEOUT 30 -#define DEFAULT_STREAM_PORT 8001 -#define DEFAULT_WEB_PORT 80 -#define DEFAULT_UPDATE_INTERVAL 2 - -extern bool m_bCreated; -extern std::string g_strHostname; -extern int g_iPortStream; -extern int g_iPortWeb; -extern std::string g_strUsername; -extern std::string g_strPassword; -extern std::string g_strIconPath; -extern std::string g_strRecordingPath; -extern int g_iUpdateInterval; -//extern int g_iClientId; -extern unsigned int g_iPacketSequence; -extern bool g_bShowTimerNotifications; -extern bool g_bZap; -extern bool g_bAutomaticTimerlistCleanup; -extern bool g_bUseSecureHTTP; -extern bool g_bOnlyCurrentLocation; -extern bool g_bSetPowerstate; -extern bool g_bOnlyOneGroup; -extern bool g_bOnlinePicons; -extern std::string g_strOneGroup; -extern std::string g_szUserPath; -extern std::string g_szClientPath; -extern std::string g_strChannelDataPath; extern ADDON::CHelper_libXBMC_addon * XBMC; extern CHelper_libXBMC_pvr * PVR; + +/*! + * @brief PVR macros for string exchange + */ +#define PVR_STRCPY(dest, source) do { strncpy(dest, source, sizeof(dest)-1); dest[sizeof(dest)-1] = '\0'; } while(0) diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/Admin.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/Admin.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/Admin.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/Admin.cpp 2018-11-21 13:14:33.000000000 +0000 @@ -0,0 +1,518 @@ +#include "Admin.h" + +#include + +#include "../client.h" +#include "../Enigma2.h" +#include "utilities/FileUtils.h" +#include "utilities/LocalizedString.h" +#include "utilities/Logger.h" +#include "utilities/WebUtils.h" + +#include "util/XMLUtils.h" +#include "p8-platform/util/StringUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::extract; +using namespace enigma2::utilities; + +void Admin::SendPowerstate() +{ + if (Settings::GetInstance().GetPowerstateModeOnAddonExit() != PowerstateMode::DISABLED) + { + if (Settings::GetInstance().GetPowerstateModeOnAddonExit() == PowerstateMode::WAKEUP_THEN_STANDBY) + { + std::string strTmp = StringUtils::Format("web/powerstate?newstate=4"); //Wakeup + + std::string strResult; + WebUtils::SendSimpleCommand(strTmp, strResult, true); + } + + if (Settings::GetInstance().GetPowerstateModeOnAddonExit() == PowerstateMode::STANDBY || + Settings::GetInstance().GetPowerstateModeOnAddonExit() == PowerstateMode::WAKEUP_THEN_STANDBY) + { + std::string strTmp = StringUtils::Format("web/powerstate?newstate=5"); //Standby + + std::string strResult; + WebUtils::SendSimpleCommand(strTmp, strResult, true); + } + + if (Settings::GetInstance().GetPowerstateModeOnAddonExit() == PowerstateMode::DEEP_STANDBY) + { + std::string strTmp = StringUtils::Format("web/powerstate?newstate=1"); //Deep Standby + + std::string strResult; + WebUtils::SendSimpleCommand(strTmp, strResult, true); + } + } +} + +bool Admin::Initialise() +{ + Settings::GetInstance().SetAdmin(this); + + bool deviceInfoLoaded = LoadDeviceInfo(); + + if (deviceInfoLoaded) + { + Settings::GetInstance().SetDeviceInfo(&m_deviceInfo); + + if (LoadDeviceSettings()) + { + Settings::GetInstance().SetDeviceSettings(&m_deviceSettings); + + //If OpenWebVersion is new enough to allow the setting of AutoTimer setttings + if (Settings::GetInstance().GetWebIfVersionAsNum() >= Settings::GetInstance().GenerateWebIfVersionAsNum(1, 3, 0)) + SendAutoTimerSettings(); + } + } + + return deviceInfoLoaded; +} + +bool Admin::LoadDeviceInfo() +{ + const std::string url = StringUtils::Format("%s%s", Settings::GetInstance().GetConnectionURL().c_str(), "web/deviceinfo"); + + const std::string strXML = WebUtils::GetHttpXML(url); + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(strXML.c_str())) + { + Logger::Log(LEVEL_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return false; + } + + std::string enigmaVersion; + std::string imageVersion; + std::string webIfVersion; + std::string serverName = "Enigma2"; + unsigned int webIfVersionAsNum; + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("e2deviceinfo").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); + return false; + } + + std::string strTmp; + + Logger::Log(LEVEL_NOTICE, "%s - DeviceInfo", __FUNCTION__); + + // Get EnigmaVersion + if (!XMLUtils::GetString(pElem, "e2enigmaversion", strTmp)) + { + Logger::Log(LEVEL_ERROR, "%s Could not parse e2enigmaversion from result!", __FUNCTION__); + return false; + } + enigmaVersion = strTmp.c_str(); + Logger::Log(LEVEL_NOTICE, "%s - E2EnigmaVersion: %s", __FUNCTION__, enigmaVersion.c_str()); + + // Get ImageVersion + if (!XMLUtils::GetString(pElem, "e2imageversion", strTmp)) + { + Logger::Log(LEVEL_ERROR, "%s Could not parse e2imageversion from result!", __FUNCTION__); + return false; + } + imageVersion = strTmp.c_str(); + Logger::Log(LEVEL_NOTICE, "%s - E2ImageVersion: %s", __FUNCTION__, imageVersion.c_str()); + + // Get WebIfVersion + if (!XMLUtils::GetString(pElem, "e2webifversion", strTmp)) + { + Logger::Log(LEVEL_ERROR, "%s Could not parse e2webifversion from result!", __FUNCTION__); + return false; + } + webIfVersion = strTmp.c_str(); + webIfVersionAsNum = ParseWebIfVersion(webIfVersion); + + Logger::Log(LEVEL_NOTICE, "%s - E2WebIfVersion: %s", __FUNCTION__, webIfVersion.c_str()); + + // Get DeviceName + if (!XMLUtils::GetString(pElem, "e2devicename", strTmp)) + { + Logger::Log(LEVEL_ERROR, "%s Could not parse e2devicename from result!", __FUNCTION__); + return false; + } + serverName = strTmp.c_str(); + Logger::Log(LEVEL_NOTICE, "%s - E2DeviceName: %s", __FUNCTION__, serverName.c_str()); + + m_deviceInfo = DeviceInfo(serverName, enigmaVersion, imageVersion, webIfVersion, webIfVersionAsNum); + + return true; +} + +unsigned int Admin::ParseWebIfVersion(const std::string &webIfVersion) +{ + unsigned int webIfVersionAsNum = 0; + + std::regex regex ("^.*[0-9]+\\.[0-9]+\\.[0-9].*$"); + if (regex_match(webIfVersion, regex)) + { + int count = 0; + unsigned int versionPart = 0; + std::regex pattern("([0-9]+)"); + for (auto i = std::sregex_iterator(webIfVersion.begin(), webIfVersion.end(), pattern); i != std::sregex_iterator(); ++i) + { + switch (count) + { + case 0: + versionPart = atoi(i->str().c_str()); + webIfVersionAsNum = versionPart << 16; + break; + case 1: + versionPart = atoi(i->str().c_str()); + webIfVersionAsNum |= versionPart << 8; + break; + case 2: + versionPart = atoi(i->str().c_str()); + webIfVersionAsNum |= versionPart; + break; + } + + count++; + } + } + + return webIfVersionAsNum; +} + +bool Admin::LoadDeviceSettings() +{ + //TODO: Include once addon starts to use new API + //kodi::SetSettingString("webifversion", m_deviceInfo.GetWebIfVersion()); + + if (!LoadAutoTimerSettings()) + { + return false; + } + else + { + std::string autoTimerTagInTags = LocalizedString(30094); // N/A + std::string autoTimerNameInTags = LocalizedString(30094); // N/A + + //If OpenWebVersion is new enough to allow the setting of AutoTimer setttings + if (Settings::GetInstance().GetWebIfVersionAsNum() >= Settings::GetInstance().GenerateWebIfVersionAsNum(1, 3, 0)) + { + if (m_deviceSettings.IsAddTagAutoTimerToTagsEnabled()) + autoTimerTagInTags = LocalizedString(30095); // True + else + autoTimerTagInTags = LocalizedString(30096); // False + if (m_deviceSettings.IsAddAutoTimerNameToTagsEnabled()) + autoTimerNameInTags = LocalizedString(30095); // True + else + autoTimerNameInTags = LocalizedString(30096); //False + } + + //TODO: Include once addon starts to use new API + //kodi::SetSettingString("autotimertagintags", autoTimerTagInTags); + //kodi::SetSettingString("autotimernameintags", autoTimerNameInTags); + } + + if (!LoadRecordingMarginSettings()) + { + return false; + } + else + { + //TODO: Include once addon starts to use new API + //kodi::SetSettingInt("globalstartpaddingstb", m_deviceSettings.GetGlobalRecordingStartMargin()); + //kodi::SetSettingInt("globalendpaddingstb", m_deviceSettings.GetGlobalRecordingEndMargin()); + } + + return true; +} + +bool Admin::LoadAutoTimerSettings() +{ + const std::string url = StringUtils::Format("%s%s", Settings::GetInstance().GetConnectionURL().c_str(), "autotimer/get"); + + const std::string strXML = WebUtils::GetHttpXML(url); + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(strXML.c_str())) + { + Logger::Log(LEVEL_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return false; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("e2settings").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); + return false; + } + + hRoot=TiXmlHandle(pElem); + + TiXmlElement* pNode = hRoot.FirstChildElement("e2setting").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_DEBUG, "Could not find element"); + return false; + } + + std::string settingName; + std::string settingValue; + bool setAutoTimerToTags = false; + bool setAutoTimerNameToTags = false; + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2setting")) + { + if (!XMLUtils::GetString(pNode, "e2settingname", settingName)) + return false; + + if (!XMLUtils::GetString(pNode, "e2settingvalue", settingValue)) + return false; + + if (settingName == "config.plugins.autotimer.add_autotimer_to_tags") + { + m_deviceSettings.SetAddTagAutoTimerToTagsEnabled(settingValue == "True"); + setAutoTimerToTags = true; + } + else if (settingName == "config.plugins.autotimer.add_name_to_tags") + { + m_deviceSettings.SetAddAutoTimerNameToTagsEnabled(settingValue == "True"); + setAutoTimerNameToTags = true; + } + + if (setAutoTimerNameToTags && setAutoTimerToTags) + break; + } + + Logger::Log(LEVEL_DEBUG, "%s Add Tag AutoTimer to Tags: %d, Add AutoTimer Name to tags: %d", __FUNCTION__, m_deviceSettings.IsAddTagAutoTimerToTagsEnabled(), m_deviceSettings.IsAddAutoTimerNameToTagsEnabled()); + + return true; +} + +bool Admin::LoadRecordingMarginSettings() +{ + const std::string url = StringUtils::Format("%s%s", Settings::GetInstance().GetConnectionURL().c_str(), "web/settings"); + + const std::string strXML = WebUtils::GetHttpXML(url); + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(strXML.c_str())) + { + Logger::Log(LEVEL_ERROR, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return false; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("e2settings").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_DEBUG, "%s Could not find element!", __FUNCTION__); + return false; + } + + hRoot=TiXmlHandle(pElem); + + TiXmlElement* pNode = hRoot.FirstChildElement("e2setting").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_DEBUG, "Could not find element"); + return false; + } + + std::string settingName; + std::string settingValue; + bool readMarginBefore = false; + bool readMarginAfter = false; + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2setting")) + { + if (!XMLUtils::GetString(pNode, "e2settingname", settingName)) + continue; + + if (!XMLUtils::GetString(pNode, "e2settingvalue", settingValue)) + continue; + + if (settingName == "config.recording.margin_before") + { + m_deviceSettings.SetGlobalRecordingStartMargin(atoi(settingValue.c_str())); + readMarginBefore = true; + } + else if (settingName == "config.recording.margin_after") + { + m_deviceSettings.SetGlobalRecordingEndMargin(atoi(settingValue.c_str())); + readMarginAfter = true; + } + + if (readMarginBefore && readMarginAfter) + break; + } + + Logger::Log(LEVEL_DEBUG, "%s Margin Before: %d, Margin After: %d", __FUNCTION__, m_deviceSettings.GetGlobalRecordingStartMargin(), m_deviceSettings.GetGlobalRecordingEndMargin()); + + return true; +} + +bool Admin::SendAutoTimerSettings() +{ + if (!(m_deviceSettings.IsAddTagAutoTimerToTagsEnabled() && m_deviceSettings.IsAddAutoTimerNameToTagsEnabled())) + { + Logger::Log(LEVEL_DEBUG, "%s Setting AutoTimer Settings on Backend", __FUNCTION__); + std::string url = StringUtils::Format("%s", "autotimer/set?add_name_to_tags=true&add_autotimer_to_tags=true"); + std::string strResult; + + if (!WebUtils::SendSimpleCommand(url, strResult)) + return false; + } + + return true; +} + +bool Admin::SendGlobalRecordingStartMarginSetting(int newValue) +{ + if (m_deviceSettings.GetGlobalRecordingStartMargin() != newValue) + { + Logger::Log(LEVEL_NOTICE, "%s Setting Global Recording Start Margin Backend, from: %d, to: %d", __FUNCTION__, m_deviceSettings.GetGlobalRecordingStartMargin(), newValue); + std::string url = StringUtils::Format("%s%d", "api/saveconfig?key=config.recording.margin_before&value=", newValue); + std::string strResult; + + if (!WebUtils::SendSimpleJsonPostCommand(url, strResult)) + return false; + else + m_deviceSettings.SetGlobalRecordingStartMargin(newValue); + } + + return true; +} + +bool Admin::SendGlobalRecordingEndMarginSetting(int newValue) +{ + if (m_deviceSettings.GetGlobalRecordingEndMargin() != newValue) + { + Logger::Log(LEVEL_NOTICE, "%s Setting Global Recording End Margin Backend, from: %d, to: %d", __FUNCTION__, m_deviceSettings.GetGlobalRecordingEndMargin(), newValue); + std::string url = StringUtils::Format("%s%d", "api/saveconfig?key=config.recording.margin_after&value=", newValue); + std::string strResult; + + if (!WebUtils::SendSimpleJsonPostCommand(url, strResult)) + return false; + else + m_deviceSettings.SetGlobalRecordingEndMargin(newValue); + } + + return true; +} + +PVR_ERROR Admin::GetDriveSpace(long long *iTotal, long long *iUsed, std::vector &locations) +{ + long long totalKb = 0; + long long freeKb = 0; + + const std::string url = StringUtils::Format("%s%s", Settings::GetInstance().GetConnectionURL().c_str(), "web/deviceinfo"); + + const std::string strXML = WebUtils::GetHttpXML(url); + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(strXML.c_str())) + { + Logger::Log(LEVEL_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return PVR_ERROR_SERVER_ERROR; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("e2deviceinfo").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); + return PVR_ERROR_SERVER_ERROR; + } + + hRoot=TiXmlHandle(pElem); + + TiXmlElement* pNode = hRoot.FirstChildElement("e2hdds").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_DEBUG, "Could not find element"); + return PVR_ERROR_SERVER_ERROR; + } + + TiXmlElement* hddNode = pNode->FirstChildElement("e2hdd"); + + if (!hddNode) + { + Logger::Log(LEVEL_DEBUG, "Could not find element"); + return PVR_ERROR_SERVER_ERROR; + } + + for (; hddNode != nullptr; hddNode = hddNode->NextSiblingElement("e2hdd")) + { + std::string capacity; + std::string freeSpace; + std::string mount; + + XMLUtils::GetString(hddNode, "e2capacity", capacity); + XMLUtils::GetString(hddNode, "e2free", freeSpace); + XMLUtils::GetString(hddNode, "e2mount", mount); + + if (!mount.empty()) + { + auto it = std::find_if(locations.begin(), locations.end(), + [&mount](std::string& location) { return location.find(mount) != std::string::npos; }); + + if (it == locations.end()) + continue; // no valid mount point + } + + totalKb += GetKbFromString(capacity); + freeKb += GetKbFromString(freeSpace); + } + + *iTotal = totalKb; + *iUsed = totalKb - freeKb; + + Logger::Log(LEVEL_INFO, "GetDriveSpace Total: %lld, Used %lld", *iTotal, *iUsed); + + return PVR_ERROR_NO_ERROR; +} + +long long Admin::GetKbFromString(const std::string &stringInMbGbTb) const +{ + long long sizeInKb = 0; + + static const std::vector sizes = {"MB", "GB", "TB"}; + long multiplier = 1024; + std::string replaceWith = ""; + for (const std::string& size : sizes) + { + std::regex regexSize ("^.* " + size); + std::regex regexReplaceSize (" " + size); + + if (regex_match(stringInMbGbTb, regexSize)) + { + double sizeValue = atof(regex_replace(stringInMbGbTb, regexReplaceSize, replaceWith).c_str()); + + sizeInKb += static_cast(sizeValue * multiplier); + + break; + } + + multiplier = multiplier * 1024; + } + + return sizeInKb; +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/Admin.h kodi-pvr-vuplus-3.15.0/src/enigma2/Admin.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/Admin.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/Admin.h 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,62 @@ +#pragma once +/* + * Copyright (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include + +#include "utilities/DeviceInfo.h" +#include "utilities/DeviceSettings.h" + +#include "libXBMC_pvr.h" + +namespace enigma2 +{ + + class Admin + { + public: + void SendPowerstate(); + bool Initialise(); + bool LoadDeviceSettings(); + bool SendAutoTimerSettings(); + bool SendGlobalRecordingStartMarginSetting(int newValue); + bool SendGlobalRecordingEndMarginSetting(int newValue); + const utilities::DeviceInfo& GetDeviceInfo() const { return m_deviceInfo; } + PVR_ERROR GetDriveSpace(long long *iTotal, long long *iUsed, std::vector &locations); + const std::string& GetServerName() const { return m_deviceInfo.GetServerName(); } + const std::string& GetEnigmaVersion() const { return m_deviceInfo.GetEnigmaVersion(); } + const std::string& GetImageVersion() const { return m_deviceInfo.GetImageVersion(); } + const std::string& GetWebIfVersion() const { return m_deviceInfo.GetWebIfVersion(); } + unsigned int GetWebIfVersionAsNum() const { return m_deviceInfo.GetWebIfVersionAsNum(); } + + private: + bool LoadDeviceInfo(); + bool LoadAutoTimerSettings(); + bool LoadRecordingMarginSettings(); + unsigned int ParseWebIfVersion(const std::string &webIfVersion); + long long GetKbFromString(const std::string &stringInMbGbTb) const; + + enigma2::utilities::DeviceInfo m_deviceInfo; + enigma2::utilities::DeviceSettings m_deviceSettings; + }; +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/ChannelGroups.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/ChannelGroups.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/ChannelGroups.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/ChannelGroups.cpp 2018-11-18 15:43:06.000000000 +0000 @@ -0,0 +1,305 @@ +#include "ChannelGroups.h" + +#include + +#include "../client.h" +#include "../Enigma2.h" +#include "utilities/LocalizedString.h" +#include "utilities/Logger.h" +#include "utilities/WebUtils.h" + +#include "util/XMLUtils.h" +#include "p8-platform/util/StringUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::utilities; + +void ChannelGroups::GetChannelGroups(std::vector &kodiChannelGroups, bool radio) const +{ + for (const auto& channelGroup : m_channelGroups) + { + Logger::Log(LEVEL_DEBUG, "%s - Transfer channelGroup '%s', ChannelGroupIndex '%d'", __FUNCTION__, channelGroup->GetGroupName().c_str(), channelGroup->GetUniqueId()); + + if (channelGroup->IsRadio() == radio) + { + PVR_CHANNEL_GROUP kodiChannelGroup; + memset(&kodiChannelGroup, 0 , sizeof(PVR_CHANNEL_GROUP)); + + channelGroup->UpdateTo(kodiChannelGroup); + + kodiChannelGroups.emplace_back(kodiChannelGroup); + } + } +} + +PVR_ERROR ChannelGroups::GetChannelGroupMembers(std::vector &channelGroupMembers, const std::string &groupName) +{ + std::shared_ptr channelGroup = GetChannelGroup(groupName); + + if (!channelGroup) + return PVR_ERROR_NO_ERROR; + + for (const auto& channel : channelGroup->GetChannelList()) + { + PVR_CHANNEL_GROUP_MEMBER tag; + memset(&tag,0 , sizeof(PVR_CHANNEL_GROUP_MEMBER)); + + strncpy(tag.strGroupName, groupName.c_str(), sizeof(tag.strGroupName)); + tag.iChannelUniqueId = channel->GetUniqueId(); + tag.iChannelNumber = channel->GetChannelNumber(); + + Logger::Log(LEVEL_DEBUG, "%s - add channel %s (%d) to group '%s' channel number %d", + __FUNCTION__, channel->GetChannelName().c_str(), tag.iChannelUniqueId, groupName.c_str(), channel->GetChannelNumber()); + + channelGroupMembers.emplace_back(tag); + } + + return PVR_ERROR_NO_ERROR; +} + +int ChannelGroups::GetChannelGroupUniqueId(const std::string &groupName) const +{ + for (const auto& channelGroup : m_channelGroups) + { + if (groupName == channelGroup->GetGroupName()) + return channelGroup->GetUniqueId(); + } + return -1; +} + +std::string ChannelGroups::GetChannelGroupServiceReference(const std::string &groupName) +{ + for (const auto& channelGroup : m_channelGroups) + { + if (groupName == channelGroup->GetGroupName()) + return channelGroup->GetServiceReference(); + } + return "error"; +} + +std::shared_ptr ChannelGroups::GetChannelGroup(int uniqueId) +{ + return m_channelGroups.at(uniqueId - 1); +} + +std::shared_ptr ChannelGroups::GetChannelGroup(std::string groupName) +{ + std::shared_ptr channelGroup = nullptr; + + auto channelGroupPair = m_channelGroupsNameMap.find(groupName); + if (channelGroupPair != m_channelGroupsNameMap.end()) + { + channelGroup = channelGroupPair->second; + } + + return channelGroup; +} + +bool ChannelGroups::IsValid(int uniqueId) const +{ + return (uniqueId - 1) < m_channelGroups.size(); +} + +bool ChannelGroups::IsValid(std::string groupName) +{ + return GetChannelGroup(groupName) != nullptr; +} + +int ChannelGroups::GetNumChannelGroups() const +{ + return m_channelGroups.size(); +} + +void ChannelGroups::ClearChannelGroups() +{ + m_channelGroups.clear(); +} + +void ChannelGroups::AddChannelGroup(ChannelGroup& newChannelGroup) +{ + std::shared_ptr foundChannelGroup = GetChannelGroup(newChannelGroup.GetGroupName()); + + if (!foundChannelGroup) + { + newChannelGroup.SetUniqueId(m_channelGroups.size() + 1); + + m_channelGroups.emplace_back(new ChannelGroup(newChannelGroup)); + + std::shared_ptr channelGroup = m_channelGroups.back(); + m_channelGroupsNameMap.insert({channelGroup->GetGroupName(), channelGroup}); + } +} + +std::vector>& ChannelGroups::GetChannelGroupsList() +{ + return m_channelGroups; +} + +bool ChannelGroups::LoadChannelGroups() +{ + m_channelGroups.clear(); + + bool successful = LoadTVChannelGroups(); + + if (successful) + LoadRadioChannelGroups(); + + return successful; +} + +bool ChannelGroups::LoadTVChannelGroups() +{ + if ((Settings::GetInstance().GetTVFavouritesMode() == FavouritesGroupMode::AS_FIRST_GROUP && + Settings::GetInstance().GetTVChannelGroupMode() != ChannelGroupMode::FAVOURITES_GROUP) || + Settings::GetInstance().GetTVChannelGroupMode() == ChannelGroupMode::FAVOURITES_GROUP) + { + AddTVFavouritesChannelGroup(); + } + + if (Settings::GetInstance().GetTVChannelGroupMode() != ChannelGroupMode::FAVOURITES_GROUP) + { + std::string strTmp; + + strTmp = StringUtils::Format("%sweb/getservices", Settings::GetInstance().GetConnectionURL().c_str()); + + std::string strXML = WebUtils::GetHttpXML(strTmp); + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(strXML.c_str())) + { + Logger::Log(LEVEL_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return false; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("e2servicelist").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_DEBUG, "%s Could not find element!", __FUNCTION__); + return false; + } + + hRoot=TiXmlHandle(pElem); + + TiXmlElement* pNode = hRoot.FirstChildElement("e2service").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_DEBUG, "%s Could not find element", __FUNCTION__); + return false; + } + + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2service")) + { + ChannelGroup newChannelGroup; + + if (!newChannelGroup.UpdateFrom(pNode, false)) + continue; + + AddChannelGroup(newChannelGroup); + + Logger::Log(LEVEL_INFO, "%s Loaded channelgroup: %s", __FUNCTION__, newChannelGroup.GetGroupName().c_str()); + } + } + + if (Settings::GetInstance().GetTVFavouritesMode() == FavouritesGroupMode::AS_LAST_GROUP && + Settings::GetInstance().GetTVChannelGroupMode() != ChannelGroupMode::FAVOURITES_GROUP) + { + AddTVFavouritesChannelGroup(); + } + + Logger::Log(LEVEL_INFO, "%s Loaded %d TV Channelgroups", __FUNCTION__, m_channelGroups.size()); + return true; +} + +bool ChannelGroups::LoadRadioChannelGroups() +{ + if ((Settings::GetInstance().GetRadioFavouritesMode() == FavouritesGroupMode::AS_FIRST_GROUP && + Settings::GetInstance().GetRadioChannelGroupMode() != ChannelGroupMode::FAVOURITES_GROUP) || + Settings::GetInstance().GetRadioChannelGroupMode() == ChannelGroupMode::FAVOURITES_GROUP) + { + AddRadioFavouritesChannelGroup(); + } + + if (Settings::GetInstance().GetRadioChannelGroupMode() != ChannelGroupMode::FAVOURITES_GROUP) + { + std::string strTmp = StringUtils::Format("%sweb/getallservices?type=radio&renameserviceforxbmc=yes", Settings::GetInstance().GetConnectionURL().c_str()); + + std::string strXML = WebUtils::GetHttpXML(strTmp); + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(strXML.c_str())) + { + Logger::Log(LEVEL_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return false; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("e2servicelistrecursive").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_DEBUG, "%s Could not find element!", __FUNCTION__); + return false; + } + + hRoot=TiXmlHandle(pElem); + + TiXmlElement* pNode = hRoot.FirstChildElement("e2bouquet").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_DEBUG, "%s Could not find element", __FUNCTION__); + return false; + } + + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2bouquet")) + { + ChannelGroup newChannelGroup; + + if (!newChannelGroup.UpdateFrom(pNode, true)) + continue; + + AddChannelGroup(newChannelGroup); + + Logger::Log(LEVEL_INFO, "%s Loaded channelgroup: %s", __FUNCTION__, newChannelGroup.GetGroupName().c_str()); + } + } + + if (Settings::GetInstance().GetRadioFavouritesMode() == FavouritesGroupMode::AS_LAST_GROUP && + Settings::GetInstance().GetRadioChannelGroupMode() != ChannelGroupMode::FAVOURITES_GROUP) + { + AddRadioFavouritesChannelGroup(); + } + + Logger::Log(LEVEL_INFO, "%s Loaded %d Radio Channelgroups", __FUNCTION__, m_channelGroups.size()); + return true; +} + +void ChannelGroups::AddTVFavouritesChannelGroup() +{ + ChannelGroup newChannelGroup; + newChannelGroup.SetRadio(false); + newChannelGroup.SetGroupName(LocalizedString(30079)); //Favourites (TV) + newChannelGroup.SetServiceReference("1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"userbouquet.favourites.tv\" ORDER BY bouquet"); + AddChannelGroup(newChannelGroup); + Logger::Log(LEVEL_INFO, "%s Loaded channelgroup: %s", __FUNCTION__, newChannelGroup.GetGroupName().c_str()); +} + +void ChannelGroups::AddRadioFavouritesChannelGroup() +{ + ChannelGroup newChannelGroup; + newChannelGroup.SetRadio(true); + newChannelGroup.SetGroupName(LocalizedString(30080)); //Favourites (Radio) + newChannelGroup.SetServiceReference("1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"userbouquet.favourites.radio\" ORDER BY bouquet"); + AddChannelGroup(newChannelGroup); + Logger::Log(LEVEL_INFO, "%s Loaded channelgroup: %s", __FUNCTION__, newChannelGroup.GetGroupName().c_str()); +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/ChannelGroups.h kodi-pvr-vuplus-3.15.0/src/enigma2/ChannelGroups.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/ChannelGroups.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/ChannelGroups.h 2018-11-18 15:43:06.000000000 +0000 @@ -0,0 +1,63 @@ +#pragma once +/* + * Copyright (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include +#include +#include + +#include "data/Channel.h" +#include "data/ChannelGroup.h" + +#include "libXBMC_pvr.h" + +namespace enigma2 +{ + class ChannelGroups + { + public: + void GetChannelGroups(std::vector &channelGroups, bool radio) const; + PVR_ERROR GetChannelGroupMembers(std::vector &channelGroupMembers, const std::string &groupName); + + int GetChannelGroupUniqueId(const std::string &groupName) const; + std::string GetChannelGroupServiceReference(const std::string &groupName); + std::shared_ptr GetChannelGroup(int uniqueId); + std::shared_ptr GetChannelGroup(std::string groupName); + bool IsValid(int uniqueId) const; + bool IsValid(std::string groupName); + int GetNumChannelGroups() const; + void ClearChannelGroups(); + std::vector>& GetChannelGroupsList(); + bool LoadChannelGroups(); + + private: + bool LoadTVChannelGroups(); + bool LoadRadioChannelGroups(); + void AddTVFavouritesChannelGroup(); + void AddRadioFavouritesChannelGroup(); + void AddChannelGroup(enigma2::data::ChannelGroup& channelGroup); + + std::vector> m_channelGroups; + std::unordered_map> m_channelGroupsNameMap; + }; +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/Channels.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/Channels.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/Channels.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/Channels.cpp 2018-11-18 15:43:06.000000000 +0000 @@ -0,0 +1,204 @@ +#include "Channels.h" + +#include + +#include "../client.h" +#include "../Enigma2.h" +#include "ChannelGroups.h" +#include "utilities/Logger.h" +#include "utilities/WebUtils.h" + +#include "util/XMLUtils.h" +#include "p8-platform/util/StringUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::utilities; + +void Channels::GetChannels(std::vector &kodiChannels, bool bRadio) const +{ + for (const auto& channel : m_channels) + { + if (channel->IsRadio() == bRadio) + { + Logger::Log(LEVEL_DEBUG, "%s - Transfer channel '%s', ChannelIndex '%d'", __FUNCTION__, channel->GetChannelName().c_str(), channel->GetUniqueId()); + PVR_CHANNEL kodiChannel; + memset(&kodiChannel, 0, sizeof(PVR_CHANNEL)); + + channel->UpdateTo(kodiChannel); + + kodiChannels.emplace_back(kodiChannel); + } + } +} + +int Channels::GetChannelUniqueId(const std::string &channelServiceReference) +{ + std::shared_ptr channel = GetChannel(channelServiceReference); + int uniqueId = -1; + + if (channel) + uniqueId = channel->GetUniqueId(); + + return uniqueId; +} + +std::shared_ptr Channels::GetChannel(int uniqueId) +{ + return m_channels.at(uniqueId - 1); +} + +std::shared_ptr Channels::GetChannel(const std::string &channelServiceReference) +{ + std::shared_ptr channel = nullptr; + + auto channelPair = m_channelsServiceReferenceMap.find(channelServiceReference); + if (channelPair != m_channelsServiceReferenceMap.end()) + { + channel = channelPair->second; + } + + return channel; +} + +bool Channels::IsValid(int uniqueId) const +{ + return (uniqueId - 1) < m_channels.size(); +} + +bool Channels::IsValid(const std::string &channelServiceReference) +{ + return GetChannel(channelServiceReference) != nullptr; +} + +int Channels::GetNumChannels() const +{ + return m_channels.size(); +} + +void Channels::ClearChannels() +{ + m_channels.clear(); +} + +void Channels::AddChannel(Channel &newChannel, std::shared_ptr &channelGroup) +{ + std::shared_ptr foundChannel = GetChannel(newChannel.GetServiceReference()); + + if (!foundChannel) + { + newChannel.SetUniqueId(m_channels.size() + 1); + newChannel.SetChannelNumber(m_channels.size() + 1); + + m_channels.emplace_back(new Channel(newChannel)); + + std::shared_ptr channel = m_channels.back(); + channel->AddChannelGroup(channelGroup); + channelGroup->AddChannel(channel); + + m_channelsServiceReferenceMap.insert({channel->GetServiceReference(), channel}); + } + else + { + foundChannel->AddChannelGroup(channelGroup); + channelGroup->AddChannel(foundChannel); + } +} + +std::vector>& Channels::GetChannelsList() +{ + return m_channels; +} + +bool Channels::CheckIfAllChannelsHaveInitialEPG() const +{ + bool someChannelsStillNeedInitialEPG = false; + for (const auto& channel : m_channels) + { + if (channel->RequiresInitialEPG()) + { + someChannelsStillNeedInitialEPG = true; + } + } + + return !someChannelsStillNeedInitialEPG; +} + +std::string Channels::GetChannelIconPath(std::string strChannelName) +{ + for (const auto& channel : m_channels) + { + if (strChannelName == channel->GetChannelName()) + return channel->GetIconPath(); + } + return ""; +} + +bool Channels::LoadChannels(ChannelGroups &channelGroups) +{ + bool bOk = false; + + ClearChannels(); + // Load Channels + for (auto& group : channelGroups.GetChannelGroupsList()) + { + if (LoadChannels(group->GetServiceReference(), group->GetGroupName(), group)) + bOk = true; + } + + return bOk; +} + +bool Channels::LoadChannels(const std::string groupServiceReference, const std::string groupName, std::shared_ptr &channelGroup) +{ + Logger::Log(LEVEL_INFO, "%s loading channel group: '%s'", __FUNCTION__, groupName.c_str()); + + std::string strTmp; + strTmp = StringUtils::Format("%sweb/getservices?sRef=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(groupServiceReference).c_str()); + + std::string strXML = WebUtils::GetHttpXML(strTmp); + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(strXML.c_str())) + { + Logger::Log(LEVEL_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return false; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("e2servicelist").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_DEBUG, "%s Could not find element!", __FUNCTION__); + return false; + } + + hRoot=TiXmlHandle(pElem); + + TiXmlElement* pNode = hRoot.FirstChildElement("e2service").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_DEBUG, "Could not find element"); + return false; + } + + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2service")) + { + Channel newChannel; + newChannel.SetRadio(channelGroup->IsRadio()); + + if (!newChannel.UpdateFrom(pNode, Settings::GetInstance().GetConnectionURL())) + continue; + + AddChannel(newChannel, channelGroup); + Logger::Log(LEVEL_DEBUG, "%s Loaded channel: %s, Group: %s, Icon: %s, ID: %d", __FUNCTION__, newChannel.GetChannelName().c_str(), groupName.c_str(), newChannel.GetIconPath().c_str(), newChannel.GetUniqueId()); + } + + Logger::Log(LEVEL_INFO, "%s Loaded %d Channels", __FUNCTION__, GetNumChannels()); + return true; +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/Channels.h kodi-pvr-vuplus-3.15.0/src/enigma2/Channels.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/Channels.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/Channels.h 2018-11-18 15:43:06.000000000 +0000 @@ -0,0 +1,66 @@ +#pragma once +/* + * Copyright (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include +#include +#include + +#include "data/Channel.h" + +#include "libXBMC_pvr.h" + +namespace enigma2 +{ + class ChannelGroups; + + namespace data + { + class ChannelGroup; + } + + class Channels + { + public: + void GetChannels(std::vector &timers, bool bRadio) const; + + int GetChannelUniqueId(const std::string &channelServiceReference); + std::shared_ptr GetChannel(int uniqueId); + std::shared_ptr GetChannel(const std::string &channelServiceReference); + bool IsValid(int uniqueId) const; + bool IsValid(const std::string &channelServiceReference); + int GetNumChannels() const; + void ClearChannels(); + std::vector>& GetChannelsList(); + bool CheckIfAllChannelsHaveInitialEPG() const; + std::string GetChannelIconPath(std::string strChannelName); + bool LoadChannels(enigma2::ChannelGroups &channelGroups); + + private: + void AddChannel(enigma2::data::Channel &channel, std::shared_ptr &channelGroup); + bool LoadChannels(const std::string groupServiceReference, const std::string groupName, std::shared_ptr &channelGroup); + + std::vector> m_channels; + std::unordered_map> m_channelsServiceReferenceMap; + }; +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/data/AutoTimer.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/data/AutoTimer.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/data/AutoTimer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/data/AutoTimer.cpp 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,236 @@ +#include "AutoTimer.h" + +#include "inttypes.h" +#include "util/XMLUtils.h" +#include "p8-platform/util/StringUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::utilities; + +bool AutoTimer::Like(const AutoTimer &right) const +{ + return m_backendId == right.m_backendId;; +} + +bool AutoTimer::operator==(const AutoTimer &right) const +{ + bool bChanged = true; + bChanged = bChanged && (!m_title.compare(right.m_title)); + bChanged = bChanged && (m_startTime == right.m_startTime); + bChanged = bChanged && (m_endTime == right.m_endTime); + bChanged = bChanged && (m_channelId == right.m_channelId); + bChanged = bChanged && (m_weekdays == right.m_weekdays); + + bChanged = bChanged && (m_searchPhrase == right.m_searchPhrase); + bChanged = bChanged && (m_searchType == right.m_searchType); + bChanged = bChanged && (m_searchCase == right.m_searchCase); + bChanged = bChanged && (m_state == right.m_state); + bChanged = bChanged && (m_searchFulltext == right.m_searchFulltext); + bChanged = bChanged && (m_startAnyTime == right.m_startAnyTime); + bChanged = bChanged && (m_endAnyTime == right.m_endAnyTime); + bChanged = bChanged && (m_anyChannel == right.m_anyChannel); + bChanged = bChanged && (m_deDup == right.m_deDup); + + return bChanged; +} + +void AutoTimer::UpdateFrom(const AutoTimer &right) +{ + Timer::UpdateFrom(right); + + m_searchPhrase = right.m_searchPhrase; + m_encoding = right.m_encoding; + m_searchCase = right.m_searchCase; + m_searchType = right.m_searchType; + m_searchFulltext = right.m_searchFulltext; + m_startAnyTime = right.m_startAnyTime; + m_endAnyTime = right.m_endAnyTime; + m_anyChannel = right.m_anyChannel; + m_deDup = right.m_deDup; +} + +void AutoTimer::UpdateTo(PVR_TIMER &left) const +{ + strncpy(left.strTitle, m_title.c_str(), sizeof(left.strTitle)); + //strncpy(tag.strDirectory, "/", sizeof(tag.strDirectory)); // unused + //strncpy(tag.strSummary, timer.strPlot.c_str(), sizeof(tag.strSummary)); + strncpy(left.strEpgSearchString, m_searchPhrase.c_str(), sizeof(left.strEpgSearchString)); + left.iTimerType = m_type; + if (m_anyChannel) + left.iClientChannelUid = PVR_TIMER_ANY_CHANNEL; + else + left.iClientChannelUid = m_channelId; + left.startTime = m_startTime; + left.endTime = m_endTime; + left.state = m_state; + left.iPriority = 0; // unused + left.iLifetime = 0; // unused + left.firstDay = 0; // unused + left.iWeekdays = m_weekdays; + //right.iEpgUid = timer.iEpgID; + left.iMarginStart = 0; // unused + left.iMarginEnd = 0; // unused + left.iGenreType = 0; // unused + left.iGenreSubType = 0; // unused + left.iClientIndex = m_clientIndex; + left.bStartAnyTime = m_startAnyTime; + left.bEndAnyTime = m_endAnyTime; + left.bFullTextEpgSearch = m_searchFulltext; + left.iPreventDuplicateEpisodes = m_deDup; +} + +bool AutoTimer::UpdateFrom(TiXmlElement* autoTimerNode, Channels &channels) +{ + std::string strTmp; + int iTmp; + + m_type = Timer::EPG_AUTO_SEARCH; + + //this is an auto timer so the state is always scheduled unless it's disabled + m_state = PVR_TIMER_STATE_SCHEDULED; + + if (autoTimerNode->QueryStringAttribute("name", &strTmp) == TIXML_SUCCESS) + m_title = strTmp; + + if (autoTimerNode->QueryStringAttribute("match", &strTmp) == TIXML_SUCCESS) + m_searchPhrase = strTmp; + + if (autoTimerNode->QueryStringAttribute("enabled", &strTmp) == TIXML_SUCCESS) + { + if (strTmp == AUTOTIMER_ENABLED_NO) + { + m_state = PVR_TIMER_STATE_CANCELLED; + } + } + + if (autoTimerNode->QueryIntAttribute("id", &iTmp) == TIXML_SUCCESS) + m_backendId = iTmp; + + std::string from; + std::string to; + std::string avoidDuplicateDescription; + std::string searchForDuplicateDescription; + autoTimerNode->QueryStringAttribute("from", &from); + autoTimerNode->QueryStringAttribute("to", &to); + autoTimerNode->QueryStringAttribute("avoidDuplicateDescription", &avoidDuplicateDescription); + autoTimerNode->QueryStringAttribute("searchForDuplicateDescription", &searchForDuplicateDescription); + + if (avoidDuplicateDescription != AUTOTIMER_AVOID_DUPLICATE_DISABLED) + { + if (searchForDuplicateDescription == AUTOTIMER_CHECK_SEARCH_FOR_DUP_IN_TITLE) + m_deDup = AutoTimer::DeDup::CHECK_TITLE; + else if (searchForDuplicateDescription == AUTOTIMER_CHECK_SEARCH_FOR_DUP_IN_TITLE_AND_SHORT_DESC) + m_deDup = AutoTimer::DeDup::CHECK_TITLE_AND_SHORT_DESC; + else if (searchForDuplicateDescription.empty() || searchForDuplicateDescription == AUTOTIMER_CHECK_SEARCH_FOR_DUP_IN_TITLE_AND_ALL_DESCS) //Even though this value should be 2 it is sent as ommitted for this attribute, we'll allow 2 anyway incase it changes in the future + m_deDup = AutoTimer::DeDup::CHECK_TITLE_AND_ALL_DESCS; + } + + if (autoTimerNode->QueryStringAttribute("encoding", &strTmp) == TIXML_SUCCESS) + m_encoding = strTmp; + + if (autoTimerNode->QueryStringAttribute("searchType", &strTmp) == TIXML_SUCCESS) + { + m_searchType = strTmp; + if (strTmp == AUTOTIMER_SEARCH_TYPE_DESCRIPTION) + m_searchFulltext = true; + } + + if (autoTimerNode->QueryStringAttribute("searchCase", &strTmp) == TIXML_SUCCESS) + m_searchCase = strTmp; + + TiXmlElement* serviceNode = autoTimerNode->FirstChildElement("e2service"); + + if (serviceNode) + { + const TiXmlElement *nextServiceNode = serviceNode->NextSiblingElement("e2service"); + + if (!nextServiceNode) + { + //If we only have one channel + if (XMLUtils::GetString(serviceNode, "e2servicereference", strTmp)) + { + m_channelId = channels.GetChannelUniqueId(strTmp.c_str()); + + // Skip autotimers for channels we don't know about, such as when the addon only uses one bouquet or an old channel referene that doesn't exist + if (m_channelId < 0) + { + Logger::Log(LEVEL_DEBUG, "%s could not find channel so skipping autotimer: '%s'", __FUNCTION__, m_title.c_str()); + return false; + } + + m_channelName = channels.GetChannel(m_channelId)->GetChannelName(); + } + } + else //otherwise set to any channel + { + m_channelId = PVR_TIMER_ANY_CHANNEL; + m_anyChannel = true; + } + } + else //otherwise set to any channel + { + m_channelId = PVR_TIMER_ANY_CHANNEL; + m_anyChannel = true; + } + + m_weekdays = 0; + + TiXmlElement* includeNode = autoTimerNode->FirstChildElement("include"); + + if (includeNode) + { + for (; includeNode != nullptr; includeNode = includeNode->NextSiblingElement("include")) + { + std::string includeVal = includeNode->GetText(); + + std::string where; + if (includeNode->QueryStringAttribute("where", &where) == TIXML_SUCCESS) + { + if (where == "dayofweek") + { + m_weekdays = m_weekdays |= (1 << atoi(includeVal.c_str())); + } + } + } + } + + if (m_weekdays != PVR_WEEKDAY_NONE) + { + std::time_t t = std::time(nullptr); + std::tm timeinfo = *std::localtime(&t); + timeinfo.tm_sec = 0; + m_startTime = 0; + if (!from.empty()) + { + ParseTime(from, timeinfo); + m_startTime = std::mktime(&timeinfo); + } + + timeinfo = *std::localtime(&t); + timeinfo.tm_sec = 0; + m_endTime = 0; + if (!to.empty()) + { + ParseTime(to, timeinfo); + m_endTime = std::mktime(&timeinfo); + } + } + else + { + for (int i = 0; i < DAYS_IN_WEEK; i++) + { + m_weekdays = m_weekdays |= (1 << i); + } + m_startAnyTime = true; + m_endAnyTime = true; + } + + return true; +} + +void AutoTimer::ParseTime(const std::string &time, std::tm &timeinfo) const +{ + std::sscanf(time.c_str(), "%02d:%02d", &timeinfo.tm_hour, + &timeinfo.tm_min); +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/data/AutoTimer.h kodi-pvr-vuplus-3.15.0/src/enigma2/data/AutoTimer.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/data/AutoTimer.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/data/AutoTimer.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,128 @@ +#pragma once +/* + * Copyright (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include +#include + +#include "Timer.h" + +#include "libXBMC_pvr.h" +#include "tinyxml.h" + +namespace enigma2 +{ + static const std::string AUTOTIMER_SEARCH_CASE_SENSITIVE = "sensitive"; + static const std::string AUTOTIMER_SEARCH_CASE_INSENITIVE = ""; + + static const std::string AUTOTIMER_ENABLED_YES = "yes"; + static const std::string AUTOTIMER_ENABLED_NO = "no"; + + static const std::string AUTOTIMER_ENCODING = "UTF-8"; + + static const std::string AUTOTIMER_SEARCH_TYPE_EXACT = "exact"; + static const std::string AUTOTIMER_SEARCH_TYPE_DESCRIPTION = "description"; + static const std::string AUTOTIMER_SEARCH_TYPE_START = "start"; + static const std::string AUTOTIMER_SEARCH_TYPE_PARTIAL = ""; + + static const std::string AUTOTIMER_AVOID_DUPLICATE_DISABLED = ""; //Require Description to be unique - No + static const std::string AUTOTIMER_AVOID_DUPLICATE_SAME_SERVICE = "1"; //Require Description to be unique - On same service + static const std::string AUTOTIMER_AVOID_DUPLICATE_ANY_SERVICE = "2"; //Require Description to be unique - On any service + static const std::string AUTOTIMER_AVOID_DUPLICATE_ANY_SERVICE_OR_RECORDING = "3"; //Require Description to be unique - On any service/recording + + static const std::string AUTOTIMER_CHECK_SEARCH_FOR_DUP_IN_TITLE = "0"; //Check for uniqueness in - Title + static const std::string AUTOTIMER_CHECK_SEARCH_FOR_DUP_IN_TITLE_AND_SHORT_DESC = "1"; //Check for uniqueness in - Title and Short description + static const std::string AUTOTIMER_CHECK_SEARCH_FOR_DUP_IN_TITLE_AND_ALL_DESCS = "2"; //Check for uniqueness in - Title and all descpritions + + static const std::string AUTOTIMER_DEFAULT = ""; + + static const int DAYS_IN_WEEK = 7; + + namespace data + { + class AutoTimer + : public Timer + { + public: + enum DeDup + : unsigned int // same type as PVR_TIMER_TYPE.iPreventDuplicateEpisodes + { + DISABLED = 0, + CHECK_TITLE = 1, + CHECK_TITLE_AND_SHORT_DESC = 2, + CHECK_TITLE_AND_ALL_DESCS = 3 + }; + + AutoTimer() = default; + + const std::string& GetSearchPhrase() const { return m_searchPhrase; } + void SetSearchPhrase(const std::string& value ) { m_searchPhrase = value; } + + const std::string& GetEncoding() const { return m_encoding; } + void SetEncoding(const std::string& value ) { m_encoding = value; } + + const std::string& GetSearchCase() const { return m_searchCase; } + void SetSearchCase(const std::string& value ) { m_searchCase = value; } + + const std::string& GetSearchType() const { return m_searchType; } + void SetSearchType(const std::string& value ) { m_searchType = value; } + + unsigned int GetBackendId() const { return m_backendId; } + void SetBackendId(unsigned int value) { m_backendId = value; } + + bool GetSearchFulltext() const { return m_searchFulltext; } + void SetSearchFulltext(bool value) { m_searchFulltext = value; } + + bool GetStartAnyTime() const { return m_startAnyTime; } + void SetStartAnyTime(bool value) { m_startAnyTime = value; } + + bool GetEndAnyTime() const { return m_endAnyTime; } + void SetEndAnyTime(bool value) { m_endAnyTime = value; } + + bool GetAnyChannel() const { return m_anyChannel; } + void SetAnyChannel(bool value) { m_anyChannel = value; } + + std::underlying_type::type GetDeDup() const { return m_deDup; } + void SetDeDup(const std::underlying_type::type value ) { m_deDup = value; } + + bool Like(const AutoTimer &right) const; + bool operator==(const AutoTimer &right) const; + void UpdateFrom(const AutoTimer &right); + void UpdateTo(PVR_TIMER &right) const; + bool UpdateFrom(TiXmlElement* autoTimerNode, Channels &channels); + void ParseTime(const std::string &time, std::tm &timeinfo) const; + + private: + std::string m_searchPhrase; + std::string m_encoding; + std::string m_searchCase; + std::string m_searchType; + unsigned int m_backendId; + bool m_searchFulltext = false; + bool m_startAnyTime = false; + bool m_endAnyTime = false; + bool m_anyChannel = false; + std::underlying_type::type m_deDup = DeDup::DISABLED; + }; + } //namespace data +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/data/BaseEntry.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/data/BaseEntry.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/data/BaseEntry.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/data/BaseEntry.cpp 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,24 @@ +#include "BaseEntry.h" + +#include "inttypes.h" +#include "p8-platform/util/StringUtils.h" + +using namespace enigma2; +using namespace enigma2::data; + +void BaseEntry::ProcessPrependMode(PrependOutline prependOutlineMode) +{ + // Some providers only use PlotOutline (e.g. freesat) and Kodi does not display it, if this is the case swap them + if (m_plot.empty()) + { + m_plot = m_plotOutline; + m_plotOutline.clear(); + } + else if ((Settings::GetInstance().GetPrependOutline() == prependOutlineMode || + Settings::GetInstance().GetPrependOutline() == PrependOutline::ALWAYS) + && !m_plotOutline.empty()) + { + m_plot.insert(0, m_plotOutline + "\n"); + m_plotOutline.clear(); + } +} diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/data/BaseEntry.h kodi-pvr-vuplus-3.15.0/src/enigma2/data/BaseEntry.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/data/BaseEntry.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/data/BaseEntry.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,80 @@ +#pragma once +/* + * Copyright (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include + +#include "../Settings.h" + +namespace enigma2 +{ + namespace data + { + class BaseEntry + { + public: + const std::string& GetTitle() const { return m_title; } + void SetTitle(const std::string& value ) { m_title = value; } + + const std::string& GetPlotOutline() const { return m_plotOutline; } + void SetPlotOutline(const std::string& value ) { m_plotOutline = value; } + + const std::string& GetPlot() const { return m_plot; } + void SetPlot(const std::string& value ) { m_plot = value; } + + int GetGenreType() const { return m_genreType; } + void SetGenreType(int value) { m_genreType = value; } + + int GetGenreSubType() const { return m_genreSubType; } + void SetGenreSubType(int value) { m_genreSubType = value; } + + const std::string& GetGenreDescription() const { return m_genreDescription; } + void SetGenreDescription(const std::string& value ) { m_genreDescription = value; } + + int GetEpisodeNumber() const { return m_episodeNumber; } + void SetEpisodeNumber(int value) { m_episodeNumber = value; } + + int GetEpisodePartNumber() const { return m_episodePartNumber; } + void SetEpisodePartNumber(int value) { m_episodePartNumber = value; } + + int GetSeasonNumber() const { return m_seasonNumber; } + void SetSeasonNumber(int value) { m_seasonNumber = value; } + + int GetYear() const { return m_year; } + void SetYear(int value) { m_year = value; } + + void ProcessPrependMode(PrependOutline prependOutlineMode); + + protected: + std::string m_title; + std::string m_plotOutline; + std::string m_plot; + int m_genreType = 0; + int m_genreSubType = 0; + std::string m_genreDescription; + int m_episodeNumber = 0; + int m_episodePartNumber = 0; + int m_seasonNumber = 0; + int m_year = 0; + }; + } //namespace data +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/data/Channel.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/data/Channel.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/data/Channel.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/data/Channel.cpp 2018-11-18 15:43:06.000000000 +0000 @@ -0,0 +1,105 @@ +#include "Channel.h" + +#include + +#include "ChannelGroup.h" +#include "../Settings.h" +#include "../utilities/WebUtils.h" + +#include "inttypes.h" +#include "util/XMLUtils.h" +#include "p8-platform/util/StringUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::utilities; + +bool Channel::UpdateFrom(TiXmlElement* channelNode, const std::string &enigmaURL) +{ + if (!XMLUtils::GetString(channelNode, "e2servicereference", m_serviceReference)) + return false; + + // Check whether the current element is not just a label + if (m_serviceReference.compare(0,5,"1:64:") == 0) + return false; + + if (!XMLUtils::GetString(channelNode, "e2servicename", m_channelName)) + return false; + + Logger::Log(LEVEL_DEBUG, "%s: Loaded Channel: %s, sRef=%s", __FUNCTION__, m_channelName.c_str(), m_serviceReference.c_str()); + + std::string iconPath = m_serviceReference; + + int j = 0; + std::string::iterator it = iconPath.begin(); + + while (j < 10 && it != iconPath.end()) + { + if (*it == ':') + j++; + + it++; + } + std::string::size_type index = it-iconPath.begin(); + + iconPath = iconPath.substr(0, index); + + it = iconPath.end() - 1; + if (*it == ':') + { + iconPath.erase(it); + } + + if (Settings::GetInstance().UsePiconsEuFormat()) + { + //Extract the unique part of the icon name and apply the standard pre and post-fix + std::regex startPrefixRegex ("^\\d+:\\d+:\\d+:"); + std::string replaceWith = ""; + iconPath = regex_replace(iconPath, startPrefixRegex, replaceWith); + std::regex endPostfixRegex (":\\d+:\\d+:\\d+$"); + iconPath = regex_replace(iconPath, endPostfixRegex, replaceWith); + iconPath = SERVICE_REF_ICON_PREFIX + iconPath + SERVICE_REF_ICON_POSTFIX; + } + + std::string tempString = StringUtils::Format("%s", iconPath.c_str()); + + std::replace(iconPath.begin(), iconPath.end(), ':', '_'); + iconPath = Settings::GetInstance().GetIconPath().c_str() + iconPath + ".png"; + + m_m3uURL = StringUtils::Format("%s/web/stream.m3u?ref=%s", enigmaURL.c_str(), WebUtils::URLEncodeInline(m_serviceReference).c_str()); + + m_streamURL = StringUtils::Format( + "http%s://%s%s:%d/%s", + Settings::GetInstance().UseSecureConnectionStream() ? "s" : "", + Settings::GetInstance().UseLoginStream() ? StringUtils::Format("%s:%s@", Settings::GetInstance().GetUsername().c_str(), Settings::GetInstance().GetPassword().c_str()).c_str() : "", + Settings::GetInstance().GetHostname().c_str(), + Settings::GetInstance().GetStreamPortNum(), + tempString.c_str() + ); + + if (Settings::GetInstance().UseOnlinePicons()) + { + std::replace(tempString.begin(), tempString.end(), ':', '_'); + iconPath = StringUtils::Format("%spicon/%s.png", enigmaURL.c_str(), tempString.c_str()); + } + m_iconPath = iconPath; + + return true; +} + +void Channel::UpdateTo(PVR_CHANNEL &left) const +{ + left.iUniqueId = m_uniqueId; + left.bIsRadio = m_radio; + left.iChannelNumber = m_channelNumber; + strncpy(left.strChannelName, m_channelName.c_str(), sizeof(left.strChannelName)); + strncpy(left.strInputFormat, "", 0); // unused + left.iEncryptionSystem = 0; + left.bIsHidden = false; + strncpy(left.strIconPath, m_iconPath.c_str(), sizeof(left.strIconPath)); +} + +void Channel::AddChannelGroup(std::shared_ptr &channelGroup) +{ + m_channelGroupList.emplace_back(channelGroup); +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/data/ChannelGroup.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/data/ChannelGroup.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/data/ChannelGroup.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/data/ChannelGroup.cpp 2018-11-18 15:43:06.000000000 +0000 @@ -0,0 +1,59 @@ +#include "ChannelGroup.h" + +#include "inttypes.h" +#include "util/XMLUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::utilities; + +bool ChannelGroup::UpdateFrom(TiXmlElement* groupNode, bool radio) +{ + std::string serviceReference; + std::string groupName; + + if (!XMLUtils::GetString(groupNode, "e2servicereference", serviceReference)) + return false; + + // Check whether the current element is not just a label + if (serviceReference.compare(0, 5, "1:64:") == 0) + return false; + + if (!XMLUtils::GetString(groupNode, "e2servicename", groupName)) + return false; + + // Check if the current element is hidden, a separator or last scanned + if (groupName == "" || groupName.compare(groupName.length() - 12, 12, " - Separator") == 0 || groupName == "Last Scanned") + return false; + + if (!radio && Settings::GetInstance().GetTVChannelGroupMode() == ChannelGroupMode::ONLY_ONE_GROUP && + Settings::GetInstance().GetOneTVGroupName() != groupName) + { + Logger::Log(LEVEL_DEBUG, "%s Only one TV group is set, but current e2servicename '%s' does not match requested name '%s'", __FUNCTION__, serviceReference.c_str(), Settings::GetInstance().GetOneTVGroupName().c_str()); + return false; + } + else if (radio && Settings::GetInstance().GetRadioChannelGroupMode() == ChannelGroupMode::ONLY_ONE_GROUP && + Settings::GetInstance().GetOneRadioGroupName() != groupName) + { + Logger::Log(LEVEL_DEBUG, "%s Only one Radio group is set, but current e2servicename '%s' does not match requested name '%s'", __FUNCTION__, serviceReference.c_str(), Settings::GetInstance().GetOneRadioGroupName().c_str()); + return false; + } + + m_serviceReference = serviceReference; + m_groupName = groupName; + m_radio = radio; + + return true; +} + +void ChannelGroup::UpdateTo(PVR_CHANNEL_GROUP &left) const +{ + left.bIsRadio = m_radio; + left.iPosition = 0; // groups default order, unused + strncpy(left.strGroupName, m_groupName.c_str(), sizeof(left.strGroupName)); +} + +void ChannelGroup::AddChannel(std::shared_ptr channel) +{ + m_channelList.emplace_back(channel); +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/data/ChannelGroup.h kodi-pvr-vuplus-3.15.0/src/enigma2/data/ChannelGroup.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/data/ChannelGroup.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/data/ChannelGroup.h 2018-11-18 15:43:06.000000000 +0000 @@ -0,0 +1,81 @@ +#pragma once +/* + * Copyright (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include +#include + +#include "Channel.h" +#include "EpgEntry.h" + +#include "libXBMC_pvr.h" +#include "tinyxml.h" + +namespace enigma2 +{ + namespace data + { + class ChannelGroup + { + public: + ChannelGroup() = default; + ChannelGroup(ChannelGroup &c) : m_radio(c.IsRadio()), m_uniqueId(c.GetUniqueId()), + m_groupName(c.GetGroupName()), m_serviceReference(c.GetServiceReference()) {}; + ~ChannelGroup() = default; + + bool IsRadio() const { return m_radio; } + void SetRadio(bool value) { m_radio = value; } + + int GetUniqueId() const { return m_uniqueId; } + void SetUniqueId(int value) { m_uniqueId = value; } + + const std::string& GetServiceReference() const { return m_serviceReference; } + void SetServiceReference(const std::string& value ) { m_serviceReference = value; } + + const std::string& GetGroupName() const { return m_groupName; } + void SetGroupName(const std::string& value ) { m_groupName = value; } + + int GetGroupState() const { return m_groupState; } + void SetGroupState(int value) { m_groupState = value; } + + void AddChannel(std::shared_ptr channel); + + std::vector& GetInitialEPG() { return m_initialEPG; } + + bool UpdateFrom(TiXmlElement* groupNode, bool radio); + void UpdateTo(PVR_CHANNEL_GROUP &left) const; + + std::vector> GetChannelList() { return m_channelList; }; + + private: + bool m_radio; + int m_uniqueId; + std::string m_serviceReference; + std::string m_groupName; + int m_groupState; + std::vector m_initialEPG; + + std::vector> m_channelList; + }; + } //namespace data +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/data/Channel.h kodi-pvr-vuplus-3.15.0/src/enigma2/data/Channel.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/data/Channel.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/data/Channel.h 2018-11-18 15:43:06.000000000 +0000 @@ -0,0 +1,96 @@ +#pragma once +/* + * Copyright (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include +#include + +#include "libXBMC_pvr.h" +#include "tinyxml.h" + +namespace enigma2 +{ + namespace data + { + class ChannelGroup; + + class Channel + { + public: + const std::string SERVICE_REF_ICON_PREFIX = "1:0:1:"; + const std::string SERVICE_REF_ICON_POSTFIX = ":0:0:0"; + + Channel() = default; + Channel(Channel &c) : m_radio(c.IsRadio()), m_uniqueId(c.GetUniqueId()), m_channelNumber(c.GetChannelNumber()), + m_channelName(c.GetChannelName()), m_serviceReference(c.GetServiceReference()), + m_streamURL(c.GetStreamURL()), m_m3uURL(c.GetM3uURL()), m_iconPath(c.GetIconPath()) {}; + ~Channel() = default; + + bool IsRadio() const { return m_radio; } + void SetRadio(bool value) { m_radio = value; } + + bool RequiresInitialEPG() const { return m_requiresInitialEPG; } + void SetRequiresInitialEPG(bool value) { m_requiresInitialEPG = value; } + + int GetUniqueId() const { return m_uniqueId; } + void SetUniqueId(int value) { m_uniqueId = value; } + + int GetChannelNumber() const { return m_channelNumber; } + void SetChannelNumber(int value) { m_channelNumber = value; } + + const std::string& GetChannelName() const { return m_channelName; } + void SetChannelName(const std::string& value ) { m_channelName = value; } + + const std::string& GetServiceReference() const { return m_serviceReference; } + void SetServiceReference(const std::string& value ) { m_serviceReference = value; } + + const std::string& GetStreamURL() const { return m_streamURL; } + void SetStreamURL(const std::string& value ) { m_streamURL = value; } + + const std::string& GetM3uURL() const { return m_m3uURL; } + void SetM3uURL(const std::string& value ) { m_m3uURL = value; } + + const std::string& GetIconPath() const { return m_iconPath; } + void SetIconPath(const std::string& value ) { m_iconPath = value; } + + bool UpdateFrom(TiXmlElement* channelNode, const std::string &enigmaURL); + void UpdateTo(PVR_CHANNEL &left) const; + + void AddChannelGroup(std::shared_ptr &channelGroup); + std::vector> GetChannelGroupList() { return m_channelGroupList; }; + + private: + bool m_radio; + bool m_requiresInitialEPG = true; + int m_uniqueId; + int m_channelNumber; + std::string m_channelName; + std::string m_serviceReference; + std::string m_streamURL; + std::string m_m3uURL; + std::string m_iconPath; + + std::vector> m_channelGroupList; + }; + } //namespace data +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/data/EpgEntry.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/data/EpgEntry.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/data/EpgEntry.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/data/EpgEntry.cpp 2018-11-18 15:43:06.000000000 +0000 @@ -0,0 +1,129 @@ +#include "EpgEntry.h" + +#include "inttypes.h" +#include "util/XMLUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::utilities; + +void EpgEntry::UpdateTo(EPG_TAG &left) const +{ + left.iUniqueBroadcastId = m_eventId; + left.strTitle = m_title.c_str(); + left.iUniqueChannelId = m_channelId; + left.startTime = m_startTime; + left.endTime = m_endTime; + left.strPlotOutline = m_plotOutline.c_str(); + left.strPlot = m_plot.c_str(); + left.strOriginalTitle = nullptr; // unused + left.strCast = nullptr; // unused + left.strDirector = nullptr; // unused + left.strWriter = nullptr; // unused + left.iYear = m_year; + left.strIMDBNumber = nullptr; // unused + left.strIconPath = ""; // unused + left.iGenreType = m_genreType; + left.iGenreSubType = m_genreSubType; + left.strGenreDescription = m_genreDescription.c_str(); + left.firstAired = 0; // unused + left.iParentalRating = 0; // unused + left.iStarRating = 0; // unused + left.bNotify = false; + left.iSeriesNumber = m_seasonNumber; + left.iEpisodeNumber = m_episodeNumber; + left.iEpisodePartNumber = m_episodePartNumber; + left.strEpisodeName = ""; // unused + left.iFlags = EPG_TAG_FLAG_UNDEFINED; +} + +bool EpgEntry::UpdateFrom(TiXmlElement* eventNode, Channels &channels) +{ + std::string strTmp; + + if(!XMLUtils::GetString(eventNode, "e2eventservicereference", strTmp)) + return false; + + // Check whether the current element is not just a label or that it's not an empty record + if (strTmp.compare(0,5,"1:64:") == 0) + return false; + + m_serviceReference = strTmp; + + m_channelId = channels.GetChannelUniqueId(m_serviceReference); + + if (m_channelId < 0) + { + Logger::Log(LEVEL_DEBUG, "%s could not find channel so skipping entry: '%s'", __FUNCTION__, m_title.c_str()); + return false; + } + + const std::shared_ptr myChannel = channels.GetChannel(m_channelId);; + + return UpdateFrom(eventNode, myChannel, 0, 0); +} + +bool EpgEntry::UpdateFrom(TiXmlElement* eventNode, const std::shared_ptr &channel, time_t iStart, time_t iEnd) +{ + std::string strTmp; + + int iTmpStart; + int iTmp; + + // check and set event starttime and endtimes + if (!XMLUtils::GetInt(eventNode, "e2eventstart", iTmpStart)) + return false; + + // Skip unneccessary events + if (iStart > iTmpStart) + return false; + + if (!XMLUtils::GetInt(eventNode, "e2eventduration", iTmp)) + return false; + + if ((iEnd > 1) && (iEnd < (iTmpStart + iTmp))) + return false; + + m_startTime = iTmpStart; + m_endTime = iTmpStart + iTmp; + + if (!XMLUtils::GetInt(eventNode, "e2eventid", iTmp)) + return false; + + m_eventId = iTmp; + m_channelId = channel->GetUniqueId(); + + if(!XMLUtils::GetString(eventNode, "e2eventtitle", strTmp)) + return false; + + m_title = strTmp; + + m_serviceReference = channel->GetServiceReference().c_str(); + + // Check that it's not an empty record + if (m_eventId == 0 && m_title == "None") + return false; + + if (XMLUtils::GetString(eventNode, "e2eventdescriptionextended", strTmp)) + m_plot = strTmp; + + if (XMLUtils::GetString(eventNode, "e2eventdescription", strTmp)) + m_plotOutline = strTmp; + + ProcessPrependMode(PrependOutline::IN_EPG); + + if (XMLUtils::GetString(eventNode, "e2eventgenre", strTmp)) + { + m_genreDescription = strTmp; + + TiXmlElement* genreNode = eventNode->FirstChildElement("e2eventgenre"); + int genreId = 0; + if (genreNode->QueryIntAttribute("id", &genreId) == TIXML_SUCCESS) + { + m_genreType = genreId & 0xF0; + m_genreSubType = genreId & 0x0F; + } + } + + return true; +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/data/EpgEntry.h kodi-pvr-vuplus-3.15.0/src/enigma2/data/EpgEntry.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/data/EpgEntry.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/data/EpgEntry.h 2018-11-18 15:43:06.000000000 +0000 @@ -0,0 +1,67 @@ +#pragma once +/* + * Copyleft (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include + +#include "BaseEntry.h" +#include "Channel.h" +#include "../Channels.h" + +#include "libXBMC_pvr.h" +#include "tinyxml.h" + +namespace enigma2 +{ + namespace data + { + class EpgEntry : public BaseEntry + { + public: + int GetEventId() const { return m_eventId; } + void SetEventId(int value) { m_eventId = value; } + + const std::string& GetServiceReference() const { return m_serviceReference; } + void SetServiceReference(const std::string& value ) { m_serviceReference = value; } + + int GetChannelId() const { return m_channelId; } + void SetChannelId(int value) { m_channelId = value; } + + time_t GetStartTime() const { return m_startTime; } + void SetStartTime(time_t value) { m_startTime = value; } + + time_t GetEndTime() const { return m_endTime; } + void SetEndTime(time_t value) { m_endTime = value; } + + void UpdateTo(EPG_TAG &left) const; + bool UpdateFrom(TiXmlElement* eventNode, enigma2::Channels &channels); + bool UpdateFrom(TiXmlElement* eventNode, const std::shared_ptr &channel, time_t iStart, time_t iEnd); + + private: + int m_eventId; + std::string m_serviceReference; + int m_channelId; + time_t m_startTime; + time_t m_endTime; + }; + } //namespace data +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/data/RecordingEntry.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/data/RecordingEntry.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/data/RecordingEntry.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/data/RecordingEntry.cpp 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,149 @@ +#include "RecordingEntry.h" + +#include "../utilities/WebUtils.h" + +#include "inttypes.h" +#include "util/XMLUtils.h" +#include "p8-platform/util/StringUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::utilities; + +bool RecordingEntry::UpdateFrom(TiXmlElement* recordingNode, const std::string &directory, Channels &channels) +{ + std::string strTmp; + int iTmp; + + m_directory = directory; + + m_lastPlayedPosition = 0; + if (XMLUtils::GetString(recordingNode, "e2servicereference", strTmp)) + m_recordingId = strTmp; + + if (XMLUtils::GetString(recordingNode, "e2title", strTmp)) + m_title = strTmp; + + if (XMLUtils::GetString(recordingNode, "e2description", strTmp)) + m_plotOutline = strTmp; + + if (XMLUtils::GetString(recordingNode, "e2descriptionextended", strTmp)) + m_plot = strTmp; + + if (XMLUtils::GetString(recordingNode, "e2servicename", strTmp)) + m_channelName = strTmp; + + m_iconPath = channels.GetChannelIconPath(strTmp.c_str()); + + if (XMLUtils::GetInt(recordingNode, "e2time", iTmp)) + m_startTime = iTmp; + + if (XMLUtils::GetString(recordingNode, "e2length", strTmp)) + { + iTmp = TimeStringToSeconds(strTmp.c_str()); + m_duration = iTmp; + } + else + m_duration = 0; + + if (XMLUtils::GetString(recordingNode, "e2filename", strTmp)) + { + strTmp = StringUtils::Format("%sfile?file=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(strTmp).c_str()); + m_streamURL = strTmp; + } + + ProcessPrependMode(PrependOutline::IN_RECORDINGS); + + if (XMLUtils::GetString(recordingNode, "e2eventgenre", strTmp)) + { + m_genreDescription = strTmp; + + TiXmlElement* genreNode = recordingNode->FirstChildElement("e2eventgenre"); + int genreId = 0; + if (genreNode->QueryIntAttribute("id", &genreId) == TIXML_SUCCESS) + { + m_genreType = genreId & 0xF0; + m_genreSubType = genreId & 0x0F; + } + } + + return true; +} + +long RecordingEntry::TimeStringToSeconds(const std::string &timeString) +{ + std::vector tokens; + + std::string s = timeString; + std::string delimiter = ":"; + + size_t pos = 0; + std::string token; + while ((pos = s.find(delimiter)) != std::string::npos) + { + token = s.substr(0, pos); + tokens.emplace_back(token); + s.erase(0, pos + delimiter.length()); + } + tokens.emplace_back(s); + + int timeInSecs = 0; + + if (tokens.size() == 2) + { + timeInSecs += atoi(tokens[0].c_str()) * 60; + timeInSecs += atoi(tokens[1].c_str()); + } + + return timeInSecs; +} + +void RecordingEntry::UpdateTo(PVR_RECORDING &left, Channels &channels, bool isInRecordingFolder) +{ + std::string strTmp; + strncpy(left.strRecordingId, m_recordingId.c_str(), sizeof(left.strRecordingId)); + strncpy(left.strTitle, m_title.c_str(), sizeof(left.strTitle)); + strncpy(left.strPlotOutline, m_plotOutline.c_str(), sizeof(left.strPlotOutline)); + strncpy(left.strPlot, m_plot.c_str(), sizeof(left.strPlot)); + strncpy(left.strChannelName, m_channelName.c_str(), sizeof(left.strChannelName)); + strncpy(left.strIconPath, m_iconPath.c_str(), sizeof(left.strIconPath)); + + if (!Settings::GetInstance().GetKeepRecordingsFolders()) + { + if(isInRecordingFolder) + strTmp = StringUtils::Format("/%s/", m_title.c_str()); + else + strTmp = StringUtils::Format("/"); + + m_directory = strTmp; + } + + strncpy(left.strDirectory, m_directory.c_str(), sizeof(left.strDirectory)); + left.recordingTime = m_startTime; + left.iDuration = m_duration; + + left.iChannelUid = PVR_CHANNEL_INVALID_UID; + left.channelType = PVR_RECORDING_CHANNEL_TYPE_UNKNOWN; + + for (const auto& channel : channels.GetChannelsList()) + { + if (m_channelName == channel->GetChannelName()) + { + /* PVR API 5.0.0: iChannelUid in recordings */ + left.iChannelUid = channel->GetUniqueId(); + + /* PVR API 5.1.0: Support channel type in recordings */ + if (channel->IsRadio()) + left.channelType = PVR_RECORDING_CHANNEL_TYPE_RADIO; + else + left.channelType = PVR_RECORDING_CHANNEL_TYPE_TV; + } + } + + left.iSeriesNumber = m_seasonNumber; + left.iEpisodeNumber = m_episodeNumber; + left.iYear = m_year; + left.iGenreType = m_genreType; + left.iGenreSubType = m_genreSubType; + strncpy(left.strGenreDescription, m_genreDescription.c_str(), sizeof(left.strGenreDescription)); +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/data/RecordingEntry.h kodi-pvr-vuplus-3.15.0/src/enigma2/data/RecordingEntry.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/data/RecordingEntry.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/data/RecordingEntry.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,79 @@ +#pragma once +/* + * Copyright (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include + +#include "BaseEntry.h" +#include "Channel.h" +#include "../Channels.h" + +#include "libXBMC_pvr.h" +#include "tinyxml.h" +namespace enigma2 +{ + namespace data + { + class RecordingEntry : public BaseEntry + { + public: + const std::string& GetRecordingId() const { return m_recordingId; } + void SetRecordingId(const std::string& value ) { m_recordingId = value; } + + time_t GetStartTime() const { return m_startTime; } + void SetStartTime(time_t value) { m_startTime = value; } + + int GetDuration() const { return m_duration; } + void SetDuration(int value) { m_duration = value; } + + int GetLastPlayedPosition() const { return m_lastPlayedPosition; } + void SetLastPlayedPosition(int value) { m_lastPlayedPosition = value; } + + const std::string& GetStreamURL() const { return m_streamURL; } + void SetStreamURL(const std::string& value ) { m_streamURL = value; } + + const std::string& GetChannelName() const { return m_channelName; } + void SetChannelName(const std::string& value ) { m_channelName = value; } + + const std::string& GetDirectory() const { return m_directory; } + void SetDirectory(const std::string& value ) { m_directory = value; } + + const std::string& GetIconPath() const { return m_iconPath; } + void SetIconPath(const std::string& value ) { m_iconPath = value; } + + bool UpdateFrom(TiXmlElement* recordingNode, const std::string &directory, enigma2::Channels &channels); + void UpdateTo(PVR_RECORDING &left, Channels &channels, bool isInRecordingFolder); + + private: + long TimeStringToSeconds(const std::string &timeString); + + std::string m_recordingId; + time_t m_startTime; + int m_duration; + int m_lastPlayedPosition; + std::string m_streamURL; + std::string m_channelName; + std::string m_directory; + std::string m_iconPath; + }; + } //namespace data +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/data/Timer.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/data/Timer.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/data/Timer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/data/Timer.cpp 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,271 @@ +#include "Timer.h" + +#include + +#include "inttypes.h" +#include "util/XMLUtils.h" +#include "p8-platform/util/StringUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::utilities; + +bool Timer::Like(const Timer &right) const +{ + bool bChanged = true; + bChanged = bChanged && (m_startTime == right.m_startTime); + bChanged = bChanged && (m_endTime == right.m_endTime); + bChanged = bChanged && (m_channelId == right.m_channelId); + bChanged = bChanged && (m_weekdays == right.m_weekdays); + bChanged = bChanged && (m_epgId == right.m_epgId); + + return bChanged; +} + +bool Timer::operator==(const Timer &right) const +{ + bool bChanged = true; + bChanged = bChanged && (m_startTime == right.m_startTime); + bChanged = bChanged && (m_endTime == right.m_endTime); + bChanged = bChanged && (m_channelId == right.m_channelId); + bChanged = bChanged && (m_weekdays == right.m_weekdays); + bChanged = bChanged && (m_epgId == right.m_epgId); + bChanged = bChanged && (m_state == right.m_state); + bChanged = bChanged && (m_title == right.m_title); + bChanged = bChanged && (m_plot == right.m_plot); + + return bChanged; +} + +void Timer::UpdateFrom(const Timer &right) +{ + m_title = right.m_title; + m_plot = right.m_plot; + m_channelId = right.m_channelId; + m_channelName = right.m_channelName; + m_startTime = right.m_startTime; + m_endTime = right.m_endTime; + m_weekdays = right.m_weekdays; + m_epgId = right.m_epgId; + m_tags = right.m_tags; + m_state = right.m_state; +} + +void Timer::UpdateTo(PVR_TIMER &left) const +{ + strncpy(left.strTitle, m_title.c_str(), sizeof(left.strTitle)); + strncpy(left.strDirectory, "/", sizeof(left.strDirectory)); // unused + strncpy(left.strSummary, m_plot.c_str(), sizeof(left.strSummary)); + left.iTimerType = m_type; + left.iClientChannelUid = m_channelId; + left.startTime = m_startTime; + left.endTime = m_endTime; + left.state = m_state; + left.iPriority = 0; // unused + left.iLifetime = 0; // unused + left.firstDay = 0; // unused + left.iWeekdays = m_weekdays; + left.iEpgUid = m_epgId; + left.iMarginStart = 0; // unused + left.iMarginEnd = 0; // unused + left.iGenreType = 0; // unused + left.iGenreSubType = 0; // unused + left.iClientIndex = m_clientIndex; + left.iParentClientIndex = m_parentClientIndex; +} + +bool Timer::isScheduled() const +{ + return m_state == PVR_TIMER_STATE_SCHEDULED + || m_state == PVR_TIMER_STATE_RECORDING; +} + +bool Timer::isRunning(std::time_t *now, std::string *channelName) const +{ + if (!isScheduled()) + return false; + if (now && !(m_startTime <= *now && *now <= m_endTime)) + return false; + if (channelName && m_channelName != *channelName) + return false; + return true; +} + +bool Timer::isChildOfParent(const Timer &parent) const +{ + time_t time; + std::tm timeinfo; + int weekday = 0; + + time = m_startTime; + timeinfo = *std::localtime(&time); + std::string childStartTime = StringUtils::Format("%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min); + int tmDayOfWeek = timeinfo.tm_wday - 1; + if (tmDayOfWeek < 0) + tmDayOfWeek = 6; + weekday = (1 << tmDayOfWeek); + + time = m_endTime; + timeinfo = *std::localtime(&time); + std::string childEndTime = StringUtils::Format("%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min); + + time = parent.m_startTime; + timeinfo = *std::localtime(&time); + std::string parentStartTime = StringUtils::Format("%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min); + + time = parent.m_endTime; + timeinfo = *std::localtime(&time); + std::string parentEndTime = StringUtils::Format("%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min); + + bool isChild = true; + + isChild = isChild && (m_title == parent.m_title); + isChild = isChild && (childStartTime == parentStartTime); + isChild = isChild && (childEndTime == parentEndTime); + isChild = isChild && (m_channelId == parent.m_channelId); + isChild = isChild && (weekday & parent.m_weekdays); + + return isChild; +} + +bool Timer::UpdateFrom(TiXmlElement* timerNode, Channels &channels) +{ + std::string strTmp; + + int iTmp; + bool bTmp; + int iDisabled; + + if (XMLUtils::GetString(timerNode, "e2name", strTmp)) + Logger::Log(LEVEL_DEBUG, "%s Processing timer '%s'", __FUNCTION__, strTmp.c_str()); + + if (!XMLUtils::GetInt(timerNode, "e2state", iTmp)) + return false; + + if (!XMLUtils::GetInt(timerNode, "e2disabled", iDisabled)) + return false; + + m_title = strTmp; + + if (XMLUtils::GetString(timerNode, "e2servicereference", strTmp)) + m_channelId = channels.GetChannelUniqueId(strTmp.c_str()); + + // Skip timers for channels we don't know about, such as when the addon only uses one bouquet or an old channel referene that doesn't exist + if (m_channelId < 0) + { + Logger::Log(LEVEL_DEBUG, "%s could not find channel so skipping timer: '%s'", __FUNCTION__, m_title.c_str()); + return false; + } + + m_channelName = channels.GetChannel(m_channelId)->GetChannelName(); + + if (!XMLUtils::GetInt(timerNode, "e2timebegin", iTmp)) + return false; + + m_startTime = iTmp; + + if (!XMLUtils::GetInt(timerNode, "e2timeend", iTmp)) + return false; + + m_endTime = iTmp; + + if (XMLUtils::GetString(timerNode, "e2description", strTmp)) + m_plot = strTmp; + + if (XMLUtils::GetInt(timerNode, "e2repeated", iTmp)) + m_weekdays = iTmp; + else + m_weekdays = 0; + + if (XMLUtils::GetInt(timerNode, "e2eit", iTmp)) + m_epgId = iTmp; + else + m_epgId = 0; + + m_state = PVR_TIMER_STATE_NEW; + + if (!XMLUtils::GetInt(timerNode, "e2state", iTmp)) + return false; + + Logger::Log(LEVEL_DEBUG, "%s e2state is: %d ", __FUNCTION__, iTmp); + + if (iTmp == 0) + { + m_state = PVR_TIMER_STATE_SCHEDULED; + Logger::Log(LEVEL_DEBUG, "%s Timer state is: SCHEDULED", __FUNCTION__); + } + + if (iTmp == 2) + { + m_state = PVR_TIMER_STATE_RECORDING; + Logger::Log(LEVEL_DEBUG, "%s Timer state is: RECORDING", __FUNCTION__); + } + + if (iTmp == 3 && iDisabled == 0) + { + m_state = PVR_TIMER_STATE_COMPLETED; + Logger::Log(LEVEL_DEBUG, "%s Timer state is: COMPLETED", __FUNCTION__); + } + + if (XMLUtils::GetBoolean(timerNode, "e2cancled", bTmp)) + { + if (bTmp) + { + m_state = PVR_TIMER_STATE_ABORTED; + Logger::Log(LEVEL_DEBUG, "%s Timer state is: ABORTED", __FUNCTION__); + } + } + + if (iDisabled == 1) + { + m_state = PVR_TIMER_STATE_CANCELLED; + Logger::Log(LEVEL_DEBUG, "%s Timer state is: Cancelled", __FUNCTION__); + } + + if (m_state == PVR_TIMER_STATE_NEW) + Logger::Log(LEVEL_DEBUG, "%s Timer state is: NEW", __FUNCTION__); + + m_tags = ""; + if (XMLUtils::GetString(timerNode, "e2tags", strTmp)) + m_tags = strTmp; + + if (ContainsTag(TAG_FOR_MANUAL_TIMER)) + { + //We create a Manual tag on Manual timers created from Kodi, this allows us to set the Timer Type correctly + if (m_weekdays != PVR_WEEKDAY_NONE) + { + m_type = Timer::MANUAL_REPEATING; + } + else + { + m_type = Timer::MANUAL_ONCE; + } + } + else + { //Default to EPG for all other standard timers + if (m_weekdays != PVR_WEEKDAY_NONE) + { + m_type = Timer::EPG_REPEATING; + } + else + { + if (ContainsTag(TAG_FOR_AUTOTIMER)) + { + m_type = Timer::EPG_AUTO_ONCE; + } + else + { + m_type = Timer::EPG_ONCE; + } + } + } + + return true; +} + +bool Timer::ContainsTag(const std::string &tag) const +{ + std::regex regex ("^.* ?" + tag + " ?.*$"); + + return (regex_match(m_tags, regex)); +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/data/Timer.h kodi-pvr-vuplus-3.15.0/src/enigma2/data/Timer.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/data/Timer.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/data/Timer.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,134 @@ +#pragma once +/* + * Copyright (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include +#include + +#include "../Channels.h" +#include "../utilities/UpdateState.h" + +#include "libXBMC_pvr.h" +#include "tinyxml.h" + +namespace enigma2 +{ + namespace data + { + static const std::string TAG_FOR_AUTOTIMER = "AutoTimer"; + static const std::string TAG_FOR_MANUAL_TIMER = "Manual"; + static const std::string TAG_FOR_EPG_TIMER = "EPG"; + + class Timer + { + public: + + enum Type + : unsigned int // same type as PVR_TIMER_TYPE.iId + { + MANUAL_ONCE = PVR_TIMER_TYPE_NONE + 1, + MANUAL_REPEATING = PVR_TIMER_TYPE_NONE + 2, + READONLY_REPEATING_ONCE = PVR_TIMER_TYPE_NONE + 3, + EPG_ONCE = PVR_TIMER_TYPE_NONE + 4, + EPG_REPEATING = PVR_TIMER_TYPE_NONE + 5, //Can't be created on Kodi, only on the engima2 box + EPG_AUTO_SEARCH = PVR_TIMER_TYPE_NONE + 6, + EPG_AUTO_ONCE = PVR_TIMER_TYPE_NONE + 7, + }; + + Timer() + { + m_updateState = enigma2::utilities::UPDATE_STATE_NEW; + m_parentClientIndex = PVR_TIMER_NO_PARENT; + } + + Type GetType() const { return m_type; } + void SetType(const Type value ) { m_type = value; } + + const std::string& GetTitle() const { return m_title; } + void SetTitle(const std::string& value ) { m_title = value; } + + const std::string& GetPlot() const { return m_plot; } + void SetPlot(const std::string& value ) { m_plot = value; } + + int GetChannelId() const { return m_channelId; } + void SetChannelId(int value) { m_channelId = value; } + + const std::string& GetChannelName() const { return m_channelName; } + void SetChannelName(const std::string& value ) { m_channelName = value; } + + time_t GetStartTime() const { return m_startTime; } + void SetStartTime(time_t value) { m_startTime = value; } + + time_t GetEndTime() const { return m_endTime; } + void SetEndTime(time_t value) { m_endTime = value; } + + int GetWeekdays() const { return m_weekdays; } + void SetWeekdays(int value) { m_weekdays = value; } + + unsigned int GetEpgId() const { return m_epgId; } + void SetEpgId(unsigned int value) { m_epgId = value; } + + PVR_TIMER_STATE GetState() const { return m_state; } + void SetState(PVR_TIMER_STATE value) { m_state = value; } + + int GetUpdateState() const { return m_updateState; } + void SetUpdateState(int value) { m_updateState = value; } + + unsigned int GetClientIndex() const { return m_clientIndex; } + void SetClientIndex(unsigned int value) { m_clientIndex = value; } + + unsigned int GetParentClientIndex() const { return m_parentClientIndex; } + void SetParentClientIndex(unsigned int value) { m_parentClientIndex = value; } + + const std::string& GetTags() const { return m_tags; } + void SetTags(const std::string& value ) { m_tags = value; } + + bool isScheduled() const; + bool isRunning(std::time_t *now, std::string *channelName = nullptr) const; + bool isChildOfParent(const Timer &parent) const; + + bool Like(const Timer &right) const; + bool operator==(const Timer &right) const; + void UpdateFrom(const Timer &right); + void UpdateTo(PVR_TIMER &right) const; + bool UpdateFrom(TiXmlElement* timerNode, Channels &channels); + bool ContainsTag(const std::string &tag) const; + + protected: + Type m_type = Type::MANUAL_ONCE; + std::string m_title; + std::string m_plot; + int m_channelId; + std::string m_channelName; + time_t m_startTime; + time_t m_endTime; + int m_weekdays; + unsigned int m_epgId; + PVR_TIMER_STATE m_state; + int m_updateState; + unsigned int m_clientIndex; + unsigned int m_parentClientIndex; + std::string m_tags; + }; + } //namespace data +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/Epg.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/Epg.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/Epg.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/Epg.cpp 2018-11-18 15:43:06.000000000 +0000 @@ -0,0 +1,265 @@ +#include "Epg.h" + +#include + +#include "../client.h" +#include "../Enigma2.h" +#include "utilities/Logger.h" +#include "utilities/WebUtils.h" + +#include "util/XMLUtils.h" +#include "p8-platform/util/StringUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::extract; +using namespace enigma2::utilities; + +Epg::Epg (enigma2::Channels &channels, enigma2::ChannelGroups &channelGroups, enigma2::extract::EpgEntryExtractor &entryExtractor) + : m_channels(channels), m_channelGroups(channelGroups), m_entryExtractor(entryExtractor) +{ + InitialiseEpgReadyFile(); +} + +void Epg::InitialiseEpgReadyFile() +{ + m_writeHandle = XBMC->OpenFileForWrite(INITIAL_EPG_READY_FILE.c_str(), true); + XBMC->WriteFile(m_writeHandle, "Y", 1); + XBMC->CloseFile(m_writeHandle); +} + +bool Epg::IsInitialEpgCompleted() +{ + m_readHandle = XBMC->OpenFile(INITIAL_EPG_READY_FILE.c_str(), 0); + char buf[1]; + XBMC->ReadFile(m_readHandle, buf, 1); + XBMC->CloseFile(m_readHandle); + char buf2[] = { "N" }; + if (buf[0] == buf2[0]) + { + Logger::Log(LEVEL_DEBUG, "%s - Intial EPG update COMPLETE!", __FUNCTION__); + return true; + } + else + { + Logger::Log(LEVEL_DEBUG, "%s - Intial EPG update not completed yet.", __FUNCTION__); + return false; + } +} + +void Epg::TriggerEpgUpdatesForChannels() +{ + for (auto& channel : m_channels.GetChannelsList()) + { + Logger::Log(LEVEL_DEBUG, "%s - Trigger EPG update for channel '%d'", __FUNCTION__, channel->GetUniqueId()); + PVR->TriggerEpgUpdate(channel->GetUniqueId()); + } +} + +PVR_ERROR Epg::GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd) +{ + if (!m_channels.IsValid(channel.iUniqueId)) + { + Logger::Log(LEVEL_ERROR, "%s Could not fetch channel object - not fetching EPG for channel with UniqueID '%d'", __FUNCTION__, channel.iUniqueId); + return PVR_ERROR_NO_ERROR; + } + + std::shared_ptr myChannel = m_channels.GetChannel(channel.iUniqueId); + + Logger::Log(LEVEL_DEBUG, "%s Getting EPG for channel '%s'", __FUNCTION__, myChannel->GetChannelName().c_str()); + + // Check if the initial short import has already been done for this channel + if (myChannel->RequiresInitialEPG()) + { + myChannel->SetRequiresInitialEPG(false); + + if (!m_allChannelsHaveInitialEPG) + m_allChannelsHaveInitialEPG = m_channels.CheckIfAllChannelsHaveInitialEPG(); + + if (m_allChannelsHaveInitialEPG) + { + std::string initialEPGReady = "special://userdata/addon_data/pvr.vuplus/initialEPGReady"; + m_writeHandle = XBMC->OpenFileForWrite(initialEPGReady.c_str(), true); + XBMC->WriteFile(m_writeHandle, "N", 1); + XBMC->CloseFile(m_writeHandle); + } + + return GetInitialEPGForChannel(handle, myChannel, iStart, iEnd); + } + + const std::string url = StringUtils::Format("%s%s%s", Settings::GetInstance().GetConnectionURL().c_str(), "web/epgservice?sRef=", + WebUtils::URLEncodeInline(myChannel->GetServiceReference()).c_str()); + + const std::string strXML = WebUtils::GetHttpXML(url); + + int iNumEPG = 0; + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(strXML.c_str())) + { + Logger::Log(LEVEL_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return PVR_ERROR_SERVER_ERROR; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("e2eventlist").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_DEBUG, "%s could not find element!", __FUNCTION__); + // Return "NO_ERROR" as the EPG could be empty for this channel + return PVR_ERROR_NO_ERROR; + } + + hRoot=TiXmlHandle(pElem); + + TiXmlElement* pNode = hRoot.FirstChildElement("e2event").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_DEBUG, "Could not find element"); + // RETURN "NO_ERROR" as the EPG could be empty for this channel + return PVR_ERROR_SERVER_ERROR; + } + + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2event")) + { + EpgEntry entry; + + if (!entry.UpdateFrom(pNode, myChannel, iStart, iEnd)) + continue; + + if (m_entryExtractor.IsEnabled()) + m_entryExtractor.ExtractFromEntry(entry); + + EPG_TAG broadcast; + memset(&broadcast, 0, sizeof(EPG_TAG)); + + entry.UpdateTo(broadcast); + + PVR->TransferEpgEntry(handle, &broadcast); + + iNumEPG++; + + Logger::Log(LEVEL_DEBUG, "%s loaded EPG entry '%d:%s' channel '%d' start '%d' end '%d'", __FUNCTION__, broadcast.iUniqueBroadcastId, broadcast.strTitle, entry.GetChannelId(), entry.GetStartTime(), entry.GetEndTime()); + } + + Logger::Log(LEVEL_INFO, "%s Loaded %u EPG Entries for channel '%s'", __FUNCTION__, iNumEPG, channel.strChannelName); + return PVR_ERROR_NO_ERROR; +} + +bool Epg::GetInitialEPGForGroup(std::shared_ptr group) +{ + const std::string url = StringUtils::Format("%s%s%s", Settings::GetInstance().GetConnectionURL().c_str(), "web/epgnownext?bRef=", + WebUtils::URLEncodeInline(group->GetServiceReference()).c_str()); + + const std::string strXML = WebUtils::GetHttpXML(url); + + int iNumEPG = 0; + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(strXML.c_str())) + { + Logger::Log(LEVEL_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return false; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("e2eventlist").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_DEBUG, "%s could not find element!", __FUNCTION__); + // Return "NO_ERROR" as the EPG could be empty for this channel + return false; + } + + hRoot=TiXmlHandle(pElem); + + TiXmlElement* pNode = hRoot.FirstChildElement("e2event").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_DEBUG, "Could not find element"); + // RETURN "NO_ERROR" as the EPG could be empty for this channel + return false; + } + + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2event")) + { + EpgEntry entry; + + if (!entry.UpdateFrom(pNode, m_channels)) + continue; + + if (m_entryExtractor.IsEnabled()) + m_entryExtractor.ExtractFromEntry(entry); + + iNumEPG++; + + group->GetInitialEPG().emplace_back(entry); + } + + Logger::Log(LEVEL_INFO, "%s Loaded %u EPG Entries for group '%s'", __FUNCTION__, iNumEPG, group->GetGroupName().c_str()); + return true; +} + +PVR_ERROR Epg::GetInitialEPGForChannel(ADDON_HANDLE handle, const std::shared_ptr &channel, time_t iStart, time_t iEnd) +{ + if (m_channelGroups.GetNumChannelGroups() < 1) + return PVR_ERROR_SERVER_ERROR; + + if (channel->IsRadio()) + { + Logger::Log(LEVEL_DEBUG, "%s Channel '%s' is a radio channel so no Initial EPG", __FUNCTION__, channel->GetChannelName().c_str()); + return PVR_ERROR_NO_ERROR; + } + + std::shared_ptr myGroupPtr = nullptr; + for (auto& group : channel->GetChannelGroupList()) + { + bool retrievedInitialEPGForGroup = false; + + Logger::Log(LEVEL_DEBUG, "%s Checking for initialEPG for group '%s', num groups %d, channel %s", __FUNCTION__, group->GetGroupName().c_str(), m_channelGroups.GetNumChannelGroups(), channel->GetChannelName().c_str()); + + myGroupPtr = group; + + if (group->GetInitialEPG().size() == 0) + { + Logger::Log(LEVEL_DEBUG, "%s Fetching initialEPG for group '%s'", __FUNCTION__, group->GetGroupName().c_str()); + retrievedInitialEPGForGroup = GetInitialEPGForGroup(group); + } + + if (retrievedInitialEPGForGroup) + Logger::Log(LEVEL_DEBUG, "%s InitialEPG size for group '%s' is now '%d'", __FUNCTION__, group->GetGroupName().c_str(), myGroupPtr->GetInitialEPG().size()); + else + Logger::Log(LEVEL_DEBUG, "%s Already have initialEPG for group '%s', it's size is '%d'", __FUNCTION__, group->GetGroupName().c_str(), myGroupPtr->GetInitialEPG().size()); + } + + if (!myGroupPtr) + { + Logger::Log(LEVEL_DEBUG, "%s No groups found for channel '%s' so no Initial EPG", __FUNCTION__, channel->GetChannelName().c_str()); + return PVR_ERROR_NO_ERROR; + } + + for (const auto& entry : myGroupPtr->GetInitialEPG()) + { + if (channel->GetServiceReference() == entry.GetServiceReference()) + { + EPG_TAG broadcast; + memset(&broadcast, 0, sizeof(EPG_TAG)); + + entry.UpdateTo(broadcast); + + PVR->TransferEpgEntry(handle, &broadcast); + } + } + + return PVR_ERROR_NO_ERROR; +} diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/Epg.h kodi-pvr-vuplus-3.15.0/src/enigma2/Epg.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/Epg.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/Epg.h 2018-11-18 15:43:06.000000000 +0000 @@ -0,0 +1,60 @@ +#pragma once +/* + * Copyright (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include + +#include "Channels.h" +#include "ChannelGroups.h" +#include "extract/EpgEntryExtractor.h" + +#include "libXBMC_pvr.h" + +namespace enigma2 +{ + static const std::string INITIAL_EPG_READY_FILE = "special://userdata/addon_data/pvr.vuplus/initialEPGReady"; + + class Epg + { + public: + Epg (enigma2::Channels &channels, enigma2::ChannelGroups &channelGroups, enigma2::extract::EpgEntryExtractor &entryExtractor); + + bool IsInitialEpgCompleted(); + void TriggerEpgUpdatesForChannels(); + PVR_ERROR GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd); + + private: + void InitialiseEpgReadyFile(); + + bool GetInitialEPGForGroup(std::shared_ptr group); + PVR_ERROR GetInitialEPGForChannel(ADDON_HANDLE handle, const std::shared_ptr &channel, time_t iStart, time_t iEnd); + + enigma2::Channels &m_channels; + enigma2::ChannelGroups &m_channelGroups; + enigma2::extract::EpgEntryExtractor &m_entryExtractor; + + void *m_writeHandle; + void *m_readHandle; + bool m_allChannelsHaveInitialEPG = false; + }; +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/extract/EpgEntryExtractor.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/extract/EpgEntryExtractor.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/extract/EpgEntryExtractor.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/extract/EpgEntryExtractor.cpp 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,46 @@ +#include "EpgEntryExtractor.h" + +#include "GenreIdMapper.h" +#include "GenreRytecTextMapper.h" +#include "ShowInfoExtractor.h" +#include "../utilities/FileUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::extract; +using namespace enigma2::utilities; + +EpgEntryExtractor::EpgEntryExtractor() + : IExtractor() +{ + FileUtils::CopyDirectory(FileUtils::GetResourceDataPath() + GENRE_DIR, GENRE_ADDON_DATA_BASE_DIR, true); + + m_extractors.emplace_back(new GenreIdMapper()); + m_extractors.emplace_back(new GenreRytecTextMapper()); + m_extractors.emplace_back(new ShowInfoExtractor()); + + m_anyExtractorEnabled = false; + for (auto& extractor : m_extractors) + { + if (extractor->IsEnabled()) + m_anyExtractorEnabled = true; + } +} + +EpgEntryExtractor::~EpgEntryExtractor(void) +{ +} + +void EpgEntryExtractor::ExtractFromEntry(BaseEntry &entry) +{ + for (auto& extractor : m_extractors) + { + if (extractor->IsEnabled()) + extractor->ExtractFromEntry(entry); + } +} + +bool EpgEntryExtractor::IsEnabled() +{ + return m_anyExtractorEnabled; +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/extract/EpgEntryExtractor.h kodi-pvr-vuplus-3.15.0/src/enigma2/extract/EpgEntryExtractor.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/extract/EpgEntryExtractor.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/extract/EpgEntryExtractor.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include + +#include "IExtractor.h" + +namespace enigma2 +{ + namespace extract + { + static const std::string GENRE_DIR = "/genres"; + static const std::string GENRE_ADDON_DATA_BASE_DIR = "special://userdata/addon_data/pvr.vuplus" + GENRE_DIR; + + class EpgEntryExtractor + : public IExtractor + { + public: + EpgEntryExtractor(); + ~EpgEntryExtractor(void); + + void ExtractFromEntry(enigma2::data::BaseEntry &entry); + bool IsEnabled(); + + private: + std::vector> m_extractors; + bool m_anyExtractorEnabled; + }; + } //namespace extract +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/extract/EpisodeSeasonPattern.h kodi-pvr-vuplus-3.15.0/src/enigma2/extract/EpisodeSeasonPattern.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/extract/EpisodeSeasonPattern.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/extract/EpisodeSeasonPattern.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,32 @@ +#pragma once + +#include + +namespace enigma2 +{ + namespace extract + { + struct EpisodeSeasonPattern + { + EpisodeSeasonPattern(const std::string &masterPattern, const std::string &seasonPattern, const std::string &episodePattern) + { + masterRegex = std::regex(masterPattern); + seasonRegex = std::regex(seasonPattern); + episodeRegex = std::regex(episodePattern); + hasSeasonRegex = true; + } + + EpisodeSeasonPattern(const std::string &masterPattern, const std::string &episodePattern) + { + masterRegex = std::regex(masterPattern); + episodeRegex = std::regex(episodePattern); + hasSeasonRegex = false; + } + + std::regex masterRegex; + std::regex seasonRegex; + std::regex episodeRegex; + bool hasSeasonRegex; + }; + } //namespace extract +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/extract/GenreIdMapper.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/extract/GenreIdMapper.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/extract/GenreIdMapper.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/extract/GenreIdMapper.cpp 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,150 @@ +#include "GenreIdMapper.h" + +#include "../utilities/FileUtils.h" + +#include "libXBMC_pvr.h" +#include "tinyxml.h" +#include "util/XMLUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::extract; +using namespace enigma2::utilities; + +GenreIdMapper::GenreIdMapper() + : IExtractor() +{ + LoadGenreIdMapFile(); +} + +GenreIdMapper::~GenreIdMapper(void) +{ +} + +void GenreIdMapper::ExtractFromEntry(BaseEntry &entry) +{ + if (entry.GetGenreType() != 0) + { + int combinedGenreType = entry.GetGenreType() | entry.GetGenreSubType(); + + const int mappedGenreId = LookupGenreIdInMap(combinedGenreType); + + if (mappedGenreId != EPG_EVENT_CONTENTMASK_UNDEFINED) + { + entry.SetGenreType(GetGenreTypeFromCombined(mappedGenreId)); + entry.SetGenreSubType(GetGenreSubTypeFromCombined(mappedGenreId)); + } + } +} + +bool GenreIdMapper::IsEnabled() +{ + return Settings::GetInstance().GetMapGenreIds(); +} + +int GenreIdMapper::GetGenreTypeFromCombined(int combinedGenreType) +{ + return combinedGenreType & 0xF0; +} + +int GenreIdMapper::GetGenreSubTypeFromCombined(int combinedGenreType) +{ + return combinedGenreType & 0x0F; +} + +int GenreIdMapper::LookupGenreIdInMap(const int combinedGenreType) +{ + int genreType = EPG_EVENT_CONTENTMASK_UNDEFINED; + + auto genreMapSearch = genreIdToDvbIdMap.find(combinedGenreType); + if (genreMapSearch != genreIdToDvbIdMap.end()) + { + genreType = genreMapSearch->second; + } + + return genreType; +} + +void GenreIdMapper::LoadGenreIdMapFile() +{ + if (!LoadIdToIdGenreFile(Settings::GetInstance().GetMapGenreIdsFile(), genreIdToDvbIdMap)) + Logger::Log(LEVEL_ERROR, "%s Could not load genre id to dvb id file: %s", __FUNCTION__, Settings::GetInstance().GetMapGenreIdsFile().c_str()); +} + +bool GenreIdMapper::LoadIdToIdGenreFile(const std::string &xmlFile, std::map &map) +{ + map.clear(); + + if (!FileUtils::FileExists(xmlFile.c_str())) + { + Logger::Log(LEVEL_ERROR, "%s No XML file found: %s", __FUNCTION__, xmlFile.c_str()); + return false; + } + + Logger::Log(LEVEL_DEBUG, "%s Loading XML File: %s", __FUNCTION__, xmlFile.c_str()); + + std::string fileContents = FileUtils::ReadXmlFileToString(xmlFile); + + if (fileContents.empty()) + { + Logger::Log(LEVEL_ERROR, "%s No Content in XML file: %s", __FUNCTION__, xmlFile.c_str()); + return false; + } + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(fileContents.c_str())) + { + Logger::Log(LEVEL_ERROR, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return false; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("genreIdMappings").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); + return false; + } + + std::string mapperName; + + if (!XMLUtils::GetString(pElem, "mapperName", mapperName)) + return false; + + hRoot=TiXmlHandle(pElem); + + TiXmlElement* pNode = hRoot.FirstChildElement("mappings").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); + return false; + } + + pNode = pNode->FirstChildElement("mapping"); + + if (!pNode) + { + Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); + return false; + } + + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("mapping")) + { + std::string sourceIdString = pNode->Attribute("sourceId"); + std::string targetIdString = pNode->GetText(); + + int sourceId = strtol(sourceIdString.c_str(), nullptr, 16); + int targetId = strtol(targetIdString.c_str(), nullptr, 16); + + map.insert({sourceId, targetId}); + + Logger::Log(LEVEL_DEBUG, "%s Read ID Mapping for: %s, sourceId=%#02X, targetId=%#02X", __FUNCTION__, mapperName.c_str(), sourceId, targetId); + } + + return true; +} diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/extract/GenreIdMapper.h kodi-pvr-vuplus-3.15.0/src/enigma2/extract/GenreIdMapper.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/extract/GenreIdMapper.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/extract/GenreIdMapper.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,35 @@ +#pragma once + +#include "IExtractor.h" + +#include +#include + +namespace enigma2 +{ + namespace extract + { + class GenreIdMapper + : public IExtractor + { + public: + GenreIdMapper(); + ~GenreIdMapper(); + + void ExtractFromEntry(enigma2::data::BaseEntry &entry); + bool IsEnabled(); + + private: + static int GetGenreTypeFromCombined(int combinedGenreType); + static int GetGenreSubTypeFromCombined(int combinedGenreType); + + int LookupGenreIdInMap(const int genreId); + + void LoadGenreIdMapFile(); + bool LoadIdToIdGenreFile(const std::string &xmlFile, std::map &map); + void CreateGenreAddonDataDirectories(); + + std::map genreIdToDvbIdMap; + }; + } //namespace extract +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/extract/GenreRytecTextMapper.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/extract/GenreRytecTextMapper.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/extract/GenreRytecTextMapper.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/extract/GenreRytecTextMapper.cpp 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,202 @@ +#include "GenreRytecTextMapper.h" + +#include "../utilities/FileUtils.h" + +#include "libXBMC_pvr.h" +#include "tinyxml.h" +#include "util/XMLUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::extract; +using namespace enigma2::utilities; + +GenreRytecTextMapper::GenreRytecTextMapper() + : IExtractor() +{ + LoadGenreTextMappingFiles(); + + for (const auto& genreMapEntry : kodiGenreTextToDvbIdMap) + { + kodiDvbIdToGenreTextMap.insert({genreMapEntry.second, genreMapEntry.first}); + } + + genrePattern = std::regex(GENRE_PATTERN); + genreMajorPattern = std::regex(GENRE_MAJOR_PATTERN); +} + +GenreRytecTextMapper::~GenreRytecTextMapper(void) +{ +} + +void GenreRytecTextMapper::ExtractFromEntry(BaseEntry &entry) +{ + if (entry.GetGenreType() == 0) + { + const std::string genreText = GetMatchedText(entry.GetPlotOutline(), entry.GetPlot(), genrePattern); + + if (!genreText.empty() && genreText != GENRE_RESERVED_IGNORE) + { + int combinedGenreType = GetGenreTypeFromText(genreText, entry.GetTitle()); + + if (combinedGenreType == EPG_EVENT_CONTENTMASK_UNDEFINED) + { + if (m_settings.GetLogMissingGenreMappings()) + Logger::Log(LEVEL_NOTICE, "%s: Could not lookup genre using genre description string instead:'%s'", __FUNCTION__, genreText.c_str()); + + entry.SetGenreType(EPG_GENRE_USE_STRING); + entry.SetGenreDescription(genreText); + } + else + { + entry.SetGenreType(GetGenreTypeFromCombined(combinedGenreType)); + entry.SetGenreSubType(GetGenreSubTypeFromCombined(combinedGenreType)); + } + } + } +} + +bool GenreRytecTextMapper::IsEnabled() +{ + return Settings::GetInstance().GetMapRytecTextGenres(); +} + +int GenreRytecTextMapper::GetGenreTypeFromCombined(int combinedGenreType) +{ + return combinedGenreType & 0xF0; +} + +int GenreRytecTextMapper::GetGenreSubTypeFromCombined(int combinedGenreType) +{ + return combinedGenreType & 0x0F; +} + +int GenreRytecTextMapper::GetGenreTypeFromText(const std::string &genreText, const std::string &showName) +{ + int genreType = LookupGenreValueInMaps(genreText); + + if (genreType == EPG_EVENT_CONTENTMASK_UNDEFINED) + { + if (m_settings.GetLogMissingGenreMappings()) + Logger::Log(LEVEL_NOTICE, "%s: Tried to find genre text but no value: '%s', show - '%s'", __FUNCTION__, genreText.c_str(), showName.c_str()); + + std::string genreMajorText = GetMatchTextFromString(genreText, genreMajorPattern); + + if (!genreMajorText.empty()) + { + genreType = LookupGenreValueInMaps(genreMajorText); + + if (genreType == EPG_EVENT_CONTENTMASK_UNDEFINED && m_settings.GetLogMissingGenreMappings()) + Logger::Log(LEVEL_NOTICE, "%s: Tried to find major genre text but no value: '%s', show - '%s'", __FUNCTION__, genreMajorText.c_str(), showName.c_str()); + } + } + + return genreType; +} + +int GenreRytecTextMapper::LookupGenreValueInMaps(const std::string &genreText) +{ + int genreType = EPG_EVENT_CONTENTMASK_UNDEFINED; + + auto genreMapSearch = genreMap.find(genreText); + if (genreMapSearch != genreMap.end()) + { + genreType = genreMapSearch->second; + } + else + { + auto kodiGenreMapSearch = kodiGenreTextToDvbIdMap.find(genreText); + if (kodiGenreMapSearch != kodiGenreTextToDvbIdMap.end()) + { + genreType = kodiGenreMapSearch->second; + } + } + + return genreType; +} + +void GenreRytecTextMapper::LoadGenreTextMappingFiles() +{ + if (!LoadTextToIdGenreFile(GENRE_KODI_DVB_FILEPATH, kodiGenreTextToDvbIdMap)) + Logger::Log(LEVEL_ERROR, "%s Could not load text to genre id file: %s", __FUNCTION__, GENRE_KODI_DVB_FILEPATH.c_str()); + + if (!LoadTextToIdGenreFile(Settings::GetInstance().GetMapRytecTextGenresFile(), genreMap)) + Logger::Log(LEVEL_ERROR, "%s Could not load genre id to dvb id file: %s", __FUNCTION__, Settings::GetInstance().GetMapRytecTextGenresFile().c_str()); +} + +bool GenreRytecTextMapper::LoadTextToIdGenreFile(const std::string &xmlFile, std::map &map) +{ + map.clear(); + + if (!FileUtils::FileExists(xmlFile.c_str())) + { + Logger::Log(LEVEL_ERROR, "%s No XML file found: %s", __FUNCTION__, xmlFile.c_str()); + return false; + } + + Logger::Log(LEVEL_DEBUG, "%s Loading XML File: %s", __FUNCTION__, xmlFile.c_str()); + + std::string fileContents = FileUtils::ReadXmlFileToString(xmlFile); + + if (fileContents.empty()) + { + Logger::Log(LEVEL_ERROR, "%s No Content in XML file: %s", __FUNCTION__, xmlFile.c_str()); + return false; + } + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(fileContents.c_str())) + { + Logger::Log(LEVEL_ERROR, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return false; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("genreTextMappings").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); + return false; + } + + std::string mapperName; + + if (!XMLUtils::GetString(pElem, "mapperName", mapperName)) + return false; + + hRoot=TiXmlHandle(pElem); + + TiXmlElement* pNode = hRoot.FirstChildElement("mappings").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); + return false; + } + + pNode = pNode->FirstChildElement("mapping"); + + if (!pNode) + { + Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); + return false; + } + + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("mapping")) + { + std::string targetIdString = pNode->Attribute("targetId"); + std::string textMapping = pNode->GetText(); + + int targetId = strtol(targetIdString.c_str(), nullptr, 16); + + map.insert({textMapping, targetId}); + + Logger::Log(LEVEL_DEBUG, "%s Read Text Mapping for: %s, text=%s, targetId=%#02X", __FUNCTION__, mapperName.c_str(), textMapping.c_str(), targetId); + } + + return true; +} diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/extract/GenreRytecTextMapper.h kodi-pvr-vuplus-3.15.0/src/enigma2/extract/GenreRytecTextMapper.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/extract/GenreRytecTextMapper.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/extract/GenreRytecTextMapper.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,47 @@ +#pragma once + +#include "IExtractor.h" + +#include +#include +#include + +namespace enigma2 +{ + namespace extract + { + static const std::string GENRE_PATTERN = "^\\[([a-zA-Z /]{3}[a-zA-Z ./]+)\\][^]*"; + static const std::string GENRE_MAJOR_PATTERN = "^([a-zA-Z /]{3,})\\.?.*"; + static const std::string GENRE_RESERVED_IGNORE = "reserved"; + + static const std::string GENRE_KODI_DVB_FILEPATH = "special://userdata/addon_data/pvr.vuplus/genres/kodiDvbGenres.xml"; + + class GenreRytecTextMapper + : public IExtractor + { + public: + GenreRytecTextMapper(); + ~GenreRytecTextMapper(); + + void ExtractFromEntry(enigma2::data::BaseEntry &entry); + bool IsEnabled(); + + private: + static int GetGenreTypeFromCombined(int combinedGenreType); + static int GetGenreSubTypeFromCombined(int combinedGenreType); + + int GetGenreTypeFromText(const std::string &genreText, const std::string &showName); + int LookupGenreValueInMaps(const std::string &genreText); + + void LoadGenreTextMappingFiles(); + bool LoadTextToIdGenreFile(const std::string &xmlFile, std::map &map); + void CreateGenreAddonDataDirectories(); + + std::regex genrePattern; + std::regex genreMajorPattern; + std::map kodiGenreTextToDvbIdMap; + std::map kodiDvbIdToGenreTextMap; + std::map genreMap; + }; + } //namespace extract +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/extract/IExtractor.h kodi-pvr-vuplus-3.15.0/src/enigma2/extract/IExtractor.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/extract/IExtractor.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/extract/IExtractor.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,51 @@ +#pragma once + +#include "../Settings.h" +#include "../data/BaseEntry.h" + +#include + +namespace enigma2 +{ + namespace extract + { + class IExtractor + { + public: + IExtractor() = default; + virtual ~IExtractor() = default; + virtual void ExtractFromEntry(enigma2::data::BaseEntry &entry) = 0; + virtual bool IsEnabled() = 0; + + protected: + static std::string GetMatchTextFromString(const std::string &text, const std::regex &pattern) + { + std::string matchText = ""; + std::smatch match; + + if (regex_match(text, match, pattern)) + { + if (match.size() == 2) + { + std::ssub_match base_sub_match = match[1]; + matchText = base_sub_match.str(); + } + } + + return matchText; + }; + + static std::string GetMatchedText(const std::string &firstText, const std::string &secondText, const std::regex &pattern) + { + std::string matchedText = GetMatchTextFromString(firstText, pattern); + + if (matchedText.empty()) + matchedText = GetMatchTextFromString(secondText, pattern); + + return matchedText; + } + + enigma2::Settings &m_settings = Settings::GetInstance(); + }; + } //namespace extract +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/extract/ShowInfoExtractor.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/extract/ShowInfoExtractor.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/extract/ShowInfoExtractor.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/extract/ShowInfoExtractor.cpp 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,215 @@ +#include "ShowInfoExtractor.h" + +#include "../utilities/FileUtils.h" + +#include "tinyxml.h" +#include "util/XMLUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::extract; +using namespace enigma2::utilities; + +ShowInfoExtractor::ShowInfoExtractor() + : IExtractor() +{ + FileUtils::CopyDirectory(FileUtils::GetResourceDataPath() + SHOW_INFO_DIR, SHOW_INFO_ADDON_DATA_BASE_DIR, true); + + if (!LoadShowInfoPatternsFile(Settings::GetInstance().GetExtractShowInfoFile(), m_episodeSeasonPatterns, m_yearPatterns)) + Logger::Log(LEVEL_ERROR, "%s Could not load show info patterns file: %s", __FUNCTION__, Settings::GetInstance().GetExtractShowInfoFile().c_str()); +} + +ShowInfoExtractor::~ShowInfoExtractor(void) +{ +} + +void ShowInfoExtractor::ExtractFromEntry(BaseEntry &entry) +{ + for (const auto& patternSet : m_episodeSeasonPatterns) + { + std::string masterText = GetMatchedText(entry.GetPlotOutline(), entry.GetPlot(), patternSet.masterRegex); + + if (!masterText.empty()) + { + if (patternSet.hasSeasonRegex && entry.GetSeasonNumber() == 0) + { + std::string seasonText = GetMatchTextFromString(masterText, patternSet.seasonRegex); + if (!seasonText.empty()) + { + entry.SetSeasonNumber(atoi(seasonText.c_str())); + } + } + + if (entry.GetEpisodeNumber() == 0) + { + std::string episodeText = GetMatchTextFromString(masterText, patternSet.episodeRegex); + if (!episodeText.empty()) + { + entry.SetEpisodeNumber(atoi(episodeText.c_str())); + } + } + } + + //Once we have at least an episode number we are done + if (entry.GetEpisodeNumber() != 0) + break; + } + + for (const auto& pattern : m_yearPatterns) + { + std::string yearText = GetMatchedText(entry.GetPlotOutline(), entry.GetPlot(), pattern); + + if (!yearText.empty() && entry.GetYear() == 0) + { + entry.SetYear(atoi(yearText.c_str())); + } + + if (entry.GetYear() != 0) + break; + } +} + +bool ShowInfoExtractor::IsEnabled() +{ + return Settings::GetInstance().GetExtractShowInfo(); +} + +bool ShowInfoExtractor::LoadShowInfoPatternsFile(const std::string &xmlFile, std::vector &episodeSeasonPatterns, std::vector yearPatterns) +{ + episodeSeasonPatterns.clear(); + yearPatterns.clear(); + + if (!FileUtils::FileExists(xmlFile.c_str())) + { + Logger::Log(LEVEL_ERROR, "%s No XML file found: %s", __FUNCTION__, xmlFile.c_str()); + return false; + } + + Logger::Log(LEVEL_DEBUG, "%s Loading XML File: %s", __FUNCTION__, xmlFile.c_str()); + + std::string fileContents = FileUtils::ReadXmlFileToString(xmlFile); + + if (fileContents.empty()) + { + Logger::Log(LEVEL_ERROR, "%s No Content in XML file: %s", __FUNCTION__, xmlFile.c_str()); + return false; + } + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(fileContents.c_str())) + { + Logger::Log(LEVEL_ERROR, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return false; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("showInfo").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); + return false; + } + + std::string name; + + if (!XMLUtils::GetString(pElem, "name", name)) + return false; + + hRoot=TiXmlHandle(pElem); + + //First we do the seasonEpisodes + TiXmlElement* pNode = hRoot.FirstChildElement("seasonEpisodes").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); + return false; + } + + pNode = pNode->FirstChildElement("seasonEpisode"); + + if (!pNode) + { + Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); + return false; + } + + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("seasonEpisode")) + { + TiXmlElement* childNode = pNode->FirstChildElement("master"); + + if (childNode) + { + std::string masterPattern = childNode->Attribute("pattern"); + + childNode = pNode->FirstChildElement("episode"); + + if (childNode) + { + std::string episodePattern = childNode->Attribute("pattern"); + + childNode = pNode->FirstChildElement("season"); + if (childNode != nullptr) + { + std::string seasonPattern = childNode->Attribute("pattern"); + + if (!masterPattern.empty() && !seasonPattern.empty() && !episodePattern.empty()) + { + episodeSeasonPatterns.emplace_back(EpisodeSeasonPattern(masterPattern, seasonPattern, episodePattern)); + + Logger::Log(LEVEL_DEBUG, "%s Adding seasonEpisode pattern: %s, master: %s, season: %s, episode: %s", __FUNCTION__, name.c_str(), masterPattern.c_str(), seasonPattern.c_str(), episodePattern.c_str()); + } + } + else + { + if (!masterPattern.empty() && !episodePattern.empty()) + { + episodeSeasonPatterns.emplace_back(EpisodeSeasonPattern(masterPattern, episodePattern)); + + Logger::Log(LEVEL_DEBUG, "%s Adding episode pattern from: %s, master: %s, episode: %s", __FUNCTION__, name.c_str(), masterPattern.c_str(), episodePattern.c_str()); + } + } + } + else + { + Logger::Log(LEVEL_ERROR, "%s Could find element, skipping pattern from: %s", __FUNCTION__, name.c_str()); + } + } + else + { + Logger::Log(LEVEL_ERROR, "%s Could find element, skipping pattern from: %s", __FUNCTION__, name.c_str()); + } + } + + //Now we do the years + pNode = hRoot.FirstChildElement("years").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); + return false; + } + + pNode = pNode->FirstChildElement("year"); + + if (!pNode) + { + Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); + return false; + } + + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("year")) + { + std::string yearPattern = pNode->Attribute("pattern"); + + yearPatterns.emplace_back(std::regex(yearPattern)); + + Logger::Log(LEVEL_DEBUG, "%s Adding year pattern from: %s, pattern: %s", __FUNCTION__, name.c_str(), yearPattern.c_str()); + } + + return true; +} diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/extract/ShowInfoExtractor.h kodi-pvr-vuplus-3.15.0/src/enigma2/extract/ShowInfoExtractor.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/extract/ShowInfoExtractor.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/extract/ShowInfoExtractor.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,55 @@ +#pragma once + +#include "IExtractor.h" + +#include +#include +#include + +#include "EpisodeSeasonPattern.h" + +namespace enigma2 +{ + static const std::string SHOW_INFO_DIR = "/showInfo"; + static const std::string SHOW_INFO_ADDON_DATA_BASE_DIR = "special://userdata/addon_data/pvr.vuplus" + SHOW_INFO_DIR; + + namespace extract + { + // (S4E37) (S04E37) (S2 Ep3/6) (S2 Ep7) + static const std::string MASTER_SEASON_EPISODE_PATTERN = "^.*\\(?([sS]\\.?[0-9]+ ?[eE][pP]?\\.?[0-9]+/?[0-9]*)\\)?[^]*$"; + // (E130) (Ep10) (E7/9) (Ep7/10) (Ep.25) + static const std::string MASTER_EPISODE_PATTERN = "^.*\\(?([eE][pP]?\\.?[0-9]+/?[0-9]*)\\)?[^]*$"; + // (2015E22) (2007E3) (2007E3/6) + static const std::string MASTER_YEAR_EPISODE_PATTERN = "^.*\\(?([12][0-9][0-9][0-9][eE][pP]?\\.?[0-9]+\\.?/?[0-9]*)\\)?[^]*$"; + // Starts with 2/4 6/6, no prefix + static const std::string MASTER_EPISODE_NO_PREFIX_PATTERN = "^.*([0-9]+/[0-9]+)\\.? +[^]*$"; + + // Get from matster match, prefixed by S,s,E,e,Ep + static const std::string GET_SEASON_PATTERN = "^.*[sS]\\.?([0-9][0-9]*).*$"; + static const std::string GET_EPISODE_PATTERN = "^.*[eE][pP]?\\.?([0-9][0-9]*).*$"; + // Get from master match, no prefix + static const std::string GET_EPISODE_NO_PREFIX_PATTERN = "^([0-9]+)/[0-9]+"; + + // (2018) + static const std::string GET_YEAR_PATTERN = "^.*\\(([12][0-9][0-9][0-9])\\)[^]*$"; + // (2018E25) + static const std::string GET_YEAR_EPISODE_PATTERN = "^.*\\(([12][0-9][0-9][0-9])[eE][pP]?\\.?[0-9]+/?[0-9]*\\)[^]*$"; + + class ShowInfoExtractor + : public IExtractor + { + public: + ShowInfoExtractor(); + ~ShowInfoExtractor(void); + + void ExtractFromEntry(enigma2::data::BaseEntry &entry); + bool IsEnabled(); + + private: + bool LoadShowInfoPatternsFile(const std::string &xmlFile, std::vector &episodeSeasonPatterns, std::vector yearPatterns); + + std::vector m_episodeSeasonPatterns; + std::vector m_yearPatterns; + }; + } //namespace extract +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/IStreamReader.h kodi-pvr-vuplus-3.15.0/src/enigma2/IStreamReader.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/IStreamReader.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/IStreamReader.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,23 @@ +#pragma once + +#include + +#include "libXBMC_addon.h" + +namespace enigma2 +{ + class IStreamReader + { + public: + virtual ~IStreamReader(void) = default; + virtual bool Start() = 0; + virtual ssize_t ReadData(unsigned char *buffer, unsigned int size) = 0; + virtual int64_t Seek(long long position, int whence) = 0; + virtual int64_t Position() = 0; + virtual int64_t Length() = 0; + virtual std::time_t TimeStart() = 0; + virtual std::time_t TimeEnd() = 0; + virtual bool IsRealTime() = 0; + virtual bool IsTimeshifting() = 0; + }; +} // namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/LocalizedString.h kodi-pvr-vuplus-3.15.0/src/enigma2/LocalizedString.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/LocalizedString.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/LocalizedString.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,55 @@ +#pragma once + +#include "client.h" + +#include + +namespace VUPLUS +{ + +class LocalizedString +{ +public: + explicit LocalizedString(int id) + { + Load(id); + } + + bool Load(int id) + { + char *str; + if ((str = XBMC->GetLocalizedString(id))) + { + m_localizedString = str; + XBMC->FreeString(str); + return true; + } + + m_localizedString = ""; + return false; + } + + std::string Get() + { + return m_localizedString; + } + + operator std::string() + { + return Get(); + } + + const char* c_str() + { + return m_localizedString.c_str(); + } + +private: + LocalizedString() = delete; + LocalizedString(const LocalizedString&) = delete; + LocalizedString &operator =(const LocalizedString&) = delete; + + std::string m_localizedString; +}; + +} //namespace VUPLUS diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/RecordingReader.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/RecordingReader.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/RecordingReader.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/RecordingReader.cpp 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,84 @@ +#include "RecordingReader.h" + +#include + +#include "../client.h" +#include "utilities/Logger.h" + +#include "p8-platform/threads/mutex.h" + +using namespace ADDON; +using namespace enigma2; +using namespace enigma2::utilities; + +RecordingReader::RecordingReader(const std::string &streamURL, std::time_t end) + : m_streamURL(streamURL), m_end(end) +{ + m_readHandle = XBMC->CURLCreate(m_streamURL.c_str()); + (void)XBMC->CURLOpen(m_readHandle, XFILE::READ_NO_CACHE); + m_len = XBMC->GetFileLength(m_readHandle); + m_nextReopen = time(nullptr) + REOPEN_INTERVAL; + Logger::Log(LEVEL_DEBUG, "RecordingReader: Started; url=%s, end=%u", + m_streamURL.c_str(), m_end); +} + +RecordingReader::~RecordingReader(void) +{ + if (m_readHandle) + XBMC->CloseFile(m_readHandle); + Logger::Log(LEVEL_DEBUG, "RecordingReader: Stopped"); +} + +bool RecordingReader::Start() +{ + return (m_readHandle != nullptr); +} + +ssize_t RecordingReader::ReadData(unsigned char *buffer, unsigned int size) +{ + /* check for playback of ongoing recording */ + if (m_end) + { + std::time_t now = std::time(nullptr); + if (m_pos == m_len || now > m_nextReopen) + { + /* reopen stream */ + Logger::Log(LEVEL_DEBUG, "RecordingReader: Reopening stream..."); + (void)XBMC->CURLOpen(m_readHandle, XFILE::READ_REOPEN | XFILE::READ_NO_CACHE); + m_len = XBMC->GetFileLength(m_readHandle); + XBMC->SeekFile(m_readHandle, m_pos, SEEK_SET); + + // random value (10 MiB) we choose to switch to fast reopen interval + bool nearEnd = m_len - m_pos <= 10 * 1024 * 1024; + m_nextReopen = now + (nearEnd ? REOPEN_INTERVAL_FAST : REOPEN_INTERVAL); + + /* recording has finished */ + if (now > m_end) + m_end = 0; + } + } + + ssize_t read = XBMC->ReadFile(m_readHandle, buffer, size); + m_pos += read; + return read; +} + +int64_t RecordingReader::Seek(long long position, int whence) +{ + int64_t ret = XBMC->SeekFile(m_readHandle, position, whence); + // for unknown reason seek sometimes doesn't return the correct position + // so let's sync with the underlaying implementation + m_pos = XBMC->GetFilePosition(m_readHandle); + m_len = XBMC->GetFileLength(m_readHandle); + return ret; +} + +int64_t RecordingReader::Position() +{ + return m_pos; +} + +int64_t RecordingReader::Length() +{ + return m_len; +} diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/RecordingReader.h kodi-pvr-vuplus-3.15.0/src/enigma2/RecordingReader.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/RecordingReader.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/RecordingReader.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#include "libXBMC_addon.h" + +namespace enigma2 +{ + class RecordingReader + { + public: + RecordingReader(const std::string &streamURL, std::time_t end); + ~RecordingReader(void); + + bool Start(); + ssize_t ReadData(unsigned char *buffer, unsigned int size); + int64_t Seek(long long position, int whence); + int64_t Position(); + int64_t Length(); + + private: + static const int REOPEN_INTERVAL = 30; + static const int REOPEN_INTERVAL_FAST = 10; + + std::string m_streamURL; + void *m_readHandle; + + /*!< @brief end time of the recording in case this an ongoing recording */ + std::time_t m_end; + std::time_t m_nextReopen; + uint64_t m_pos = { 0 }; + uint64_t m_len; + }; +} // namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/Recordings.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/Recordings.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/Recordings.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/Recordings.cpp 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,234 @@ +#include "Recordings.h" + +#include + +#include "../client.h" +#include "../Enigma2.h" +#include "utilities/Logger.h" +#include "utilities/WebUtils.h" + +#include "util/XMLUtils.h" +#include "p8-platform/util/StringUtils.h" + +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::extract; +using namespace enigma2::utilities; + +void Recordings::GetRecordings(std::vector &kodiRecordings) +{ + for (auto& recording : m_recordings) + { + Logger::Log(LEVEL_DEBUG, "%s - Transfer recording '%s', Recording Id '%s'", __FUNCTION__, recording.GetTitle().c_str(), recording.GetRecordingId().c_str()); + PVR_RECORDING kodiRecording; + memset(&kodiRecording, 0, sizeof(PVR_RECORDING)); + + recording.UpdateTo(kodiRecording, m_channels, IsInRecordingFolder(recording.GetTitle())); + + kodiRecordings.emplace_back(kodiRecording); + } +} + +int Recordings::GetNumRecordings() const +{ + return m_recordings.size(); +} + +void Recordings::ClearRecordings() +{ + m_recordings.clear(); +} + +bool Recordings::IsInRecordingFolder(const std::string &recordingFolder) const +{ + int iMatches = 0; + for (const auto& recording : m_recordings) + { + if (recordingFolder == recording.GetTitle()) + { + iMatches++; + Logger::Log(LEVEL_DEBUG, "%s Found Recording title '%s' in recordings vector!", __FUNCTION__, recordingFolder.c_str()); + if (iMatches > 1) + { + Logger::Log(LEVEL_DEBUG, "%s Found Recording title twice '%s' in recordings vector!", __FUNCTION__, recordingFolder.c_str()); + return true; + } + } + } + + return false; +} + +PVR_ERROR Recordings::DeleteRecording(const PVR_RECORDING &recinfo) +{ + std::string strTmp = StringUtils::Format("web/moviedelete?sRef=%s", WebUtils::URLEncodeInline(recinfo.strRecordingId).c_str()); + + std::string strResult; + if(!WebUtils::SendSimpleCommand(strTmp, strResult)) + return PVR_ERROR_FAILED; + + PVR->TriggerRecordingUpdate(); + + return PVR_ERROR_NO_ERROR; +} + +const std::string Recordings::GetRecordingURL(const PVR_RECORDING &recinfo) +{ + for (const auto& recording : m_recordings) + { + if (recinfo.strRecordingId == recording.GetRecordingId()) + return recording.GetStreamURL(); + } + return ""; +} + +std::vector& Recordings::GetLocations() +{ + return m_locations; +} + +void Recordings::ClearLocations() +{ + m_locations.clear(); +} + +bool Recordings::LoadLocations() +{ + std::string url; + if (Settings::GetInstance().GetRecordingsFromCurrentLocationOnly()) + url = StringUtils::Format("%s%s", Settings::GetInstance().GetConnectionURL().c_str(), "web/getcurrlocation"); + else + url = StringUtils::Format("%s%s", Settings::GetInstance().GetConnectionURL().c_str(), "web/getlocations"); + + const std::string strXML = WebUtils::GetHttpXML(url); + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(strXML.c_str())) + { + Logger::Log(LEVEL_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return false; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("e2locations").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_DEBUG, "Could not find element"); + return false; + } + + hRoot=TiXmlHandle(pElem); + + TiXmlElement* pNode = hRoot.FirstChildElement("e2location").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_DEBUG, "Could not find element"); + return false; + } + + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2location")) + { + std::string strTmp; + strTmp = pNode->GetText(); + + m_locations.emplace_back(strTmp); + + Logger::Log(LEVEL_DEBUG, "%s Added '%s' as a recording location", __FUNCTION__, strTmp.c_str()); + } + + Logger::Log(LEVEL_INFO, "%s Loaded '%d' recording locations", __FUNCTION__, m_locations.size()); + + return true; +} + +void Recordings::LoadRecordings() +{ + ClearRecordings(); + + for (const auto& location : m_locations) + { + if (!GetRecordingsFromLocation(location)) + { + Logger::Log(LEVEL_ERROR, "%s Error fetching lists for folder: '%s'", __FUNCTION__, location.c_str()); + } + } +} + +bool Recordings::GetRecordingsFromLocation(std::string recordingLocation) +{ + std::string url; + std::string directory; + + if (recordingLocation == "default") + { + url = StringUtils::Format("%s%s", Settings::GetInstance().GetConnectionURL().c_str(), "web/movielist"); + directory = StringUtils::Format("/"); + } + else + { + url = StringUtils::Format("%s%s?dirname=%s", Settings::GetInstance().GetConnectionURL().c_str(), "web/movielist", + WebUtils::URLEncodeInline(recordingLocation).c_str()); + directory = recordingLocation; + } + + std::string strXML; + strXML = WebUtils::GetHttpXML(url); + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(strXML.c_str())) + { + Logger::Log(LEVEL_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return false; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("e2movielist").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_DEBUG, "%s Could not find element!", __FUNCTION__); + return false; + } + + hRoot=TiXmlHandle(pElem); + + TiXmlElement* pNode = hRoot.FirstChildElement("e2movie").Element(); + + int iNumRecordings = 0; + + if (!pNode) + { + Logger::Log(LEVEL_DEBUG, "Could not find element, no movies at location: %s", directory.c_str()); + } + else + { + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2movie")) + { + + RecordingEntry recordingEntry; + + if (!recordingEntry.UpdateFrom(pNode, directory, m_channels)) + continue; + + if (m_entryExtractor.IsEnabled()) + m_entryExtractor.ExtractFromEntry(recordingEntry); + + iNumRecordings++; + + m_recordings.emplace_back(recordingEntry); + + Logger::Log(LEVEL_DEBUG, "%s loaded Recording entry '%s', start '%d', length '%d'", __FUNCTION__, recordingEntry.GetTitle().c_str(), recordingEntry.GetStartTime(), recordingEntry.GetDuration()); + } + + Logger::Log(LEVEL_INFO, "%s Loaded %u Recording Entries from folder '%s'", __FUNCTION__, iNumRecordings, recordingLocation.c_str()); + } + return true; +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/Recordings.h kodi-pvr-vuplus-3.15.0/src/enigma2/Recordings.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/Recordings.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/Recordings.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,62 @@ +#pragma once +/* + * Copyright (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include + +#include "Channels.h" +#include "data/RecordingEntry.h" +#include "extract/EpgEntryExtractor.h" + +#include "libXBMC_pvr.h" + +namespace enigma2 +{ + class Recordings + { + public: + Recordings(Channels &channels, enigma2::extract::EpgEntryExtractor &entryExtractor) + : m_channels(channels), m_entryExtractor(entryExtractor) {}; + void GetRecordings(std::vector &recordings); + int GetNumRecordings() const; + void ClearRecordings(); + bool IsInRecordingFolder(const std::string &strRecordingFolder) const; + const std::string GetRecordingURL(const PVR_RECORDING &recinfo); + PVR_ERROR DeleteRecording(const PVR_RECORDING &recinfo); + + std::vector& GetLocations(); + void ClearLocations(); + + bool LoadLocations(); + void LoadRecordings(); + + private: + bool GetRecordingsFromLocation(std::string recordingFolder); + + std::vector m_recordings; + std::vector m_locations; + + Channels &m_channels; + enigma2::extract::EpgEntryExtractor &m_entryExtractor; + }; +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/Settings.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/Settings.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/Settings.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/Settings.cpp 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,304 @@ +#include "Settings.h" + +#include "../client.h" +#include "utilities/LocalizedString.h" + +#include "p8-platform/util/StringUtils.h" + +using namespace ADDON; +using namespace enigma2; +using namespace enigma2::utilities; + +/*************************************************************************** + * PVR settings + **************************************************************************/ +void Settings::ReadFromAddon() +{ + char buffer[1024]; + buffer[0] = 0; + + //Connection + if (XBMC->GetSetting("host", buffer)) + m_hostname = buffer; + else + m_hostname = DEFAULT_HOST; + buffer[0] = 0; + + if (!XBMC->GetSetting("webport", &m_portWeb)) + m_portWeb = DEFAULT_WEB_PORT; + + if (!XBMC->GetSetting("use_secure", &m_useSecureHTTP)) + m_useSecureHTTP = false; + + if (XBMC->GetSetting("user", buffer)) + m_username = buffer; + else + m_username = ""; + buffer[0] = 0; + + if (XBMC->GetSetting("pass", buffer)) + m_password = buffer; + else + m_password = ""; + buffer[0] = 0; + + if (!XBMC->GetSetting("autoconfig", &m_autoConfig)) + m_autoConfig = false; + + if (!XBMC->GetSetting("streamport", &m_portStream)) + m_portStream = DEFAULT_STREAM_PORT; + + if (!XBMC->GetSetting("use_secure_stream", &m_useSecureHTTPStream)) + m_useSecureHTTPStream = false; + + if (!XBMC->GetSetting("use_login_stream", &m_useLoginStream)) + m_useLoginStream = false; + + //General + if (!XBMC->GetSetting("onlinepicons", &m_onlinePicons)) + m_onlinePicons = true; + + if (!XBMC->GetSetting("usepiconseuformat", &m_usePiconsEuFormat)) + m_usePiconsEuFormat = false; + + if (XBMC->GetSetting("iconpath", buffer)) + m_iconPath = buffer; + else + m_iconPath = ""; + buffer[0] = 0; + + if (!XBMC->GetSetting("updateint", &m_updateInterval)) + m_updateInterval = DEFAULT_UPDATE_INTERVAL; + + if (!XBMC->GetSetting("updatemode", &m_updateMode)) + m_updateMode = UpdateMode::TIMERS_AND_RECORDINGS; + + //Channels + if (!XBMC->GetSetting("zap", &m_zap)) + m_zap = false; + + if (!XBMC->GetSetting("tvgroupmode", &m_tvChannelGroupMode)) + m_tvChannelGroupMode = ChannelGroupMode::ALL_GROUPS; + + if (XBMC->GetSetting("onetvgroup", buffer)) + m_oneTVGroup = buffer; + else + m_oneTVGroup = ""; + buffer[0] = 0; + + if (!XBMC->GetSetting("tvfavouritesmode", &m_tvFavouritesMode)) + m_tvFavouritesMode = FavouritesGroupMode::DISABLED; + + if (!XBMC->GetSetting("radiogroupmode", &m_radioChannelGroupMode)) + m_radioChannelGroupMode = ChannelGroupMode::FAVOURITES_GROUP; + + if (XBMC->GetSetting("oneradiogroup", buffer)) + m_oneRadioGroup = buffer; + else + m_oneRadioGroup = ""; + buffer[0] = 0; + + if (!XBMC->GetSetting("radiofavouritesmode", &m_radioFavouritesMode)) + m_radioFavouritesMode = FavouritesGroupMode::DISABLED; + + //EPG + if (!XBMC->GetSetting("extractshowinfoenabled", &m_extractShowInfo)) + m_extractShowInfo = false; + + if (XBMC->GetSetting("extractshowinfofile", buffer)) + m_extractShowInfoFile = buffer; + else + m_extractShowInfoFile = DEFAULT_SHOW_INFO_FILE; + buffer[0] = 0; + + if (!XBMC->GetSetting("genreidmapenabled", &m_mapGenreIds)) + m_mapGenreIds = false; + + if (XBMC->GetSetting("genreidmapfile", buffer)) + m_mapGenreIdsFile = buffer; + else + m_mapGenreIdsFile = DEFAULT_GENRE_ID_MAP_FILE; + buffer[0] = 0; + + if (!XBMC->GetSetting("rytecgenretextmapenabled", &m_mapRytecTextGenres)) + m_mapRytecTextGenres = false; + + if (XBMC->GetSetting("rytecgenretextmapfile", buffer)) + m_mapRytecTextGenresFile = buffer; + else + m_mapRytecTextGenresFile = DEFAULT_GENRE_ID_MAP_FILE; + buffer[0] = 0; + + if (!XBMC->GetSetting("logmissinggenremapping", &m_logMissingGenreMappings)) + m_logMissingGenreMappings = false; + + //Recording and Timers + if (XBMC->GetSetting("recordingpath", buffer)) + m_recordingPath = buffer; + else + m_recordingPath = ""; + buffer[0] = 0; + + if (!XBMC->GetSetting("onlycurrent", &m_onlyCurrentLocation)) + m_onlyCurrentLocation = false; + + if (!XBMC->GetSetting("keepfolders", &m_keepFolders)) + m_keepFolders = false; + + if (!XBMC->GetSetting("enablegenrepeattimers", &m_enableGenRepeatTimers)) + m_enableGenRepeatTimers = true; + + if (!XBMC->GetSetting("numgenrepeattimers", &m_numGenRepeatTimers)) + m_numGenRepeatTimers = DEFAULT_NUM_GEN_REPEAT_TIMERS; + + if (!XBMC->GetSetting("enableautotimers", &m_enableAutoTimers)) + m_enableAutoTimers = true; + + if (!XBMC->GetSetting("timerlistcleanup", &m_automaticTimerlistCleanup)) + m_automaticTimerlistCleanup = false; + + //Timeshift + if (!XBMC->GetSetting("enabletimeshift", &m_timeshift)) + m_timeshift = Timeshift::OFF; + + if (XBMC->GetSetting("timeshiftbufferpath", buffer) && !std::string(buffer).empty()) + m_timeshiftBufferPath = buffer; + else + m_timeshiftBufferPath = DEFAULT_TSBUFFERPATH; + buffer[0] = 0; + + //Advanced + if (!XBMC->GetSetting("prependoutline", &m_prependOutline)) + m_prependOutline = PrependOutline::IN_EPG; + + if (!XBMC->GetSetting("powerstatemode", &m_powerstateMode)) + m_powerstateMode = PowerstateMode::DISABLED; + + if (!XBMC->GetSetting("readtimeout", &m_readTimeout)) + m_readTimeout = 0; + + if (!XBMC->GetSetting("streamreadchunksize", &m_streamReadChunkSize)) + m_streamReadChunkSize = 0; + + // Now that we've read all the settings construct the connection URL + + m_connectionURL.clear(); + // simply add user@pass in front of the URL if username/password is set + if ((m_username.length() > 0) && (m_password.length() > 0)) + m_connectionURL = StringUtils::Format("%s:%s@", m_username.c_str(), m_password.c_str()); + if (!m_useSecureHTTP) + m_connectionURL = StringUtils::Format("http://%s%s:%u/", m_connectionURL.c_str(), m_hostname.c_str(), m_portWeb); + else + m_connectionURL = StringUtils::Format("https://%s%s:%u/", m_connectionURL.c_str(), m_hostname.c_str(), m_portWeb); +} + +ADDON_STATUS Settings::SetValue(const std::string &settingName, const void *settingValue) +{ + //Connection + if (settingName == "host") + return SetStringSetting(settingName, settingValue, m_hostname, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "webport") + return SetSetting(settingName, settingValue, m_portWeb, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "use_secure") + return SetSetting(settingName, settingValue, m_useSecureHTTP, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "user") + return SetStringSetting(settingName, settingValue, m_username, ADDON_STATUS_OK, ADDON_STATUS_OK); + else if (settingName == "pass") + return SetStringSetting(settingName, settingValue, m_password, ADDON_STATUS_OK, ADDON_STATUS_OK); + else if (settingName == "autoconfig") + return SetSetting(settingName, settingValue, m_autoConfig, ADDON_STATUS_OK, ADDON_STATUS_OK); + else if (settingName == "streamport") + return SetSetting(settingName, settingValue, m_portStream, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "use_secure_stream") + return SetSetting(settingName, settingValue, m_useSecureHTTPStream, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "use_login_stream") + return SetSetting(settingName, settingValue, m_useLoginStream, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + //General + else if (settingName == "onlinepicons") + return SetSetting(settingName, settingValue, m_onlinePicons, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "usepiconseuformat") + return SetSetting(settingName, settingValue, m_usePiconsEuFormat, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "iconpath") + return SetStringSetting(settingName, settingValue, m_iconPath, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "updateint") + return SetSetting(settingName, settingValue, m_updateInterval, ADDON_STATUS_OK, ADDON_STATUS_OK); + else if (settingName == "updatemode") + return SetSetting(settingName, settingValue, m_updateMode, ADDON_STATUS_OK, ADDON_STATUS_OK); + //Channels + else if (settingName == "zap") + return SetSetting(settingName, settingValue, m_zap, ADDON_STATUS_OK, ADDON_STATUS_OK); + else if (settingName == "tvgroupmode") + return SetSetting(settingName, settingValue, m_tvChannelGroupMode, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "onetvgroup") + return SetStringSetting(settingName, settingValue, m_oneTVGroup, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "tvfavouritesmode") + return SetSetting(settingName, settingValue, m_tvFavouritesMode, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "radiogroupmode") + return SetSetting(settingName, settingValue, m_radioChannelGroupMode, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "oneradiogroup") + return SetStringSetting(settingName, settingValue, m_oneRadioGroup, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "radiofavouritesmode") + return SetSetting(settingName, settingValue, m_radioFavouritesMode, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + //EPG + else if (settingName == "extractepginfoenabled") + return SetSetting(settingName, settingValue, m_extractShowInfo, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "extractepginfofile") + return SetStringSetting(settingName, settingValue, m_extractShowInfoFile, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "genreidmapenabled") + return SetSetting(settingName, settingValue, m_mapGenreIds, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "genreidmapfile") + return SetStringSetting(settingName, settingValue, m_mapGenreIdsFile, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "rytecgenretextmapenabled") + return SetSetting(settingName, settingValue, m_mapRytecTextGenres, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "rytecgenretextmapfile") + return SetStringSetting(settingName, settingValue, m_mapRytecTextGenresFile, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "logmissinggenremapping") + return SetSetting(settingName, settingValue, m_logMissingGenreMappings, ADDON_STATUS_OK, ADDON_STATUS_OK); + //Recordings and Timers + else if (settingName == "recordingpath") + return SetStringSetting(settingName, settingValue, m_recordingPath, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "onlycurrent") + return SetSetting(settingName, settingValue, m_onlyCurrentLocation, ADDON_STATUS_OK, ADDON_STATUS_OK); + else if (settingName == "keepfolders") + return SetSetting(settingName, settingValue, m_keepFolders, ADDON_STATUS_OK, ADDON_STATUS_OK); + else if (settingName == "enablegenrepeattimers") + return SetSetting(settingName, settingValue, m_enableAutoTimers, ADDON_STATUS_OK, ADDON_STATUS_OK); + else if (settingName == "numgenrepeattimers") + return SetSetting(settingName, settingValue, m_numGenRepeatTimers, ADDON_STATUS_OK, ADDON_STATUS_OK); + else if (settingName == "enableautotimers") + return SetSetting(settingName, settingValue, m_enableAutoTimers, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "timerlistcleanup") + return SetSetting(settingName, settingValue, m_automaticTimerlistCleanup, ADDON_STATUS_OK, ADDON_STATUS_OK); + //Timeshift + else if (settingName == "enabletimeshift") + return SetSetting(settingName, settingValue, m_timeshift, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "timeshiftbufferpath") + return SetStringSetting(settingName, settingValue, m_timeshiftBufferPath, ADDON_STATUS_OK, ADDON_STATUS_OK); + //Advanced + else if (settingName == "prependoutline") + return SetSetting(settingName, settingValue, m_prependOutline, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "powerstatemode") + return SetSetting(settingName, settingValue, m_powerstateMode, ADDON_STATUS_OK, ADDON_STATUS_OK); + else if (settingName == "readtimeout") + return SetSetting(settingName, settingValue, m_readTimeout, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); + else if (settingName == "streamreadchunksize") + return SetSetting(settingName, settingValue, m_streamReadChunkSize, ADDON_STATUS_OK, ADDON_STATUS_OK); + //Backend + else if (settingName == "globalstartpaddingstb") + { + if (SetSetting(settingName, settingValue, m_globalStartPaddingStb, true, false)) + m_admin->SendGlobalRecordingStartMarginSetting(m_globalStartPaddingStb); + } + else if (settingName == "globalendpaddingstb") + { + if (SetSetting(settingName, settingValue, m_globalEndPaddingStb, true, false)) + m_admin->SendGlobalRecordingEndMarginSetting(m_globalEndPaddingStb); + } + + return ADDON_STATUS_OK; +} + +bool Settings::IsTimeshiftBufferPathValid() const +{ + return XBMC->DirectoryExists(m_timeshiftBufferPath.c_str()); +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/Settings.h kodi-pvr-vuplus-3.15.0/src/enigma2/Settings.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/Settings.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/Settings.h 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,272 @@ +#pragma once + +#include + +#include "Admin.h" +#include "utilities/Logger.h" +#include "utilities/DeviceInfo.h" +#include "utilities/DeviceSettings.h" + +#include "xbmc_addon_types.h" + +class Vu; + +namespace enigma2 +{ + static const std::string DEFAULT_HOST = "127.0.0.1"; + static const int DEFAULT_CONNECT_TIMEOUT = 30; + static const int DEFAULT_STREAM_PORT = 8001; + static const int DEFAULT_WEB_PORT = 80; + static const int DEFAULT_UPDATE_INTERVAL = 2; + static const std::string DEFAULT_TSBUFFERPATH = "special://userdata/addon_data/pvr.vuplus"; + static const std::string DEFAULT_SHOW_INFO_FILE = "special://userdata/addon_data/pvr.vuplus/showInfo/English-ShowInfo.xml"; + static const std::string DEFAULT_GENRE_ID_MAP_FILE = "special://userdata/addon_data/pvr.vuplus/genres/genreIdMappings/Sky-UK.xml"; + static const std::string DEFAULT_GENRE_TEXT_MAP_FILE = "special://userdata/addon_data/pvr.vuplus/genres/genreTextMappings/Rytec-UK-Ireland"; + static const int DEFAULT_NUM_GEN_REPEAT_TIMERS = 1; + + enum class UpdateMode + : int // same type as addon settings + { + TIMERS_AND_RECORDINGS = 0, + TIMERS_ONLY + }; + + enum class ChannelGroupMode + : int // same type as addon settings + { + ALL_GROUPS = 0, + ONLY_ONE_GROUP, + FAVOURITES_GROUP + }; + + enum class FavouritesGroupMode + : int // same type as addon settings + { + DISABLED = 0, + AS_FIRST_GROUP, + AS_LAST_GROUP + }; + + enum class Timeshift + : int // same type as addon settings + { + OFF = 0, + ON_PLAYBACK, + ON_PAUSE + }; + + enum class PrependOutline + : int // same type as addon settings + { + NEVER = 0, + IN_EPG, + IN_RECORDINGS, + ALWAYS + }; + + enum class PowerstateMode + : int // same type as addon settings + { + DISABLED = 0, + STANDBY, + DEEP_STANDBY, + WAKEUP_THEN_STANDBY + }; + + class Settings + { + public: + /** + * Singleton getter for the instance + */ + static Settings& GetInstance() + { + static Settings settings; + return settings; + } + + void ReadFromAddon(); + ADDON_STATUS SetValue(const std::string &settingName, const void *settingValue); + + //Connection + const std::string& GetHostname() const { return m_hostname; } + int GetWebPortNum() const { return m_portWeb; } + bool GetUseSecureConnection() const { return m_useSecureHTTP; } + const std::string& GetUsername() const {return m_username; } + const std::string& GetPassword() const { return m_password; } + bool GetAutoConfigLiveStreamsEnabled() const { return m_autoConfig; } + int GetStreamPortNum() const { return m_portStream; } + bool UseSecureConnectionStream() const { return m_useSecureHTTPStream; } + bool UseLoginStream() const { return m_useLoginStream; } + + //General + bool UseOnlinePicons() const { return m_onlinePicons; } + bool UsePiconsEuFormat() const { return m_usePiconsEuFormat; } + const std::string& GetIconPath() const { return m_iconPath; } + unsigned int GetUpdateIntervalMins() const { return m_updateInterval; } + UpdateMode GetUpdateMode() const { return m_updateMode; } + + //Channel + bool GetZapBeforeChannelSwitch() const { return m_zap; } + const ChannelGroupMode& GetTVChannelGroupMode() const { return m_tvChannelGroupMode; } + const std::string& GetOneTVGroupName() const { return m_oneTVGroup; } + const FavouritesGroupMode& GetTVFavouritesMode() const { return m_tvFavouritesMode; } + const ChannelGroupMode& GetRadioChannelGroupMode() const { return m_radioChannelGroupMode; } + const std::string& GetOneRadioGroupName() const { return m_oneRadioGroup; } + const FavouritesGroupMode& GetRadioFavouritesMode() const { return m_radioFavouritesMode; } + + //EPG + bool GetExtractShowInfo() const { return m_extractShowInfo; } + const std::string& GetExtractShowInfoFile() const { return m_extractShowInfoFile; } + bool GetMapGenreIds() const { return m_mapGenreIds; } + const std::string& GetMapGenreIdsFile() const { return m_mapGenreIdsFile; } + bool GetMapRytecTextGenres() const { return m_mapRytecTextGenres; } + const std::string& GetMapRytecTextGenresFile() const { return m_mapRytecTextGenresFile; } + bool GetLogMissingGenreMappings() const { return m_logMissingGenreMappings; } + + //Recordings and Timers + const std::string& GetRecordingPath() const { return m_recordingPath; } + bool GetRecordingsFromCurrentLocationOnly() const { return m_onlyCurrentLocation; } + bool GetKeepRecordingsFolders() const { return m_keepFolders; } + bool GetGenRepeatTimersEnabled() const { return m_enableGenRepeatTimers; } + int GetNumGenRepeatTimers() const { return m_numGenRepeatTimers; } + bool GetAutoTimersEnabled() const { return m_enableAutoTimers; } + bool GetAutoTimerListCleanupEnabled() const { return m_automaticTimerlistCleanup; } + + //Timeshift + const Timeshift& GetTimeshift() const { return m_timeshift; } + const std::string& GetTimeshiftBufferPath() const { return m_timeshiftBufferPath; } + bool IsTimeshiftBufferPathValid() const; + + //Advanced + const PrependOutline& GetPrependOutline() const { return m_prependOutline; } + PowerstateMode GetPowerstateModeOnAddonExit() const { return m_powerstateMode; } + int GetReadTimeoutSecs() const { return m_readTimeout; } + int GetStreamReadChunkSizeKb() const { return m_streamReadChunkSize; } + + const std::string& GetConnectionURL() const { return m_connectionURL; } + + unsigned int GetWebIfVersionAsNum() const { return m_deviceInfo->GetWebIfVersionAsNum(); } + + const enigma2::utilities::DeviceInfo* GetDeviceInfo() const { return m_deviceInfo; } + void SetDeviceInfo(enigma2::utilities::DeviceInfo* deviceInfo) { m_deviceInfo = deviceInfo; } + + const enigma2::utilities::DeviceSettings* GetDeviceSettings() const { return m_deviceSettings; } + void SetDeviceSettings(enigma2::utilities::DeviceSettings* deviceSettings) + { + m_deviceSettings = deviceSettings; + m_globalStartPaddingStb = deviceSettings->GetGlobalRecordingStartMargin(); + m_globalEndPaddingStb = deviceSettings->GetGlobalRecordingEndMargin(); + } + + void SetAdmin(enigma2::Admin* admin) { m_admin = admin; } + + inline unsigned int GenerateWebIfVersionAsNum(unsigned int major, unsigned int minor, unsigned int patch) + { + return (major << 16 | minor << 8 | patch); + }; + + private: + Settings() = default; + + Settings(Settings const &) = delete; + void operator=(Settings const &) = delete; + + template + V SetSetting(const std::string& settingName, const void* settingValue, T& currentValue, V returnValueIfChanged, V defaultReturnValue) + { + T newValue = *static_cast(settingValue); + if (newValue != currentValue) + { + utilities::Logger::Log(utilities::LogLevel::LEVEL_NOTICE, "%s - Changed Setting '%s' from %d to %d", __FUNCTION__, settingName.c_str(), currentValue, newValue); + currentValue = newValue; + return returnValueIfChanged; + } + + return defaultReturnValue; + }; + + template + V SetStringSetting(const std::string &settingName, const void* settingValue, std::string ¤tValue, V returnValueIfChanged, V defaultReturnValue) + { + const std::string strSettingValue = static_cast(settingValue); + + if (strSettingValue != currentValue) + { + utilities::Logger::Log(utilities::LogLevel::LEVEL_NOTICE, "%s - Changed Setting '%s' from %s to %s", __FUNCTION__, settingName.c_str(), currentValue.c_str(), strSettingValue.c_str()); + currentValue = strSettingValue; + return returnValueIfChanged; + } + + return defaultReturnValue; + } + + //Connection + std::string m_hostname = DEFAULT_HOST; + int m_portWeb = DEFAULT_WEB_PORT; + bool m_useSecureHTTP = false; + std::string m_username = ""; + std::string m_password = ""; + bool m_autoConfig = false; + int m_portStream = DEFAULT_STREAM_PORT; + bool m_useSecureHTTPStream = false; + bool m_useLoginStream = false; + + //General + bool m_onlinePicons = true; + bool m_usePiconsEuFormat = false; + std::string m_iconPath = ""; + unsigned int m_updateInterval = DEFAULT_UPDATE_INTERVAL; + UpdateMode m_updateMode = UpdateMode::TIMERS_AND_RECORDINGS; + + //Channel + bool m_zap = false; + ChannelGroupMode m_tvChannelGroupMode = ChannelGroupMode::ALL_GROUPS; + std::string m_oneTVGroup = ""; + FavouritesGroupMode m_tvFavouritesMode = FavouritesGroupMode::DISABLED; + ChannelGroupMode m_radioChannelGroupMode = ChannelGroupMode::FAVOURITES_GROUP; + std::string m_oneRadioGroup = ""; + FavouritesGroupMode m_radioFavouritesMode = FavouritesGroupMode::DISABLED; + + //EPG + bool m_extractShowInfo = true; + std::string m_extractShowInfoFile; + bool m_mapGenreIds = true; + std::string m_mapGenreIdsFile; + bool m_mapRytecTextGenres = true; + std::string m_mapRytecTextGenresFile; + bool m_logMissingGenreMappings = true; + + //Recordings and Timers + std::string m_recordingPath = ""; + bool m_onlyCurrentLocation = false; + bool m_keepFolders = false; + bool m_enableGenRepeatTimers = true; + int m_numGenRepeatTimers = DEFAULT_NUM_GEN_REPEAT_TIMERS; + bool m_enableAutoTimers = true; + bool m_automaticTimerlistCleanup = false; + + //Timeshift + Timeshift m_timeshift = Timeshift::OFF; + std::string m_timeshiftBufferPath = DEFAULT_TSBUFFERPATH; + + //Advanced + PrependOutline m_prependOutline = PrependOutline::IN_EPG; + PowerstateMode m_powerstateMode = PowerstateMode::DISABLED; + int m_readTimeout = 0; + int m_streamReadChunkSize = 0; + + //Backend + int m_globalStartPaddingStb = 0; + int m_globalEndPaddingStb = 0; + + std::string m_connectionURL; + enigma2::utilities::DeviceInfo* m_deviceInfo; + enigma2::utilities::DeviceSettings* m_deviceSettings; + enigma2::Admin* m_admin; + + //PVR Props + std::string m_szUserPath = ""; + std::string m_szClientPath = ""; + }; +} //namespace enigma2 diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/StreamReader.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/StreamReader.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/StreamReader.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/StreamReader.cpp 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,71 @@ +#include "StreamReader.h" + +#include "../client.h" +#include "utilities/Logger.h" + +using namespace ADDON; +using namespace enigma2; +using namespace enigma2::utilities; + +StreamReader::StreamReader(const std::string &streamURL, + const unsigned int m_readTimeout) +{ + m_streamHandle = XBMC->CURLCreate(streamURL.c_str()); + if (m_readTimeout > 0) + XBMC->CURLAddOption(m_streamHandle, XFILE::CURL_OPTION_PROTOCOL, + "connection-timeout", std::to_string(0).c_str()); + + Logger::Log(LEVEL_DEBUG, "StreamReader: Started; url=%s", streamURL.c_str()); +} + +StreamReader::~StreamReader(void) +{ + if (m_streamHandle) + XBMC->CloseFile(m_streamHandle); + Logger::Log(LEVEL_DEBUG, "StreamReader: Stopped"); +} + +bool StreamReader::Start() +{ + return XBMC->CURLOpen(m_streamHandle, XFILE::READ_NO_CACHE); +} + +ssize_t StreamReader::ReadData(unsigned char *buffer, unsigned int size) +{ + return XBMC->ReadFile(m_streamHandle, buffer, size); +} + +int64_t StreamReader::Seek(long long position, int whence) +{ + return XBMC->SeekFile(m_streamHandle, position, whence); +} + +int64_t StreamReader::Position() +{ + return XBMC->GetFilePosition(m_streamHandle); +} + +int64_t StreamReader::Length() +{ + return XBMC->GetFileLength(m_streamHandle); +} + +std::time_t StreamReader::TimeStart() +{ + return m_start; +} + +std::time_t StreamReader::TimeEnd() +{ + return std::time(nullptr); +} + +bool StreamReader::IsRealTime() +{ + return true; +} + +bool StreamReader::IsTimeshifting() +{ + return false; +} diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/StreamReader.h kodi-pvr-vuplus-3.15.0/src/enigma2/StreamReader.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/StreamReader.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/StreamReader.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,31 @@ +#pragma once + +#include "IStreamReader.h" + +#include + +namespace enigma2 +{ + class StreamReader + : public IStreamReader + { + public: + StreamReader(const std::string &streamURL, + const unsigned int m_readTimeout); + ~StreamReader(void); + + bool Start() override; + ssize_t ReadData(unsigned char *buffer, unsigned int size) override; + int64_t Seek(long long position, int whence) override; + int64_t Position() override; + int64_t Length() override; + std::time_t TimeStart() override; + std::time_t TimeEnd() override; + bool IsRealTime() override; + bool IsTimeshifting() override; + + private: + void *m_streamHandle; + std::time_t m_start = time(nullptr); + }; +} // namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/Timers.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/Timers.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/Timers.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/Timers.cpp 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,996 @@ +#include "Timers.h" + +#include +#include + +#include "../client.h" +#include "../Enigma2.h" +#include "utilities/LocalizedString.h" +#include "utilities/Logger.h" +#include "utilities/UpdateState.h" +#include "utilities/WebUtils.h" + +#include "inttypes.h" +#include "util/XMLUtils.h" +#include "p8-platform/util/StringUtils.h" + +using namespace ADDON; +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::utilities; + +template +T *Timers::GetTimer(std::function func, + std::vector &timerlist) +{ + for (auto &timer : timerlist) + { + if (func(timer)) + return &timer; + } + return nullptr; +} + +std::vector Timers::LoadTimers() const +{ + std::vector timers; + + const std::string url = StringUtils::Format("%s%s", m_settings.GetConnectionURL().c_str(), "web/timerlist"); + + const std::string strXML = WebUtils::GetHttpXML(url); + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(strXML.c_str())) + { + Logger::Log(LEVEL_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return timers; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("e2timerlist").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_DEBUG, "%s Could not find element!", __FUNCTION__); + return timers; + } + + hRoot=TiXmlHandle(pElem); + + TiXmlElement* pNode = hRoot.FirstChildElement("e2timer").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_DEBUG, "Could not find element"); + return timers; + } + + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2timer")) + { + Timer newTimer; + + if (!newTimer.UpdateFrom(pNode, m_channels)) + continue; + + timers.emplace_back(newTimer); + + if ((newTimer.GetType() == Timer::MANUAL_REPEATING || newTimer.GetType() == Timer::EPG_REPEATING) + && m_settings.GetGenRepeatTimersEnabled() && m_settings.GetNumGenRepeatTimers() > 0) + { + GenerateChildManualRepeatingTimers(&timers, &newTimer); + } + + Logger::Log(LEVEL_INFO, "%s fetched Timer entry '%s', begin '%d', end '%d'", + __FUNCTION__, newTimer.GetTitle().c_str(), newTimer.GetStartTime(), newTimer.GetEndTime()); + } + + Logger::Log(LEVEL_INFO, "%s fetched %u Timer Entries", __FUNCTION__, timers.size()); + return timers; +} + +void Timers::GenerateChildManualRepeatingTimers(std::vector *timers, Timer *timer) const +{ + int genTimerCount = 0; + int weekdays = timer->GetWeekdays(); + const time_t ONE_DAY = 24 * 60 * 60 ; + + if (m_settings.GetNumGenRepeatTimers() && weekdays != PVR_WEEKDAY_NONE) + { + time_t nextStartTime = timer->GetStartTime(); + time_t nextEndTime = timer->GetEndTime(); + + for (int i = 0; i < m_settings.GetNumGenRepeatTimers(); i++) + { + //Even if one day a week the max we can hit is 3 weeks + for (int i = 0; i < DAYS_IN_WEEK; i++) + { + std::tm nextTimeInfo = *std::localtime(&nextStartTime); + + // Get the weekday and convert to PVR day of week + int pvrWeekday = nextTimeInfo.tm_wday - 1; + if (pvrWeekday < 0) + pvrWeekday = 6; + + if (timer->GetWeekdays() & (1 << pvrWeekday)) + { + //Create a timer + Timer newTimer; + newTimer.SetType(Timer::READONLY_REPEATING_ONCE); + newTimer.SetTitle(timer->GetTitle()); + newTimer.SetChannelId(timer->GetChannelId()); + newTimer.SetChannelName(timer->GetChannelName()); + newTimer.SetStartTime(nextStartTime); + newTimer.SetEndTime(nextEndTime); + newTimer.SetPlot(timer->GetPlot()); + newTimer.SetWeekdays(0); + newTimer.SetState(PVR_TIMER_STATE_NEW); + newTimer.SetEpgId(timer->GetEpgId()); + + time_t now = time(0); + if (now < nextStartTime) + newTimer.SetState(PVR_TIMER_STATE_SCHEDULED); + else if (nextStartTime <= now && now <= nextEndTime) + newTimer.SetState(PVR_TIMER_STATE_RECORDING); + else + newTimer.SetState(PVR_TIMER_STATE_COMPLETED); + + timers->emplace_back(newTimer); + + genTimerCount++; + + if (genTimerCount >= m_settings.GetNumGenRepeatTimers()) + break; + } + + nextStartTime += ONE_DAY; + nextEndTime += ONE_DAY; + } + + if (genTimerCount >= m_settings.GetNumGenRepeatTimers()) + break; + } + } +} + +std::string Timers::ConvertToAutoTimerTag(std::string tag) +{ + std::regex regex (" "); + std::string replaceWith = "_"; + + return regex_replace(tag, regex, replaceWith); +} + +std::vector Timers::LoadAutoTimers() const +{ + std::vector autoTimers; + + const std::string url = StringUtils::Format("%s%s", m_settings.GetConnectionURL().c_str(), "autotimer"); + + const std::string strXML = WebUtils::GetHttpXML(url); + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(strXML.c_str())) + { + Logger::Log(LEVEL_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return autoTimers; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("autotimer").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_DEBUG, "%s Could not find element!", __FUNCTION__); + return autoTimers; + } + + hRoot=TiXmlHandle(pElem); + + TiXmlElement* pNode = hRoot.FirstChildElement("timer").Element(); + + if (!pNode) + { + Logger::Log(LEVEL_DEBUG, "Could not find element"); + return autoTimers; + } + + for (; pNode != nullptr; pNode = pNode->NextSiblingElement("timer")) + { + AutoTimer newAutoTimer; + + if (!newAutoTimer.UpdateFrom(pNode, m_channels)) + continue; + + autoTimers.emplace_back(newAutoTimer); + + Logger::Log(LEVEL_INFO, "%s fetched AutoTimer entry '%s', begin '%d', end '%d'", __FUNCTION__, newAutoTimer.GetTitle().c_str(), newAutoTimer.GetStartTime(), newAutoTimer.GetEndTime()); + } + + Logger::Log(LEVEL_INFO, "%s fetched %u AutoTimer Entries", __FUNCTION__, autoTimers.size()); + return autoTimers; +} + +bool Timers::CanAutoTimers() const +{ + return m_settings.GetWebIfVersionAsNum() >= m_settings.GenerateWebIfVersionAsNum(1, 3, 0); +} + +bool Timers::IsAutoTimer(const PVR_TIMER &timer) const +{ + return timer.iTimerType == Timer::Type::EPG_AUTO_SEARCH; +} + +void Timers::GetTimerTypes(std::vector &types) const +{ + struct TimerType + : PVR_TIMER_TYPE + { + TimerType(unsigned int id, unsigned int attributes, + const std::string &description = std::string(), + const std::vector> &groupValues + = std::vector>(), + const std::vector> &deDupValues + = std::vector>()) + { + int i; + memset(this, 0, sizeof(PVR_TIMER_TYPE)); + + iId = id; + iAttributes = attributes; + PVR_STRCPY(strDescription, description.c_str()); + + if ((iRecordingGroupSize = groupValues.size())) + iRecordingGroupDefault = groupValues[0].first; + i = 0; + for (auto &group : groupValues) + { + recordingGroup[i].iValue = group.first; + PVR_STRCPY(recordingGroup[i].strDescription, group.second.c_str()); + ++i; + } + + if ((iPreventDuplicateEpisodesSize = deDupValues.size())) + iPreventDuplicateEpisodesDefault = deDupValues[0].first; + i = 0; + for (auto &deDup : deDupValues) + { + preventDuplicateEpisodes[i].iValue = deDup.first; + PVR_STRCPY(preventDuplicateEpisodes[i].strDescription, + deDup.second.c_str()); + ++i; + } + } + }; + + /* PVR_Timer.iRecordingGroup values and presentation.*/ + std::vector> groupValues = { + { 0, LocalizedString(30410) }, //automatic + }; + for (auto &recf : m_locations) + groupValues.emplace_back(groupValues.size(), recf); + + /* One-shot manual (time and channel based) */ + TimerType* t = new TimerType( + Timer::Type::MANUAL_ONCE, + PVR_TIMER_TYPE_IS_MANUAL | + PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | + PVR_TIMER_TYPE_SUPPORTS_CHANNELS | + PVR_TIMER_TYPE_SUPPORTS_START_TIME | + PVR_TIMER_TYPE_SUPPORTS_END_TIME | + PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | + PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, + "", /* Let Kodi generate the description */ + groupValues); + types.emplace_back(*t); + + /* One-shot generated by manual repeating timer - note these are completely read only and cannot be edited */ + types.emplace_back(TimerType( + Timer::Type::READONLY_REPEATING_ONCE, + PVR_TIMER_TYPE_IS_MANUAL | + PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES | + PVR_TIMER_TYPE_IS_READONLY | + PVR_TIMER_TYPE_SUPPORTS_CHANNELS | + PVR_TIMER_TYPE_SUPPORTS_START_TIME | + PVR_TIMER_TYPE_SUPPORTS_END_TIME | + PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | + PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, + LocalizedString(30421), + groupValues)); + types.emplace_back(*t); + + /* Repeating manual (time and channel based) */ + t = new TimerType( + Timer::Type::MANUAL_REPEATING, + PVR_TIMER_TYPE_IS_MANUAL | + PVR_TIMER_TYPE_IS_REPEATING | + PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | + PVR_TIMER_TYPE_SUPPORTS_CHANNELS | + PVR_TIMER_TYPE_SUPPORTS_START_TIME | + PVR_TIMER_TYPE_SUPPORTS_END_TIME | + PVR_TIMER_TYPE_SUPPORTS_WEEKDAYS | + PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | + PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, + "", /* Let Kodi generate the description */ + groupValues); + types.emplace_back(*t); + + /* One-shot epg based */ + t = new TimerType( + Timer::Type::EPG_ONCE, + PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | + PVR_TIMER_TYPE_SUPPORTS_CHANNELS | + PVR_TIMER_TYPE_SUPPORTS_START_TIME | + PVR_TIMER_TYPE_SUPPORTS_END_TIME | + PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | + PVR_TIMER_TYPE_REQUIRES_EPG_TAG_ON_CREATE, + ""); /* Let Kodi generate the description */ + types.emplace_back(*t); + + /* Repeating epg based */ + t = new TimerType( + Timer::Type::EPG_REPEATING, + PVR_TIMER_TYPE_IS_REPEATING | + PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES | + PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | + PVR_TIMER_TYPE_SUPPORTS_CHANNELS | + PVR_TIMER_TYPE_SUPPORTS_START_TIME | + PVR_TIMER_TYPE_SUPPORTS_END_TIME | + PVR_TIMER_TYPE_SUPPORTS_WEEKDAYS | + PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN, + ""); /* Let Kodi generate the description */ + types.emplace_back(*t); + + if (CanAutoTimers() && m_settings.GetAutoTimersEnabled()) + { + /* PVR_Timer.iPreventDuplicateEpisodes values and presentation.*/ + static std::vector> deDupValues = + { + { AutoTimer::DeDup::DISABLED, LocalizedString(30430) }, + { AutoTimer::DeDup::CHECK_TITLE, LocalizedString(30431) }, + { AutoTimer::DeDup::CHECK_TITLE_AND_SHORT_DESC, LocalizedString(30432) }, + { AutoTimer::DeDup::CHECK_TITLE_AND_ALL_DESCS, LocalizedString(30433) }, + }; + + /* epg auto search */ + t = new TimerType( + Timer::Type::EPG_AUTO_SEARCH, + PVR_TIMER_TYPE_IS_REPEATING | + PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | + PVR_TIMER_TYPE_SUPPORTS_CHANNELS | + PVR_TIMER_TYPE_SUPPORTS_ANY_CHANNEL | + PVR_TIMER_TYPE_SUPPORTS_START_TIME | + PVR_TIMER_TYPE_SUPPORTS_END_TIME | + PVR_TIMER_TYPE_SUPPORTS_START_ANYTIME | + PVR_TIMER_TYPE_SUPPORTS_END_ANYTIME | + PVR_TIMER_TYPE_SUPPORTS_WEEKDAYS | + PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | + PVR_TIMER_TYPE_SUPPORTS_TITLE_EPG_MATCH | + PVR_TIMER_TYPE_SUPPORTS_FULLTEXT_EPG_MATCH | + PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP | + PVR_TIMER_TYPE_SUPPORTS_RECORD_ONLY_NEW_EPISODES, + "", /* Let Kodi generate the description */ + groupValues, deDupValues); + types.emplace_back(*t); + types.back().iPreventDuplicateEpisodesDefault = + AutoTimer::DeDup::CHECK_TITLE_AND_ALL_DESCS; + + /* One-shot created by epg auto search */ + types.emplace_back(TimerType( + Timer::Type::EPG_AUTO_ONCE, + PVR_TIMER_TYPE_IS_MANUAL | + PVR_TIMER_TYPE_FORBIDS_NEW_INSTANCES | + PVR_TIMER_TYPE_IS_READONLY | + PVR_TIMER_TYPE_SUPPORTS_ENABLE_DISABLE | + PVR_TIMER_TYPE_SUPPORTS_CHANNELS | + PVR_TIMER_TYPE_SUPPORTS_START_TIME | + PVR_TIMER_TYPE_SUPPORTS_END_TIME | + PVR_TIMER_TYPE_SUPPORTS_START_END_MARGIN | + PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP, + LocalizedString(30420), + groupValues)); + types.emplace_back(*t); + } +} + +int Timers::GetTimerCount() const +{ + return m_timers.size(); +} + +int Timers::GetAutoTimerCount() const +{ + return m_autotimers.size(); +} + +void Timers::GetTimers(std::vector &timers) const +{ + for (const auto& timer : m_timers) + { + Logger::Log(LEVEL_DEBUG, "%s - Transfer timer '%s', ClientIndex '%d'", __FUNCTION__, timer.GetTitle().c_str(), timer.GetClientIndex()); + PVR_TIMER tag; + memset(&tag, 0, sizeof(PVR_TIMER)); + + timer.UpdateTo(tag); + + timers.emplace_back(tag); + } +} + +void Timers::GetAutoTimers(std::vector &timers) const +{ + for (const auto& autoTimer : m_autotimers) + { + Logger::Log(LEVEL_DEBUG, "%s - Transfer timer '%s', ClientIndex '%d'", __FUNCTION__, autoTimer.GetTitle().c_str(), autoTimer.GetClientIndex()); + PVR_TIMER tag; + memset(&tag, 0, sizeof(PVR_TIMER)); + + autoTimer.UpdateTo(tag); + + timers.emplace_back(tag); + } +} + +Timer *Timers::GetTimer(std::function func) +{ + return GetTimer(func, m_timers); +} + +AutoTimer *Timers::GetAutoTimer(std::function func) +{ + return GetTimer(func, m_autotimers); +} + +PVR_ERROR Timers::AddTimer(const PVR_TIMER &timer) +{ + if (IsAutoTimer(timer)) + return AddAutoTimer(timer); + + Logger::Log(LEVEL_DEBUG, "%s - channelUid=%d title=%s epgid=%d", __FUNCTION__, timer.iClientChannelUid, timer.strTitle, timer.iEpgUid); + + std::string tags = TAG_FOR_EPG_TIMER; + if (timer.iTimerType == Timer::MANUAL_ONCE || timer.iTimerType == Timer::MANUAL_REPEATING) + tags = TAG_FOR_MANUAL_TIMER; + + std::string strTmp; + std::string strServiceReference = m_channels.GetChannel(timer.iClientChannelUid)->GetServiceReference().c_str(); + + time_t startTime, endTime; + startTime = timer.startTime - (timer.iMarginStart * 60); + endTime = timer.endTime + (timer.iMarginEnd * 60); + + if (!m_settings.GetRecordingPath().compare("")) + strTmp = StringUtils::Format("web/timeradd?sRef=%s&repeated=%d&begin=%d&end=%d&name=%s&description=%s&eit=%d&tags=%s&dirname=&s", + WebUtils::URLEncodeInline(strServiceReference).c_str(), timer.iWeekdays, startTime, endTime, + WebUtils::URLEncodeInline(timer.strTitle).c_str(), WebUtils::URLEncodeInline(timer.strSummary).c_str(), timer.iEpgUid, + WebUtils::URLEncodeInline(tags).c_str(), WebUtils::URLEncodeInline(m_settings.GetRecordingPath()).c_str()); + else + strTmp = StringUtils::Format("web/timeradd?sRef=%s&repeated=%d&begin=%d&end=%d&name=%s&description=%s&eit=%d&tags=%s", + WebUtils::URLEncodeInline(strServiceReference).c_str(), timer.iWeekdays, startTime, endTime, + WebUtils::URLEncodeInline(timer.strTitle).c_str(), WebUtils::URLEncodeInline(timer.strSummary).c_str(), timer.iEpgUid, + WebUtils::URLEncodeInline(tags).c_str()); + + std::string strResult; + if (!WebUtils::SendSimpleCommand(strTmp, strResult)) + return PVR_ERROR_SERVER_ERROR; + + TimerUpdates(); + + return PVR_ERROR_NO_ERROR; +} + +PVR_ERROR Timers::AddAutoTimer(const PVR_TIMER &timer) +{ + std::string strTmp; + strTmp = StringUtils::Format("autotimer/edit?"); + + strTmp += StringUtils::Format("name=%s", WebUtils::URLEncodeInline(timer.strTitle).c_str()); + strTmp += StringUtils::Format("&match=%s", WebUtils::URLEncodeInline(timer.strEpgSearchString).c_str()); + + if (timer.state != PVR_TIMER_STATE_CANCELLED) + strTmp += StringUtils::Format("&enabled=%s", WebUtils::URLEncodeInline(AUTOTIMER_ENABLED_YES).c_str()); + else + strTmp += StringUtils::Format("&enabled=%s", WebUtils::URLEncodeInline(AUTOTIMER_ENABLED_NO).c_str()); + + + if (!timer.bStartAnyTime) + { + time_t startTime = timer.startTime; + std::tm timeinfo = *std::localtime(&startTime); + strTmp += StringUtils::Format("×panFrom=%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min); + } + + if (!timer.bEndAnyTime) + { + time_t endTime = timer.endTime; + std::tm timeinfo = *std::localtime(&endTime); + strTmp += StringUtils::Format("×panTo=%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min); + } + + strTmp += StringUtils::Format("&encoding=%s", WebUtils::URLEncodeInline(AUTOTIMER_ENCODING).c_str()); + strTmp += StringUtils::Format("&searchCase=%s", WebUtils::URLEncodeInline(AUTOTIMER_SEARCH_CASE_SENSITIVE).c_str()); + if (timer.bFullTextEpgSearch) + strTmp += StringUtils::Format("&searchType=%s", WebUtils::URLEncodeInline(AUTOTIMER_SEARCH_TYPE_DESCRIPTION).c_str()); + else + strTmp += StringUtils::Format("&searchType=%s", WebUtils::URLEncodeInline(AUTOTIMER_SEARCH_TYPE_EXACT).c_str()); + + std::underlying_type::type deDup = static_cast(timer.iPreventDuplicateEpisodes); + if (deDup == AutoTimer::DeDup::DISABLED) + { + strTmp += StringUtils::Format("&avoidDuplicateDescription=0"); + } + else + { + strTmp += StringUtils::Format("&avoidDuplicateDescription=%s", AUTOTIMER_AVOID_DUPLICATE_ANY_SERVICE_OR_RECORDING.c_str()); + switch (deDup) + { + case AutoTimer::DeDup::CHECK_TITLE: + strTmp += StringUtils::Format("&searchForDuplicateDescription=%s", AUTOTIMER_CHECK_SEARCH_FOR_DUP_IN_TITLE.c_str()); + break; + case AutoTimer::DeDup::CHECK_TITLE_AND_SHORT_DESC: + strTmp += StringUtils::Format("&searchForDuplicateDescription=%s", AUTOTIMER_CHECK_SEARCH_FOR_DUP_IN_TITLE_AND_SHORT_DESC.c_str()); + break; + case AutoTimer::DeDup::CHECK_TITLE_AND_ALL_DESCS: + strTmp += StringUtils::Format("&searchForDuplicateDescription=%s", AUTOTIMER_CHECK_SEARCH_FOR_DUP_IN_TITLE_AND_ALL_DESCS.c_str()); + break; + } + } + + if (timer.iClientChannelUid != PVR_TIMER_ANY_CHANNEL) + { + //single channel + strTmp += StringUtils::Format("&services=%s", WebUtils::URLEncodeInline(m_channels.GetChannel(timer.iClientChannelUid)->GetServiceReference()).c_str()); + } + + strTmp += Timers::BuildAddUpdateAutoTimerIncludeParams(timer.iWeekdays); + + std::string strResult; + if (!WebUtils::SendSimpleCommand(strTmp, strResult)) + return PVR_ERROR_SERVER_ERROR; + + if (timer.state == PVR_TIMER_STATE_RECORDING) + PVR->TriggerRecordingUpdate(); + + TimerUpdates(); + + return PVR_ERROR_NO_ERROR; +} + +PVR_ERROR Timers::UpdateTimer(const PVR_TIMER &timer) +{ + if (IsAutoTimer(timer)) + return UpdateAutoTimer(timer); + + Logger::Log(LEVEL_DEBUG, "%s timer channelid '%d'", __FUNCTION__, timer.iClientChannelUid); + + std::string strTmp; + std::string strServiceReference = m_channels.GetChannel(timer.iClientChannelUid)->GetServiceReference().c_str(); + + const auto it = std::find_if(m_timers.cbegin(), m_timers.cend(), [timer](const Timer& myTimer) + { + return myTimer.GetClientIndex() == timer.iClientIndex; + }); + + if (it != m_timers.cend()) + { + Timer oldTimer = *it; + std::string strOldServiceReference = m_channels.GetChannel(oldTimer.GetChannelId())->GetServiceReference().c_str(); + Logger::Log(LEVEL_DEBUG, "%s old timer channelid '%d'", __FUNCTION__, oldTimer.GetChannelId()); + + int iDisabled = 0; + if (timer.state == PVR_TIMER_STATE_CANCELLED) + iDisabled = 1; + + strTmp = StringUtils::Format("web/timerchange?sRef=%s&begin=%d&end=%d&name=%s&eventID=&description=%s&tags=%s&afterevent=3&eit=0&disabled=%d&justplay=0&repeated=%d&channelOld=%s&beginOld=%d&endOld=%d&deleteOldOnSave=1", + WebUtils::URLEncodeInline(strServiceReference).c_str(), timer.startTime, timer.endTime, + WebUtils::URLEncodeInline(timer.strTitle).c_str(), WebUtils::URLEncodeInline(timer.strSummary).c_str(), + WebUtils::URLEncodeInline(oldTimer.GetTags()).c_str(), iDisabled, timer.iWeekdays, + WebUtils::URLEncodeInline(strOldServiceReference).c_str(), oldTimer.GetStartTime(), + oldTimer.GetEndTime()); + + std::string strResult; + if (!WebUtils::SendSimpleCommand(strTmp, strResult)) + return PVR_ERROR_SERVER_ERROR; + + TimerUpdates(); + + return PVR_ERROR_NO_ERROR; + } + + return PVR_ERROR_SERVER_ERROR; +} + +PVR_ERROR Timers::UpdateAutoTimer(const PVR_TIMER &timer) +{ + const auto it = std::find_if(m_autotimers.cbegin(), m_autotimers.cend(), [timer](const AutoTimer& autoTimer) + { + return autoTimer.GetClientIndex() == timer.iClientIndex; + }); + + if (it != m_autotimers.cend()) + { + AutoTimer timerToUpdate = *it; + + std::string strTmp = StringUtils::Format("autotimer/edit?id=%d", timerToUpdate.GetBackendId()); + + strTmp += StringUtils::Format("&name=%s", WebUtils::URLEncodeInline(timer.strTitle).c_str()); + strTmp += StringUtils::Format("&match=%s", WebUtils::URLEncodeInline(timer.strEpgSearchString).c_str()); + + if (timer.state != PVR_TIMER_STATE_CANCELLED) + strTmp += StringUtils::Format("&enabled=%s", WebUtils::URLEncodeInline(AUTOTIMER_ENABLED_YES).c_str()); + else + strTmp += StringUtils::Format("&enabled=%s", WebUtils::URLEncodeInline(AUTOTIMER_ENABLED_NO).c_str()); + + + if (!timer.bStartAnyTime) + { + time_t startTime = timer.startTime; + std::tm timeinfo = *std::localtime(&startTime); + strTmp += StringUtils::Format("×panFrom=%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min); + } + + if (!timer.bEndAnyTime) + { + time_t endTime = timer.endTime; + std::tm timeinfo = *std::localtime(&endTime); + strTmp += StringUtils::Format("×panTo=%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min); + } + + strTmp += StringUtils::Format("&encoding=%s", WebUtils::URLEncodeInline(AUTOTIMER_ENCODING).c_str()); + + if (timer.bFullTextEpgSearch) + strTmp += StringUtils::Format("&searchType=%s", WebUtils::URLEncodeInline(AUTOTIMER_SEARCH_TYPE_DESCRIPTION).c_str()); + else + strTmp += StringUtils::Format("&searchType=%s", WebUtils::URLEncodeInline(AUTOTIMER_SEARCH_TYPE_EXACT).c_str()); + + if (!timerToUpdate.GetSearchCase().empty()) + strTmp += StringUtils::Format("&searchCase=%s", WebUtils::URLEncodeInline(AUTOTIMER_SEARCH_CASE_SENSITIVE).c_str()); + + std::underlying_type::type deDup = static_cast(timer.iPreventDuplicateEpisodes); + if (deDup == AutoTimer::DeDup::DISABLED) + { + strTmp += StringUtils::Format("&avoidDuplicateDescription=0"); + } + else + { + strTmp += StringUtils::Format("&avoidDuplicateDescription=%s", AUTOTIMER_AVOID_DUPLICATE_ANY_SERVICE_OR_RECORDING.c_str()); + switch (deDup) + { + case AutoTimer::DeDup::CHECK_TITLE: + strTmp += StringUtils::Format("&searchForDuplicateDescription=%s", AUTOTIMER_CHECK_SEARCH_FOR_DUP_IN_TITLE.c_str()); + break; + case AutoTimer::DeDup::CHECK_TITLE_AND_SHORT_DESC: + strTmp += StringUtils::Format("&searchForDuplicateDescription=%s", AUTOTIMER_CHECK_SEARCH_FOR_DUP_IN_TITLE_AND_SHORT_DESC.c_str()); + break; + case AutoTimer::DeDup::CHECK_TITLE_AND_ALL_DESCS: + strTmp += StringUtils::Format("&searchForDuplicateDescription=%s", AUTOTIMER_CHECK_SEARCH_FOR_DUP_IN_TITLE_AND_ALL_DESCS.c_str()); + break; + } + } + + if (timerToUpdate.GetAnyChannel() && timer.iClientChannelUid != PVR_TIMER_ANY_CHANNEL) + { + //move to single channel + strTmp += StringUtils::Format("&services=%s", WebUtils::URLEncodeInline(m_channels.GetChannel(timer.iClientChannelUid)->GetServiceReference()).c_str()); + } + else if (!timerToUpdate.GetAnyChannel() && timer.iClientChannelUid == PVR_TIMER_ANY_CHANNEL) + { + //Move to any channel + strTmp += StringUtils::Format("&services="); + } + + strTmp += Timers::BuildAddUpdateAutoTimerIncludeParams(timer.iWeekdays); + + std::string strResult; + if (!WebUtils::SendSimpleCommand(strTmp, strResult)) + return PVR_ERROR_SERVER_ERROR; + + if (timer.state == PVR_TIMER_STATE_RECORDING) + PVR->TriggerRecordingUpdate(); + + TimerUpdates(); + + return PVR_ERROR_NO_ERROR; + } + return PVR_ERROR_SERVER_ERROR; +} + +std::string Timers::BuildAddUpdateAutoTimerIncludeParams(int weekdays) +{ + bool everyday = true; + std::string includeParams; + if (weekdays != PVR_WEEKDAY_NONE) + { + for (int i = 0; i < DAYS_IN_WEEK; i++) + { + if (1 & (weekdays >> i)) + { + includeParams += StringUtils::Format("&dayofweek=%d", i); + } + else + { + everyday = false; + } + } + + if (everyday) + includeParams = "&dayofweek="; + } + else + { + includeParams = "&dayofweek="; + } + + return includeParams; +} + +PVR_ERROR Timers::DeleteTimer(const PVR_TIMER &timer) +{ + if (IsAutoTimer(timer)) + return DeleteAutoTimer(timer); + + std::string strTmp; + std::string strServiceReference = m_channels.GetChannel(timer.iClientChannelUid)->GetServiceReference().c_str(); + + time_t startTime, endTime; + startTime = timer.startTime - (timer.iMarginStart * 60); + endTime = timer.endTime + (timer.iMarginEnd * 60); + + strTmp = StringUtils::Format("web/timerdelete?sRef=%s&begin=%d&end=%d", WebUtils::URLEncodeInline(strServiceReference).c_str(), startTime, endTime); + + std::string strResult; + if (!WebUtils::SendSimpleCommand(strTmp, strResult)) + return PVR_ERROR_SERVER_ERROR; + + if (timer.state == PVR_TIMER_STATE_RECORDING) + PVR->TriggerRecordingUpdate(); + + TimerUpdates(); + + return PVR_ERROR_NO_ERROR; +} + +PVR_ERROR Timers::DeleteAutoTimer(const PVR_TIMER &timer) +{ + const auto it = std::find_if(m_autotimers.cbegin(), m_autotimers.cend(), [timer](const AutoTimer& autoTimer) + { + return autoTimer.GetClientIndex() == timer.iClientIndex; + }); + + if (it != m_autotimers.cend()) + { + AutoTimer timerToDelete = *it; + + std::string strTmp; + strTmp = StringUtils::Format("autotimer/remove?id=%u", timerToDelete.GetBackendId()); + + std::string strResult; + if (!WebUtils::SendSimpleCommand(strTmp, strResult)) + return PVR_ERROR_SERVER_ERROR; + + if (timer.state == PVR_TIMER_STATE_RECORDING) + PVR->TriggerRecordingUpdate(); + + TimerUpdates(); + + return PVR_ERROR_NO_ERROR; + } + + return PVR_ERROR_SERVER_ERROR; +} + +void Timers::ClearTimers() +{ + m_timers.clear(); + m_autotimers.clear(); + m_timerChangeWatchers.clear(); +} + +void Timers::AddTimerChangeWatcher(std::atomic_bool* watcher) +{ + m_timerChangeWatchers.emplace_back(watcher); +} + +bool Timers::TimerUpdates() +{ + bool regularTimersChanged = TimerUpdatesRegular(); + bool autoTimersChanged = false; + + if (CanAutoTimers() && m_settings.GetAutoTimersEnabled()) + autoTimersChanged = TimerUpdatesAuto(); + + if (regularTimersChanged || autoTimersChanged) + { + Logger::Log(LEVEL_INFO, "%s Changes in timerlist detected, trigger an update!", __FUNCTION__); + PVR->TriggerTimerUpdate(); + + for (auto watcher : m_timerChangeWatchers) + watcher->store(true); + + return true; + } + + return false; +} + +bool Timers::TimerUpdatesRegular() +{ + std::vector newtimers = LoadTimers(); + + for (auto& timer : m_timers) + { + timer.SetUpdateState(UPDATE_STATE_NONE); + } + + //Update any timers + unsigned int iUpdated=0; + unsigned int iUnchanged=0; + + for (auto& newTimer : newtimers) + { + for (auto& existingTimer : m_timers) + { + if (existingTimer.Like(newTimer)) + { + if(existingTimer == newTimer) + { + existingTimer.SetUpdateState(UPDATE_STATE_FOUND); + newTimer.SetUpdateState(UPDATE_STATE_FOUND); + iUnchanged++; + } + else + { + newTimer.SetUpdateState(UPDATE_STATE_UPDATED); + existingTimer.SetUpdateState(UPDATE_STATE_UPDATED); + + existingTimer.UpdateFrom(newTimer); + + iUpdated++; + } + } + } + } + + //Remove any timers that are no longer valid + unsigned int iRemoved = m_timers.size(); + + m_timers.erase( + std::remove_if(m_timers.begin(), m_timers.end(), + [](const Timer& timer) { return timer.GetUpdateState() == UPDATE_STATE_NONE; }), + m_timers.end()); + + iRemoved -= m_timers.size(); + + //Add any new autotimers + unsigned int iNew=0; + + for (auto& newTimer : newtimers) + { + if(newTimer.GetUpdateState() == UPDATE_STATE_NEW) + { + newTimer.SetClientIndex(m_clientIndexCounter); + Logger::Log(LEVEL_INFO, "%s New timer: '%s', ClientIndex: '%d'", __FUNCTION__, newTimer.GetTitle().c_str(), m_clientIndexCounter); + m_timers.emplace_back(newTimer); + m_clientIndexCounter++; + iNew++; + } + } + + //Link any Readonly timers to Repeating Timers + for (const auto& repeatingTimer : m_timers) + { + for (auto& readonlyRepeatingOnceTimer : m_timers) + { + if ((repeatingTimer.GetType() == Timer::MANUAL_REPEATING || repeatingTimer.GetType() == Timer::EPG_REPEATING) && + readonlyRepeatingOnceTimer.GetType() == Timer::READONLY_REPEATING_ONCE && readonlyRepeatingOnceTimer.isChildOfParent(repeatingTimer)) + { + readonlyRepeatingOnceTimer.SetParentClientIndex(repeatingTimer.GetClientIndex()); + continue; + } + } + } + + Logger::Log(LEVEL_INFO , "%s No of timers: removed [%d], untouched [%d], updated '%d', new '%d'", __FUNCTION__, iRemoved, iUnchanged, iUpdated, iNew); + + return (iRemoved != 0 || iUpdated != 0 || iNew != 0); +} + +bool Timers::TimerUpdatesAuto() +{ + std::vector newautotimers = LoadAutoTimers(); + + for (auto& autoTimer : m_autotimers) + { + autoTimer.SetUpdateState(UPDATE_STATE_NONE); + } + + //Update any autotimers + unsigned int iUpdated=0; + unsigned int iUnchanged=0; + + for (auto& newAutoTimer : newautotimers) + { + for (auto& existingAutoTimer : m_autotimers) + { + if (existingAutoTimer.Like(newAutoTimer)) + { + if(existingAutoTimer == newAutoTimer) + { + existingAutoTimer.SetUpdateState(UPDATE_STATE_FOUND); + newAutoTimer.SetUpdateState(UPDATE_STATE_FOUND); + iUnchanged++; + } + else + { + newAutoTimer.SetUpdateState(UPDATE_STATE_UPDATED); + existingAutoTimer.SetUpdateState(UPDATE_STATE_UPDATED); + + existingAutoTimer.UpdateFrom(newAutoTimer); + + iUpdated++; + } + } + } + } + + //Remove any autotimers that are no longer valid + unsigned int iRemoved = m_autotimers.size(); + + m_autotimers.erase( + std::remove_if(m_autotimers.begin(), m_autotimers.end(), + [](const AutoTimer& autoTimer) { return autoTimer.GetUpdateState() == UPDATE_STATE_NONE; }), + m_autotimers.end()); + + iRemoved -= m_autotimers.size(); + + //Add any new autotimers + unsigned int iNew=0; + + for (auto& newAutoTimer : newautotimers) + { + if(newAutoTimer.GetUpdateState() == UPDATE_STATE_NEW) + { + newAutoTimer.SetClientIndex(m_clientIndexCounter); + + if ((newAutoTimer.GetChannelId()) == PVR_TIMER_ANY_CHANNEL) + newAutoTimer.SetAnyChannel(true); + Logger::Log(LEVEL_INFO, "%s New auto timer: '%s', ClientIndex: '%d'", __FUNCTION__, newAutoTimer.GetTitle().c_str(), m_clientIndexCounter); + m_autotimers.emplace_back(newAutoTimer); + m_clientIndexCounter++; + iNew++; + } + } + + //Link Any child timers to autotimers + for (const auto& autoTimer : m_autotimers) + { + for (auto& timer : m_timers) + { + std::string autotimerTag = ConvertToAutoTimerTag(autoTimer.GetTitle()); + + if (timer.GetType() == Timer::EPG_AUTO_ONCE && timer.ContainsTag(TAG_FOR_AUTOTIMER) + && timer.ContainsTag(autotimerTag)) + { + timer.SetParentClientIndex(autoTimer.GetClientIndex()); + continue; + } + } + } + + Logger::Log(LEVEL_INFO, "%s No of autotimers: removed [%d], untouched [%d], updated '%d', new '%d'", __FUNCTION__, iRemoved, iUnchanged, iUpdated, iNew); + + return (iRemoved != 0 || iUpdated != 0 || iNew != 0); +} + +void Timers::RunAutoTimerListCleanup() +{ + std::string strTmp = StringUtils::Format("web/timercleanup?cleanup=true"); + std::string strResult; + if(!WebUtils::SendSimpleCommand(strTmp, strResult)) + Logger::Log(LEVEL_ERROR, "%s - AutomaticTimerlistCleanup failed!", __FUNCTION__); +} diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/Timers.h kodi-pvr-vuplus-3.15.0/src/enigma2/Timers.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/Timers.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/Timers.h 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,80 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "data/Timer.h" +#include "data/AutoTimer.h" + +#include "libXBMC_pvr.h" +#include "tinyxml.h" + +namespace enigma2 +{ + class Timers + { + public: + Timers(Channels &channels, std::vector &locations) + : m_channels(channels), m_locations(locations) + { + m_clientIndexCounter = 1; + }; + + void GetTimerTypes(std::vector &types) const; + + int GetTimerCount() const; + int GetAutoTimerCount() const; + + void GetTimers(std::vector &timers) const; + void GetAutoTimers(std::vector &timers) const; + + enigma2::data::Timer *GetTimer(std::function func); + enigma2::data::AutoTimer *GetAutoTimer(std::function func); + + PVR_ERROR AddTimer(const PVR_TIMER &timer); + PVR_ERROR AddAutoTimer(const PVR_TIMER &timer); + + PVR_ERROR UpdateTimer(const PVR_TIMER &timer); + PVR_ERROR UpdateAutoTimer(const PVR_TIMER &timer); + + PVR_ERROR DeleteTimer(const PVR_TIMER &timer); + PVR_ERROR DeleteAutoTimer(const PVR_TIMER &timer); + + void ClearTimers(); + bool TimerUpdates(); + void RunAutoTimerListCleanup(); + void AddTimerChangeWatcher(std::atomic_bool* watcher); + + private: + //templates + template + T *GetTimer(std::function func, + std::vector &timerlist); + + // functions + std::vector LoadTimers() const; + void GenerateChildManualRepeatingTimers(std::vector *timers, enigma2::data::Timer *timer) const; + static std::string ConvertToAutoTimerTag(std::string tag); + std::vector LoadAutoTimers() const; + bool CanAutoTimers() const; + bool IsAutoTimer(const PVR_TIMER &timer) const; + bool TimerUpdatesRegular(); + bool TimerUpdatesAuto(); + static std::string BuildAddUpdateAutoTimerIncludeParams(int weekdays); + + // members + unsigned int m_clientIndexCounter; + std::vector m_timerChangeWatchers; + + enigma2::Settings &m_settings = enigma2::Settings::GetInstance(); + std::vector m_timers; + std::vector m_autotimers; + + Channels &m_channels; + std::vector &m_locations; + }; +} // namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/TimeshiftBuffer.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/TimeshiftBuffer.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/TimeshiftBuffer.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/TimeshiftBuffer.cpp 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,142 @@ +#include "TimeshiftBuffer.h" + +#include "../client.h" +#include "StreamReader.h" +#include "utilities/Logger.h" + +#include "p8-platform/util/util.h" + +using namespace ADDON; +using namespace enigma2; +using namespace enigma2::utilities; + +TimeshiftBuffer::TimeshiftBuffer(IStreamReader *m_streamReader, + const std::string &m_timeshiftBufferPath, const unsigned int m_readTimeoutX) + : m_streamReader(m_streamReader) +{ + m_bufferPath = m_timeshiftBufferPath + "/tsbuffer.ts"; + m_readTimeout = (m_readTimeoutX) ? m_readTimeout + : DEFAULT_READ_TIMEOUT; + + m_filebufferWriteHandle = XBMC->OpenFileForWrite(m_bufferPath.c_str(), true); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + m_filebufferReadHandle = XBMC->OpenFile(m_bufferPath.c_str(), XFILE::READ_NO_CACHE); +} + +TimeshiftBuffer::~TimeshiftBuffer(void) +{ + m_running = false; + if (m_inputThread.joinable()) + m_inputThread.join(); + + if (m_filebufferWriteHandle) + { + // XBMC->TruncateFile doesn't work for unknown reasons + XBMC->CloseFile(m_filebufferWriteHandle); + void *tmp; + if ((tmp = XBMC->OpenFileForWrite(m_bufferPath.c_str(), true)) != nullptr) + XBMC->CloseFile(tmp); + } + if (m_filebufferReadHandle) + XBMC->CloseFile(m_filebufferReadHandle); + + if (!XBMC->DeleteFile(m_bufferPath.c_str())) + Logger::Log(LEVEL_ERROR, "%s Unable to delete file when timeshift buffer is deleted: %s", __FUNCTION__, m_bufferPath.c_str()); + + SAFE_DELETE(m_streamReader); + Logger::Log(LEVEL_DEBUG, "Timeshift: Stopped"); +} + +bool TimeshiftBuffer::Start() +{ + if (m_streamReader == nullptr + || m_filebufferWriteHandle == nullptr + || m_filebufferReadHandle == nullptr) + return false; + if (m_running) + return true; + + Logger::Log(LEVEL_INFO, "Timeshift: Started"); + m_start = time(nullptr); + m_running = true; + m_inputThread = std::thread([&] { DoReadWrite(); }); + + return true; +} + +void TimeshiftBuffer::DoReadWrite() +{ + Logger::Log(LEVEL_DEBUG, "Timeshift: Thread started"); + uint8_t buffer[BUFFER_SIZE]; + + m_streamReader->Start(); + while (m_running) + { + ssize_t read = m_streamReader->ReadData(buffer, sizeof(buffer)); + + // don't handle any errors here, assume write fully succeeds + ssize_t write = XBMC->WriteFile(m_filebufferWriteHandle, buffer, read); + + std::lock_guard lock(m_mutex); + m_writePos += write; + + m_condition.notify_one(); + } + Logger::Log(LEVEL_DEBUG, "Timeshift: Thread stopped"); + return; +} + +int64_t TimeshiftBuffer::Seek(long long position, int whence) +{ + return XBMC->SeekFile(m_filebufferReadHandle, position, whence); +} + +int64_t TimeshiftBuffer::Position() +{ + return XBMC->GetFilePosition(m_filebufferReadHandle); +} + +int64_t TimeshiftBuffer::Length() +{ + return m_writePos; +} + +ssize_t TimeshiftBuffer::ReadData(unsigned char *buffer, unsigned int size) +{ + int64_t requiredLength = Position() + size; + + /* make sure we never read above the current write position */ + std::unique_lock lock(m_mutex); + bool available = m_condition.wait_for(lock, std::chrono::seconds(m_readTimeout), + [&] { return Length() >= requiredLength; }); + + if (!available) + { + Logger::Log(LEVEL_DEBUG, "Timeshift: Read timed out; waited %d", m_readTimeout); + return -1; + } + + return XBMC->ReadFile(m_filebufferReadHandle, buffer, size); +} + +std::time_t TimeshiftBuffer::TimeStart() +{ + return m_start; +} + +std::time_t TimeshiftBuffer::TimeEnd() +{ + return std::time(nullptr); +} + +bool TimeshiftBuffer::IsRealTime() +{ + // other PVRs use 10 seconds here, but we aren't doing any demuxing + // we'll therefore just asume 1 secs needs about 1mb + return Length() - Position() <= 10 * 1048576; +} + +bool TimeshiftBuffer::IsTimeshifting() +{ + return true; +} diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/TimeshiftBuffer.h kodi-pvr-vuplus-3.15.0/src/enigma2/TimeshiftBuffer.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/TimeshiftBuffer.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/TimeshiftBuffer.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,50 @@ +#pragma once + +#include "IStreamReader.h" + +#include +#include +#include +#include + +namespace enigma2 +{ + class TimeshiftBuffer + : public IStreamReader + { + public: + TimeshiftBuffer(IStreamReader *strReader, + const std::string &m_timeshiftBufferPath, const unsigned int m_readTimeoutX); + ~TimeshiftBuffer(void); + + bool Start() override; + ssize_t ReadData(unsigned char *buffer, unsigned int size) override; + int64_t Seek(long long position, int whence) override; + int64_t Position() override; + int64_t Length() override; + std::time_t TimeStart() override; + std::time_t TimeEnd() override; + bool IsRealTime() override; + bool IsTimeshifting() override; + + private: + void DoReadWrite(); + + static const int BUFFER_SIZE = 32 * 1024; + static const int DEFAULT_READ_TIMEOUT = 10; + static const int READ_WAITTIME = 50; + + std::string m_bufferPath; + IStreamReader *m_streamReader; + void *m_filebufferReadHandle; + void *m_filebufferWriteHandle; + int m_readTimeout; + std::time_t m_start = 0; + std::atomic m_writePos = { 0 }; + + std::atomic m_running = { false }; + std::thread m_inputThread; + std::condition_variable m_condition; + std::mutex m_mutex; + }; +} // namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/CurlFile.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/CurlFile.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/CurlFile.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/CurlFile.cpp 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2005-2015 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "CurlFile.h" + +#include + +#include "Logger.h" + +using namespace enigma2::utilities; + +bool CurlFile::Get(const std::string &strURL, std::string &strResult) +{ + void* fileHandle = XBMC->OpenFile(strURL.c_str(), 0); + if (fileHandle) + { + char buffer[1024]; + while (XBMC->ReadFileString(fileHandle, buffer, 1024)) + strResult.append(buffer); + XBMC->CloseFile(fileHandle); + return true; + } + return false; +} + +bool CurlFile::Post(const std::string &strURL, std::string &strResult) +{ + void *fileHandle = XBMC->CURLCreate(strURL.c_str()); + + if (!fileHandle) + { + Logger::Log(LEVEL_DEBUG, "%s Unable to create curl handle for %s", __FUNCTION__, strURL.c_str()); + return false; + } + + XBMC->CURLAddOption(fileHandle, XFILE::CURL_OPTION_PROTOCOL, "postdata", "POST"); + + if (!XBMC->CURLOpen(fileHandle, XFILE::READ_NO_CACHE)) + { + Logger::Log(LEVEL_DEBUG, "%s Unable to open url: %s", __FUNCTION__, strURL.c_str()); + XBMC->CloseFile(fileHandle); + return false; + } + + char buffer[1024]; + while (XBMC->ReadFileString(fileHandle, buffer, 1024)) + strResult.append(buffer); + XBMC->CloseFile(fileHandle); + + if (!strResult.empty()) + return true; + + return false; +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/CurlFile.h kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/CurlFile.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/CurlFile.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/CurlFile.h 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,42 @@ +#pragma once + +/* + * Copyright (C) 2005-2015 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include + +#include "../../client.h" + +namespace enigma2 +{ + namespace utilities + { + class CurlFile + { + public: + CurlFile(void) {}; + ~CurlFile(void) {}; + + bool Get(const std::string &strURL, std::string &strResult); + bool Post(const std::string &strURL, std::string &strResult); + }; + } +} diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/DeviceInfo.h kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/DeviceInfo.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/DeviceInfo.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/DeviceInfo.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,32 @@ +#pragma once + +#include + +namespace enigma2 +{ + namespace utilities + { + class DeviceInfo + { + public: + DeviceInfo() = default; + DeviceInfo(const std::string &serverName, const std::string &enigmaVersion, const std::string &imageVersion, + const std::string &webIfVersion, unsigned int webIfVersionAsNum) + : m_serverName(serverName), m_enigmaVersion(enigmaVersion), m_imageVersion(imageVersion), + m_webIfVersion(webIfVersion), m_webIfVersionAsNum(webIfVersionAsNum) {}; + + const std::string& GetServerName() const { return m_serverName; } + const std::string& GetEnigmaVersion() const { return m_enigmaVersion; } + const std::string& GetImageVersion() const { return m_imageVersion; } + const std::string& GetWebIfVersion() const { return m_webIfVersion; } + unsigned int GetWebIfVersionAsNum() const { return m_webIfVersionAsNum; } + + private: + std::string m_serverName = "Enigma2"; + std::string m_enigmaVersion; + std::string m_imageVersion; + std::string m_webIfVersion; + unsigned int m_webIfVersionAsNum; + }; + } //namespace utilities +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/DeviceSettings.h kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/DeviceSettings.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/DeviceSettings.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/DeviceSettings.h 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,33 @@ +#pragma once + +#include + +namespace enigma2 +{ + namespace utilities + { + class DeviceSettings + { + public: + DeviceSettings() = default; + + bool IsAddTagAutoTimerToTagsEnabled() const { return m_addTagAutoTimerToTagsEnabled; } + void SetAddTagAutoTimerToTagsEnabled(bool value) { m_addTagAutoTimerToTagsEnabled = value; } + + bool IsAddAutoTimerNameToTagsEnabled() const { return m_addAutoTimerNameToTagsEnabled; } + void SetAddAutoTimerNameToTagsEnabled(bool value) { m_addAutoTimerNameToTagsEnabled = value; } + + int GetGlobalRecordingStartMargin() const { return m_globalRecrordingStartMargin; } + void SetGlobalRecordingStartMargin(int value) { m_globalRecrordingStartMargin = value; } + + int GetGlobalRecordingEndMargin() const { return m_globalRecrordingEndMargin; } + void SetGlobalRecordingEndMargin(int value) { m_globalRecrordingEndMargin = value; } + + private: + bool m_addTagAutoTimerToTagsEnabled = false; + bool m_addAutoTimerNameToTagsEnabled = false; + int m_globalRecrordingStartMargin = 0; + int m_globalRecrordingEndMargin = 0; + }; + } //namespace utilities +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/FileUtils.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/FileUtils.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/FileUtils.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/FileUtils.cpp 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2005-2015 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "FileUtils.h" + +#include "Logger.h" +#include "../../client.h" + +#include + +using namespace enigma2; +using namespace enigma2::utilities; + +bool FileUtils::FileExists(const std::string &file) +{ + return XBMC->FileExists(file.c_str(), false); +} + +bool FileUtils::CopyFile(const std::string &sourceFile, const std::string &targetFile) +{ + bool copySuccessful = true; + + Logger::Log(LEVEL_DEBUG, "%s Copying file: %s, to $s", __FUNCTION__, sourceFile.c_str(), targetFile.c_str()); + + void* sourceFileHandle = XBMC->OpenFile(sourceFile.c_str(), 0x08); //READ_NO_CACHE + + if (sourceFileHandle) + { + std::string fileContents = ReadFileContents(sourceFileHandle); + + XBMC->CloseFile(sourceFileHandle); + + void* targetFileHandle = XBMC->OpenFileForWrite(targetFile.c_str(), true); + + if (targetFileHandle) + { + XBMC->WriteFile(targetFileHandle, fileContents.c_str(), fileContents.length()); + XBMC->CloseFile(targetFileHandle); + } + else + { + Logger::Log(LEVEL_ERROR, "%s Could not open target file to copy to: %s", __FUNCTION__, targetFile.c_str()); + copySuccessful = false; + } + } + else + { + Logger::Log(LEVEL_ERROR, "%s Could not open source file to copy: %s", __FUNCTION__, sourceFile.c_str()); + copySuccessful = false; + } + + return copySuccessful; +} + +bool FileUtils::WriteStringToFile(const std::string &fileContents, const std::string &targetFile) +{ + bool writeSuccessful = true; + + Logger::Log(LEVEL_DEBUG, "%s Writing strig to file: %s", __FUNCTION__, targetFile.c_str()); + + void* targetFileHandle = XBMC->OpenFileForWrite(targetFile.c_str(), true); + + if (targetFileHandle) + { + XBMC->WriteFile(targetFileHandle, fileContents.c_str(), fileContents.length()); + XBMC->CloseFile(targetFileHandle); + } + else + { + Logger::Log(LEVEL_ERROR, "%s Could not open target file to write to: %s", __FUNCTION__, targetFile.c_str()); + writeSuccessful = false; + } + + return writeSuccessful; +} + +std::string FileUtils::ReadXmlFileToString(const std::string &sourceFile) +{ + return ReadFileToString(sourceFile) + "\n"; +} + +std::string FileUtils::ReadFileToString(const std::string &sourceFile) +{ + std::string fileContents; + + Logger::Log(LEVEL_DEBUG, "%s Reading file to string: %s", __FUNCTION__, sourceFile.c_str()); + + void* sourceFileHandle = XBMC->OpenFile(sourceFile.c_str(), 0x08); //READ_NO_CACHE + + if (sourceFileHandle) + { + fileContents = ReadFileContents(sourceFileHandle); + + XBMC->CloseFile(sourceFileHandle); + } + else + { + Logger::Log(LEVEL_ERROR, "%s Could not open source file to read: %s", __FUNCTION__, sourceFile.c_str()); + } + + return fileContents; +} + +std::string FileUtils::ReadFileContents(void *fileHandle) +{ + std::string fileContents; + + char buffer[1024]; + int bytesRead = 0; + + // Read until EOF or explicit error + while ((bytesRead = XBMC->ReadFile(fileHandle, buffer, sizeof(buffer) - 1)) > 0) + fileContents.append(buffer, bytesRead); + + return fileContents; +} + +bool FileUtils::CopyDirectory(const std::string &sourceDir, const std::string &targetDir, bool recursiveCopy) +{ + bool copySuccessful = true; + + XBMC->CreateDirectory(targetDir.c_str()); + + VFSDirEntry* entries; + unsigned int numEntries; + + if (XBMC->GetDirectory(sourceDir.c_str(), "", &entries, &numEntries)) + { + for (int i = 0; i < numEntries; i++) + { + if (entries[i].folder && recursiveCopy) + { + copySuccessful = CopyDirectory(sourceDir + "/" + entries[i].label, targetDir + "/" + entries[i].label, true); + } + else if (!entries[i].folder) + { + copySuccessful = CopyFile(sourceDir + "/" + entries[i].label, targetDir + "/" + entries[i].label); + } + } + + XBMC->FreeDirectory(entries, numEntries); + } + else + { + Logger::Log(LEVEL_ERROR, "%s Could not copy directory: %s, to directory: %s", __FUNCTION__, sourceDir.c_str(), targetDir.c_str()); + copySuccessful = false; + } + return copySuccessful; +} + +std::vector FileUtils::GetFilesInDirectory(const std::string &dir) +{ + std::vector files; + + VFSDirEntry* entries; + unsigned int numEntries; + + if (XBMC->GetDirectory(dir.c_str(), "", &entries, &numEntries)) + { + for (int i = 0; i < numEntries; i++) + { + if (!entries[i].folder) + { + files.emplace_back(entries[i].label); + } + } + + XBMC->FreeDirectory(entries, numEntries); + } + else + { + Logger::Log(LEVEL_ERROR, "%s Could not get files in directory: %s", __FUNCTION__, dir.c_str()); + } + + return files; +} + +std::string FileUtils::GetResourceDataPath() +{ + char path[1024]; + XBMC->GetSetting("__addonpath__", path); + std::string resourcesDataPath = path; + resourcesDataPath += "/resources/data"; + + return resourcesDataPath; +} diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/FileUtils.h kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/FileUtils.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/FileUtils.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/FileUtils.h 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,48 @@ +#pragma once + +/* + * Copyright (C) 2005-2015 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include + +namespace enigma2 +{ + namespace utilities + { + class FileUtils + { + public: + + static bool FileExists(const std::string &file); + static bool CopyFile(const std::string &sourceFile, const std::string &targetFile); + static bool WriteStringToFile(const std::string &fileContents, const std::string &targetFile); + static std::string ReadFileToString(const std::string &sourceFile); + static std::string ReadXmlFileToString(const std::string &sourceFile); + static bool CopyDirectory(const std::string &sourceDir, const std::string &targetDir, bool recursiveCopy); + static std::vector GetFilesInDirectory(const std::string &dir); + static std::string GetResourceDataPath(); + + private: + static std::string ReadFileContents(void *fileHandle); + }; + } +} diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/LocalizedString.h kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/LocalizedString.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/LocalizedString.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/LocalizedString.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,53 @@ +#pragma once + +#include "../../client.h" + +#include + +namespace enigma2 +{ + class LocalizedString + { + public: + explicit LocalizedString(int id) + { + Load(id); + } + + bool Load(int id) + { + char *str; + if ((str = XBMC->GetLocalizedString(id))) + { + m_localizedString = str; + XBMC->FreeString(str); + return true; + } + + m_localizedString = ""; + return false; + } + + std::string Get() + { + return m_localizedString; + } + + operator std::string() + { + return Get(); + } + + const char* c_str() + { + return m_localizedString.c_str(); + } + + private: + LocalizedString() = delete; + LocalizedString(const LocalizedString&) = delete; + LocalizedString &operator =(const LocalizedString&) = delete; + + std::string m_localizedString; + }; +} //namespace enigma2 diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/Logger.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/Logger.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/Logger.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/Logger.cpp 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2005-2015 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "Logger.h" + +#include + +using namespace enigma2::utilities; + +Logger::Logger() +{ + // Use an empty implementation by default + SetImplementation([](LogLevel level, const char *message) + { + + }); +} + +Logger &Logger::GetInstance() +{ + static Logger instance; + return instance; +} + +void Logger::Log(LogLevel level, const char *message, ...) +{ + auto &logger = GetInstance(); + + char buffer[MESSAGE_BUFFER_SIZE]; + std::string logMessage = message; + std::string prefix = logger.m_prefix; + + // Prepend the prefix when set + if (!prefix.empty()) + logMessage = prefix + " - " + message; + + va_list arguments; + va_start(arguments, message); + vsprintf(buffer, logMessage.c_str(), arguments); + va_end(arguments); + + logger.m_implementation(level, buffer); +} + +void Logger::SetImplementation(LoggerImplementation implementation) +{ + m_implementation = implementation; +} + +void Logger::SetPrefix(const std::string &prefix) +{ + m_prefix = prefix; +} diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/Logger.h kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/Logger.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/Logger.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/Logger.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,100 @@ +#pragma once + +/* + * Copyright (C) 2005-2015 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include + +namespace enigma2 +{ + namespace utilities + { + /** + * Represents the log level + */ + enum LogLevel + { + LEVEL_ERROR, + LEVEL_INFO, + LEVEL_NOTICE, + LEVEL_DEBUG, + LEVEL_TRACE + }; + + /** + * Short-hand for a function that acts as the logger implementation + */ + typedef std::function LoggerImplementation; + + /** + * The logger class. It is a singleton that by default comes with no + * underlying implementation. It is up to the user to supply a suitable + * implementation as a lambda using SetImplementation(). + */ + class Logger + { + public: + + /** + * Returns the singleton instance + * @return + */ + static Logger &GetInstance(); + + /** + * Logs the specified message using the specified log level + * @param level the log level + * @param message the log message + * @param ... parameters for the log message + */ + static void Log(LogLevel level, const char *message, ...); + + /** + * Configures the logger to use the specified implementation + * @param implementation lambda + */ + void SetImplementation(LoggerImplementation implementation); + + /** + * Sets the prefix to use in log messages + * @param prefix + */ + void SetPrefix(const std::string &prefix); + + private: + static const unsigned int MESSAGE_BUFFER_SIZE = 16384; + + Logger(); + + /** + * The logger implementation + */ + LoggerImplementation m_implementation; + + /** + * The log message prefix + */ + std::string m_prefix; + + }; + } +} diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/UpdateState.h kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/UpdateState.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/UpdateState.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/UpdateState.h 2018-11-05 17:50:27.000000000 +0000 @@ -0,0 +1,40 @@ +#pragma once +/* + * Copyright (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include + +#include "../data/BaseEntry.h" + +namespace enigma2 +{ + namespace utilities + { + typedef enum UPDATE_STATE + { + UPDATE_STATE_NONE, + UPDATE_STATE_FOUND, + UPDATE_STATE_UPDATED, + UPDATE_STATE_NEW + } UPDATE_STATE; + } //namespace data +} //namespace enigma2 \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/WebUtils.cpp kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/WebUtils.cpp --- kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/WebUtils.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/WebUtils.cpp 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2005-2015 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "WebUtils.h" + +#include "CurlFile.h" +#include "Logger.h" +#include "../Settings.h" + +#include "tinyxml.h" +#include "util/XMLUtils.h" +#include "p8-platform/util/StringUtils.h" + +using namespace enigma2; +using namespace enigma2::utilities; + +const char SAFE[256] = +{ + /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ + /* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* 2 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* 3 */ 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, + + /* 4 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, + /* 5 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, + /* 6 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, + /* 7 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, + + /* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* 9 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* A */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* B */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + + /* C */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* D */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* E */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, + /* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 +}; + +std::string WebUtils::URLEncodeInline(const std::string &sSrc) +{ + const char DEC2HEX[16 + 1] = "0123456789ABCDEF"; + const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); + const int SRC_LEN = sSrc.length(); + unsigned char * const pStart = new unsigned char[SRC_LEN * 3]; + unsigned char * pEnd = pStart; + const unsigned char * const SRC_END = pSrc + SRC_LEN; + + for (; pSrc < SRC_END; ++pSrc) + { + if (SAFE[*pSrc]) + *pEnd++ = *pSrc; + else + { + // escape this char + *pEnd++ = '%'; + *pEnd++ = DEC2HEX[*pSrc >> 4]; + *pEnd++ = DEC2HEX[*pSrc & 0x0F]; + } + } + + std::string sResult((char *)pStart, (char *)pEnd); + delete [] pStart; + return sResult; +} + +std::string WebUtils::GetHttpXML(const std::string& url) +{ + Logger::Log(LEVEL_INFO, "%s Open webAPI with URL: '%s'", __FUNCTION__, url.c_str()); + + std::string strTmp; + + CurlFile http; + if(!http.Get(url, strTmp)) + { + Logger::Log(LEVEL_DEBUG, "%s - Could not open webAPI.", __FUNCTION__); + return ""; + } + + // If there is no newline add it as it not being there will cause a parse error + // TODO: Remove once bug is fixed in Open WebIf + if (strTmp.back() != '\n') + strTmp += "\n"; + + Logger::Log(LEVEL_INFO, "%s Got result. Length: %u", __FUNCTION__, strTmp.length()); + + return strTmp; +} + +std::string WebUtils::PostHttpJson(const std::string& url) +{ + Logger::Log(LEVEL_INFO, "%s Open webAPI with URL: '%s'", __FUNCTION__, url.c_str()); + + std::string strTmp; + + CurlFile http; + if(!http.Post(url, strTmp)) + { + Logger::Log(LEVEL_DEBUG, "%s - Could not open webAPI.", __FUNCTION__); + return ""; + } + + // If there is no newline add it as it not being there will cause a parse error + // TODO: Remove once bug is fixed in Open WebIf + if (strTmp.back() != '\n') + strTmp += "\n"; + + Logger::Log(LEVEL_INFO, "%s Got result. Length: %u", __FUNCTION__, strTmp.length()); + + return strTmp; +} + +bool WebUtils::SendSimpleCommand(const std::string& strCommandURL, std::string& strResultText, bool bIgnoreResult) +{ + const std::string url = StringUtils::Format("%s%s", Settings::GetInstance().GetConnectionURL().c_str(), strCommandURL.c_str()); + + std::string strXML = WebUtils::GetHttpXML(url); + + if (!bIgnoreResult) + { + + TiXmlDocument xmlDoc; + if (!xmlDoc.Parse(strXML.c_str())) + { + Logger::Log(LEVEL_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); + return false; + } + + TiXmlHandle hDoc(&xmlDoc); + TiXmlElement* pElem; + TiXmlHandle hRoot(0); + + pElem = hDoc.FirstChildElement("e2simplexmlresult").Element(); + + if (!pElem) + { + Logger::Log(LEVEL_DEBUG, "%s Could not find element!", __FUNCTION__); + return false; + } + + bool bTmp; + + if (!XMLUtils::GetBoolean(pElem, "e2state", bTmp)) + { + Logger::Log(LEVEL_ERROR, "%s Could not parse e2state from result!", __FUNCTION__); + strResultText = StringUtils::Format("Could not parse e2state!"); + return false; + } + + if (!XMLUtils::GetString(pElem, "e2statetext", strResultText)) + { + Logger::Log(LEVEL_ERROR, "%s Could not parse e2state from result!", __FUNCTION__); + return false; + } + + if (!bTmp) + Logger::Log(LEVEL_ERROR, "%s Error message from backend: '%s'", __FUNCTION__, strResultText.c_str()); + + return bTmp; + } + return true; +} + +bool WebUtils::SendSimpleJsonPostCommand(const std::string& strCommandURL, std::string& strResultText, bool bIgnoreResult) +{ + const std::string url = StringUtils::Format("%s%s", Settings::GetInstance().GetConnectionURL().c_str(), strCommandURL.c_str()); + + std::string strJson = WebUtils::PostHttpJson(url); + + if (!bIgnoreResult) + { + if (strJson.find("true") != std::string::npos) + { + strResultText = "Success!"; + } + else + { + strResultText = StringUtils::Format("Invalid Command"); + Logger::Log(LEVEL_ERROR, "%s Error message from backend: '%s'", __FUNCTION__, strResultText.c_str()); + return false; + } + } + + return true; +} + +std::string& WebUtils::Escape(std::string &s, const std::string from, const std::string to) +{ + std::string::size_type pos = -1; + while ( (pos = s.find(from, pos+1) ) != std::string::npos) + s.erase(pos, from.length()).insert(pos, to); + + return s; +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/WebUtils.h kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/WebUtils.h --- kodi-pvr-vuplus-2.4.12/src/enigma2/utilities/WebUtils.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/enigma2/utilities/WebUtils.h 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,42 @@ +#pragma once + +/* + * Copyright (C) 2005-2015 Team Kodi + * http://kodi.tv + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include + +namespace enigma2 +{ + namespace utilities + { + class WebUtils + { + public: + + static std::string URLEncodeInline(const std::string &sStr); + static std::string GetHttpXML(const std::string& url); + static std::string PostHttpJson(const std::string& url); + static bool SendSimpleCommand(const std::string& strCommandURL, std::string& strResultText, bool bIgnoreResult=false); + static bool SendSimpleJsonPostCommand(const std::string& strCommandURL, std::string& strResultText, bool bIgnoreResult=false); + static std::string& Escape(std::string &s, const std::string from, const std::string to); + }; + } +} diff -Nru kodi-pvr-vuplus-2.4.12/src/Enigma2.cpp kodi-pvr-vuplus-3.15.0/src/Enigma2.cpp --- kodi-pvr-vuplus-2.4.12/src/Enigma2.cpp 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/Enigma2.cpp 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,468 @@ +/* + * Copyright (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "Enigma2.h" + +#include +#include +#include +#include +#include +#include + +#include "client.h" +#include "enigma2/utilities/CurlFile.h" +#include "enigma2/utilities/LocalizedString.h" +#include "enigma2/utilities/Logger.h" +#include "enigma2/utilities/WebUtils.h" + + +#include "util/XMLUtils.h" +#include + +using namespace ADDON; +using namespace P8PLATFORM; +using namespace enigma2; +using namespace enigma2::data; +using namespace enigma2::extract; +using namespace enigma2::utilities; + +Enigma2::Enigma2() +{ + m_lastUpdateTimeSeconds = time(nullptr); +} + +Enigma2::~Enigma2() +{ + CLockObject lock(m_mutex); + Logger::Log(LEVEL_DEBUG, "%s Stopping update thread...", __FUNCTION__); + StopThread(); + + Logger::Log(LEVEL_DEBUG, "%s Removing internal channels list...", __FUNCTION__); + m_channels.ClearChannels(); + + Logger::Log(LEVEL_DEBUG, "%s Removing internal timers list...", __FUNCTION__); + m_timers.ClearTimers(); + + Logger::Log(LEVEL_DEBUG, "%s Removing internal recordings list...", __FUNCTION__); + m_recordings.ClearRecordings(); + + Logger::Log(LEVEL_DEBUG, "%s Removing internal group list...", __FUNCTION__); + m_channelGroups.ClearChannelGroups(); + m_isConnected = false; +} + +/*************************************************************************** + * Device and helpers + **************************************************************************/ + +bool Enigma2::Open() +{ + CLockObject lock(m_mutex); + + Logger::Log(LEVEL_NOTICE, "%s - VU+ Addon Configuration options", __FUNCTION__); + Logger::Log(LEVEL_NOTICE, "%s - Hostname: '%s'", __FUNCTION__, m_settings.GetHostname().c_str()); + Logger::Log(LEVEL_NOTICE, "%s - WebPort: '%d'", __FUNCTION__, m_settings.GetWebPortNum()); + Logger::Log(LEVEL_NOTICE, "%s - StreamPort: '%d'", __FUNCTION__, m_settings.GetStreamPortNum()); + if (!m_settings.GetUseSecureConnection()) + Logger::Log(LEVEL_NOTICE, "%s Use HTTPS: 'false'", __FUNCTION__); + else + Logger::Log(LEVEL_NOTICE, "%s Use HTTPS: 'true'", __FUNCTION__); + + if ((m_settings.GetUsername().length() > 0) && (m_settings.GetPassword().length() > 0)) + { + if ((m_settings.GetUsername().find("@") != std::string::npos) || (m_settings.GetPassword().find("@") != std::string::npos)) + { + Logger::Log(LEVEL_ERROR, "%s - You cannot use the '@' character in either the username or the password with this addon. Please change your configuraton!", __FUNCTION__); + return false; + } + } + m_isConnected = m_admin.Initialise(); + + if (!m_isConnected) + { + Logger::Log(LEVEL_ERROR, "%s It seem's that the webinterface cannot be reached. Make sure that you set the correct configuration options in the addon settings!", __FUNCTION__); + return false; + } + + m_settings.ReadFromAddon(); + + m_recordings.ClearLocations(); + m_recordings.LoadLocations(); + + if (m_channels.GetNumChannels() == 0) + { + // Load the TV channels - close connection if no channels are found + if (!m_channelGroups.LoadChannelGroups()) + return false; + + if (!m_channels.LoadChannels(m_channelGroups)) + return false; + + } + m_timers.AddTimerChangeWatcher(&m_dueRecordingUpdate); + m_timers.TimerUpdates(); + + Logger::Log(LEVEL_INFO, "%s Starting separate client update thread...", __FUNCTION__); + CreateThread(); + + return IsRunning(); +} + +void *Enigma2::Process() +{ + Logger::Log(LEVEL_DEBUG, "%s - starting", __FUNCTION__); + + // Wait for the initial EPG update to complete + bool bwait = true; + int cycles = 0; + + while (bwait) + { + if (cycles == 30) + bwait = false; + + cycles++; + + if (!m_epg.IsInitialEpgCompleted()) + Sleep(5 * 1000); + } + + // Trigger "Real" EPG updates + m_epg.TriggerEpgUpdatesForChannels(); + + while(!IsStopped()) + { + Sleep(5 * 1000); + + time_t currentUpdateTimeSeconds = time(nullptr); + m_updateTimer += static_cast(currentUpdateTimeSeconds - m_lastUpdateTimeSeconds); + m_lastUpdateTimeSeconds = currentUpdateTimeSeconds; + + if (m_dueRecordingUpdate || m_updateTimer >= (m_settings.GetUpdateIntervalMins() * 60)) + { + m_updateTimer = 0; + + // Trigger Timer and Recording updates acording to the addon settings + CLockObject lock(m_mutex); + Logger::Log(LEVEL_INFO, "%s Perform Updates!", __FUNCTION__); + + if (m_settings.GetAutoTimerListCleanupEnabled()) + { + m_timers.RunAutoTimerListCleanup(); + } + m_timers.TimerUpdates(); + + m_dueRecordingUpdate = false; + + PVR->TriggerRecordingUpdate(); + } + } + + //CLockObject lock(m_mutex); + m_started.Broadcast(); + + return nullptr; +} + +void Enigma2::SendPowerstate() +{ + CLockObject lock(m_mutex); + + m_admin.SendPowerstate(); +} + +const char * Enigma2::GetServerName() const +{ + return m_admin.GetServerName().c_str(); +} + +const char * Enigma2::GetServerVersion() const +{ + return m_admin.GetWebIfVersion().c_str(); +} + +bool Enigma2::IsConnected() const +{ + return m_isConnected; +} + +/*************************************************************************** + * Channel Groups + **************************************************************************/ + +unsigned int Enigma2::GetNumChannelGroups() const +{ + return m_channelGroups.GetNumChannelGroups(); +} + +PVR_ERROR Enigma2::GetChannelGroups(ADDON_HANDLE handle, bool radio) +{ + std::vector channelGroups; + { + CLockObject lock(m_mutex); + m_channelGroups.GetChannelGroups(channelGroups, radio); + } + + Logger::Log(LEVEL_DEBUG, "%s - channel groups available '%d'", __FUNCTION__, channelGroups.size()); + + for (const auto& channelGroup : channelGroups) + PVR->TransferChannelGroup(handle, &channelGroup); + + return PVR_ERROR_NO_ERROR; +} + +PVR_ERROR Enigma2::GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group) +{ + std::vector channelGroupMembers; + { + CLockObject lock(m_mutex); + m_channelGroups.GetChannelGroupMembers(channelGroupMembers, group.strGroupName); + } + + Logger::Log(LEVEL_DEBUG, "%s - group '%s' members available '%d'", __FUNCTION__, group.strGroupName, channelGroupMembers.size()); + + for (const auto& channelGroupMember : channelGroupMembers) + PVR->TransferChannelGroupMember(handle, &channelGroupMember); + + return PVR_ERROR_NO_ERROR; +} + +/*************************************************************************** + * Channels + **************************************************************************/ + +int Enigma2::GetChannelsAmount() const +{ + return m_channels.GetNumChannels(); +} + + +PVR_ERROR Enigma2::GetChannels(ADDON_HANDLE handle, bool bRadio) +{ + std::vector channels; + { + CLockObject lock(m_mutex); + m_channels.GetChannels(channels, bRadio); + } + + Logger::Log(LEVEL_DEBUG, "%s - channels available '%d', radio = %d", __FUNCTION__, channels.size(), bRadio); + + for (auto &channel : channels) + PVR->TransferChannelEntry(handle, &channel); + + return PVR_ERROR_NO_ERROR; +} + +/*************************************************************************** + * EPG + **************************************************************************/ + +PVR_ERROR Enigma2::GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd) +{ + return m_epg.GetEPGForChannel(handle, channel, iStart, iEnd); +} + +/*************************************************************************** + * Livestream + **************************************************************************/ +bool Enigma2::OpenLiveStream(const PVR_CHANNEL &channelinfo) +{ + Logger::Log(LEVEL_DEBUG, "%s: channel=%u", __FUNCTION__, channelinfo.iUniqueId); + CLockObject lock(m_mutex); + + if (channelinfo.iUniqueId != m_currentChannel) + { + m_currentChannel = channelinfo.iUniqueId; + + if (m_settings.GetZapBeforeChannelSwitch()) + { + // Zapping is set to true, so send the zapping command to the PVR box + std::string strServiceReference = m_channels.GetChannel(channelinfo.iUniqueId)->GetServiceReference().c_str(); + + std::string strTmp; + strTmp = StringUtils::Format("web/zap?sRef=%s", WebUtils::URLEncodeInline(strServiceReference).c_str()); + + std::string strResult; + if(!WebUtils::SendSimpleCommand(strTmp, strResult)) + return false; + } + } + return true; +} + +void Enigma2::CloseLiveStream(void) +{ + CLockObject lock(m_mutex); + m_currentChannel = -1; +} + +const std::string Enigma2::GetLiveStreamURL(const PVR_CHANNEL &channelinfo) +{ + if (m_settings.GetAutoConfigLiveStreamsEnabled()) + { + // we need to download the M3U file that contains the URL for the stream... + // we do it here for 2 reasons: + // 1. This is faster than doing it during initialization + // 2. The URL can change, so this is more up-to-date. + return GetStreamURL(m_channels.GetChannel(channelinfo.iUniqueId)->GetM3uURL()); + } + + return m_channels.GetChannel(channelinfo.iUniqueId)->GetStreamURL(); +} + + +/** + * GetStreamURL() reads out a stream-URL from a M3U-file. + * + * This method downloads a M3U-file from the address that is given by strM3uURL. + * It returns the first line that starts with "http". + * If no line starts with "http" the last line is returned. + */ +std::string Enigma2::GetStreamURL(const std::string& strM3uURL) +{ + std::string strTmp; + strTmp = strM3uURL; + std::string strM3U; + strM3U = WebUtils::GetHttpXML(strTmp); + std::istringstream streamM3U(strM3U); + std::string strURL = ""; + while (std::getline(streamM3U, strURL)) + { + if (strURL.compare(0, 4, "http", 4) == 0) + break; + }; + return strURL; +} + +/*************************************************************************** + * Recordings + **************************************************************************/ + +unsigned int Enigma2::GetRecordingsAmount() +{ + return m_recordings.GetNumRecordings(); +} + +PVR_ERROR Enigma2::GetRecordings(ADDON_HANDLE handle) +{ + m_recordings.LoadRecordings(); + + std::vector recordings; + { + CLockObject lock(m_mutex); + m_recordings.GetRecordings(recordings); + } + + Logger::Log(LEVEL_DEBUG, "%s - recordings available '%d'", __FUNCTION__, recordings.size()); + + for (const auto& recording : recordings) + PVR->TransferRecordingEntry(handle, &recording); + + return PVR_ERROR_NO_ERROR; +} + +PVR_ERROR Enigma2::DeleteRecording(const PVR_RECORDING &recinfo) +{ + return m_recordings.DeleteRecording(recinfo); +} + +RecordingReader *Enigma2::OpenRecordedStream(const PVR_RECORDING &recinfo) +{ + CLockObject lock(m_mutex); + std::time_t now = std::time(nullptr), end = 0; + std::string channelName = recinfo.strChannelName; + auto timer = m_timers.GetTimer([&](const Timer &timer) + { + return timer.isRunning(&now, &channelName); + }); + if (timer) + end = timer->GetEndTime(); + + return new RecordingReader(m_recordings.GetRecordingURL(recinfo).c_str(), end); +} + +/*************************************************************************** + * Timers + **************************************************************************/ + +void Enigma2::GetTimerTypes(PVR_TIMER_TYPE types[], int *size) +{ + std::vector timerTypes; + { + CLockObject lock(m_mutex); + m_timers.GetTimerTypes(timerTypes); + } + + int i = 0; + for (auto &timerType : timerTypes) + types[i++] = timerType; + *size = timerTypes.size(); + Logger::Log(LEVEL_NOTICE, "Transfered %u timer types", *size); +} + +int Enigma2::GetTimersAmount() +{ + CLockObject lock(m_mutex); + return m_timers.GetTimerCount(); +} + +PVR_ERROR Enigma2::GetTimers(ADDON_HANDLE handle) +{ + std::vector timers; + { + CLockObject lock(m_mutex); + m_timers.GetTimers(timers); + m_timers.GetAutoTimers(timers); + } + + Logger::Log(LEVEL_DEBUG, "%s - timers available '%d'", __FUNCTION__, timers.size()); + + for (auto &timer : timers) + PVR->TransferTimerEntry(handle, &timer); + + return PVR_ERROR_NO_ERROR; +} + +PVR_ERROR Enigma2::AddTimer(const PVR_TIMER &timer) +{ + return m_timers.AddTimer(timer); +} + +PVR_ERROR Enigma2::UpdateTimer(const PVR_TIMER &timer) +{ + return m_timers.UpdateTimer(timer); +} + +PVR_ERROR Enigma2::DeleteTimer(const PVR_TIMER &timer) +{ + return m_timers.DeleteTimer(timer); +} + +/*************************************************************************** + * Misc + **************************************************************************/ + +PVR_ERROR Enigma2::GetDriveSpace(long long *iTotal, long long *iUsed) +{ + return m_admin.GetDriveSpace(iTotal, iUsed, m_locations); +} \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/Enigma2.h kodi-pvr-vuplus-3.15.0/src/Enigma2.h --- kodi-pvr-vuplus-2.4.12/src/Enigma2.h 1970-01-01 00:00:00.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/Enigma2.h 2018-11-18 11:16:20.000000000 +0000 @@ -0,0 +1,110 @@ +#pragma once +/* + * Copyright (C) 2005-2015 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-1335, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include + +#include "client.h" +#include "enigma2/Admin.h" +#include "enigma2/Channels.h" +#include "enigma2/ChannelGroups.h" +#include "enigma2/Epg.h" +#include "enigma2/RecordingReader.h" +#include "enigma2/Recordings.h" +#include "enigma2/Settings.h" +#include "enigma2/Timers.h" +#include "enigma2/data/BaseEntry.h" +#include "enigma2/data/Channel.h" +#include "enigma2/data/ChannelGroup.h" +#include "enigma2/data/EpgEntry.h" +#include "enigma2/data/RecordingEntry.h" +#include "enigma2/extract/EpgEntryExtractor.h" + +#include "tinyxml.h" +#include "p8-platform/threads/threads.h" + +class Enigma2 : public P8PLATFORM::CThread +{ +public: + Enigma2(); + ~Enigma2(); + + //device and helper functions + bool Open(); + void SendPowerstate(); + const char * GetServerName() const; + const char * GetServerVersion() const; + bool IsConnected() const; + + //groups, channels and EPG + unsigned int GetNumChannelGroups(void) const; + PVR_ERROR GetChannelGroups(ADDON_HANDLE handle, bool radio); + PVR_ERROR GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group); + int GetChannelsAmount(void) const; + PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio); + PVR_ERROR GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd); + + //live streams, recordings and Timers + bool OpenLiveStream(const PVR_CHANNEL &channelinfo); + void CloseLiveStream(); + const std::string GetLiveStreamURL(const PVR_CHANNEL &channelinfo); + unsigned int GetRecordingsAmount(); + PVR_ERROR GetRecordings(ADDON_HANDLE handle); + PVR_ERROR DeleteRecording(const PVR_RECORDING &recinfo); + bool GetRecordingsFromLocation(std::string strRecordingFolder); + enigma2::RecordingReader *OpenRecordedStream(const PVR_RECORDING &recinfo); + void GetTimerTypes(PVR_TIMER_TYPE types[], int *size); + int GetTimersAmount(void); + PVR_ERROR GetTimers(ADDON_HANDLE handle); + PVR_ERROR AddTimer(const PVR_TIMER &timer); + PVR_ERROR UpdateTimer(const PVR_TIMER &timer); + PVR_ERROR DeleteTimer(const PVR_TIMER &timer); + PVR_ERROR GetDriveSpace(long long *iTotal, long long *iUsed); + +protected: + virtual void *Process(void); + +private: + // helper functions + std::string GetStreamURL(const std::string& strM3uURL); + + // members + bool m_isConnected = false; + unsigned int m_updateTimer = 0; + time_t m_lastUpdateTimeSeconds; + int m_currentChannel = -1; + std::atomic_bool m_dueRecordingUpdate{true}; + + enigma2::Channels m_channels; + enigma2::ChannelGroups m_channelGroups; + enigma2::Recordings m_recordings = enigma2::Recordings(m_channels, m_entryExtractor); + std::vector& m_locations = m_recordings.GetLocations(); + enigma2::Timers m_timers = enigma2::Timers(m_channels, m_locations); + enigma2::Settings &m_settings = enigma2::Settings::GetInstance(); + enigma2::Admin m_admin; + enigma2::Epg m_epg = enigma2::Epg(m_channels, m_channelGroups, m_entryExtractor); + enigma2::extract::EpgEntryExtractor m_entryExtractor; + + P8PLATFORM::CMutex m_mutex; + P8PLATFORM::CCondition m_started; +}; \ No newline at end of file diff -Nru kodi-pvr-vuplus-2.4.12/src/VuData.cpp kodi-pvr-vuplus-3.15.0/src/VuData.cpp --- kodi-pvr-vuplus-2.4.12/src/VuData.cpp 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/src/VuData.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,1885 +0,0 @@ -/* - * Copyright (C) 2005-2015 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-1335, USA. - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#include "VuData.h" -#include "client.h" -#include -#include -#include -#include "util/XMLUtils.h" - - -using namespace ADDON; -using namespace P8PLATFORM; - -bool CCurlFile::Get(const std::string &strURL, std::string &strResult) -{ - void* fileHandle = XBMC->OpenFile(strURL.c_str(), 0); - if (fileHandle) - { - char buffer[1024]; - while (XBMC->ReadFileString(fileHandle, buffer, 1024)) - strResult.append(buffer); - XBMC->CloseFile(fileHandle); - return true; - } - return false; -} - -std::string& Vu::Escape(std::string &s, std::string from, std::string to) -{ - std::string::size_type pos = -1; - while ( (pos = s.find(from, pos+1) ) != std::string::npos) - s.erase(pos, from.length()).insert(pos, to); - - return s; -} - -bool Vu::LoadLocations() -{ - CStdString url; - if (g_bOnlyCurrentLocation) - url.Format("%s%s", m_strURL.c_str(), "web/getcurrlocation"); - else - url.Format("%s%s", m_strURL.c_str(), "web/getlocations"); - - CStdString strXML; - strXML = GetHttpXML(url); - - int iNumLocations = 0; - - TiXmlDocument xmlDoc; - if (!xmlDoc.Parse(strXML.c_str())) - { - XBMC->Log(LOG_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); - return false; - } - - TiXmlHandle hDoc(&xmlDoc); - TiXmlElement* pElem; - TiXmlHandle hRoot(0); - - pElem = hDoc.FirstChildElement("e2locations").Element(); - - if (!pElem) - { - XBMC->Log(LOG_DEBUG, "Could not find element"); - return false; - } - - hRoot=TiXmlHandle(pElem); - - TiXmlElement* pNode = hRoot.FirstChildElement("e2location").Element(); - - if (!pNode) - { - XBMC->Log(LOG_DEBUG, "Could not find element"); - return false; - } - - for (; pNode != NULL; pNode = pNode->NextSiblingElement("e2location")) - { - CStdString strTmp; - strTmp = pNode->GetText(); - - m_locations.push_back(strTmp); - iNumLocations++; - - XBMC->Log(LOG_DEBUG, "%s Added '%s' as a recording location", __FUNCTION__, strTmp.c_str()); - } - - XBMC->Log(LOG_INFO, "%s Loded '%d' recording locations", __FUNCTION__, iNumLocations); - - return true; -} - -void Vu::TimerUpdates() -{ - std::vector newtimer = LoadTimers(); - - for (unsigned int i=0; iLog(LOG_INFO, "%s Removed timer: '%s', ClientIndex: '%d'", __FUNCTION__, m_timers.at(i).strTitle.c_str(), m_timers.at(i).iClientIndex); - m_timers.erase(m_timers.begin()+i); - i=0; - iRemoved++; - } - } - unsigned int iNew=0; - - for (unsigned int i=0; iLog(LOG_INFO, "%s New timer: '%s', ClientIndex: '%d'", __FUNCTION__, timer.strTitle.c_str(), m_iClientIndexCounter); - m_timers.push_back(timer); - m_iClientIndexCounter++; - iNew++; - } - } - - XBMC->Log(LOG_INFO, "%s No of timers: removed [%d], untouched [%d], updated '%d', new '%d'", __FUNCTION__, iRemoved, iUnchanged, iUpdated, iNew); - - if (iRemoved != 0 || iUpdated != 0 || iNew != 0) - { - XBMC->Log(LOG_INFO, "%s Changes in timerlist detected, trigger an update!", __FUNCTION__); - PVR->TriggerTimerUpdate(); - } -} - -Vu::Vu() -{ - m_bIsConnected = false; - m_strServerName = "Vu"; - CStdString strURL = ""; - - // simply add user@pass in front of the URL if username/password is set - if ((g_strUsername.length() > 0) && (g_strPassword.length() > 0)) - { - strURL.Format("%s:%s@", g_strUsername.c_str(), g_strPassword.c_str()); - } - - if (!g_bUseSecureHTTP) - strURL.Format("http://%s%s:%u/", strURL.c_str(), g_strHostname.c_str(), g_iPortWeb); - else - strURL.Format("https://%s%s:%u/", strURL.c_str(), g_strHostname.c_str(), g_iPortWeb); - - m_strURL = strURL.c_str(); - - m_iNumRecordings = 0; - m_iNumChannelGroups = 0; - m_iCurrentChannel = -1; - m_iClientIndexCounter = 1; - - m_bUpdating = false; - m_iUpdateTimer = 0; - m_bInitialEPG = true; - - std::string initialEPGReady = "special://userdata/addon_data/pvr.vuplus/initialEPGReady"; - m_writeHandle = XBMC->OpenFileForWrite(initialEPGReady.c_str(), true); - XBMC->WriteFile(m_writeHandle, "Y", 1); - XBMC->CloseFile(m_writeHandle); - -} - -bool Vu::Open() -{ - CLockObject lock(m_mutex); - - XBMC->Log(LOG_NOTICE, "%s - VU+ Addon Configuration options", __FUNCTION__); - XBMC->Log(LOG_NOTICE, "%s - Hostname: '%s'", __FUNCTION__, g_strHostname.c_str()); - XBMC->Log(LOG_NOTICE, "%s - WebPort: '%d'", __FUNCTION__, g_iPortWeb); - XBMC->Log(LOG_NOTICE, "%s - StreamPort: '%d'", __FUNCTION__, g_iPortStream); - if (!g_bUseSecureHTTP) - XBMC->Log(LOG_NOTICE, "%s Use HTTPS: 'false'", __FUNCTION__); - else - XBMC->Log(LOG_NOTICE, "%s Use HTTPS: 'true'", __FUNCTION__); - - if ((g_strUsername.length() > 0) && (g_strPassword.length() > 0)) - { - if ((g_strUsername.find("@") != std::string::npos) || (g_strPassword.find("@") != std::string::npos)) - { - XBMC->Log(LOG_ERROR, "%s - You cannot use the '@' character in either the username or the password with this addon. Please change your configuraton!", __FUNCTION__); - return false; - } - } - m_bIsConnected = GetDeviceInfo(); - - if (!m_bIsConnected) - { - XBMC->Log(LOG_ERROR, "%s It seem's that the webinterface cannot be reached. Make sure that you set the correct configuration options in the addon settings!", __FUNCTION__); - return false; - } - - LoadLocations(); - - if (m_channels.size() == 0) - { - // Load the TV channels - close connection if no channels are found - if (!LoadChannelGroups()) - return false; - - if (!LoadChannels()) - return false; - - } - TimerUpdates(); - - XBMC->Log(LOG_INFO, "%s Starting separate client update thread...", __FUNCTION__); - CreateThread(); - - return IsRunning(); -} - -void *Vu::Process() -{ - XBMC->Log(LOG_DEBUG, "%s - starting", __FUNCTION__); - - // Wait for the initial EPG update to complete - bool bwait = true; - int cycles = 0; - - while (bwait) - { - if (cycles == 30) - bwait = false; - - cycles++; - std::string initialEPGReady = "special://userdata/addon_data/pvr.vuplus/initialEPGReady"; - m_readHandle = XBMC->OpenFile(initialEPGReady.c_str(), 0); - byte buf[1]; - XBMC->ReadFile(m_readHandle, buf, 1); - XBMC->CloseFile(m_readHandle); - char buf2[] = { "N" }; - if (buf[0] == buf2[0]) - { - XBMC->Log(LOG_DEBUG, "%s - Intial EPG update COMPLETE!", __FUNCTION__); - } - else - { - XBMC->Log(LOG_DEBUG, "%s - Intial EPG update not completed yet.", __FUNCTION__); - Sleep(5 * 1000); - } - } - - // Trigger "Real" EPG updates - for (unsigned int iChannelPtr = 0; iChannelPtr < m_channels.size(); iChannelPtr++) - { - XBMC->Log(LOG_DEBUG, "%s - Trigger EPG update for channel '%d'", __FUNCTION__, iChannelPtr); - PVR->TriggerEpgUpdate(m_channels.at(iChannelPtr).iUniqueId); - } - - while(!IsStopped()) - { - Sleep(5 * 1000); - m_iUpdateTimer += 5; - - if ((int)m_iUpdateTimer > (g_iUpdateInterval * 60)) - { - m_iUpdateTimer = 0; - - // Trigger Timer and Recording updates acording to the addon settings - CLockObject lock(m_mutex); - XBMC->Log(LOG_INFO, "%s Perform Updates!", __FUNCTION__); - - if (g_bAutomaticTimerlistCleanup) - { - CStdString strTmp; - strTmp.Format("web/timercleanup?cleanup=true"); - CStdString strResult; - if(!SendSimpleCommand(strTmp, strResult)) - XBMC->Log(LOG_ERROR, "%s - AutomaticTimerlistCleanup failed!", __FUNCTION__); - } - TimerUpdates(); - PVR->TriggerRecordingUpdate(); - } - - } - - //CLockObject lock(m_mutex); - m_started.Broadcast(); - - return NULL; -} - -bool Vu::LoadChannels() -{ - bool bOk = false; - - m_channels.clear(); - // Load Channels - for (int i = 0;iLog(LOG_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); - return false; - } - - TiXmlHandle hDoc(&xmlDoc); - TiXmlElement* pElem; - TiXmlHandle hRoot(0); - - pElem = hDoc.FirstChildElement("e2servicelist").Element(); - - if (!pElem) - { - XBMC->Log(LOG_DEBUG, "%s Could not find element!", __FUNCTION__); - return false; - } - - hRoot=TiXmlHandle(pElem); - - TiXmlElement* pNode = hRoot.FirstChildElement("e2service").Element(); - - if (!pNode) - { - XBMC->Log(LOG_DEBUG, "%s Could not find element", __FUNCTION__); - return false; - } - - m_groups.clear(); - m_iNumChannelGroups = 0; - - for (; pNode != NULL; pNode = pNode->NextSiblingElement("e2service")) - { - CStdString strTmp; - - if (!XMLUtils::GetString(pNode, "e2servicereference", strTmp)) - continue; - - // Check whether the current element is not just a label - if (strTmp.compare(0,5,"1:64:") == 0) - continue; - - VuChannelGroup newGroup; - newGroup.strServiceReference = strTmp; - - if (!XMLUtils::GetString(pNode, "e2servicename", strTmp)) - continue; - - newGroup.strGroupName = strTmp; - - if (g_bOnlyOneGroup && g_strOneGroup.compare(strTmp.c_str())) { - XBMC->Log(LOG_INFO, "%s Only one group is set, but current e2servicename '%s' does not match requested name '%s'", __FUNCTION__, strTmp.c_str(), g_strOneGroup.c_str()); - continue; - } - - m_groups.push_back(newGroup); - - XBMC->Log(LOG_INFO, "%s Loaded channelgroup: %s", __FUNCTION__, newGroup.strGroupName.c_str()); - m_iNumChannelGroups++; - } - - XBMC->Log(LOG_INFO, "%s Loaded %d Channelsgroups", __FUNCTION__, m_iNumChannelGroups); - return true; -} - -bool Vu::LoadChannels(CStdString strServiceReference, CStdString strGroupName) -{ - XBMC->Log(LOG_INFO, "%s loading channel group: '%s'", __FUNCTION__, strGroupName.c_str()); - - CStdString strTmp; - strTmp.Format("%sweb/getservices?sRef=%s", m_strURL.c_str(), URLEncodeInline(strServiceReference.c_str())); - - CStdString strXML = GetHttpXML(strTmp); - - TiXmlDocument xmlDoc; - if (!xmlDoc.Parse(strXML.c_str())) - { - XBMC->Log(LOG_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); - return false; - } - - TiXmlHandle hDoc(&xmlDoc); - TiXmlElement* pElem; - TiXmlHandle hRoot(0); - - pElem = hDoc.FirstChildElement("e2servicelist").Element(); - - if (!pElem) - { - XBMC->Log(LOG_DEBUG, "%s Could not find element!", __FUNCTION__); - return false; - } - - hRoot=TiXmlHandle(pElem); - - TiXmlElement* pNode = hRoot.FirstChildElement("e2service").Element(); - - if (!pNode) - { - XBMC->Log(LOG_DEBUG, "Could not find element"); - return false; - } - - bool bRadio; - - bRadio = !strGroupName.compare("radio"); - - for (; pNode != NULL; pNode = pNode->NextSiblingElement("e2service")) - { - CStdString strTmp; - - if (!XMLUtils::GetString(pNode, "e2servicereference", strTmp)) - continue; - - // Check whether the current element is not just a label - if (strTmp.compare(0,5,"1:64:") == 0) - continue; - - VuChannel newChannel; - newChannel.bRadio = bRadio; - newChannel.bInitialEPG = true; - newChannel.strGroupName = strGroupName; - newChannel.iUniqueId = m_channels.size()+1; - newChannel.iChannelNumber = m_channels.size()+1; - newChannel.strServiceReference = strTmp; - - if (!XMLUtils::GetString(pNode, "e2servicename", strTmp)) - continue; - - newChannel.strChannelName = strTmp; - - std::string strIcon; - strIcon = newChannel.strServiceReference.c_str(); - - int j = 0; - std::string::iterator it = strIcon.begin(); - - while (j<10 && it != strIcon.end()) - { - if (*it == ':') - j++; - - it++; - } - std::string::size_type index = it-strIcon.begin(); - - strIcon = strIcon.substr(0,index); - - it = strIcon.end() - 1; - if (*it == ':') - { - strIcon.erase(it); - } - - CStdString strTmp2; - - strTmp2.Format("%s", strIcon.c_str()); - - std::replace(strIcon.begin(), strIcon.end(), ':', '_'); - strIcon = g_strIconPath.c_str() + strIcon + ".png"; - - newChannel.strIconPath = strIcon; - - strTmp.Format(""); - - strTmp.Format("http://%s:%d/%s", g_strHostname, g_iPortStream, strTmp2.c_str()); - - newChannel.strStreamURL = strTmp; - - if (g_bOnlinePicons == true) - { - std::replace(strTmp2.begin(), strTmp2.end(), ':', '_'); - strTmp.Format("%spicon/%s.png", m_strURL.c_str(), strTmp2.c_str()); - newChannel.strIconPath = strTmp; - } - - m_channels.push_back(newChannel); - XBMC->Log(LOG_INFO, "%s Loaded channel: %s, Icon: %s", __FUNCTION__, newChannel.strChannelName.c_str(), newChannel.strIconPath.c_str()); - } - - XBMC->Log(LOG_INFO, "%s Loaded %d Channels", __FUNCTION__, m_channels.size()); - return true; -} - -bool Vu::IsConnected() -{ - return m_bIsConnected; -} - -CStdString Vu::GetHttpXML(CStdString& url) -{ -// CLockObject lock(m_mutex); - - XBMC->Log(LOG_INFO, "%s Open webAPI with URL: '%s'", __FUNCTION__, url.c_str()); - - CStdString strTmp; - - CCurlFile http; - if(!http.Get(url, strTmp)) - { - XBMC->Log(LOG_DEBUG, "%s - Could not open webAPI.", __FUNCTION__); - return ""; - } - - XBMC->Log(LOG_INFO, "%s Got result. Length: %u", __FUNCTION__, strTmp.length()); - - - return strTmp; -} - -const char * Vu::GetServerName() -{ - return m_strServerName.c_str(); -} - -int Vu::GetChannelsAmount() -{ - return m_channels.size(); -} - -int Vu::GetTimersAmount() -{ - return m_timers.size(); -} - -unsigned int Vu::GetRecordingsAmount() { - return m_iNumRecordings; -} - -PVR_ERROR Vu::GetChannels(ADDON_HANDLE handle, bool bRadio) -{ - // is the addon is currently updating the channels, then delay the call - unsigned int iTimer = 0; - while(m_bUpdating == true && iTimer < 120) - { - Sleep(1000); - iTimer++; - } - - for (unsigned int iChannelPtr = 0; iChannelPtr < m_channels.size(); iChannelPtr++) - { - VuChannel &channel = m_channels.at(iChannelPtr); - if (channel.bRadio == bRadio) - { - PVR_CHANNEL xbmcChannel; - memset(&xbmcChannel, 0, sizeof(PVR_CHANNEL)); - - xbmcChannel.iUniqueId = channel.iUniqueId; - xbmcChannel.bIsRadio = channel.bRadio; - xbmcChannel.iChannelNumber = channel.iChannelNumber; - strncpy(xbmcChannel.strChannelName, channel.strChannelName.c_str(), sizeof(xbmcChannel.strChannelName)); - strncpy(xbmcChannel.strInputFormat, "", 0); // unused - xbmcChannel.iEncryptionSystem = 0; - xbmcChannel.bIsHidden = false; - strncpy(xbmcChannel.strIconPath, channel.strIconPath.c_str(), sizeof(xbmcChannel.strIconPath)); - - CStdString strStream; - strStream.Format("pvr://stream/tv/%i.ts", channel.iUniqueId); - strncpy(xbmcChannel.strStreamURL, strStream.c_str(), sizeof(xbmcChannel.strStreamURL)); - - PVR->TransferChannelEntry(handle, &xbmcChannel); - } - } - - return PVR_ERROR_NO_ERROR; -} - -Vu::~Vu() -{ - CLockObject lock(m_mutex); - XBMC->Log(LOG_DEBUG, "%s Stopping update thread...", __FUNCTION__); - StopThread(); - - XBMC->Log(LOG_DEBUG, "%s Removing internal channels list...", __FUNCTION__); - m_channels.clear(); - - XBMC->Log(LOG_DEBUG, "%s Removing internal timers list...", __FUNCTION__); - m_timers.clear(); - - XBMC->Log(LOG_DEBUG, "%s Removing internal recordings list...", __FUNCTION__); - m_recordings.clear(); - - XBMC->Log(LOG_DEBUG, "%s Removing internal group list...", __FUNCTION__); - m_groups.clear(); - m_bIsConnected = false; -} - -bool Vu::GetInitialEPGForGroup(VuChannelGroup &group) -{ - // is the addon is currently updating the channels, then delay the call - unsigned int iTimer = 0; - while(m_bUpdating == true && iTimer < 120) - { - Sleep(1000); - iTimer++; - } - - CStdString url; - url.Format("%s%s%s", m_strURL.c_str(), "web/epgnownext?bRef=", URLEncodeInline(group.strServiceReference.c_str())); - - CStdString strXML; - strXML = GetHttpXML(url); - - int iNumEPG = 0; - - TiXmlDocument xmlDoc; - if (!xmlDoc.Parse(strXML.c_str())) - { - XBMC->Log(LOG_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); - return false; - } - - TiXmlHandle hDoc(&xmlDoc); - TiXmlElement* pElem; - TiXmlHandle hRoot(0); - - pElem = hDoc.FirstChildElement("e2eventlist").Element(); - - if (!pElem) - { - XBMC->Log(LOG_DEBUG, "%s could not find element!", __FUNCTION__); - // Return "NO_ERROR" as the EPG could be empty for this channel - return false; - } - - hRoot=TiXmlHandle(pElem); - - TiXmlElement* pNode = hRoot.FirstChildElement("e2event").Element(); - - if (!pNode) - { - XBMC->Log(LOG_DEBUG, "Could not find element"); - // RETURN "NO_ERROR" as the EPG could be empty for this channel - return false; - } - - for (; pNode != NULL; pNode = pNode->NextSiblingElement("e2event")) - { - CStdString strTmp; - - int iTmpStart; - int iTmp; - - // check and set event starttime and endtimes - if (!XMLUtils::GetInt(pNode, "e2eventstart", iTmpStart)) - continue; - - if (!XMLUtils::GetInt(pNode, "e2eventduration", iTmp)) - continue; - - VuEPGEntry entry; - entry.startTime = iTmpStart; - entry.endTime = iTmpStart + iTmp; - - if (!XMLUtils::GetInt(pNode, "e2eventid", entry.iEventId)) - continue; - - - if(!XMLUtils::GetString(pNode, "e2eventtitle", strTmp)) - continue; - - entry.strTitle = strTmp; - - if(!XMLUtils::GetString(pNode, "e2eventservicereference", strTmp)) - continue; - - entry.strServiceReference = strTmp; - - entry.iChannelId = GetChannelNumber(entry.strServiceReference.c_str()); - - if (XMLUtils::GetString(pNode, "e2eventdescriptionextended", strTmp)) - entry.strPlot = strTmp; - - if (XMLUtils::GetString(pNode, "e2eventdescription", strTmp)) - entry.strPlotOutline = strTmp; - - iNumEPG++; - - group.initialEPG.push_back(entry); - } - - XBMC->Log(LOG_INFO, "%s Loaded %u EPG Entries for group '%s'", __FUNCTION__, iNumEPG, group.strGroupName.c_str()); - return true; -} - -PVR_ERROR Vu::GetInitialEPGForChannel(ADDON_HANDLE handle, const VuChannel &channel, time_t iStart, time_t iEnd) -{ - if (m_iNumChannelGroups < 1) - return PVR_ERROR_SERVER_ERROR; - - XBMC->Log(LOG_DEBUG, "%s Fetch information for group '%s'", __FUNCTION__, channel.strGroupName.c_str()); - - VuChannelGroup &myGroup = m_groups.at(0); - for (int i = 0;iLog(LOG_DEBUG, "%s initialEPG size is now '%d'", __FUNCTION__, myGroup.initialEPG.size()); - - for (unsigned int i = 0;iTransferEpgEntry(handle, &broadcast); - } - } - return PVR_ERROR_NO_ERROR; -} - -PVR_ERROR Vu::GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd) -{ - // is the addon is currently updating the channels, then delay the call - unsigned int iTimer = 0; - while(m_bUpdating == true && iTimer < 120) - { - Sleep(1000); - iTimer++; - } - - if (channel.iUniqueId-1 > m_channels.size()) - { - XBMC->Log(LOG_ERROR, "%s Could not fetch cannel object - not fetching EPG for channel with UniqueID '%d'", __FUNCTION__, channel.iUniqueId); - return PVR_ERROR_NO_ERROR; - } - - VuChannel myChannel; - myChannel = m_channels.at(channel.iUniqueId-1); - - // Check if the initial short import has already been done for this channel - if (m_channels.at(channel.iUniqueId-1).bInitialEPG == true) - { - m_channels.at(channel.iUniqueId-1).bInitialEPG = false; - - // Check if all channels have completed the initial EPG import - m_bInitialEPG = false; - for (unsigned int iChannelPtr = 0; iChannelPtr < m_channels.size(); iChannelPtr++) - { - if (m_channels.at(iChannelPtr).bInitialEPG == true) - { - m_bInitialEPG = true; - } - } - - if (!m_bInitialEPG) - { - std::string initialEPGReady = "special://userdata/addon_data/pvr.vuplus/initialEPGReady"; - m_writeHandle = XBMC->OpenFileForWrite(initialEPGReady.c_str(), true); - XBMC->WriteFile(m_writeHandle, "N", 1); - XBMC->CloseFile(m_writeHandle); - } - return GetInitialEPGForChannel(handle, myChannel, iStart, iEnd); - } - - CStdString url; - url.Format("%s%s%s", m_strURL.c_str(), "web/epgservice?sRef=", URLEncodeInline(myChannel.strServiceReference.c_str())); - - CStdString strXML; - strXML = GetHttpXML(url); - - int iNumEPG = 0; - - TiXmlDocument xmlDoc; - if (!xmlDoc.Parse(strXML.c_str())) - { - XBMC->Log(LOG_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); - return PVR_ERROR_SERVER_ERROR; - } - - TiXmlHandle hDoc(&xmlDoc); - TiXmlElement* pElem; - TiXmlHandle hRoot(0); - - pElem = hDoc.FirstChildElement("e2eventlist").Element(); - - if (!pElem) - { - XBMC->Log(LOG_DEBUG, "%s could not find element!", __FUNCTION__); - // Return "NO_ERROR" as the EPG could be empty for this channel - return PVR_ERROR_NO_ERROR; - } - - hRoot=TiXmlHandle(pElem); - - TiXmlElement* pNode = hRoot.FirstChildElement("e2event").Element(); - - if (!pNode) - { - XBMC->Log(LOG_DEBUG, "Could not find element"); - // RETURN "NO_ERROR" as the EPG could be empty for this channel - return PVR_ERROR_SERVER_ERROR; - } - - for (; pNode != NULL; pNode = pNode->NextSiblingElement("e2event")) - { - CStdString strTmp; - - int iTmpStart; - int iTmp; - - // check and set event starttime and endtimes - if (!XMLUtils::GetInt(pNode, "e2eventstart", iTmpStart)) - continue; - - // Skip unneccessary events - if (iStart > iTmpStart) - continue; - - if (!XMLUtils::GetInt(pNode, "e2eventduration", iTmp)) - continue; - - if ((iEnd > 1) && (iEnd < (iTmpStart + iTmp))) - continue; - - VuEPGEntry entry; - entry.startTime = iTmpStart; - entry.endTime = iTmpStart + iTmp; - - if (!XMLUtils::GetInt(pNode, "e2eventid", entry.iEventId)) - continue; - - entry.iChannelId = channel.iUniqueId; - - if(!XMLUtils::GetString(pNode, "e2eventtitle", strTmp)) - continue; - - entry.strTitle = strTmp; - - entry.strServiceReference = myChannel.strServiceReference.c_str(); - - if (XMLUtils::GetString(pNode, "e2eventdescriptionextended", strTmp)) - entry.strPlot = strTmp; - - if (XMLUtils::GetString(pNode, "e2eventdescription", strTmp)) - entry.strPlotOutline = strTmp; - - EPG_TAG broadcast; - memset(&broadcast, 0, sizeof(EPG_TAG)); - - broadcast.iUniqueBroadcastId = entry.iEventId; - broadcast.strTitle = entry.strTitle.c_str(); - broadcast.iChannelNumber = channel.iChannelNumber; - broadcast.startTime = entry.startTime; - broadcast.endTime = entry.endTime; - broadcast.strPlotOutline = entry.strPlotOutline.c_str(); - broadcast.strPlot = entry.strPlot.c_str(); - broadcast.strOriginalTitle = NULL; // unused - broadcast.strCast = NULL; // unused - broadcast.strDirector = NULL; // unused - broadcast.strWriter = NULL; // unused - broadcast.iYear = 0; // unused - broadcast.strIMDBNumber = NULL; // unused - broadcast.strIconPath = ""; // unused - broadcast.iGenreType = 0; // unused - broadcast.iGenreSubType = 0; // unused - broadcast.strGenreDescription = ""; - broadcast.firstAired = 0; // unused - broadcast.iParentalRating = 0; // unused - broadcast.iStarRating = 0; // unused - broadcast.bNotify = false; - broadcast.iSeriesNumber = 0; // unused - broadcast.iEpisodeNumber = 0; // unused - broadcast.iEpisodePartNumber = 0; // unused - broadcast.strEpisodeName = ""; // unused - broadcast.iFlags = EPG_TAG_FLAG_UNDEFINED; - - PVR->TransferEpgEntry(handle, &broadcast); - - iNumEPG++; - - XBMC->Log(LOG_DEBUG, "%s loaded EPG entry '%d:%s' channel '%d' start '%d' end '%d'", __FUNCTION__, broadcast.iUniqueBroadcastId, broadcast.strTitle, entry.iChannelId, entry.startTime, entry.endTime); - } - - XBMC->Log(LOG_INFO, "%s Loaded %u EPG Entries for channel '%s'", __FUNCTION__, iNumEPG, channel.strChannelName); - return PVR_ERROR_NO_ERROR; -} - -int Vu::GetChannelNumber(CStdString strServiceReference) -{ - for (unsigned int i = 0;iLog(LOG_INFO, "%s - timers available '%d'", __FUNCTION__, m_timers.size()); - for (unsigned int i=0; iLog(LOG_DEBUG, "%s - Transfer timer '%s', ClientIndex '%d'", __FUNCTION__, timer.strTitle.c_str(), timer.iClientIndex); - PVR_TIMER tag; - memset(&tag, 0, sizeof(PVR_TIMER)); - - /* TODO: Implement own timer types to get support for the timer features introduced with PVR API 1.9.7 */ - tag.iTimerType = PVR_TIMER_TYPE_NONE; - - tag.iClientChannelUid = timer.iChannelId; - tag.startTime = timer.startTime; - tag.endTime = timer.endTime; - strncpy(tag.strTitle, timer.strTitle.c_str(), sizeof(tag.strTitle)); - strncpy(tag.strDirectory, "/", sizeof(tag.strDirectory)); // unused - strncpy(tag.strSummary, timer.strPlot.c_str(), sizeof(tag.strSummary)); - tag.state = timer.state; - tag.iPriority = 0; // unused - tag.iLifetime = 0; // unused - tag.firstDay = 0; // unused - tag.iWeekdays = timer.iWeekdays; - tag.iEpgUid = timer.iEpgID; - tag.iMarginStart = 0; // unused - tag.iMarginEnd = 0; // unused - tag.iGenreType = 0; // unused - tag.iGenreSubType = 0; // unused - tag.iClientIndex = timer.iClientIndex; - - PVR->TransferTimerEntry(handle, &tag); - } - - return PVR_ERROR_NO_ERROR; -} - -std::vector Vu::LoadTimers() -{ - std::vector timers; - - CStdString url; - url.Format("%s%s", m_strURL.c_str(), "web/timerlist"); - - CStdString strXML; - strXML = GetHttpXML(url); - - TiXmlDocument xmlDoc; - if (!xmlDoc.Parse(strXML.c_str())) - { - XBMC->Log(LOG_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); - return timers; - } - - TiXmlHandle hDoc(&xmlDoc); - TiXmlElement* pElem; - TiXmlHandle hRoot(0); - - pElem = hDoc.FirstChildElement("e2timerlist").Element(); - - if (!pElem) - { - XBMC->Log(LOG_DEBUG, "%s Could not find element!", __FUNCTION__); - return timers; - } - - hRoot=TiXmlHandle(pElem); - - TiXmlElement* pNode = hRoot.FirstChildElement("e2timer").Element(); - - if (!pNode) - { - XBMC->Log(LOG_DEBUG, "Could not find element"); - return timers; - } - - for (; pNode != NULL; pNode = pNode->NextSiblingElement("e2timer")) - { - CStdString strTmp; - - int iTmp; - bool bTmp; - int iDisabled; - - if (XMLUtils::GetString(pNode, "e2name", strTmp)) - XBMC->Log(LOG_DEBUG, "%s Processing timer '%s'", __FUNCTION__, strTmp.c_str()); - - if (!XMLUtils::GetInt(pNode, "e2state", iTmp)) - continue; - - if (!XMLUtils::GetInt(pNode, "e2disabled", iDisabled)) - continue; - - VuTimer timer; - - timer.strTitle = strTmp; - - if (XMLUtils::GetString(pNode, "e2servicereference", strTmp)) - timer.iChannelId = GetChannelNumber(strTmp.c_str()); - - if (!XMLUtils::GetInt(pNode, "e2timebegin", iTmp)) - continue; - - timer.startTime = iTmp; - - if (!XMLUtils::GetInt(pNode, "e2timeend", iTmp)) - continue; - - timer.endTime = iTmp; - - if (XMLUtils::GetString(pNode, "e2description", strTmp)) - timer.strPlot = strTmp.c_str(); - - if (XMLUtils::GetInt(pNode, "e2repeated", iTmp)) - timer.iWeekdays = iTmp; - else - timer.iWeekdays = 0; - - if (XMLUtils::GetInt(pNode, "e2eit", iTmp)) - timer.iEpgID = iTmp; - else - timer.iEpgID = 0; - - timer.state = PVR_TIMER_STATE_NEW; - - if (!XMLUtils::GetInt(pNode, "e2state", iTmp)) - continue; - - XBMC->Log(LOG_DEBUG, "%s e2state is: %d ", __FUNCTION__, iTmp); - - if (iTmp == 0) - { - timer.state = PVR_TIMER_STATE_SCHEDULED; - XBMC->Log(LOG_DEBUG, "%s Timer state is: SCHEDULED", __FUNCTION__); - } - - if (iTmp == 2) - { - timer.state = PVR_TIMER_STATE_RECORDING; - XBMC->Log(LOG_DEBUG, "%s Timer state is: RECORDING", __FUNCTION__); - } - - if (iTmp == 3 && iDisabled == 0) - { - timer.state = PVR_TIMER_STATE_COMPLETED; - XBMC->Log(LOG_DEBUG, "%s Timer state is: COMPLETED", __FUNCTION__); - } - - if (XMLUtils::GetBoolean(pNode, "e2cancled", bTmp)) - { - if (bTmp) - { - timer.state = PVR_TIMER_STATE_ABORTED; - XBMC->Log(LOG_DEBUG, "%s Timer state is: ABORTED", __FUNCTION__); - } - } - - if (iDisabled == 1) - { - timer.state = PVR_TIMER_STATE_CANCELLED; - XBMC->Log(LOG_DEBUG, "%s Timer state is: Cancelled", __FUNCTION__); - } - - if (timer.state == PVR_TIMER_STATE_NEW) - XBMC->Log(LOG_DEBUG, "%s Timer state is: NEW", __FUNCTION__); - - timers.push_back(timer); - - XBMC->Log(LOG_INFO, "%s fetched Timer entry '%s', begin '%d', end '%d'", __FUNCTION__, timer.strTitle.c_str(), timer.startTime, timer.endTime); - } - - XBMC->Log(LOG_INFO, "%s fetched %u Timer Entries", __FUNCTION__, timers.size()); - return timers; -} - -bool Vu::SendSimpleCommand(const CStdString& strCommandURL, CStdString& strResultText, bool bIgnoreResult) -{ - CStdString url; - url.Format("%s%s", m_strURL.c_str(), strCommandURL.c_str()); - - CStdString strXML; - strXML = GetHttpXML(url); - - if (!bIgnoreResult) - { - TiXmlDocument xmlDoc; - if (!xmlDoc.Parse(strXML.c_str())) - { - XBMC->Log(LOG_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); - return false; - } - - TiXmlHandle hDoc(&xmlDoc); - TiXmlElement* pElem; - TiXmlHandle hRoot(0); - - pElem = hDoc.FirstChildElement("e2simplexmlresult").Element(); - - if (!pElem) - { - XBMC->Log(LOG_DEBUG, "%s Could not find element!", __FUNCTION__); - return false; - } - - bool bTmp; - - if (!XMLUtils::GetBoolean(pElem, "e2state", bTmp)) - { - XBMC->Log(LOG_ERROR, "%s Could not parse e2state from result!", __FUNCTION__); - strResultText.Format("Could not parse e2state!"); - return false; - } - - if (!XMLUtils::GetString(pElem, "e2statetext", strResultText)) - { - XBMC->Log(LOG_ERROR, "%s Could not parse e2state from result!", __FUNCTION__); - return false; - } - - if (!bTmp) - XBMC->Log(LOG_ERROR, "%s Error message from backend: '%s'", __FUNCTION__, strResultText.c_str()); - - return bTmp; - } - return true; -} - - -PVR_ERROR Vu::AddTimer(const PVR_TIMER &timer) -{ - XBMC->Log(LOG_DEBUG, "%s - channelUid=%d title=%s epgid=%d", __FUNCTION__, timer.iClientChannelUid, timer.strTitle, timer.iEpgUid); - - CStdString strTmp; - CStdString strServiceReference = m_channels.at(timer.iClientChannelUid-1).strServiceReference.c_str(); - - time_t startTime, endTime; - startTime = timer.startTime - (timer.iMarginStart * 60); - endTime = timer.endTime + (timer.iMarginEnd * 60); - - if (!g_strRecordingPath.compare("")) - strTmp.Format("web/timeradd?sRef=%s&repeated=%d&begin=%d&end=%d&name=%s&description=%s&eit=%d&dirname=&s", URLEncodeInline(strServiceReference), timer.iWeekdays, startTime, endTime, URLEncodeInline(timer.strTitle), URLEncodeInline(timer.strSummary),timer.iEpgUid, URLEncodeInline(g_strRecordingPath)); - else - strTmp.Format("web/timeradd?sRef=%s&repeated=%d&begin=%d&end=%d&name=%s&description=%s&eit=%d", URLEncodeInline(strServiceReference), timer.iWeekdays, startTime, endTime, URLEncodeInline(timer.strTitle), URLEncodeInline(timer.strSummary),timer.iEpgUid); - - CStdString strResult; - if(!SendSimpleCommand(strTmp, strResult)) - return PVR_ERROR_SERVER_ERROR; - - TimerUpdates(); - - return PVR_ERROR_NO_ERROR; -} - -PVR_ERROR Vu::DeleteTimer(const PVR_TIMER &timer) -{ - CStdString strTmp; - CStdString strServiceReference = m_channels.at(timer.iClientChannelUid-1).strServiceReference.c_str(); - - time_t startTime, endTime; - startTime = timer.startTime - (timer.iMarginStart * 60); - endTime = timer.endTime + (timer.iMarginEnd * 60); - - strTmp.Format("web/timerdelete?sRef=%s&begin=%d&end=%d", URLEncodeInline(strServiceReference.c_str()), startTime, endTime); - - CStdString strResult; - if(!SendSimpleCommand(strTmp, strResult)) - return PVR_ERROR_SERVER_ERROR; - - if (timer.state == PVR_TIMER_STATE_RECORDING) - PVR->TriggerRecordingUpdate(); - - TimerUpdates(); - - return PVR_ERROR_NO_ERROR; -} - -PVR_ERROR Vu::GetRecordings(ADDON_HANDLE handle) -{ - // is the addon is currently updating the channels, then delay the call - unsigned int iTimer = 0; - while(m_bUpdating == true && iTimer < 120) - { - Sleep(1000); - iTimer++; - } - - m_iNumRecordings = 0; - m_recordings.clear(); - - for (unsigned int i=0; iLog(LOG_ERROR, "%s Error fetching lists for folder: '%s'", __FUNCTION__, m_locations[i].c_str()); - } - } - - TransferRecordings(handle); - - return PVR_ERROR_NO_ERROR; -} - -bool Vu::IsInRecordingFolder(CStdString strRecordingFolder) -{ - int iMatches = 0; - for (unsigned int i = 0; i < m_recordings.size(); i++) - { - if (strRecordingFolder.compare(m_recordings.at(i).strTitle) == 0) - { - iMatches++; - XBMC->Log(LOG_DEBUG, "%s Found Recording title '%s' in recordings vector!", __FUNCTION__, strRecordingFolder.c_str()); - if (iMatches > 1) - { - XBMC->Log(LOG_DEBUG, "%s Found Recording title twice '%s' in recordings vector!", __FUNCTION__, strRecordingFolder.c_str()); - return true; - } - } - } - - return false; -} - -void Vu::TransferRecordings(ADDON_HANDLE handle) -{ - for (unsigned int i=0; iTransferRecordingEntry(handle, &tag); - } -} - -bool Vu::GetRecordingFromLocation(CStdString strRecordingFolder) -{ - CStdString url; - - if (!strRecordingFolder.compare("default")) - url.Format("%s%s", m_strURL.c_str(), "web/movielist"); - else - url.Format("%s%s?dirname=%s", m_strURL.c_str(), "web/movielist", URLEncodeInline(strRecordingFolder.c_str())); - - CStdString strXML; - strXML = GetHttpXML(url); - - TiXmlDocument xmlDoc; - if (!xmlDoc.Parse(strXML.c_str())) - { - XBMC->Log(LOG_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); - return false; - } - - TiXmlHandle hDoc(&xmlDoc); - TiXmlElement* pElem; - TiXmlHandle hRoot(0); - - pElem = hDoc.FirstChildElement("e2movielist").Element(); - - if (!pElem) - { - XBMC->Log(LOG_DEBUG, "%s Could not find element!", __FUNCTION__); - return false; - } - - hRoot=TiXmlHandle(pElem); - - TiXmlElement* pNode = hRoot.FirstChildElement("e2movie").Element(); - - if (!pNode) - { - XBMC->Log(LOG_DEBUG, "Could not find element"); - return false; - } - - int iNumRecording = 0; - - for (; pNode != NULL; pNode = pNode->NextSiblingElement("e2movie")) - { - CStdString strTmp; - int iTmp; - - VuRecording recording; - - recording.iLastPlayedPosition = 0; - if (XMLUtils::GetString(pNode, "e2servicereference", strTmp)) - recording.strRecordingId = strTmp; - - if (XMLUtils::GetString(pNode, "e2title", strTmp)) - recording.strTitle = strTmp; - - if (XMLUtils::GetString(pNode, "e2description", strTmp)) - recording.strPlotOutline = strTmp; - - if (XMLUtils::GetString(pNode, "e2descriptionextended", strTmp)) - recording.strPlot = strTmp; - - if (XMLUtils::GetString(pNode, "e2servicename", strTmp)) - recording.strChannelName = strTmp; - - recording.strIconPath = GetChannelIconPath(strTmp.c_str()); - - if (XMLUtils::GetInt(pNode, "e2time", iTmp)) - recording.startTime = iTmp; - - if (XMLUtils::GetString(pNode, "e2length", strTmp)) - { - iTmp = TimeStringToSeconds(strTmp.c_str()); - recording.iDuration = iTmp; - } - else - recording.iDuration = 0; - - if (XMLUtils::GetString(pNode, "e2filename", strTmp)) - { - strTmp.Format("%sfile?file=%s", m_strURL.c_str(), URLEncodeInline(strTmp.c_str())); - recording.strStreamURL = strTmp; - } - - m_iNumRecordings++; - iNumRecording++; - - m_recordings.push_back(recording); - - XBMC->Log(LOG_DEBUG, "%s loaded Recording entry '%s', start '%d', length '%d'", __FUNCTION__, recording.strTitle.c_str(), recording.startTime, recording.iDuration); - } - - XBMC->Log(LOG_INFO, "%s Loaded %u Recording Entries from folder '%s'", __FUNCTION__, iNumRecording, strRecordingFolder.c_str()); - - return true; -} - -PVR_ERROR Vu::DeleteRecording(const PVR_RECORDING &recinfo) -{ - CStdString strTmp; - - strTmp.Format("web/moviedelete?sRef=%s", URLEncodeInline(recinfo.strRecordingId)); - - CStdString strResult; - if(!SendSimpleCommand(strTmp, strResult)) - return PVR_ERROR_FAILED; - - PVR->TriggerRecordingUpdate(); - - return PVR_ERROR_NO_ERROR; -} - -PVR_ERROR Vu::UpdateTimer(const PVR_TIMER &timer) -{ - - XBMC->Log(LOG_DEBUG, "%s timer channelid '%d'", __FUNCTION__, timer.iClientChannelUid); - - CStdString strTmp; - CStdString strServiceReference = m_channels.at(timer.iClientChannelUid-1).strServiceReference.c_str(); - - unsigned int i=0; - - while (iLog(LOG_DEBUG, "%s old timer channelid '%d'", __FUNCTION__, oldTimer.iChannelId); - - int iDisabled = 0; - if (timer.state == PVR_TIMER_STATE_CANCELLED) - iDisabled = 1; - - strTmp.Format("web/timerchange?sRef=%s&begin=%d&end=%d&name=%s&eventID=&description=%s&tags=&afterevent=3&eit=0&disabled=%d&justplay=0&repeated=%d&channelOld=%s&beginOld=%d&endOld=%d&deleteOldOnSave=1", URLEncodeInline(strServiceReference.c_str()), timer.startTime, timer.endTime, URLEncodeInline(timer.strTitle), URLEncodeInline(timer.strSummary), iDisabled, timer.iWeekdays, URLEncodeInline(strOldServiceReference.c_str()), oldTimer.startTime, oldTimer.endTime ); - - CStdString strResult; - if(!SendSimpleCommand(strTmp, strResult)) - return PVR_ERROR_SERVER_ERROR; - - TimerUpdates(); - - return PVR_ERROR_NO_ERROR; -} - -long Vu::TimeStringToSeconds(const CStdString &timeString) -{ - CStdStringArray secs; - SplitString(timeString, ":", secs); - int timeInSecs = 0; - for (unsigned int i = 0; i < secs.size(); i++) - { - timeInSecs *= 60; - timeInSecs += atoi(secs[i]); - } - return timeInSecs; -} - -int Vu::SplitString(const CStdString& input, const CStdString& delimiter, CStdStringArray &results, unsigned int iMaxStrings) -{ - int iPos = -1; - int newPos = -1; - int sizeS2 = delimiter.GetLength(); - int isize = input.GetLength(); - - results.clear(); - std::vector positions; - - newPos = input.Find (delimiter, 0); - - if ( newPos < 0 ) - { - results.push_back(input); - return 1; - } - - while ( newPos > iPos ) - { - positions.push_back(newPos); - iPos = newPos; - newPos = input.Find (delimiter, iPos + sizeS2); - } - - // numFound is the number of delimeters which is one less - // than the number of substrings - unsigned int numFound = positions.size(); - if (iMaxStrings > 0 && numFound >= iMaxStrings) - numFound = iMaxStrings - 1; - - for ( unsigned int i = 0; i <= numFound; i++ ) - { - CStdString s; - if ( i == 0 ) - { - if ( i == numFound ) - s = input; - else - s = input.Mid( i, positions[i] ); - } - else - { - int offset = positions[i - 1] + sizeS2; - if ( offset < isize ) - { - if ( i == numFound ) - s = input.Mid(offset); - else if ( i > 0 ) - s = input.Mid( positions[i - 1] + sizeS2, - positions[i] - positions[i - 1] - sizeS2 ); - } - } - results.push_back(s); - } - // return the number of substrings - return results.size(); -} - -PVR_ERROR Vu::GetChannelGroups(ADDON_HANDLE handle) -{ - // is the addon is currently updating the channels, then delay the call - unsigned int iTimer = 0; - while(m_bUpdating == true && iTimer < 120) - { - Sleep(1000); - iTimer++; - } - - for(unsigned int iTagPtr = 0; iTagPtr < m_groups.size(); iTagPtr++) - { - PVR_CHANNEL_GROUP tag; - memset(&tag, 0 , sizeof(PVR_CHANNEL_GROUP)); - - tag.bIsRadio = false; - tag.iPosition = 0; // groups default order, unused - strncpy(tag.strGroupName, m_groups[iTagPtr].strGroupName.c_str(), sizeof(tag.strGroupName)); - - PVR->TransferChannelGroup(handle, &tag); - } - - return PVR_ERROR_NO_ERROR; -} - -unsigned int Vu::GetNumChannelGroups() -{ - return m_iNumChannelGroups; -} - -CStdString Vu::GetGroupServiceReference(CStdString strGroupName) -{ - for (int i = 0;iLog(LOG_DEBUG, "%s - group '%s'", __FUNCTION__, group.strGroupName); - CStdString strTmp = group.strGroupName; - for (unsigned int i = 0;iLog(LOG_DEBUG, "%s - add channel %s (%d) to group '%s' channel number %d", - __FUNCTION__, myChannel.strChannelName.c_str(), tag.iChannelUniqueId, group.strGroupName, myChannel.iChannelNumber); - - PVR->TransferChannelGroupMember(handle, &tag); - } - } - return PVR_ERROR_NO_ERROR; -} - -const char* Vu::GetLiveStreamURL(const PVR_CHANNEL &channelinfo) -{ - SwitchChannel(channelinfo); - - return m_channels.at(channelinfo.iUniqueId-1).strStreamURL.c_str(); -} - -bool Vu::OpenLiveStream(const PVR_CHANNEL &channelinfo) -{ - XBMC->Log(LOG_INFO, "%s channel '%u'", __FUNCTION__, channelinfo.iUniqueId); - - if ((int)channelinfo.iUniqueId == m_iCurrentChannel) - return true; - - return SwitchChannel(channelinfo); -} - -void Vu::CloseLiveStream(void) -{ - m_iCurrentChannel = -1; -} - -int Vu::ReadLiveStream(unsigned char *pBuffer, unsigned int iBufferSize) -{ - return 0; -} - -long long Vu::SeekLiveStream(long long iPosition, int iWhence /* = SEEK_SET */) -{ - return 0; -} - -long long Vu::PositionLiveStream(void) -{ - return 0; -} - -long long Vu::LengthLiveStream(void) -{ - return 0; -} - -bool Vu::SwitchChannel(const PVR_CHANNEL &channel) -{ - XBMC->Log(LOG_DEBUG, "%s Switching channels", __FUNCTION__); - - if ((int)channel.iUniqueId == m_iCurrentChannel) - return true; - - m_iCurrentChannel = (int)channel.iUniqueId; - - if (g_bZap) - { - // Zapping is set to true, so send the zapping command to the PVR box - CStdString strServiceReference = m_channels.at(channel.iUniqueId-1).strServiceReference.c_str(); - - CStdString strTmp; - strTmp.Format("web/zap?sRef=%s", URLEncodeInline(strServiceReference)); - - CStdString strResult; - if(!SendSimpleCommand(strTmp, strResult)) - return false; - - } - return true; -} - -void Vu::SendPowerstate() -{ - if (!g_bSetPowerstate) - return; - - CLockObject lock(m_mutex); - CStdString strTmp; - strTmp.Format("web/powerstate?newstate=1"); - - CStdString strResult; - SendSimpleCommand(strTmp, strResult, true); -} - -bool Vu::GetDeviceInfo() -{ - CStdString url; - url.Format("%s%s", m_strURL.c_str(), "web/deviceinfo"); - - CStdString strXML; - strXML = GetHttpXML(url); - - TiXmlDocument xmlDoc; - if (!xmlDoc.Parse(strXML)) - { - XBMC->Log(LOG_DEBUG, "Unable to parse XML: %s at line %d", xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); - return false; - } - - TiXmlHandle hDoc(&xmlDoc); - TiXmlElement* pElem; - TiXmlHandle hRoot(0); - - pElem = hDoc.FirstChildElement("e2deviceinfo").Element(); - - if (!pElem) - { - XBMC->Log(LOG_ERROR, "%s Could not find element!", __FUNCTION__); - return false; - } - - CStdString strTmp;; - - XBMC->Log(LOG_NOTICE, "%s - DeviceInfo", __FUNCTION__); - - // Get EnigmaVersion - if (!XMLUtils::GetString(pElem, "e2enigmaversion", strTmp)) - { - XBMC->Log(LOG_ERROR, "%s Could not parse e2enigmaversion from result!", __FUNCTION__); - return false; - } - m_strEnigmaVersion = strTmp.c_str(); - XBMC->Log(LOG_NOTICE, "%s - E2EnigmaVersion: %s", __FUNCTION__, m_strEnigmaVersion.c_str()); - - // Get ImageVersion - if (!XMLUtils::GetString(pElem, "e2imageversion", strTmp)) - { - XBMC->Log(LOG_ERROR, "%s Could not parse e2imageversion from result!", __FUNCTION__); - return false; - } - m_strImageVersion = strTmp.c_str(); - XBMC->Log(LOG_NOTICE, "%s - E2ImageVersion: %s", __FUNCTION__, m_strImageVersion.c_str()); - - // Get WebIfVersion - if (!XMLUtils::GetString(pElem, "e2webifversion", strTmp)) - { - XBMC->Log(LOG_ERROR, "%s Could not parse e2webifversion from result!", __FUNCTION__); - return false; - } - m_strWebIfVersion = strTmp.c_str(); - XBMC->Log(LOG_NOTICE, "%s - E2WebIfVersion: %s", __FUNCTION__, m_strWebIfVersion.c_str()); - - // Get DeviceName - if (!XMLUtils::GetString(pElem, "e2devicename", strTmp)) - { - XBMC->Log(LOG_ERROR, "%s Could not parse e2devicename from result!", __FUNCTION__); - return false; - } - m_strServerName = strTmp.c_str(); - XBMC->Log(LOG_NOTICE, "%s - E2DeviceName: %s", __FUNCTION__, m_strServerName.c_str()); - - return true; -} - -const char SAFE[256] = -{ - /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ - /* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* 2 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* 3 */ 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, - - /* 4 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, - /* 5 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, - /* 6 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, - /* 7 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, - - /* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* 9 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* A */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* B */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - - /* C */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* D */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* E */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 -}; - - -CStdString Vu::URLEncodeInline(const CStdString& sSrc) -{ - const char DEC2HEX[16 + 1] = "0123456789ABCDEF"; - const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); - const int SRC_LEN = sSrc.length(); - unsigned char * const pStart = new unsigned char[SRC_LEN * 3]; - unsigned char * pEnd = pStart; - const unsigned char * const SRC_END = pSrc + SRC_LEN; - - for (; pSrc < SRC_END; ++pSrc) - { - if (SAFE[*pSrc]) - *pEnd++ = *pSrc; - else - { - // escape this char - *pEnd++ = '%'; - *pEnd++ = DEC2HEX[*pSrc >> 4]; - *pEnd++ = DEC2HEX[*pSrc & 0x0F]; - } - } - - std::string sResult((char *)pStart, (char *)pEnd); - delete [] pStart; - return sResult; -} - -int Vu::GetRecordingIndex(CStdString strStreamURL) -{ - for (unsigned int i = 0;i initialEPG; -}; - -struct VuChannel -{ - bool bRadio; - bool bInitialEPG; - int iUniqueId; - int iChannelNumber; - std::string strGroupName; - std::string strChannelName; - std::string strServiceReference; - std::string strStreamURL; - std::string strIconPath; -}; - -struct VuTimer -{ - std::string strTitle; - std::string strPlot; - int iChannelId; - time_t startTime; - time_t endTime; - int iWeekdays; - unsigned int iEpgID; - PVR_TIMER_STATE state; - int iUpdateState; - unsigned int iClientIndex; - - VuTimer() - { - iUpdateState = VU_UPDATE_STATE_NEW; - } - - bool like(const VuTimer &right) const - { - bool bChanged = true; - bChanged = bChanged && (startTime == right.startTime); - bChanged = bChanged && (endTime == right.endTime); - bChanged = bChanged && (iChannelId == right.iChannelId); - bChanged = bChanged && (iWeekdays == right.iWeekdays); - bChanged = bChanged && (iEpgID == right.iEpgID); - - return bChanged; - } - - bool operator==(const VuTimer &right) const - { - bool bChanged = true; - bChanged = bChanged && (startTime == right.startTime); - bChanged = bChanged && (endTime == right.endTime); - bChanged = bChanged && (iChannelId == right.iChannelId); - bChanged = bChanged && (iWeekdays == right.iWeekdays); - bChanged = bChanged && (iEpgID == right.iEpgID); - bChanged = bChanged && (state == right.state); - bChanged = bChanged && (! strTitle.compare(right.strTitle)); - bChanged = bChanged && (! strPlot.compare(right.strPlot)); - - return bChanged; - } -}; - -struct VuRecording -{ - std::string strRecordingId; - time_t startTime; - int iDuration; - int iLastPlayedPosition; - std::string strTitle; - std::string strStreamURL; - std::string strPlot; - std::string strPlotOutline; - std::string strChannelName; - std::string strDirectory; - std::string strIconPath; -}; - -class Vu : public P8PLATFORM::CThread -{ -private: - - // members - void *m_writeHandle; - void *m_readHandle; - std::string m_strEnigmaVersion; - std::string m_strImageVersion; - std::string m_strWebIfVersion; - bool m_bIsConnected; - std::string m_strServerName; - std::string m_strURL; - int m_iNumRecordings; - int m_iNumChannelGroups; - int m_iCurrentChannel; - unsigned int m_iUpdateTimer; - std::vector m_channels; - std::vector m_timers; - std::vector m_recordings; - std::vector m_groups; - std::vector m_locations; - unsigned int m_iClientIndexCounter; - - P8PLATFORM::CMutex m_mutex; - P8PLATFORM::CCondition m_started; - - bool m_bUpdating; - - // functions - CStdString GetHttpXML(CStdString& url); - int GetChannelNumber(CStdString strServiceReference); - CStdString GetChannelIconPath(CStdString strChannelName); - bool SendSimpleCommand(const CStdString& strCommandURL, CStdString& strResult, bool bIgnoreResult = false); - CStdString GetGroupServiceReference(CStdString strGroupName); - bool LoadChannels(CStdString strServerReference, CStdString strGroupName); - bool LoadChannels(); - bool LoadChannelGroups(); - bool LoadLocations(); - std::vector LoadTimers(); - void TimerUpdates(); - bool GetDeviceInfo(); - int GetRecordingIndex(CStdString); - - // helper functions - static long TimeStringToSeconds(const CStdString &timeString); - static int SplitString(const CStdString& input, const CStdString& delimiter, CStdStringArray &results, unsigned int iMaxStrings = 0); - bool CheckForGroupUpdate(); - bool CheckForChannelUpdate(); - std::string& Escape(std::string &s, std::string from, std::string to); - CStdString URLEncodeInline(const CStdString& sSrc); - bool IsInRecordingFolder(CStdString); - void TransferRecordings(ADDON_HANDLE handle); - -protected: - virtual void *Process(void); - -public: - Vu(void); - ~Vu(); - - const char * GetServerName(); - bool IsConnected(); - int GetChannelsAmount(void); - PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio); - PVR_ERROR GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd); - PVR_ERROR GetInitialEPGForChannel(ADDON_HANDLE handle, const VuChannel &channel, time_t iStart, time_t iEnd); - bool GetInitialEPGForGroup(VuChannelGroup &group); - int GetTimersAmount(void); - PVR_ERROR GetTimers(ADDON_HANDLE handle); - PVR_ERROR AddTimer(const PVR_TIMER &timer); - PVR_ERROR UpdateTimer(const PVR_TIMER &timer); - PVR_ERROR DeleteTimer(const PVR_TIMER &timer); - bool GetRecordingFromLocation(CStdString strRecordingFolder); - unsigned int GetRecordingsAmount(); - PVR_ERROR GetRecordings(ADDON_HANDLE handle); - PVR_ERROR DeleteRecording(const PVR_RECORDING &recinfo); - unsigned int GetNumChannelGroups(void); - PVR_ERROR GetChannelGroups(ADDON_HANDLE handle); - PVR_ERROR GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP &group); - const char* GetLiveStreamURL(const PVR_CHANNEL &channelinfo); - bool OpenLiveStream(const PVR_CHANNEL &channelinfo); - void CloseLiveStream(); - void SendPowerstate(); - bool SwitchChannel(const PVR_CHANNEL &channel); - bool Open(); - void Action(); - int ReadLiveStream(unsigned char *pBuffer, unsigned int iBufferSize); - long long SeekLiveStream(long long iPosition, int iWhence /* = SEEK_SET */); - long long PositionLiveStream(void); - long long LengthLiveStream(void); - bool m_bInitialEPG; -}; - diff -Nru kodi-pvr-vuplus-2.4.12/.travis.yml kodi-pvr-vuplus-3.15.0/.travis.yml --- kodi-pvr-vuplus-2.4.12/.travis.yml 2017-10-02 14:11:52.000000000 +0000 +++ kodi-pvr-vuplus-3.15.0/.travis.yml 2018-11-05 17:50:27.000000000 +0000 @@ -3,32 +3,28 @@ # # Define the build matrix # -# Travis defaults to building on Ubuntu Precise when building on -# Linux. We need Trusty in order to get up to date versions of +# Travis defaults to building on Ubuntu Trusty when building on +# Linux. We need Xenial in order to get up to date versions of # cmake and g++. # +env: + global: + - app_id=pvr.vuplus + matrix: include: - os: linux - dist: trusty + dist: xenial sudo: required compiler: gcc - os: linux - dist: trusty + dist: xenial sudo: required compiler: clang - os: osx - osx_image: xcode7.3 + osx_image: xcode9 - os: osx - osx_image: xcode6.1 - -# -# Some of the OS X images don't have cmake, contrary to what people -# on the Internet say -# -before_install: - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then which cmake || brew update ; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then which cmake || brew install cmake ; fi + osx_image: xcode9.4 # # The addon source is automatically checked out in $TRAVIS_BUILD_DIR, @@ -36,8 +32,10 @@ # before_script: - cd $TRAVIS_BUILD_DIR/.. - - git clone -b Krypton --depth=1 https://github.com/xbmc/xbmc.git - - cd pvr.vuplus && mkdir build && cd build - - cmake -DADDONS_TO_BUILD=pvr.vuplus -DADDON_SRC_PREFIX=$TRAVIS_BUILD_DIR/.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/../xbmc/addons -DPACKAGE_ZIP=1 $TRAVIS_BUILD_DIR/../xbmc/project/cmake/addons + - git clone --depth=1 https://github.com/xbmc/xbmc.git + - cd ${app_id} && mkdir build && cd build + - mkdir -p definition/${app_id} + - echo ${app_id} $TRAVIS_BUILD_DIR $TRAVIS_COMMIT > definition/${app_id}/${app_id}.txt + - cmake -DADDONS_TO_BUILD=${app_id} -DADDON_SRC_PREFIX=$TRAVIS_BUILD_DIR/.. -DADDONS_DEFINITION_DIR=$TRAVIS_BUILD_DIR/build/definition -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/../xbmc/addons -DPACKAGE_ZIP=1 $TRAVIS_BUILD_DIR/../xbmc/cmake/addons script: make