pax_global_header00006660000000000000000000000064135601241520014511gustar00rootroot0000000000000052 comment=e530acae22bbb6fa84e782da727eca5a72039b31 pvr.vuplus-3.28.9-Leia/000077500000000000000000000000001356012415200146305ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/.gitignore000066400000000000000000000007261356012415200166250ustar00rootroot00000000000000# build artifacts build/ debian/changelog debian/files debian/kodi-pvr-vuplus-dbg.debhelper.log debian/kodi-pvr-vuplus-dbg.substvars debian/kodi-pvr-vuplus-dbg/ debian/kodi-pvr-vuplus.debhelper.log debian/kodi-pvr-vuplus.postinst.debhelper debian/kodi-pvr-vuplus.postrm.debhelper debian/kodi-pvr-vuplus.substvars debian/kodi-pvr-vuplus/ debian/tmp/ obj-x86_64-linux-gnu/ pvr.vuplus/addon.xml # clion .idea/ # Eclipse/CDT .cproject .project .settings/ # VSCode .vscodepvr.vuplus-3.28.9-Leia/.travis.yml000066400000000000000000000022231356012415200167400ustar00rootroot00000000000000language: cpp # # Define the build matrix # # Travis defaults to building on Ubuntu Trusty when building on # Linux. We need Xenial in order to get up to date versions of # cmake and g++. # env: global: - app_id=pvr.vuplus matrix: include: - os: linux dist: xenial sudo: required compiler: gcc - os: linux dist: xenial sudo: required compiler: clang - os: osx osx_image: xcode9 - os: osx osx_image: xcode9.4 # # The addon source is automatically checked out in $TRAVIS_BUILD_DIR, # we'll put the Kodi source on the same level # before_script: - cd $TRAVIS_BUILD_DIR/.. - git clone --branch Leia --depth=1 https://github.com/xbmc/xbmc.git - cd ${app_id} && mkdir build && cd build - mkdir -p definition/${app_id} - echo ${app_id} $TRAVIS_BUILD_DIR $TRAVIS_COMMIT > definition/${app_id}/${app_id}.txt - cmake -DADDONS_TO_BUILD=${app_id} -DADDON_SRC_PREFIX=$TRAVIS_BUILD_DIR/.. -DADDONS_DEFINITION_DIR=$TRAVIS_BUILD_DIR/build/definition -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/../xbmc/addons -DPACKAGE_ZIP=1 $TRAVIS_BUILD_DIR/../xbmc/cmake/addons script: make pvr.vuplus-3.28.9-Leia/CMakeLists.txt000066400000000000000000000103021356012415200173640ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.5) project(pvr.vuplus) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}) find_package(Kodi REQUIRED) find_package(kodiplatform REQUIRED) find_package(NlohmannJson REQUIRED) find_package(p8-platform REQUIRED) find_package(TinyXML REQUIRED) include_directories(${kodiplatform_INCLUDE_DIRS} ${NLOHMANNJSON_INCLUDE_DIRS} ${p8-platform_INCLUDE_DIRS} ${TINYXML_INCLUDE_DIR} ${KODI_INCLUDE_DIR}) set(VUPLUS_SOURCES src/client.cpp src/Enigma2.cpp src/enigma2/Admin.cpp src/enigma2/Channels.cpp src/enigma2/ChannelGroups.cpp src/enigma2/ConnectionManager.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/ConnectionManager.h src/enigma2/Epg.h src/enigma2/IConnectionListener.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/BaseChannel.h src/enigma2/data/BaseEntry.h src/enigma2/data/Channel.h src/enigma2/data/ChannelGroup.h src/enigma2/data/EpgEntry.h src/enigma2/data/EpgPartialEntry.h src/enigma2/data/EpgChannel.h src/enigma2/data/RecordingEntry.h src/enigma2/data/Tags.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/SignalStatus.h src/enigma2/utilities/StreamStatus.h src/enigma2/utilities/Tuner.h src/enigma2/utilities/WebUtils.h) set(DEPLIBS ${kodiplatform_LIBRARIES} ${p8-platform_LIBRARIES} ${TINYXML_LIBRARIES}) addon_version(pvr.vuplus VUPLUS) add_definitions(-DVUPLUS_VERSION=${VUPLUS_VERSION}) build_addon(pvr.vuplus VUPLUS DEPLIBS) include(CPack) pvr.vuplus-3.28.9-Leia/FindNlohmannJson.cmake000066400000000000000000000010011356012415200210270ustar00rootroot00000000000000# - Find NlohmannJson # Find the native NlohmannJson includes # # NLOHMANNJSON_FOUND - True if NlohmannJson found. # NLOHMANNJSON_INCLUDE_DIRS - where to find nlohmann/json.hpp, etc. # find_path(NLOHMANNJSON_INCLUDE_DIR nlohmann/json.hpp) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(NlohmannJson DEFAULT_MSG NLOHMANNJSON_INCLUDE_DIR) if(NLOHMANNJSON_FOUND) set(NLOHMANNJSON_INCLUDE_DIRS ${NLOHMANNJSON_INCLUDE_DIR}) endif() mark_as_advanced(NLOHMANNJSON_INCLUDE_DIR) pvr.vuplus-3.28.9-Leia/FindTinyXML.cmake000066400000000000000000000015311356012415200177370ustar00rootroot00000000000000# - Find TinyXML # Find the native TinyXML includes and library # # TINYXML_FOUND - True if TinyXML found. # TINYXML_INCLUDE_DIRS - where to find tinyxml.h, etc. # TINYXML_LIBRARIES - List of libraries when using TinyXML. # find_package(PkgConfig) if(PKG_CONFIG_FOUND) pkg_check_modules(PC_TINYXML tinyxml QUIET) endif() find_path(TINYXML_INCLUDE_DIRS NAMES tinyxml.h PATHS ${PC_TINYXML_INCLUDEDIR} PATH_SUFFIXES tinyxml) find_library(TINYXML_LIBRARIES NAMES tinyxml PATHS ${PC_TINYXML_LIBDIR} PATH_SUFFIXES tinyxml) include("FindPackageHandleStandardArgs") find_package_handle_standard_args(TinyXML REQUIRED_VARS TINYXML_INCLUDE_DIRS TINYXML_LIBRARIES) mark_as_advanced(TINYXML_INCLUDE_DIRS TINYXML_LIBRARIES) pvr.vuplus-3.28.9-Leia/Jenkinsfile000066400000000000000000000000351356012415200170120ustar00rootroot00000000000000buildPlugin(version: "Leia") pvr.vuplus-3.28.9-Leia/README.md000066400000000000000000001116231356012415200161130ustar00rootroot00000000000000[![Build Status](https://travis-ci.org/kodi-pvr/pvr.vuplus.svg?branch=Leia)](https://travis-ci.org/kodi-pvr/pvr.vuplus/branches) [![Build Status](https://ci.appveyor.com/api/projects/status/github/kodi-pvr/pvr.vuplus?branch=Leia&svg=true)](https://ci.appveyor.com/project/kodi-pvr/pvr-vuplus?branch=Leia) [![Coverity Scan Build Status](https://scan.coverity.com/projects/5120/badge.svg)](https://scan.coverity.com/projects/5120) # Enigma2 PVR Enigma2 PVR client addon for [Kodi](https://kodi.tv) ## Overview 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 leverages the OpenWebIf project to interact with the Enigma2 device via Restful APIs: (https://github.com/E2OpenPlugins/e2openplugin-OpenWebif) ### Compatibility **Note:** Some images do not use OpenWebIf as the default web interface. In these images some standard functionality may still work but is not guaranteed. Some features that may not function include: * Autotimers * Drive Space Reporting * Embedded EPG Genre IDs * Full Tuner Signal Support (Including Service Providers) * Timer and Recording descriptions: If your provider only uses short description (plot outline) instead of long descrption (plot) then info will not be displayed pertaining to the shows in question. For OpenWebIf clients a JSON API is available to populate the missing data. * Edit recording name, last played position and play count for recordings * Bouquet Backend Channel Numbers Some features are only available with at least certain OpenWebIf versions: * 1.3.0 * AutoTimers * 1.3.5 * Embedded EPG Genres * Tuner Details * Provider Name * Picon URLs * 1.3.6 * Editing Recordings * 1.3.7 * Backend Channel Numbers ### IPTV Streams The majority of Enigma2 devices support viewing and recording IPTV streams. They do not however support streaming IPTV from the device. The addon supports IPTV by simply passing the URL used on the device to Kodi PVR. This means that timeshifting cannot be used (and will not be supported in the future). Note that if your IPTV provider restricts the number of active streams each kodi instance viewing it will count as an active stream. The option `Enable automatic configuration for live streams` is ignored for channels that are IPTV Streams. ## Build instructions ### Linux 1. `git clone --branch Leia 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/build/addons -DPACKAGE_ZIP=1 ../../xbmc/cmake/addons` 5. `make` The addon files will be placed in `../../xbmc/build/addons` so if you build Kodi from source and run it directly the addon will be available as a system addon. ### Mac OSX In order to build the addon on mac the steps are different to Linux and Windows as the cmake command above will not produce an addon that will run in kodi. Instead using make directly as per the supported build steps for kodi on mac we can build the tools and just the addon on it's own. Following this we copy the addon into kodi. Note that we checkout kodi to a separate directory as this repo will only only be used to build the addon and nothing else. #### Build tools and initial addon build 1. Get the repos * `cd $HOME` * `git clone https://github.com/xbmc/xbmc xbmc-addon` * `git clone https://github.com/kodi-pvr/pvr.vuplus` 2. Build the kodi tools * `cd $HOME/xbmc-addon/tools/depends` * `./bootstrap` * `./configure --host=x86_64-apple-darwin` * `make -j$(getconf _NPROCESSORS_ONLN)` 3. Build the addon * `cd $HOME/xbmc-addon` * `make -j$(getconf _NPROCESSORS_ONLN) -C tools/depends/target/binary-addons ADDONS="pvr.vuplus" ADDON_SRC_PREFIX=$HOME` Note that the steps in the following section need to be performed before the addon is installed and you can run it in Kodi. #### To rebuild the addon and copy to kodi after changes (after the initial addon build) 1. `cd $HOME/pvr.vuplus` 2. `./build-install-mac.sh ../xbmc-addon` If you would prefer to run the rebuild steps manually instead of using the above helper script check the appendix [here](#manual-steps-to-rebuild-the-addon-on-macosx) ## Support ### Useful links * [Kodi's PVR user support forum](https://forum.kodi.tv/forumdisplay.php?fid=167) * [Report an issue on Github](https://github.com/kodi-pvr/pvr.vuplus/issues) * [Kodi's PVR development support forum](https://forum.kodi.tv/forumdisplay.php?fid=136) ### Logging When reporting issues a debug log should always be supplied. You can use the following guide: [Easy way to submit Kodi debug logs](https://kodi.wiki/view/Log_file/Easy) For more detailed info on logging please see the appendix [here](#logging-detailed) ## Configuring the addon ### Settings Levels In Kodi 18.2 the level of settings shown will correspond to the level set in the main kodi settings UI: `Basic`, `Standard`, `Advanced` and `Expert`. From Kodi 19 it will be possible to change the settingds level from within the addon settings itself. ### 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 M3U8 file. When disabled it is constructed based on the service reference of the channel. This option is rarely required and should not be enbaled unless you have a special use case. If viewing an IPTV Stream this option has no effect on those channels. * **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. * **Use secure HTTP (https) for streams**: Use https to connect to streams. * **Use login for streams**: Use the login username and password for streams. * **Connection check timeout**: The value in seconds to wait for a connection check to complete before failure. Useful for tuning on older Enigma2 devices. Note, this setting should rarely need to be changed. It's more likely the `Connection check interval` setting will have the desired effect. Default is 30 seconds. * **Connection check interval**: The value in seconds to wait between connection checks. Useful for tuning on older Enigma2 devices. Default is 10 seconds. ### General Within this tab general options are configured. * **Set program id for live channel streams**: Some TV Providers (e.g. Nos - Portugal) using MPTS send extra program stream information. Setting the program id allows kodi to select the correct stream and therefore makes the channel/recording playable. Note that it takes approx 33% longer to open any stream with this option enabled. * **Fetch picons from web interface**: Fetch the picons straight from the Enigma 2 set-top box. * **Use picons.eu file format**: Assume all picons files fetched from the set-top box start with `1_1_1_` and end with `_0_0_0`. * **Use OpenWebIf picon path**: Fetch the picon path from OpenWebIf instead of constructing from ServiceRef. Requires OpenWebIf 1.3.5 or higher. There is no effect if used on a lower version of OpenWebIf. * **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. Please note that updating the recordings frequently can keep your receiver and it's harddisk from entering standby automatically. * **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. If it's important to not spin up the HDD on your STB use this option. The HDD should then only spin up when a timer event occurs. * **Channel and groups update mode**: The mode used when the hour in the next settings is reached. Choose from one of the following three modes: - `Disabled` - Never check for channel and group changes. - `Notify on UI and Log` - Display a notice in the UI and log the fact that a change was detectetd. - `Reload Channels and Groups` - Disconnect and reconnect with E2 device to reload channels only if a change is detected. * **Channel and group update hour (24h)**: The hour of the day when the check for new channels should occur. Default is 4h as the Auto Bouquet Maker (ABM) on the E2 device defaults to 3AM. ### 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`. Note that channel numbers are set in the addon based on their first occurence when loaded, i.e. if a channel appears in multiple bouqets the channel number will be taken from the first bouquet in which it is loaded, any subsequent channel numbers will be ignored. Therefore if it's desired to keep the same channel numbers across the Enigma2 device and the addon the following guidelines should be adhered to: * If a master bouquet is used it should be the first bouquet loaded assuming it has the channel numbering/order you require. * If not using a master bouquet each channel should only appear in a single bouquet (i.e. do not use channels in multiple bouquets unless they have different service references). If Kodi PVR is set to use the channel numbers from the backend the numbers will match those on your STB. If this is not enabled each unique instance of a channel will be given the next free number starting from 1 (i.e. the 17th unique channel will be channel 17). Backend channel numbers will only work for OpenWebIf 1.3.5 and later and they have been tested using ABM (AutoBouquetsMaker). * **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. * **Use standard channel service reference**: Usually service reference's for the channels are in a standard format like `1:0:1:27F6:806:2:11A0000:0:0:0:`. On occasion depending on provider they can be extended with some text e.g. `1:0:1:27F6:806:2:11A0000:0:0:0::UTV` or `1:0:1:27F6:806:2:11A0000:0:0:0::UTV + 1`. If this option is enabled then all read service reference's will be read as standard. This is default behaviour. Functionality like autotimers will always convert to a standard reference. * **TV bouquet fetch mode**: Choose from one of the following three modes: - `All bouquets` - Fetch all TV bouquets from the set-top box. - `Some bouquets` - Only fetch the bouquet specified in the next option - `Favourites bouquet` - Only fetch the system bouquet for TV favourites. - `Custom bouquets` - Fetch a set of bouquets from the Set-top box whose names are loaded from an XML file. * **Number of TV bouquets**: The number of TV bouquets to load when `Some bouquets` is the selected fetch mode. Up to 5 can be chosen. If more than 5 are required the `Custom bouquets` fetch mode should be used instead. * **TV bouquet 1-5**: If the previous option has been has been set to `Some bouquets` you need to specify a 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. * **Custom TV Groups file**: The file used to load the custom TV bouquets (groups). If no groups can be matched the channel list will default to 'Last Scanned (TV)'. The default file is `customTVGroups-example.xml`. Details on how to customise can be found in the next section of the README. * **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. * **Exclude last scanned bouquet**: Last scanned is a system bouquet containing all the TV and Radio channels found in the last scan. Any TV channels found in the Last Scanned bouquet can be displayed as a group called ```Last Scanned (TV)``` in Kodi. For TV this group is excluded by default. Disable this option to exclude this group. Note that if no TV groups are loaded the Last Scanned group for TV will be loaded by default regardless of this setting. * **Radio bouquet fetch mode**: Choose from one of the following three modes: - `All bouquets` - Fetch all Radio bouquets from the set-top box. - `Some bouquets` - Only fetch the bouquet specified in the next option - `Favourites bouquet` - Only fetch the system bouquet for Radio favourites. - `Custom bouquets` - Fetch a set of bouquets from the Set-top box whose names are loaded from an XML file. * **Number of radio bouquets**: The number of Radio bouquets to load when `Some bouquets` is the selected fetch mode. Up to 5 can be chosen. If more than 5 are required the `Custom bouquets` fetch mode should be used instead. * **Radio bouquet 1-5**: If the previous option has been has been set to `Some bouquets` you need to specify a 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. * **Custom Radio Groups file**: The file used to load the custom Radio bouquets (groups). If no groups can be matched the channel list will default to 'Last Scanned (Radio)'. The default file is `customRadioGroups-example.xml`. Details on how to customise can be found in the next section of the README. * **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. * **Exclude last scanned bouquet**: Last scanned is a system bouquet containing all the TV and Radio channels found in the last scan. Any Radio channels found in the Last Scanned bouquet can be displayed as a group called ```Last Scanned (Radio)``` in Kodi. For Radio this group is excluded by default. Disable this option to show this group. ### 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] * **EPG update delay per channel**: For older Enigma2 devices EPG updates can effect streaming quality (such as buffer timeouts). A delay of between 250ms and 5000ms can be introduced to improve quality. Only recommended for older devices. Choose the lowest value that avoids buffer timeouts. * **Skip intial EPG load**: Ignore the intial EPG load (now and next). Enabled by default to prevent crash issues on LibreElec/CoreElec. ### Recordings The following configuration is available on the Recordings tab of the addon settings. * **Store last played/play count on the backend**: Store last played position and count on the backend so they can be shared across kodi instances. Only supported on OpenWebIf version 1.3.6+. * **Share last played across**: The options are: - `Kodi instances` - Only use the value in kodi and will not affect last played on the E2 device. - `Kodi/E2 instances` - Use the value across kodi and the E2 device so they stay in sync. Last played will be synced with the E2 device once every 5-10 minutes per recording if the PVR menus are in use. Note that only a single kodi instance is required to have this option enabled. * **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 EDLs support**: EDLs are used to define commericals etc. in recordings. If a tool like [Comskip]() is used to generate EDL files enabling this will allow Kodi PVR to use them. E.g. if there is a file called ```my recording.ts``` the EDL file should be call ```my recording.edl```. Note: enabling this setting has no effect if the files are not present. * **EDL start time padding**: Padding to use at an EDL stop. I.e. use a negative number to start the cut earlier and positive to start the cut later. Default 0. * **EDL stop time padding**: Padding to use at an EDL stop. I.e. use a negative number to stop the cut earlier and positive to stop the cut later. Default 0. ### Timers **Using Padding for Timers in Kodi PVR** Using padding for timers allows you to start a recording some time earlier and finish later in case the actual start and/or run time of a show is incorrect. It's important to note that Enigma2 devices allow you set a padding for all timers, both regular timers and autotimers but it only applies to timers created on the Enigma2 device directly. In the case of autotimers it does not matter if they are created from Kodi or directly on the Enigma2 device as new once off timers are generated on the device so will use this default device padding. It is not possible to set padding for autotimers directly in Kodi PVR at present. You can change these settings on your Enigma2 device as follows: 1. Hit `Menu` on the remote and go to `Setup->Recordings, playback & timeshift->Recording & playback` 2. Set the following options to your chosen values: * `Margin before recording (minutes)` * `Margin after recording (minutes)` If setting padding in Kodi PVR it's only supported on certain timer types, i.e. `Once off time/channel based`, `Repeating time/channel based` and `One time guide-based`. As the Enigma2 device does not support padding per Timer the `tags` field is used to store the padding set in Kodi PVR. If a padding value is not set for these timer types the addon will use the Enigma2 devices default padding value instead. So if you have set a value on the Enigma2 device, this can be overidden in the Kodi UI (note, the default from the Enigma2 device does not display in the Add Timer UI, it won't show until after the timer is created and only if no padding values are set). **Timer Types** The addon provides the following types of timers and timer rules that the user can create: * **Once off time/channel based**: This timer can be created from the add timer UI on the main PVR screen (It cannot be selected from the EPG UI). If running OpenWebIf the timer will be populated with the EPG Entry (if available) at the start time for that channel. * **Repeating time/channel based**: This timer can be created from the add timer UI on the main PVR screen (It cannot be selected from the EPG UI). This type is a timer rule and generates timers. The timers that are generated cannot be edited and will be of the type `Once off timer (set by repeating time/channel based rule)`. * **One time guide-based**: This timer can be created from the EPG UI as well as when playing a channel. It is the timer used when the user selects `Record` when accessing an EPG entry. It will create a timer that starts and ends as per the EPG entry. If playing back a channel it will start from now until the end of the current show. If using OpenWebIf, for providers that only use short description (plot outline) the addon will retrieve the correct description if available and use it in both the timer and resulting recording. * **Auto guide-based**: This is a search based timer rule, using the show name and other factors the Enigma2 device will create timers for EPG entries that satisfy the search. The timers it creates are not editable and will be of the type `Once off timer (set by auto guide-based rule)`. In addition there are some timers that can only be created by the addon and are read only: * **Once off timer (set by repeating time/channel based rule)**: Timer generated by a `Repeating time/channel based` timer rule. Will contain padding that can't be modified the same as the parent timer rule. * **Once off timer (set by auto guide-based rule)**: Timer created by an `Auto guide-based` timer rule. * **Repeating guide-based**: This type can only be created directly on the Enigma2 device. The type exists to allow users to view the timers in the PVR UI. **Timer settings** The following are the settings in the Timers tab: * **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. * **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. * **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` * **Limit 'Any Channel' autotimers to TV or Radio**: If last scanned groups are excluded attempt to limit new autotimers to either TV or Radio (dependent on channel used to create the autotimer). Note that if last scanned groups are enabled this is not possible and the setting will be ignored. * **Limit to groups of original EPG channel**: For the channel used to create the autotimer limit to channel groups that this channel is a member of. ### Timeshift Timeshifting allows you to pause live TV as well as move back and forward from your current position similar to playing back a recording. The buffer is deleted each time a channel is changed or stopped. * **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 timeshift buffer. The default is the `addon_data/pvr.vuplus` 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. Default for live streams is 0. Default for timeshifting is 10 seconds. * **Stream read chunk size**: The chunk size used by Kodi for streams. Default 0 to leave it to Kodi to decide. * **Ignore debug logging in debug mode**: Debug log statements will not be displayed for the addon even though debug logging is enabled in Kodi. This can be useful when trying to debug an issue in Kodi which is not addon related. * **Enable debug logging in normal mode**: Debug log statements will display for the addon even though debug logging may not be enabled in Kodi. Note that all debug log statements will display at NOTICE level. * **Enable trace logging in debug mode**: Very detailed and verbose log statements will display in addition to standard debug statements. If enabled along with `Enable debug logging in normal mode` both trace and debug will display without debug logging enabled. In this case both debug and trace log statements will display at NOTICE level. ## Customising Config Files The various config files have examples allowing users to create their own, making it possible to support custom config, 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 in the case of EPG relatd config and for channel related config will need to clear the full cache `Settings->PVR & Live TV->General->Clear cache`. 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. ### Custom Channel Groups (Channels) Config files are located in the `userdata/addon_data/pvr.vuplus/channelGroups` folder. The following files are currently available with the addon: - `customTVGroups-example.xml` - `customRadioGroups-example.xml` Note that both these files are provided as examples and are overwritten each time the addon starts. Therefore you should make copies and use those for your custom config. The format is quite simple, containing a number of channel group/bouquet names. ### Season, Episode and Year Show Info (EPG_) 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 (EPG) 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 (EPG) 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. ## Appendix ### Manual Steps to rebuild the addon on MacOSX The following steps can be followed manually instead of using the `build-install-mac.sh` in the root of the addon repo after the [initial addon build](#build-tools-and-initial-addon-build) has been completed. **To rebuild the addon after changes** 1. `rm tools/depends/target/binary-addons/.installed-macosx*` 2. `make -j$(getconf _NPROCESSORS_ONLN) -C tools/depends/target/binary-addons ADDONS="pvr.vuplus" ADDON_SRC_PREFIX=$HOME` or 1. `cd tools/depends/target/binary-addons/macosx*` 2. `make` **Copy the addon to the Kodi addon directory on Mac** 1. `rm -rf "$HOME/Library/Application Support/Kodi/addons/pvr.vuplus"` 2. `cp -rf $HOME/xbmc-addon/addons/pvr.vuplus "$HOME/Library/Application Support/Kodi/addons"` ### Logging detailed Some of the most useful information in your log are the details output at the start of the log, both for Kodi and the addon. The first 5 lines of the log give details on the exact kodi flavour and version you are running: ``` 01:10:45.744 T:140736264741760 NOTICE: ----------------------------------------------------------------------- 01:10:45.744 T:140736264741760 NOTICE: Starting Kodi (18.0-BETA2 Git:20180903-5d7e1dbd9c-dirty). Platform: OS X x86 64-bit 01:10:45.744 T:140736264741760 NOTICE: Using Debug Kodi x64 build 01:10:45.744 T:140736264741760 NOTICE: Kodi compiled Sep 5 2018 by Clang 9.1.0 (clang-902.0.39.2) for OS X x86 64-bit version 10.9.0 (1090) 01:10:45.745 T:140736264741760 NOTICE: Running on Apple Inc. MacBook10,1 with OS X 10.13.6, kernel: Darwin x86 64-bit version 17.7.0 ``` Secondly all the information of the Enigma2 image, web interface version etc. is also output: ``` 12:36:55.888 T:123145422725120 NOTICE: AddOnLog: Enigma2 Client: pvr.vuplus - Open - VU+ Addon Configuration options 12:36:55.888 T:123145422725120 NOTICE: AddOnLog: Enigma2 Client: pvr.vuplus - Open - Hostname: '192.168.1.201' 12:36:55.888 T:123145422725120 NOTICE: AddOnLog: Enigma2 Client: pvr.vuplus - Open - WebPort: '80' 12:36:55.888 T:123145422725120 NOTICE: AddOnLog: Enigma2 Client: pvr.vuplus - Open - StreamPort: '8001' 12:36:55.888 T:123145422725120 NOTICE: AddOnLog: Enigma2 Client: pvr.vuplus - Open Use HTTPS: 'false' 12:36:56.308 T:123145422725120 NOTICE: AddOnLog: Enigma2 Client: pvr.vuplus - LoadDeviceInfo - DeviceInfo 12:36:56.308 T:123145422725120 NOTICE: AddOnLog: Enigma2 Client: pvr.vuplus - LoadDeviceInfo - E2EnigmaVersion: 2019-01-03 12:36:56.308 T:123145422725120 NOTICE: AddOnLog: Enigma2 Client: pvr.vuplus - LoadDeviceInfo - E2ImageVersion: 5.2.022 12:36:56.309 T:123145422725120 NOTICE: AddOnLog: Enigma2 Client: pvr.vuplus - LoadDeviceInfo - E2DistroVersion: openvix 12:36:56.309 T:123145422725120 NOTICE: AddOnLog: Enigma2 Client: pvr.vuplus - LoadDeviceInfo - E2WebIfVersion: OWIF 1.3.5 12:36:56.309 T:123145422725120 NOTICE: AddOnLog: Enigma2 Client: pvr.vuplus - LoadDeviceInfo - E2DeviceName: Ultimo4K ``` #### Description of Log levels * **Error**: Something that will require intervention to resolve * **Notice**: Could be an important piece of information or a warning that something has occurred that might be undesirable but has not affected normal operation * **Info**: Some information on normal operation * **Debug**: More detailed information that can aid in diagnosing issues. * **Trace**: Extremely verbose logging, should rarely be required. Note: can only be enabled from the addon settings in the ```Advanced``` section. #### Cleaning up the log (If you have a fresh install of version 3.15.0 or later you can ignore this) As the addon was upgraded over time some old settings are no longer required. These old settings can create a lot of extra logging on startup. To date there are four of these and they will present like this in your log: ``` 23:17:22.696 T:3990016880 DEBUG: CSettingsManager: requested setting (extracteventinfo) was not found. 23:17:22.696 T:3990016880 DEBUG: CAddonSettings[pvr.vuplus]: failed to find definition for setting extracteventinfo. Creating a setting on-the-fly... 23:17:22.696 T:3990016880 DEBUG: CSettingsManager: requested setting (onegroup) was not found. 23:17:22.696 T:3990016880 DEBUG: CAddonSettings[pvr.vuplus]: failed to find definition for setting onegroup. Creating a setting on-the-fly... 23:17:22.696 T:3990016880 DEBUG: CSettingsManager: requested setting (onlyonegroup) was not found. 23:17:22.696 T:3990016880 DEBUG: CAddonSettings[pvr.vuplus]: failed to find definition for setting onlyonegroup. Creating a setting on-the-fly... 23:17:22.697 T:3990016880 DEBUG: CSettingsManager: requested setting (setpowerstate) was not found. 23:17:22.697 T:3990016880 DEBUG: CAddonSettings[pvr.vuplus]: failed to find definition for setting setpowerstate. Creating a setting on-the-fly... ``` If you see these in debug mode and would like to clean them up you can either: 1. Remove the offending lines from you settings.xml file OR 2. Delete you settings.xml and restart kodi. Note that if you use this option you will need to reconfigure the addon from scratch. Your settings.xml file can be found here: ```userdata/addon_data/pvr.vuplus/settings.xml``` pvr.vuplus-3.28.9-Leia/appveyor.yml000066400000000000000000000022411356012415200172170ustar00rootroot00000000000000version: BuildNr.{build} image: Visual Studio 2015 shallow_clone: true clone_folder: c:\projects\pvr.vuplus environment: app_id: pvr.vuplus matrix: - GENERATOR: "Visual Studio 14" CONFIG: Release - GENERATOR: "Visual Studio 14 Win64" CONFIG: Release - GENERATOR: "Visual Studio 14 Win64" CONFIG: Release WINSTORE: -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0.16299.0" - GENERATOR: "Visual Studio 14 ARM" CONFIG: Release WINSTORE: -DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION="10.0.16299.0" build_script: - cd .. - git clone --branch Leia --depth=1 https://github.com/xbmc/xbmc.git - cd %app_id% - mkdir build - cd build - mkdir -p definition\%app_id% - echo %app_id% %APPVEYOR_BUILD_FOLDER% %APPVEYOR_REPO_COMMIT% > definition\%app_id%\%app_id%.txt - cmake -T host=x64 -G "%GENERATOR%" %WINSTORE% -DADDONS_TO_BUILD=%app_id% -DCMAKE_BUILD_TYPE=%CONFIG% -DADDONS_DEFINITION_DIR=%APPVEYOR_BUILD_FOLDER%/build/definition -DADDON_SRC_PREFIX=../.. -DCMAKE_INSTALL_PREFIX=../../xbmc/addons -DPACKAGE_ZIP=1 ../../xbmc/cmake/addons - cmake --build . --config %CONFIG% --target %app_id% pvr.vuplus-3.28.9-Leia/build-install-mac.sh000077500000000000000000000030361356012415200204720ustar00rootroot00000000000000#!/bin/bash set -e if [ "$#" -ne 1 ] || ! [ -d "$1" ]; then echo "Usage: $0 " >&2 exit 1 fi if [[ "$OSTYPE" != "darwin"* ]]; then echo "Error: Script only for use on MacOSX" >&2 exit 1 fi SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" if [[ "$1" = /* ]] then #absolute path SCRIPT_DIR="" else #relative SCRIPT_DIR="$SCRIPT_DIR/" fi BINARY_ADDONS_TARGET_DIR="$1/tools/depends/target/binary-addons" MACOSX_BINARY_ADDONS_TARGET_DIR="" KODI_ADDONS_DIR="$HOME/Library/Application Support/Kodi/addons" ADDON_NAME=`basename -s .git \`git config --get remote.origin.url\`` if [ ! -d "$BINARY_ADDONS_TARGET_DIR" ]; then echo "Error: Could not find binary addons directory at: $BINARY_ADDONS_TARGET_DIR" >&2 exit 1 fi for DIR in "$BINARY_ADDONS_TARGET_DIR/"macosx*; do if [ -d "${DIR}" ]; then MACOSX_BINARY_ADDONS_TARGET_DIR="${DIR}" break fi done if [ -z "$MACOSX_BINARY_ADDONS_TARGET_DIR" ]; then echo "Error: Could not find binary addons build directory at: $BINARY_ADDONS_TARGET_DIR/macosx*" >&2 exit 1 fi if [ ! -d "$KODI_ADDONS_DIR" ]; then echo "Error: Kodi addons dir does not exist at: $KODI_ADDONS_DIR" >&2 exit 1 fi cd "$MACOSX_BINARY_ADDONS_TARGET_DIR" make XBMC_BUILD_ADDON_INSTALL_DIR=$(cd "$SCRIPT_DIR$1/addons/$ADDON_NAME" 2> /dev/null && pwd -P) rm -rf "$KODI_ADDONS_DIR/$ADDON_NAME" echo "Removed previous addon build from: $KODI_ADDONS_DIR" cp -rf "$XBMC_BUILD_ADDON_INSTALL_DIR" "$KODI_ADDONS_DIR" echo "Copied new addon build to: $KODI_ADDONS_DIR" pvr.vuplus-3.28.9-Leia/debian/000077500000000000000000000000001356012415200160525ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/debian/changelog.in000066400000000000000000000003031356012415200203250ustar00rootroot00000000000000kodi-pvr-vuplus (#PACKAGEVERSION#-#TAGREV#~#DIST#) #DIST#; urgency=low [ kodi ] * autogenerated dummy changelog -- Cristiano A. Silva Mon, 23 Feb 2015 15:56:31 +0000 pvr.vuplus-3.28.9-Leia/debian/compat000066400000000000000000000000021356012415200172500ustar00rootroot000000000000009 pvr.vuplus-3.28.9-Leia/debian/control000066400000000000000000000012341356012415200174550ustar00rootroot00000000000000Source: kodi-pvr-vuplus Priority: extra Maintainer: Cristiano A. Silva Build-Depends: debhelper (>= 9.0.0), cmake, libtinyxml-dev, libkodiplatform-dev (>= 16.0.0), kodi-addon-dev, nlohmann-json-dev (>= 3.1) | nlohmann-json3-dev (>= 3.1) Standards-Version: 3.9.4 Section: libs Package: kodi-pvr-vuplus Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: Vu+ PVR for Kodi Vu+ PVR for Kodi Package: kodi-pvr-vuplus-dbg Section: debug Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: debug symbols for Vu+ PVR for Kodi debug symbols for Vu+ PVR for Kodi pvr.vuplus-3.28.9-Leia/debian/copyright000066400000000000000000000033701356012415200200100ustar00rootroot00000000000000Format: http://dep.debian.net/deps/dep5 Upstream-Name: pvr.vuplus Files: * Copyright: 2005-2015 Team XBMC License: GPL-2+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. . This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see . On Debian systems, the complete text of the GNU General Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". Files: debian/* Copyright: 2013-2015 Cristiano A. Silva 2013 wsnipex License: GPL-2+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. . This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see . On Debian systems, the complete text of the GNU General Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". pvr.vuplus-3.28.9-Leia/debian/kodi-pvr-vuplus.install000066400000000000000000000000261356012415200225270ustar00rootroot00000000000000usr/lib/* usr/share/* pvr.vuplus-3.28.9-Leia/debian/rules000077500000000000000000000013011356012415200171250ustar00rootroot00000000000000#!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # This file was originally written by Joey Hess and Craig Small. # As a special exception, when this file is copied by dh-make into a # dh-make output file, you may use that output file without restriction. # This special exception was added by Craig Small in version 0.37 of dh-make. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 %: dh $@ override_dh_auto_configure: dh_auto_configure -- -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 -DUSE_LTO=1 override_dh_strip: dh_strip -pkodi-pvr-vuplus --dbg-package=kodi-pvr-vuplus-dbg override_dh_installdocs: dh_installdocs --link-doc=kodi-pvr-vuplus pvr.vuplus-3.28.9-Leia/debian/source/000077500000000000000000000000001356012415200173525ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/debian/source/format000066400000000000000000000000171356012415200205630ustar00rootroot000000000000003.0 (native) ßpvr.vuplus-3.28.9-Leia/depends/000077500000000000000000000000001356012415200162525ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/depends/common/000077500000000000000000000000001356012415200175425ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/depends/common/nlohmann-json/000077500000000000000000000000001356012415200223235ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/depends/common/nlohmann-json/flags.txt000066400000000000000000000000311356012415200241520ustar00rootroot00000000000000-DBUILD_TESTING:BOOL=OFF pvr.vuplus-3.28.9-Leia/depends/common/nlohmann-json/nlohmann-json.sha256000066400000000000000000000001011356012415200260260ustar00rootroot0000000000000080c45b090e40bf3d7a7f2a6e9f36206d3ff710acfa8d8cc1f8c763bb3075e22e pvr.vuplus-3.28.9-Leia/depends/common/nlohmann-json/nlohmann-json.txt000066400000000000000000000001051356012415200256410ustar00rootroot00000000000000nlohmann-json https://github.com/nlohmann/json/archive/v3.6.1.tar.gz pvr.vuplus-3.28.9-Leia/pvr.vuplus/000077500000000000000000000000001356012415200167745ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/addon.xml.in000066400000000000000000001070461356012415200212200ustar00rootroot00000000000000 @ADDON_DEPENDS@ Kodi se voorprogram vir VU+ / Enigma2 gebasseerde 'set-top' bokse Kodi's frontend for VU+ / Enigma2 based settop boxes Клиент за уÑтройÑтва, базирани на VU+ / Enigma2 Frontal de Kodi per als descodificadors basats en VU+/Enigma2 Rozhraní Kodi pro pÅ™ijímaÄe založené na Enigma2 Blaen Kodi ar gyfer blychau teledu VU+ / Enigma2 Kodi's frontend til VU+ / Enigma2 baseret pÃ¥ settop bokse 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 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 Frontend Kodi para decodificadores basados en VU+/Enigma2 Kodi frontend para cajas fijas basadas en VU + / Enigma2 Kodi liides VU+ / Enigma2 põhistele digiboksidele Kodin VU+/ Enigma2-asiakasohjelma Frontale Kodi pour les boîtiers décodeurs fondés sur Enigma2 Interface logicielle pour les enregistreurs VU+/Enigma2 Interface de Kodi para decodificadores equipados con VU+/Enigma2 לקוח טלוויזיה ×—×™×” עבור מכשירי VU+ ×ו מבוססי Enigma2 Kodi suÄelje za VU+ / Enigma2 set-top box temeljene ureÄ‘aje Kodi elÅ‘tét a VU+ és Enigma2 settop boxokhoz Frontend Kodi untuk settop boxes berbasis VU+ / Enigma2 XBMS framendi fyrir tengibox byggð á VU+ / Enigma2 Frontend con Kodi per i settop box basati su VU+ / Enigma2 VU+ / Enigma2 ベースã®ã‚»ãƒƒãƒˆãƒˆãƒƒãƒ—ボックス用 Kodi フロントエンド VU+ / Enigma2 ë² ì´ìФ 셋탑박스를 위한 Kodi 프론트엔드 Kodi sÄ…saja(-os) VU + / Enigma2 rinkinių priedų pagrindu Kodi galasistÄ“ma VU+ / Enigma2 balstÄ«tÄm pierÄ«cÄ“m Kodi's Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÑ˜Ñ Ð·Ð° VU+ / Enigma2 базирани звучници Bahagian hadapan Kodi untuk kotak settop berasaskan VU+/Enigma2 Kodis grenseflate for VU+ / Enigma2-baserte TV-bokser Kodi's frontend voor op VU+ / Enigma2 gebaseerde settopboxen Klient telewizji dla dekoderów VU+ / Enigma2 Frontend do Kodi para conversores baseados em VU+/Enigma2 Interface Kodi para caixas settop baseadas em VU+ / Enigma2 InterfaÈ›a Kodi pentru decodoare VU+ / Enigma2 ФронтÑнд Kodi Ð´Ð»Ñ Ñ‚ÑŽÐ½ÐµÑ€Ð¾Ð², оÑнованных на VU+ /Enigma2 Rozhranie Kodi pre spoluprácu s prijímaÄmi VU+ / Enigma2 Kodijev vmesnik za sprejemnike VU+ / Enigma2 Frontend i Kodi'së për Aparate VU+ / Enigma2 Kodi-јев Ð¸Ð½Ñ‚ÐµÑ€Ñ„ÐµÑ˜Ñ Ð·Ð° VU+ / Enigma2 заÑноване settop кутије Kodijev interfejs za VU+ / Enigma2 zasnovane settop kutije Kodi Frontend för Enigma2 baserade digitalboxar Klijynt telewizyjny dlÅ dekoderÅw VU+ / Enigma2 VU+ / Enigma2 alıcı kutuları için Kodi ön ucu Ðакладка VU+ / Enigma2 Ð´Ð»Ñ Kodi Giao tiếp Kodi cho VU+ / Enigma2 dá»±a trên các bá»™ Settop Box 基于 Enigma2 的机顶盒的 Kodi å‰ç«¯ 給以VU+ / Enigma2開發的機上盒所使用的Kodiå‰ç«¯ VU+ voorprogram; ondersteun stroom van Lewendige TV & Opnames, EPG, Tydhouers. VU+ frontend; supporting streaming of Live TV & Recordings, EPG, Timers. Клиент за „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í Enigma2 – podporuje streamování živého vysílání a nahrávání, televizní program, ÄasovaÄe, automatické ÄasovaÄe. Pro dokumentaci navÅ¡tivte: https://github.com/kodi-pvr/pvr.vuplus/blob/master/README.md Blaen VU+; cynnal ffrydio Teledu Byw, Recordio, Amserlenni, Amseryddion VU+ frontend; understøtter streaming af TV og Optagelser, EPG og Timere. 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. Enigma2 frontend - supporting streaming of Live TV & Recordings, EPG, Timers, Autotimers. For documentation visit: https://github.com/kodi-pvr/pvr.vuplus/blob/Leia/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. Frontend VU+; soporta TV en vivo, grabaciones, guía de programación (EPG) y temporizadores. 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. Frontale Enigma2 qui prend en charge la diffusion en continu des télés en direct et des enregistrements, le GÉP et les minuteries Pour consulter la documentation, visitez https://github.com/kodi-pvr/pvr.vuplus/blob/master/README.md (page en anglais) 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+. תומך בהזרמת ×©×™×“×•×¨×™× ×—×™×™× ×•×”×§×œ×˜×•×ª, הצגת לוח ×©×™×“×•×¨×™× ×•×ª×–×ž×•×Ÿ הקלטות. VU+ suÄelje; podržava stremanje i snimanje TV programa, elektronski programski vodiÄ (EPG) i vremeski zadano snimanje. VU+ elÅ‘tét. ÉlÅ‘ adások és felvételek támogatása EPG-vel és idÅ‘zítéssel. Frontend VU+. Mendukung pengaliran TV dan Rekaman langsung, EPG dan Timer. VU+ framendi; styður streymingu á beinum útsendingum og upptökum, rafrænum dagskrárvísum (EPG) og tímatöku. Frontend VU+; supporta EPG, i timer e lo streaming della TV dal vivo e delle registrazioni. VU+ フロントエンド。ライブテレビã®ã‚¹ãƒˆãƒªãƒ¼ãƒŸãƒ³ã‚°ã‚„録画ã€EPGã€ã‚¿ã‚¤ãƒžãƒ¼ã‚’サãƒãƒ¼ãƒˆã€‚ VU+ 프론트엔드; TV 시청 & 녹화, EPG, 타ì´ë¨¸ ì§€ì› TPB + sÄ…saja, remti transliacijos Live TV & įraÅ¡ai, EPG, LaikmaÄiai. VU+ galasistÄ“ma; atbalsta tieÅ¡raides TV & ierakstu straumēšanu, EPG, taimerus. 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 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. InterfaÈ›a VU+; suportă streaming programe TV È™i înregistrare, program electronic, cronometre - înregistrare programată VU+ фронтÑнд; поддерживает потоковое TV, запиÑÑŒ, ЕПГ, таймеры. VU+ rozhranie; je podporované streamovanie živého televízneho vysielania a nahrávok, EPG, ÄasovaÄov. Vmesnik za VU+; podpira pretakanje televizije v živo in posnetkov, EPG, Äasovnike. VU+ frontend, përkrahën transmetimin e Live TV's & Regjistrime, EPG, timer. VU+ интерфејÑ; подржава Ñтримовање ТВ Уживо & Снимака, EPG, Тајмере VU+ interfejs; podržava strimovanje TV Uživo & Snimaka, EPG, Tajmere Enigma2 frontend; stödjer strömning av Live-TV & inspelningar, EPG, timers, autotimers. För dokumentationen besök https://github.com/kodi-pvr/pvr.vuplus/blob/master/README.md Klijynt telewizyjny dlÅ VU+ podpiyrÅ szpricowanie kanaÅ‚Åw radyjowych i telewizyjnych, nagrowanie i harmÅnogram nagraÅ„ aji funkcyje EPG. VU+ ön ucu; Canlı TV akışı ve kayıt yapabilme, EPG ve zamanlayıcıları destekler. Ðакладка VU+; підтримує потоки Live TV, запиÑ, програму передач, таймери. Giao tiếp cho VU+; há»— trợ truyá»n phát và thu chương trình Live TV, hẹn giá» và hiển thị lịch trình chiếu (EPG) Enigma2 å‰ç«¯ - 支æŒç›´æ’­ç”µè§†æ’­æ”¾å’Œå½•åƒã€ç”µå­èŠ‚ç›®å•ã€å®šæ—¶å™¨ã€è‡ªåŠ¨å®šæ—¶å™¨ã€‚ 文档è§ï¼šhttps://github.com/kodi-pvr/pvr.vuplus/blob/master/README.md VU+å‰ç«¯ï¼›æ”¯æ´çš„串æµåª’體包括有:電視直播和節目錄影,電å­ç¯€ç›®è¡¨ï¼Œå®šæ™‚器。 Hierdie is onstabiele sagteware! Die outeurs is op geen manier verantwoordelik vir gefaalde opnames, inkorrekte tydhouers, gemorsde ure, of enige ander ongewensde effekte. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. Тази програма е неÑтабилна! Ðвторите не ноÑÑÑ‚ отговорноÑÑ‚ за неуÑпешно запиÑване, некоректни броÑчи, пропилÑно време и други нежелани ефекти. Això és programari inestable! Els autors no són de cap manera responsables dels enregistraments que han fallat, temporitzadors incorrectes, hores perdudes, o qualssevol altres efectes no desitjats.. Tento software není stabilní! AutoÅ™i nejsou žádným způsobem zodpovÄ›dní za 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. Ασταθές Ï€ÏόγÏαμμα! Οι δημιουÏγοί δεν είναι σε καμία πεÏίπτωση υπεÏθυνοι για αποτυχημένες εγγÏαφές, λανθασμένους χÏονοδιακόπτες, χαμένες ÏŽÏες, ή κάθε είδους ανεπιθÏμητα αποτελέσματα.. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. ¡Este software es inestable! Los autores no se responsabilizan por grabaciones fallidas, temporizadores incorrectos, horas perdidas, o cualquier otro efecto no deseado.. ¡Este 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 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. 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. זוהי ××™× × ×” הרחבה יציבה! ×”×ž×¤×ª×—×™× ××™× × ×חר××™× ×¢×œ כשלון בניגון, ×–×ž× ×™× ×©×’×•×™×™× ×‘×ž×“×¨×™×š השידורי×, שעות מבוזבזות ×ו כל תופעה ×œ× ×¨×¦×•×™×” ×חרת. Ovo je nestabilan softver! Autori nisu ni na koji naÄin odgovorni za neuspjelo snimanje, netoÄna vremena snimanja, izgubljene sate, ili bilo koje druge nepoželjne uÄinke... Ez nem stabil szoftver! A készítÅ‘k nem vállalnak felelÅ‘sséget, a hibás felvételért, rossz idÅ‘zítésért, elvesztegetett időért... ÕÕ¡ Õ¡Õ¶Õ¯Õ¡ÕµÕ¸Ö‚Õ¶ Õ®Ö€Õ¡Õ£Ö€Õ¡ÕµÕ«Õ¶ Õ¡ÕºÕ¡Õ°Õ¸Õ¾Õ¸Ö‚Õ´ Õ§: Õ€Õ¥Õ²Õ«Õ¶Õ¡Õ¯Õ¶Õ¥Ö€Õ¨ ÕºÕ¡Õ¿Õ¡Õ½Õ­Õ¡Õ¶Õ¡Õ¿Õ¸Ö‚ Õ¹Õ¥Õ¶ Õ¾Õ¡Õ¿ Õ±Õ¡ÕµÕ¶Õ¡Õ£Ö€Õ¸Ö‚Õ´Õ¶Õ¥Ö€Õ«, Õ½Õ­Õ¡Õ¬ ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ¡ÖÕ¸Ö‚ÕµÖÕ¥Ö€Õ«, Õ¯Õ¸Ö€Õ¡Õ® ÕªÕ¡Õ´Õ¡Õ¶Õ¡Õ¯Õ« Õ¯Õ¡Õ´ Õ¡ÕµÕ¬ Õ¸Õ¹ ÖÕ¡Õ¶Õ¯Õ¡Õ¬Õ« Õ¥Ö€Ö‡Õ¸Ö‚ÕµÕ©Õ¶Õ¥Ö€Õ« Õ°Õ¡Õ´Õ¡Ö€: Ini merupakan software yang tidak stabil! Penulis tidak bertanggung jawab untuk rekaman gagal, timer salah, waktu terbuang, atau efek tak diinginkan lainnya... Þetta er óstöðugur hugbúnaður! Höfundarnir eru á engan hátt ábyrgir fyrir misheppnuðum upptökum, röngum upptökutímum, klukkustundum sem að fóru í súginn eða nokkrum öðrum óæskilegum áhrifum. Questo software è instabile! Gli autori non sono in alcun modo responsabile per le fallite registrazioni, timer non corretti, ore perse o qualsiasi altro effetto non desiderato... ã“れã¯ä¸å®‰å®šãªã‚½ãƒ•トウェアã§ã™ï¼æœ¬ãƒ—ログラムã®ä½œè€…ã¯ã€éŒ²ç”»ã®å¤±æ•—ã€æ­£ç¢ºã«ä½œå‹•ã—ãªã‹ã£ãŸã‚¿ã‚¤ãƒžãƒ¼ã€ç„¡é§„ã«ã—ãŸæ™‚é–“ã€ãã®ä»–ã‚らゆる好ã¾ã—ããªã„çµæžœã«ã¤ã„ã¦è²¬ä»»ã‚’è² ã‚ãªã„ã‚‚ã®ã¨ã—ã¾ã™ã€‚ ì´ ì†Œí”„íŠ¸ì›¨ì–´ëŠ” 불안정합니다! 제작ìžëŠ” 녹화 실패, 부정확한 타ì´ë¨¸, 시간 낭비 ë° ê¸°íƒ€ 예ìƒí•˜ì§€ 못한 ê²°ê³¼ì— ëŒ€í•´ 책임지지 않습니다.. Tai yra nestabili programinÄ— įranga! Autorius jokiu bÅ«du neatsakingas už nepavykusius įraÅ¡us, neteisingus laikmaÄius, iššvaistytas valandas, ar nutikus kitiems nepageidaujamiems poveikiams ...[COLOR=red](Kodi.lt rekomenduoja/siÅ«lo testuojant šį priedÄ… persijungti į Anglų [orinali] kalbÄ…)[/COLOR] Å Ä« ir nestabila programmatÅ«ra! Autori nav atbildÄ«gi par nesanÄkuÅ¡iem ierakstiem, nepareiziem taimeriem, iztÄ“rÄ“tÄm stundÄm vai jebkÄdiem citiem nevÄ“lamiem efektiem.. Ова е неÑтабилен Ñофтвер! Ðвторите на ниту еден начин не одговараат за неуÑпешни Ñнимки, неточни тајмери, потрошени чаÑови, или било кои други неÑакани ефекти. Ð¢ÑƒÑ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼ нь гүйцÑд хийгдÑж дууÑаагүй! Зохиогч нь алдаатай бичлÑг, цагийн буруу хөтлөлт, алдагдÑан цаг хугацаа ÑÑвÑл буÑад Ñмар нÑгÑн Ñ…Ò¯ÑÑÑгүй үр дүнд хариуцлага хүлÑÑхгүй. Ini merupakan perisian tidak stabil! Pengarang tidak bertanggungjawab atas kegagalan rakaman, pemasa tidak betul, masa yang dibazirkan, atau apa jua kesan yang tidak dikehendaki.. Dan il-programm mhuwiex stabbli! L-Awturi m'humiex responsabbli bl-ebda mod għal rekordings li ma jirnexxewx, arloġġi żbaljati, siegħat moħlija, jew kwalunkwe effett ieħor mhux mixtieq. Dette er ustabil programvare! Skaperen har ikke pÃ¥ noen mÃ¥te ansvar for feilede opptak, uriktige tidsur, bortkastede timer, eller andre uønskede effekter… Dit is onstabiele software! De auteurs zijn op geen enkele manier verantwoordelijk voor mislukte opnames, incorrecte timers, verspilde uren of andere ongewenste effecten. Oprogramowanie nadal jest w fazie rozwoju i jest niestabilne! Autorzy w żaden sposób nie sÄ… odpowiedzialni za nieudane nagrania, błędy w harmonogramie nagraÅ„, zmarnowany czas ani jakiekolwiek inne niepożądane efekty. Este é um software instável! Os autores não são responsáveis por falhas nas gravações, agendamentos incorretos, horas dispendidas, ou quaisquer outros efeitos indesejáveis Este software é instável! Os autores não podem ser responsabilizados por gravações falhadas, temporizadores incorretos, horas desperdiçadas ou qualquer outro tipo de efeitos indesejáveis... Acesta nu este o aplicaÈ›ie definitivă! Autorii nu sunt în nici un fel responsabili pentru înregistrări eÈ™uate, cronometre incorecte, ore pierdute, sau orice alte efecte nedorite... Это теÑÑ‚Ð¾Ð²Ð°Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¼Ð°! Ðвторы не неÑут ответÑтвенноÑти за неудачные запиÑи, неверные таймеры, потраченное Ð²Ñ€ÐµÐ¼Ñ Ð¸ прочие нежелательные Ñффекты.. මෙය අස්ථිර මෘදුකà·à¶‚ගයකි! මෙහි සිදුවන පටිගත කිරීම් à¶…à·ƒà·à¶»à·Šà¶®à¶š වීම්, à·ƒà·à·€à¶¯à·Šâ€à¶º මුහුර්තක, à¶±à·à·ƒà·Šà¶­à·’ වූ à¶šà·à¶½à¶ºà¶±à·Š, හ෠වෙනත් යමිකිසි නුසුදුසු බලපෑම් සඳහ෠කතෘ වග කියනු නොලà·à¶¶à·š. Tento softvér nie je stabilný! Autori nenesú žiadnu zodpovednosÅ¥ za chybné nahrávky vysielania, nesprávne ÄasovaÄe alebo iné neželané udalosti spôsobené týmto softvérom.. To je nestabilna programska oprema! Avtorji niso odgovorni za neuspela snemanja, nepravilne Äasovnike, zapravljen Äas in katerikoli drug neželen uÄinek... Ky program nuk është ende stabil! Autorët e këtij programi nuk janë në as një menyr përgjegjës për rregistrime të gabuara, timer të pasaktë, kohë të humbur ose efekte të tilla të padëshirueshme. Овај Ñофтвер је неÑтабилан! Ðутори ни на који начин ниÑу одговорни за неуÑпела Ñнимања, неиÑправне тајмере, изгубљене Ñате, или било које друге нежељене ефекте. Ovaj softver je nestabilan! Autori ni na koji naÄin nisu odgovorni za neuspela snimanja, neispravne tajmere, izgubljene sate, ili bilo koje druge neželjene efekte. Detta är instabil mjukvara! Upphovsmännen är inte ansvariga för misslyckade inspelningar, inkorrekta timers, bortslösade timmar, eller nÃ¥gra andra oönskade effekter.. To software je niysztabilne! Autory w żÅdyn knif niy ôdpadajÅm za niypodarzÅne nagrania, felery w harmÅnogramie nagraÅ„, potracÅne godziny a tyż jake ino inksze niynazdane efekty. ఇది à°…à°¸à±à°¥à°¿à°° సాఫà±à°Ÿà±à°µà±‡à°°à±! విఫలమైన రికారà±à°¡à°¿à°‚à°—à±à°²à±, తపà±à°ªà± టైమరà±à°²à±, వృధా à°—à°‚à°Ÿà°², లేదా ఠఇతర అవాంఛనీయ à°ªà±à°°à°­à°¾à°µà°¾à°²à°•ౠఠవిధంగా రచయితలౠభాదà±à°¯à±à°¤à±à°²à± కారà±. Ин нармафзори ноуÑтувор аÑÑ‚! Муаллифон барои вайрониҳои Ñабт, вақтÑанҷҳои нодуруÑÑ‚, Ñоатҳои бефоида ва дигар таъÑирҳои номатлуб ҷавобгар намебошанд. นี่คือโปรà¹à¸à¸£à¸¡à¸—ี่ยังไม่เสถียร! ผู้เขียนไม่อยู่ในทางที่จะรับผิดชอบในà¸à¸²à¸£à¸šà¸±à¸™à¸—ึà¸à¸—ี่ล้มเหลว, à¸à¸²à¸£à¸•ั้งเวลาที่ไม่ถูà¸à¸•้อง, à¸à¸²à¸£à¹€à¸ªà¸µà¸¢à¹€à¸§à¸¥à¸², หรือผลà¸à¸£à¸°à¸—บที่ไม่พึงประสงค์อื่น ๆ.. Bu kararsız bir yazılımdır! Yapımcılar hatalı kayıtlardan, bozuk sürelerden, harcanan vakitten veya herhangi bir olumsuz etkiden dolayı sorumlu tutulamaz. Це неÑтабільна програма! Ðвтори не неÑуть відповідальноÑті за попÑуті запиÑи, неправильні таймери, втрачений Ñ‡Ð°Ñ Ñ‚Ð° інші небажані ефекти. Äây là phần má»m không ổn định! Các tác giả không chịu trách nhiệm đối vá»›i bản ghi chương trình thất bại, hẹn giá» không chính xác, giá» lãng phí, hoặc bất kỳ tác dụng không mong muốn khác.. 这是ä¸ç¨³å®šç‰ˆçš„软件ï¼ä½œè€…ä¸å¯¹å½•åƒå¤±è´¥ã€é”™è¯¯å®šæ—¶é€ æˆæ—¶é—´æµªè´¹æˆ–其它ä¸è‰¯å½±å“负责。 這是測試版軟體ï¼å…¶åŽŸå‰µä½œè€…ä¸¦ç„¡æ³•å°æ–¼ä»¥ä¸‹æƒ…æ³è² è²¬ï¼ŒåŒ…å«ï¼šéŒ„å½±å¤±æ•—ï¼Œä¸æ­£ç¢ºçš„定時設定,多餘時數,或任何產生的其它ä¸è‰¯å½±éŸ¿... @PLATFORM@ v3.28.9 - Fixed: Add Timer title and fallback entry fix v3.28.8 - Fixed: Fix time_t format string specifier win32 seg faults v3.28.7 - Fixed: Logger fix ported from pvr.hts v3.28.6 - Added: Epg lookup more debug logging on add timer v3.28.5 - Added: release package bump v3.28.4 - Added: added new addon icon v3.28.3 - Added: Epg lookup debug logging - When adding timer v3.28.2 - Fixed: Use correct start time for EPG lookup when adding timer - Fixed: strncpy fix possible length fault v3.28.1 - Update: Github README link in addon.xml for Leia v3.28.0 - Added: Support for IPTV Streams configured on E2 device (no timeshifting) - Added: Reload instead of reconnecting when channel/group changes are detected - Added: Use truly unique IDs for channels so EPG changes are correctly reflected - Fixed: Only get drive space for devices that have an HDD - Fixed: use correct function to lookup group when adding - Added: update README.md to show appveyor/travis badges per branch - Added: Update OSX build script - Added: update badge status for travis/appveyor - Added: add copyright notices to files - Fixed: Fix default path for genre text mapping file v3.27.1 - Update: Build sytem version - Added: AppVeyor for Windows related build tests - Fixed: Build depends search way v3.27.0 - Added: Allow creation of epg based repeating timer rules if autotimers are not available v3.26.0 - Added: Set program id option for streams with superfluous program data - Added: Undelete and trashcan (when configured on backend) for recordings - Added: Use new API for backend channel numbers - openwebif 1.3.7 - Fixed: Radio groups parsed from wrong api - Added: Support disabling addon debug logging in debug mode v3.25.0 - Added: Support backend channel numbers for all channel groups not just the first - Added: Ignore empty channel groups - Added: Readme and help info updates - Fixed: Revert support hidden entries for backend channel numbers - Fixed: Fix hanging on deleting multiple recordings at once v3.24.0 - Added: Custom Channel Groups, closes #209 - Added: Connection manager improvements - Added: Support hidden entries for backend channel numbers - Fixed: Timer descprition for providers who only use long descrption v3.23.0 - Added: Support settings levels via the current kodi settings level - Added: Fallback EPG Entries for Timers - Added: Support backend channel numbers using Openwebif v3.22.0 - Added: Help info for addon settings - Added: Delete child timers when deleting autotimers - Added: Set max connection check interval to 60 seconds - Fixed: Incorrect localisation IDs - Fixed: Timers in error state cause crash on delete - Added: Support show info fields for Timers v3.21.0 - Added: Support Edit Recording name, last played and play count - Fixed: Use v3.6.1 of nlohmann/json to relax cmake version dependency for OSMC, fixes #194 - Added: Nightly channel reload check as default - Added: Split out and move openwebif version checking to settings v3.20.0 - Added: Add options to Tune Async connection for slower E2 devices - Added: Enable option to reload channels and groups once per day if changes are detected - Added: Allow timers generated by autotimers to be deleted - Fixed: Fix for disabling timers - Added: Use genre from kodi for timers instead of lookup where possible - Added: Support recording type fully for TV/Radio/Any channel - Added: By default load Last Scanned group if no TV groups found - Fixed: Channel Service Refs Can sometimes have alphabetic characters appended at the end, fixes #202 - Added: For timers and autotimers without a valid channel put in error state instead of omitting - Fixed: IsRunning timer check not checking start time v3.19.0 - Added: Async Connection - Reconnect if Enigma2 device was or becomes unavailable, closes #154, closes #184 - Added: Notify when Channel/ChannelGroups changes are detected, closes #179 - Added: Support genres for Recordings and Timers, fixes #186 - Fixed: Instant recordings may be missing show info depending on last EPG update, fixes #185 - Added: Helper build script for MacOSX v3.18.1 - Fixed: Crash on addon start, fixes #191 v3.18.0 - Fixed: Ensure only one call to GetEPGForChannel happens at one time, fixes #181 - Added: Update/fix server version for pvr addon - Added: Option to skip initial EPG Load - Fixed: Fix for zap on channel change for dreamboxes - Added: Support for padding in certain timer types - Fixed: Change the call web/tunersignal to web/signal so it also works on DreamOS v3.17.0 - Added: Recording EDL support - Added: Update Timer Types to display correctly in Manual vs EPG UIs - Added: Updated show info regex's - Fixed: Timer Recording not displaying description - Not being stored on STB - AddTimer Call, fixes #174 - Fixed: Fix for uncaught type_error for nlohmann/json - Fixed: Include TV Favourites channels by default in settings - Added: Support Last Scanned for both TV and Radio, fixes #178 - Fixed: Null pointer check for Genre EPG data processed XML v3.16.2 - Fixed: Seg fault on shutdown - Timer Updates thread accessing released object, fixes #172 - Fixed: Incorrectly used time_t instead int64 in GetStreamTimes, fixes #171 - Added: Load Addon Version - Fixed: Clean up/partition addon debug log, fixes #159 - Added: Add user defined delay between EPG Channel Updates, fixes #158 - Added: Enable Trace Logging in debug mode - Added: Integrate Stream API details with Tuners - Fixed: JSON API requires version 1.3.5+ of OpenWebIf, fixes #169 - Added: updated language files from Transifex v3.16.1 - Fixed: Backend polled too often for Signal Quality, fixes #165 - Fixed: SNR and Signal showing as zero in PVR info overlay, fixes #164 - Fixed: When playing a current recording duration at end time is wrong, fixes #160 - Fixed: Plugin won't load channels after upgrade to 3.16.0, fixes #161 v3.16.0 - Added: Tuners and SignalStatus - Added: Use Picon Path from OpenWebIf - Fixed: Change startup issue log statements from Debug to Error, fixes #157 v3.15.5 - Added: updated language files from Transifex v3.15.4 - Fixed: In 3.15.2 WebIf that is not OpenWebIf does not support auto timer API - Addon won't load Newnigma2 image, fixes #151 v3.15.3 - Fixed: GetStreamTimes not implemented for Recordings, fixes #148 - Fixed: When starting a recording partway through start time is EPG start not recording start, fixes #147 v3.15.2 - Fixed: Only load Season info extractor and genre mappers config when enabled, fixes #136 - Fixed: 3.15.1 dont load/work on old DM800se, fixes #139 - Fixed: Missing default value from timeshift buffer path, fixes #140 - Fixed: Channel Group Member Order not preserved, fixes #141 v3.15.1 - Fixed: since 3.15.0 pvr manager cant start #134 - Added: Log Distro Version 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 pvr.vuplus-3.28.9-Leia/pvr.vuplus/changelog.txt000066400000000000000000000436341356012415200214760ustar00rootroot00000000000000v3.28.9 - Fixed: Add Timer title and fallback entry fix v3.28.8 - Fixed: Fix time_t format string specifier win32 seg faults v3.28.7 - Fixed: Logger fix ported from pvr.hts v3.28.6 - Added: Epg lookup more debug logging on add timer v3.28.5 - Added: release package bump v3.28.4 - Added: added new addon icon v3.28.3 - Added: Epg lookup debug logging - When adding timer v3.28.2 - Fixed: Use correct start time for EPG lookup when adding timer - Fixed: strncpy fix possible length fault v3.28.1 - Update: Github README link in addon.xml for Leia v3.28.0 - Added: Support for IPTV Streams configured on E2 device (no timeshifting) - Added: Reload instead of reconnecting when channel/group changes are detected - Added: Use truly unique IDs for channels so EPG changes are correctly reflected - Fixed: Only get drive space for devices that have an HDD - Fixed: use correct function to lookup group when adding - Added: update README.md to show appveyor/travis badges per branch - Added: Update OSX build script - Added: update badge status for travis/appveyor - Added: add copyright notices to files - Fixed: Fix default path for genre text mapping file v3.27.1 - Update: Build sytem version - Added: AppVeyor for Windows related build tests - Fixed: Build depends search way v3.27.0 - Added: Allow creation of epg based repeating timer rules if autotimers are not available v3.26.0 - Added: Set program id option for streams with superfluous program data - Added: Undelete and trashcan (when configured on backend) for recordings - Added: Use new API for backend channel numbers - openwebif 1.3.7 - Fixed: Radio groups parsed from wrong api - Added: Support disabling addon debug logging in debug mode v3.25.0 - Added: Support backend channel numbers for all channel groups not just the first - Added: Ignore empty channel groups - Added: Readme and help info updates - Fixed: Revert support hidden entries for backend channel numbers - Fixed: Fix hanging on deleting multiple recordings at once v3.24.0 - Added: Custom Channel Groups, closes #209 - Added: Connection manager improvements - Added: Support hidden entries for backend channel numbers - Fixed: Timer descprition for providers who only use long descrption v3.23.0 - Added: Support settings levels via the current kodi settings level - Added: Fallback EPG Entries for Timers - Added: Support backend channel numbers using Openwebif v3.22.0 - Added: Help info for addon settings - Added: Delete child timers when deleting autotimers - Added: Set max connection check interval to 60 seconds - Fixed: Incorrect localisation IDs - Fixed: Timers in error state cause crash on delete - Added: Support show info fields for Timers v3.21.0 - Added: Support Edit Recording name, last played and play count - Fixed: Use v3.6.1 of nlohmann/json to relax cmake version dependency for OSMC, fixes #194 - Added: Nightly channel reload check as default - Added: Split out and move openwebif version checking to settings v3.20.0 - Added: Add options to Tune Async connection for slower E2 devices - Added: Enable option to reload channels and groups once per day if changes are detected - Added: Allow timers generated by autotimers to be deleted - Fixed: Fix for disabling timers - Added: Use genre from kodi for timers instead of lookup where possible - Added: Support recording type fully for TV/Radio/Any channel - Added: By default load Last Scanned group if no TV groups found - Added: Limit autotimers to TV/Radio or originating channel's groups - Fixed: Channel Service Refs Can sometimes have alphabetic characters appended at the end, fixes #202 - Added: For timers and autotimers without a valid channel put in error state instead of omitting - Fixed: IsRunning timer check not checking start time v3.19.0 - Added: Async Connection - Reconnect if Enigma2 device was or becomes unavailable, closes #154, closes #184 - Added: Notify when Channel/ChannelGroups changes are detected, closes #179 - Added: Support genres for Recordings and Timers, fixes #186 - Fixed: Instant recordings may be missing show info depending on last EPG update, fixes #185 - Added: Helper build script for MacOSX v3.18.1 - Fixed: Crash on addon start, fixes #191 v3.18.0 - Fixed: Ensure only one call to GetEPGForChannel happens at one time, fixes #181 - Added: Update/fix server version for pvr addon - Added: Option to skip initial EPG Load - Fixed: Fix for zap on channel change for dreamboxes - Added: Support for padding in certain timer types - Fixed: Change the call web/tunersignal to web/signal so it also works on DreamOS v3.17.0 - Added: Recording EDL support - Added: Update Timer Types to display correctly in Manual vs EPG UIs - Added: Updated show info regex's - Fixed: Timer Recording not displaying description - Not being stored on STB - AddTimer Call, fixes #174 - Fixed: Fix for uncaught type_error for nlohmann/json - Fixed: Include TV Favourites channels by default in settings - Added: Support Last Scanned for both TV and Radio, fixes #178 - Fixed: Null pointer check for Genre EPG data from XML v3.16.2 - Fixed: Seg fault on shutdown - Timer Updates thread accessing released object, fixes #172 - Fixed: Incorrectly used time_t instead int64 in GetStreamTimes, fixes #171 - Added: Load Addon Version - Fixed: Clean up/partition addon debug log, fixes #159 - Added: Add user defined delay between EPG Channel Updates, fixes #158 - Added: Enable Trace Logging in debug mode - Added: Integrate Stream API details with Tuners - Fixed: JSON API requires version 1.3.5+ of OpenWebIf, fixes #169 - Added: updated language files from Transifex v3.16.1 - Fixed: Backend polled too often for Signal Quality, fixes #165 - Fixed: SNR and Signal showing as zero in PVR info overlay, fixes #164 - Fixed: When playing a current recording duration at end time is wrong, fixes #160 - Fixed: Plugin won't load channels after upgrade to 3.16.0, fixes #161 v3.16.0 - Added: Tuners and SignalStatus - Added: Use Picon Path from OpenWebIf - Fixed: Change startup issue log statements from Debug to Error, fixes #157 v3.15.5 - Added: updated language files from Transifex v3.15.4 - Fixed: In 3.15.2 WebIf that is not OpenWebIf does not support auto timer API - Addon won't load Newnigma2 image, fixes #151 v3.15.3 - Fixed: GetStreamTimes not implemented for Recordings, fixes #148 - Fixed: When starting a recording partway through start time is EPG start not recording start, fixes #147 v3.15.2 - Fixed: Only load Season info extractor and genre mappers config when enabled, fixes #136 - Fixed: 3.15.1 dont load/work on old DM800se, fixes #139 - Fixed: Missing default value from timeshift buffer path, fixes #140 - Fixed: Channel Group Member Order not preserved, fixes #141 v3.15.1 - Fixed: since 3.15.0 pvr manager cant start #134 - Added: Log Distro Version 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.1 - Added: 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 v3.0.2 - streaming always use anonymous http connection, regardless of the "Use https" setting v3.0.1 - updated language files from Transifex v3.0.0 - Initial Kodi v18 version 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 pvr.vuplus-3.28.9-Leia/pvr.vuplus/icon.png000066400000000000000000000232151356012415200204350ustar00rootroot00000000000000‰PNG  IHDR{C­tEXtSoftwareAdobe ImageReadyqÉe<&/IDATxÚìÝ_Œ]õa'p›šu ÌŒ elª„@ÒªÍà4‘]‘ªE‰­JIŒ³´ÄîË>`L×ÀSá-«8<$‘*;ªÚ(vPl%=mÕÆaF-̤⎠6^wÉžÅÒèÆsÏïüîïœsï9÷~>Qîpý»çž{ïïûûw~gÝôôôFÏ5N€@ €@ €@ @ €@ €@  €@ €@ €@€@ÐVëºþõºÛ>’VÜ…×ÞùðÞ{ïM+çôéÓÇÇÇÓÊ9wî\çÃÛo¿=­œW_}µóáììlZ9sss'''ÓÊYZZê|855•VÎÂÂBçɉ‰´r–——;ÞtçÝiå¼ýò™:ާªrî¸ãŽ´r^yå•Qx_U}Ÿ·nÝšVΉ'š|ž«:?UÀè€@ €@ Y;==í,è †Äº®œœL+nii©óáÄÄDZ9ËËËï½÷Þ´rNŸ>]ÇûšššJ+gaa¡óá[>VÎË'TÇûÚºukZ9'Nœè|8>>žVιsçê8Ï7ÝywZ9o¿|¦Žó\U9wÜ÷iå¼rêšü{¯ês¯êxªúþTu<333iåÌÏÏë €@ €@ *´vzzÚYÐ@  ‰u]ÿ:33“VÜüü|çé©©´rê(gvv6­œ¹¹¹Î‡iå,//w>œœœL+gii©óᆭ˜VÎÅßï|xý'?“Vλ?ùaçÃkïþxZ9—Ïü´óáͺ'­œ·þúP“?¯ªŽ§iïkëÖ­iåœ8qb>¯ªŽ§ªúY`t €@ €@ €Š¬žžvôCb]׿NLL¤·¼¼Üùprr2­œ¥¥¥:Žgjj*­œ………·wnùTZ9/Ÿüqçñ±±´rΟ?ÿŸâï~2­œÿø—Ÿt>œM+gnn®Éߟª>÷ªÞWUåÜüÉmiå¼õ“ã?ô©ÒÊyïÇ?¨ãó»uSâïâ‹uÏÌÌLZ9óóóuOUåèŒ. €@ €@P‘µÓÓÓ΀€`H¬ëú×õë×§wéҥ·“““iå,--ÕQζmÛÒÊ9~üx“ßׯÏ<˜VÎÙ~ï7>÷ß—ø¹ÿôTçÃ;·|*­œ—Oþ¸óáØØXZ9çÏŸï|øŸn½-­œÿó‹×ëø¼~ýÇ_H+gíß~§óáÄÄDZ9ËËËgggÓÊ™››ë|xÝýiZ9þî¯ë8ž{fÿ ­œçþ¡Žó|Ów§•óöËg:NMM¥•³°° €€@ €@ ¨ÐÚééig@€@0$Öuýëïÿá¥÷Oßÿ»Î‡iå,//w>¼s˧ÒÊyùäë8žëîýDZ9NÿcÇsÍïlI+çý=ÙùpÛ¶miå?~¼óáäädZ9KKKM.§ªÏkvv6­œ¹¹¹:Þׯÿø iå¬ýÛïÔñ¾nÜ|[Z9¿zãõ:ާªÏýŽ;îH+ç•W^©ãxôF—€@ €@ ¨ÈÚééig@€@0$ÖuýëÄÄDZqËËË'''ÓÊYZZª£œªÞWUåÌÌ̤•3??ßùpýïlI+çÒ¿žì|xíçw§•sù»Ïu>¼îÞO¤•sáô?þÆámß™VÎúcGšüyMMM¥•³°°Ðùpíï}:­œ_ÿóšü{Wÿô§þÑ]@ €@ € "k§§§=ÀX×õ¯“““iÅ---u>œ˜˜H+gyy¹óáììlZ9sss¯»í#iå\xý秦¦ÒÊYXX¨ãülݺ5­œ'NÔq<333iåÌÏÏw>|衇ÒÊyþùçëx_Uý..mß•VÎúc‡ãQß«?ûì³îQMP¼={ö8p ð„Ç{ìðáÃ:¼wîÝò‹?û‹÷?t]%¥­_|íÖo}uý¯¶:L×(û­fµ›ónøÿÍßüM%µfll,«€²Z2«¦k:à»ï¾;|µž®ð×ià_¶{î¹§äê“Uý‹ÿuUµæÒ¦þü¿ÿÕÙm Bœ“g×®]_ûÚ×*¯4³ÜÍz35eÀm·ÝVØ—ªïŒ…ã§ù>þš¼¿áúÿý•ÿqnöþ: ëóžE‹ ·Žsºzê©§ž|òÉú*Êš2 °’-Lˆúª×ú^:Fv¶ ë÷ZÓ1OVûw]áS•,ZÚ› ^ÙOÂ(P×\ܹsgÝg¾Ž (¬…ëû¸øÒå{'ƒÊ€¬j¾´é£u¿J{3@ÔÎ(Ðê* ¾¶ÿUURÖϨ¶Ì«ú*¸Âú}°°eË–Jb¬ÒzùšF~ºfÀ[Ÿÿ² Kk×I謤ž}öÙ¾½ÜöíÛ÷ìÙSmz…ŸPß8LáK6"kö¾Àåoysg_kä³Ûþä{·´ë÷èJà~´C³_¦õéWdMòøYßÅÅÅ£G~ÿûß_ùËøøxÖÒÌ:UñW 8pàÔ©S/¾øbùƒP*s)CÉhà›øWì(”×ÓŠÏkÞ»pÃé“×½2¿îì›+ü·\¸c&«ÓãËÉ^ô¿¼òßZtÁ°è‡¬Âªuqz‹:C‘#$YÕÿè£f÷êÿ”EÂÁƒ³¢²š=2K²gözaD^–G6Õ»yI…ÑR÷"Ôp4F&_ö´ìÉçΫõx²Š;râ7«úo9òõ¼«ºþÿß¿•5ízû³_Œ‰ì9o~þË·~ë« ß®~êgÅ'²Ÿ}ø*¡GŽyâ‰'ÂuÄádz$Èú1ûFd5rö”¿)rx'{ZåœY3¼’¾NM‡·’£ud§·übÌÓ6,ülóÿ|²°Á¾ñøó7ÌŸ\üóÇbæ“ÏÍÞŸ=¿-ˆ™èkÖ|p™hL5«ý÷ïßÓBÌžóÈ#dÏyõ}ûö• ‘bŸuäË :=>Õ= tióí1Íÿñ¹~ûk9\sí¯ÞÌž¼~ñµ˜'·èê0пNÀˆ7ÿc&c¯Ôþ=•œ=ÿرc1#å?‚Èj®Ž…@‘AMôô–ë^ SÿfUù-ßýzouåÅw#3 ë\¾ñ€è¡ùæÌ™'žx"¡ð,ûÐ ˆl_×±(rú¡¾=0* žºS*f)έßújÂTmöO"Ç÷ÿ½%Ð'Y t°‹4šŸL›ÌþÕ£>ó”¼&#²éZÇB ¦-²ì´yóæ¼h<þ|×­oD4fÑÎøÜ ÉcôÙ?¼é{ß©$„ÀÐêÚ ÙN@̪Í#GŽ”™ÌþmÌ@P™ §Æuµ£ÙKGv>2H¼éú¦Þ™).ù¦ï}»ÌKl<þü5ï]?çòÆ›/m¾]Œ¨×_½k=¨ùŸçé§Ÿ.ù*Y¢ð9eögíi#³j‡bâ_z =€„­ï8/Þ1~ ó§®ýÕ›¥*Í‹ïÞpúdáÓ.LÍ€uæÌ™®##8 ”U……+5³æù å²b:É1Üud?¯×Ríß^H ¯»“õƒóÎOMÛ‚¾¿áú›|ÅÔÝ…n˜/.D@ Ê!ˆ–Š©p«ºH"f¥rôÔu¨6º¾t²§Läý ÖÔ¶轈:7¦î..äôÉÂQ 0º²fo×NÀ޾åìDUuíÒÑ£GÃ˲J3òºøŠµë]í$g×ÒòúL}îòæüùóYý:‚êbѨËúÅתڧ¡p¹» €æ@V­þûŽŽÿT{À®§=K…gžyæؽ{wòËu­X³DéZÇU;ıº½œ½£¼èÛf;…õø‹èg' põýu¯ÌWõZ1E½¿áz0вßךh͈ÅôxòNTš“'Ov¶@³ö~VéßÿýåïŸWaå[UÒw-'0ºÒg·^Ô[GK¨0Ö•›þí3“ü^ãGlW—¬í“U@«›Y³^e8¶F-Ù2=€cÇŽeÿ§÷Ôq›7o®dh+o4)ï¼õùŽ+¾Nöö»ŽÕ…Ãîë+Û¢§sßÐöÒ¨±YÔuš®üåH-RXUÛü¿â®»îzä‘Gª­ýóÞHVÇåe@­=€ì«ÕN@à#Î"*YrT~Ýrá%`×þêÍ5€º]iøçÕn#17‰í±iø{ ´sûeB·o¥èôÿñ@ôψ@ÌÏ»îm«íÒ­vþ]ÿSU ò–å½nNKg½èT;_Ý–ý×ÀHÈGÙW¿kó'ëŒBÄLÔ}cªäÕæ….U5o»–óúë¯÷yM¯°2EÑ·i tZÐj^Ñ–ñŸÂæ|ÞÅå+¸¼ª¼ Íÿ5q»õÿr0Àà]5-ºOr×÷²R çÕqåGòv–¾R½æOß./ºêÿtí ÷óFIמ}«ÂÒ.FlõSáe •Õ_öíïú+…Q Â@[ÔèzØJÕVߥáúq° Âí÷•“ZÓß+ÖU:Üü‹¼¢Î‰šºnY'àá‡îÚ ¨cdCÄôîÛÒ(|/õ@×—.œ9ïÏÐJ Ÿ‘õVÎɹsçº^³rŠªúüÖÅw7,ü,ð„UzŸÞ‹¼Â#FEÖÎÍ €!~×1wÅjKä­]Ê>â½{÷Föú‘y²Æu׺¾?÷‹¿ @ö0/“*̪õo¼úÛ_û˾}+ /:kÅ’SC@µ7³NÞ}‘†x[ˆÂ±Ý¶, Ôt+Õ\Þ”lÉÚ-ï>0+§.o UÖ×Ǭ-ü¬[:|ùÆ[†ã¢3Ð#8¨»x×­pô£E=€¼J¼³ž· §LäÕŒ+“çYôº;áò¯šï‰ÔƸpÇ0,õ6‘: o”`X;ÃÔ(Z“¿ §ÌŠÌ˜y”AõÂïëªt@G o<¹~ñµV¼Ч&R^ƒwX °Ðö5 ‘š:†€V^+p9XÝ?øcKÛ —o¼¥ðÆ“­hþ €þ©Q azGöigý›7[&º¾tç‹ZÖuÓÒõ¨‡Úÿ-áJzg¦¸W׊ 0øÊN@ÌOº!›” ³ÎJ-¯‚Kßì>TÕG,;¶@¯¨ë”ox¸]£@#&*¹õ¼Y 1ïn´#x£àøŠlà"(Ci€¼uÕ å½n­=€ð9é:¸ñëóm,ËxÃõïÌÄÕ ó­Yà ú×MQ 2³—MYg_íB ¼:ñª±¦\ PxyZO¹¦UÓQã?-™}5:kú¹Ã× ÞËêš·Ú…@…k@¯Œ¤ÕתÏ‹tͤ+B CÜ[üiÞ0ßš ßÐõï;wî©ó0—¯Ô®v!Pä­€2¹¿ DäÚ´iS+:Á1ã?ë_kÑ}Ç@# kR S«y˜äÍv®€¼yδO6¯úŽß@©¦¸¬öÌ¢=œú­˜Žÿ?õƒ}½@¿`F†æFá;ž_õ—¼! „³‘×Ä^]‡&WkjR„‡kÍü!Øâìg*|N‹Æ@ƒ:C¼1ÜPZ]ÝZ¸½ŽoDÎ<§Rkjù¶_|ùÆ[.múhø9íÿõê:û—Y—tFÚ²txËûÈ?®é}8>¯’]:•/?-~/is­èüû¶âæÿÆ>ß®_¢@`ÔöjoD^VXÇõZ»å5‡W—Ÿ· tMms¦záÜ~ ®ÆÆÆžC¶þG 2ºþÝ(PÓäµvó"<¯‚ëµ.Î{~×òó¦ð–œ ’ÇÚÞ ÈjÿÂýÆç^¸æâ»€ÄšQ ¡¹®-|OöÕòæ{êZw/..vmï×t7‚^›ÿk"®înï<ð¹Ù†¯ù/Ã= Ôºí½zªˆîJ†€ò*Ù„[ÀWÉK€®oÑØyàË7ÞR¸üÿÚ³oµeÿŸNÃsOàìÛóÒK/UXà]wÝUkt½øk×®]‡’‘Mp¹SÞÐØØXÖ+ Œ×Çt;òFس¿çUYQÕ^s—° DüÛnˆ™þm×ò=€Áwò~®kˆ„[º6<ˆ¯Ýâ¯=î ð.òF¨"ÏOc;ïo¸~ù¾âñŸÇŸoã—\ ,ò~ _úÒ—œŸ&¬ e”Ê«dó†€ú6Pr æi œxgfKáýßÛ8ý+Ú ÍÝ¡(m*;¯¿(þ2à•fu ä@ø]†î ¼ýÙ/Uæ~ÐÒ/ù:¿óA9|øp×i€M›6e¿´¶l—_·}ûöíÝ»·Ú2#gwÃZ,/"‡€²Ôé:ô= UÛ ®$Úµ(fõçúÅ×®kÏþÏzM‘U"y;È»   Ò.¤ÊЬÚö€ ü§„iŒäæy%C@MÛôì0^ý+šÂ(P“å­ /eɫޝ,J®d“{„Uµ©³ƒ_Y9G]øFš³èÒæÛ/N},üœkϾÕÞñ0`‡ΫzZt‹Œ¡8ÿáµ.z0¦jK»p`HªªN@øà{ZlNÐæLœÞÕŸ ²_µQ f Ô›…«ÝójØ1¥’÷‚¯¯®—{Ú¦´Û‚^¾ñ–s³÷Ôžï]héêÏÃ3 œýêvïÞݺÃ>zôèÃ?¼úï;vì8xð ŠxPõ]áj÷¼¾1kròª¿ðKVÿæýê†ÔÃAÒÓUÊ­˜~ûÁâÅ?ø|KWê4…Q fêuИ'¶mó¢p€%IU}‹*YtExCˆ¬ï5ðk!cšÿkÚ¼úS4…Q f yöòjÃÂ! äk€ë^”ÕÈáà çÖ4` fë·ñ¹ÚuïÐPÃw§øðåþ­¨¬“«ãÂý™ó °}©¤Pr  Õ þ† ¶ïûþ†ëcnýxÓ÷¾=• ÁïðáÃ]§²¶ÛŽ;ºÆCÃo¨’UXUMå=ýøçWuáX ².³ë}vZåäÔ§•ôJÞ ×oÈ`W‚žÝöPÌÞCÐü×hJu™7 ”wA@ÂÎÀTRßå}R‘âð(Pò­€ëÞ`§’]€:…‡Œ¸h¤šÿ )F튰†ß1&ÐjŽŒÞ¼Fqxz³kË7kÝGî#]_' !áIÝ´Nà2 ¦ù¿aágÃÑüM‘·èÊ(Ðð½ß†ß1¦×{ÁÇ7ŠõZü}€{mS—œSÍB+!iC@e"Gó_ •„Q õI•iᆀz½LâðJ"MD6ÿÛ»õ›h®ajû* @;=r4&o¤(0·œ7:Y½žVr8¥Â+:…'6ú#Øü 2L£@mß˺ÌU`…Íö¼ê¸ä­€ë[Vá.@ñg2{Ñ>O`ó_4«ÒQ †Oª¼øÎMÞ§™7ÔSr(Ð5)Ùÿóäà)ü‡ýœ(Íæ¿h–o|ã#Mž/Ô‰ïÜäµÜ»–Ÿ·ÙräªÓúz]…C1ɯ[¸v¨Ÿ×fó_4KÞ4ÀØØX»¶…høuje ^^˽k•š—ˆUUëÉ€ú ð↾MŒló_4®ÞÌûU\Õ èõâû>kõujz§§ñîž.H¾8íØª €2ßà!úv)ÀÈ6ÿ@ãäMoß¾½sܼä•A ¯g«ªù‰¼ìÚØÏ›¨ª<œRù5Àñÿ¼?Û‚Žró_4NÞ(КVÍÄ4 «½]m…U^U{^®®×n\m{0Õî¯ÙYú:@ó_4]á(Pà ¦õÚÀ™”vÂóºk£@]GÃfÑÃÑkÜ6d’¦Ž/‰æ¿hº¼µ@ýß&7¹¡]8¾Anš’CÆê&- 7„È;à´ñŸÀÚ°^kÒæÌÒW; pùÆ[Þ~ð šÿ Ñ†àаfÞõ) ¼¨ÚX ¿¼8O[cøW=µòv'ˆj£Þ~ð‹µÿwF¡ù/-oèJƒ¨äE˜}P8Y=! ÀQ… ­FÎû˜V^«’k€Kvnênt—TaC!kþŸ›½¿ N|ïÂÆãÏH%#šëÈ‘#}h °PG-S¦²ÿÛj{+íñ¼ÔI[ëþWñ€FuÎ*<˜˜æÿÆ>ÍÅwvîܹcÇŽ­þ{Ö7Ï~Í¿ïnL¶ò (¼¼ pTáú±ÚXiw €š.óŽï4ª}á+¹B[ó_´LÞTpöûlþ^ YÝWX‘UÛ›‰i*¦í˜V&n»Î嬄M×cN¾È6ü­ˆŸuoÚôL%ÇóÖ翬ù‚5=ž|òÉ®õæ¡C‡šüY}žK¬¶¥ÓNL[]S&n³ \Ýô^ùK%ÛÀÅÄۚ莲§…;RGŽÙ¿…Üž={º^ùØ=²b\¸c時/Ûµgß‘Å?zí7 t¥Þlø~pk‚Û­¼‘ Wµ¶ÃWWÕÔ„GÞ+&çMxœ*2ê» drå Q‹þþÛ£VÀtVÿñʞͿóbÌR¥ WµVÉeª¼¼8Úä«üZ…=ž’5ÿ/N}¬°ù?>÷@;Ñ­X 3 °sçξ@ ¢ O–Ù÷8P)ç}ˆejØ@g%r ð4Öqë±Z·iþßüݯ`õ"š.o(k8·bW¸˜Q JÖxÄô$k¸r¬£W£Õw—•Èk»Â°IQÉÃ.1Íÿ ?»áôɬ^@[;mÙ"ïr¶NûöíëO$_VGó6ûøºVjµ®ï*|›ýÿ©;þíÏþ¢ð9£6÷+Zm‘ý°cFJÖ¿YeZ8””Õþ¦k¸~)ÙÙêúºy‹mj½Ózù¨©ßYÓ<ð¹Ù.o¼¹°ù?Üw}í^ Ô|ßøÆ7 Ÿóøã—y‰={ö”ÌÑZoPÓµÒÌêâ®ãNµnòQ8 P5mC[ÓÆ!o¶xôÿÖo}udëÐâN@­£ÊÛÓ¢ÓöíÛwíÚ•<¬Q>iZ¾ÍÛµÒÌÛp­d [r!Pa=[ßUáäG¯-ž˜æÿˆlû,†0šyWÅ®=˜˜ 8pà@Ú8ïSO=Ux*²JfÇ3úÐ hDd-ô:ÂìØ±cñµÿš¢5 @aÕÖŸ¶kš·/E¡’'!/b¶}F€½‘Ï}îsî.™ÅÉO<ñÈ#ô4•Ú‡5 ‘EUáSÚµ³4«?÷Ÿ(< y‡³í3`êÍ!Zi_g­õÇ{¬ü\ë‘#G²89tèP¯ÿ0¼´ÂVyx}FØ™W8Ü·P§-ŠÙ÷  ÐD‡¾ÿþû³HhcfÓ7¿ùÍx`ÿþýiÃ5…7Àª0í’ÿk¯Âq²:ó¸\B?cõÑÆlûÌjk§§§šc|||ÇŽY5ëéçÕJW¶ö̪¤ìÿô­bÀ0 €@ €@ €€@ €@ €@§@ €6ú UVõÊÃoÓ·IEND®B`‚pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/000077500000000000000000000000001356012415200210065ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/000077500000000000000000000000001356012415200217175ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/channelGroups/000077500000000000000000000000001356012415200245275ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/channelGroups/customRadioGroups-example.xml000077500000000000000000000013251356012415200323770ustar00rootroot00000000000000 FreeSat UK - Radio Channels Saorview - Radio Channels pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/channelGroups/customTVGroups-example.xml000077500000000000000000000014121356012415200316670ustar00rootroot00000000000000 FreeSat UK - All channels FreeSat UK - Saorview FreeSat UK - Movies pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/genres/000077500000000000000000000000001356012415200232025ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/genres/genreIdMappings/000077500000000000000000000000001356012415200262565ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/genres/genreIdMappings/AU-SAT.xml000077500000000000000000000417211356012415200277420ustar00rootroot00000000000000 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 pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-IT.xml000066400000000000000000000424431356012415200300670ustar00rootroot00000000000000 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 pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-NZ.xml000066400000000000000000000434401356012415200301000ustar00rootroot00000000000000 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 pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/genres/genreIdMappings/Sky-UK.xml000066400000000000000000000432571356012415200300760ustar00rootroot00000000000000 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 pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/genres/genreRytecTextMappings/000077500000000000000000000000001356012415200276555ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/genres/genreRytecTextMappings/Rytec-UK-Ireland.xml000077500000000000000000000225001356012415200333600ustar00rootroot00000000000000 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 pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/genres/kodiDvbGenres.xml000077500000000000000000000143301356012415200264560ustar00rootroot00000000000000 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 pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/showInfo/000077500000000000000000000000001356012415200235135ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/data/showInfo/English-ShowInfo.xml000077500000000000000000000040351356012415200273650ustar00rootroot00000000000000 English Show Info pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/000077500000000000000000000000001356012415200225715ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.af_za/000077500000000000000000000000001356012415200272615ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.af_za/strings.po000066400000000000000000000231211356012415200313110ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Afrikaans (South Africa) (http://www.transifex.com/projects/p/kodi-main/language/af_ZA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: af_ZA\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Enigma2 gasheernaam of IP adres" msgctxt "#30002" msgid "Streaming port" msgstr "Stroom poort" msgctxt "#30003" msgid "Username" msgstr "Gebruikersnaam" msgctxt "#30004" 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 "Web interface 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 "Update interval" msgstr "Opdateer interval" msgctxt "#30016" msgid "Check for channel updates" msgstr "Kyk vir kanaal opdaterings" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Gebruik slegs die DVB boks se huidige opneem pad" msgctxt "#30018" msgid "General" msgstr "Algemeen" msgctxt "#30019" msgid "Channels" msgstr "Kanale" msgctxt "#30020" msgid "Advanced" msgstr "Gevorderde" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Opnames / Tydhouer" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Opname vouer op die ontvanger" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "Stuur kragtoestand modus met byvoegsel uit gaan" msgctxt "#30025" msgid "TV bouquet fetch mode" msgstr "TV boeket gaan haal modus" msgctxt "#30026" msgid "TV bouquet" msgstr "TV boeket" msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "Gaan haal picons vanaf web koppelvlak" 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 "#30031" msgid "Seasons and Episodes" msgstr "Seisoene en Episodes" msgctxt "#30032" msgid "EPG" msgstr "EPG" msgctxt "#30033" msgid "Extract season, episode and year info where possible" msgstr "Onttrek seisoen, episode en jaar inligting waar moontlik" msgctxt "#30034" msgid "Enable autotimers" msgstr "Stel outotydhouers in staat" msgctxt "#30035" msgid "Use picons.eu file format" msgstr "Gebruik picons.eu lêer formaat" msgctxt "#30036" msgid "Enable generate repeat timers" msgstr "Stel genereer herhaal tydhouers in staat" msgctxt "#30037" msgid "Log missing genre text mappings" msgstr "Log ontbrekende genre teks karterings" msgctxt "#30038" msgid "Web Interface" msgstr "Webkoppelvlak" msgctxt "#30039" msgid "Streaming" msgstr "Stroom" msgctxt "#30040" msgid "Put outline (e.g. sub-title) before plot" msgstr "Plaas oorsig (bv. onderskrif) voor plot" msgctxt "#30041" msgid "Stream read chunk size" msgstr "Stroom lees stuk grootte" 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 "#30046" msgid "Extract show info file" msgstr "Onttrek vertoning inligting lêer" msgctxt "#30047" msgid "Rytec genre text Mappings" msgstr "Rytec genre teks karterings" msgctxt "#30048" msgid "Enable Rytec genre text mappings" msgstr "Stel Rytec genre teks karterings in staat" msgctxt "#30049" msgid "Rytec genre text mappings file" msgstr "Rytec genre teks karterings lêer" msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "Pasgemaakte lewendige TV tydverstreke (0 om verstek te gebruik)" msgctxt "#30051" msgid "Login" msgstr "Teken in" msgctxt "#30052" msgid "Misc" msgstr "Diverse" msgctxt "#30053" msgid "Genre ID Mappings" msgstr "Genre ID Karterings" msgctxt "#30054" msgid "Enable genre ID Mappings" msgstr "Stel genre ID Karterings in staat" msgctxt "#30055" msgid "Genre ID mappings file" msgstr "Genre ID karterings lêer" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30058" msgid "Radio bouquet fetch mode" msgstr "Radio boeket gaan haal modus" msgctxt "#30059" msgid "Radio bouquet" msgstr "Radio boeket" msgctxt "#30060" msgid "Timeshift" msgstr "Tydskuif" msgctxt "#30061" msgid "Enable timeshift" msgstr "Stel tydskuif in staat" 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 "#30066" msgid "Use secure HTTP (https) for streams" msgstr "Gebruik secure HTTP (https) vir strome" msgctxt "#30067" msgid "Use login for streams" msgstr "Gebruik inteken vir strome" msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "Gaan haal TV gunstelinge boeket" msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "Gaan haal radio gunstelinge boeket" msgctxt "#30070" msgid "Recordings & Timers" msgstr "Opnames & Tydhouers" msgctxt "#30071" msgid "Recordings" msgstr "Opnames" msgctxt "#30072" msgid "Timers" msgstr "Tydhouers" msgctxt "#30073" msgid "Number of repeat timers to generate" msgstr "Hoeveelheid herhaal tydhouers om te genereer" msgctxt "#30074" msgid "All bouquets" msgstr "Alle boekette" msgctxt "#30075" msgid "Only one bouquet" msgstr "Slegs een boeket" msgctxt "#30076" msgid "As first bouquet" msgstr "As eerste boeket" msgctxt "#30077" msgid "As last bouquet" msgstr "As laaste boeket" msgctxt "#30078" msgid "Favourites group" msgstr "Gunstelinge groep" msgctxt "#30079" msgid "Favourites (TV)" msgstr "Gunstelinge (TV)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "Gunstelinge (Radio)" msgctxt "#30081" msgid "unknown" msgstr "onbekend" msgctxt "#30082" msgid " (Not connected!)" msgstr "(Nie gekonnekteer!)" msgctxt "#30083" msgid "addon error" msgstr "byvoegsel fout" msgctxt "#30084" msgid "Enigma2 Media Server" msgstr "Enigma2 Media Bediener" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30086" msgid "Backend" msgstr "Agterkant" msgctxt "#30087" msgid "Recording Padding" msgstr "Opname Opstop" msgctxt "#30088" msgid "Global start padding" msgstr "Globale begin opstop" msgctxt "#30089" msgid "Global end padding" msgstr "Globale einde opstop" msgctxt "#30090" msgid "Device Info" msgstr "Toestel Inligting" msgctxt "#30091" msgid "WebIf version" msgstr "Weblf weergawe" msgctxt "#30092" msgid "AutoTimer tag in timer tags" msgstr "OutoTydhouer etiket in tydhouer etikette" msgctxt "#30093" msgid "AutoTimer name in timer tags" msgstr "OutoTydhouer naam in tydhouer etikette" msgctxt "#30094" msgid "N/A" msgstr "NVT" msgctxt "#30095" msgid "True" msgstr "Waar" msgctxt "#30096" msgid "False" msgstr "Vals" msgctxt "#30097" msgid "Standby" msgstr "Bystand" msgctxt "#30098" msgid "Deep standby" msgstr "Diep bystand" msgctxt "#30099" msgid "Wakeup, then standby" msgstr "Waak, dan bystand" msgctxt "#30100" msgid "Update mode" msgstr "Opdateer modus" msgctxt "#30101" msgid "Timers and recordings" msgstr "Tydhouers en opnames" msgctxt "#30102" msgid "Timers only" msgstr "Slegs tydhouers" msgctxt "#30103" msgid "Use OpenWebIf picon path" msgstr "Gebruik OpenWeblf picon pad" 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'" msgstr "Gediskonnekteer van '%s'" 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" msgctxt "#30515" msgid "Enigma2: Could not reach web interface" msgstr "Enigma2: Kon nie web koppelvlak bereik nie" msgctxt "#30516" msgid "Enigma2: No channel groups found" msgstr "Enigma2: Geen kanale groepe gevind nie" msgctxt "#30517" msgid "Enigma2: No channels found" msgstr "Enigma2: Geen kanale gevind nie" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.am_et/000077500000000000000000000000001356012415200272665ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.am_et/strings.po000066400000000000000000000050701356012415200313210ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Amharic (Ethiopia) (http://www.transifex.com/projects/p/kodi-main/language/am_ET/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: am_ET\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" msgctxt "#30003" msgid "Username" msgstr "የተጠቃሚ ስሠ" msgctxt "#30004" msgid "Password" msgstr "የመáŒá‰¢á‹« ቃáˆ" msgctxt "#30005" msgid "Connection" msgstr "áŒáŠ•áŠ™áŠá‰µ " msgctxt "#30006" msgid "Icons" msgstr "áˆáˆáŠ­á‰¶á‰½ " msgctxt "#30007" msgid "Response timeout in seconds" msgstr "መመለሻ ጊዜ በ ሰከንዶች" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "የ ማሻሻያ እረáት በ ደቂቆች" msgctxt "#30014" msgid "Folder for channeldata" msgstr "áŽáˆá‹°áˆ­ ለ ጣቢያዎች ዳታ " msgctxt "#30015" msgid "Update interval" msgstr "የ ማሻሻያ ክáተት" msgctxt "#30016" msgid "Check for channel updates" msgstr "የ ጣቢያ ማሻሻያ መáˆáˆˆáŒŠá‹«" msgctxt "#30018" msgid "General" msgstr "ባጠቃላይ" msgctxt "#30019" msgid "Channels" msgstr "ጣቢያዎች" msgctxt "#30020" msgid "Advanced" msgstr "የረቀቀ" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" 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 "#30056" msgid "TV" msgstr "ቲቪ " msgctxt "#30057" msgid "Radio" msgstr "ራዲዮ " msgctxt "#30063" msgid "Off" msgstr "ማጥáŠá‹« " msgctxt "#30071" msgid "Recordings" msgstr "መቅረጫ " msgctxt "#30072" msgid "Timers" msgstr "መá‰áŒ áˆªá‹«" msgctxt "#30085" msgid "OK" msgstr "እሺ " msgctxt "#30095" msgid "True" msgstr "እá‹áŠá‰µ" msgctxt "#30096" msgid "False" msgstr "ሀሰት" msgctxt "#30430" msgid "Disabled" msgstr "ተሰናክáˆáˆ " msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "áŒáŠ•áŠ™áŠá‰µ ተቋርጧሠከ '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "እንደገና ተገናáŠá‰·áˆ ወደ '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ar_sa/000077500000000000000000000000001356012415200272665ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ar_sa/strings.po000066400000000000000000000035511356012415200313230ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Arabic (Saudi Arabia) (http://www.transifex.com/projects/p/kodi-main/language/ar_SA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ar_SA\n" "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n" msgctxt "#30003" msgid "Username" msgstr "اسم المستخدم" msgctxt "#30004" msgid "Password" msgstr "كلمة المرور" msgctxt "#30006" msgid "Icons" msgstr "رموز" msgctxt "#30018" msgid "General" msgstr "عام" msgctxt "#30019" msgid "Channels" msgstr "محطات" msgctxt "#30020" msgid "Advanced" msgstr "منقدم" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30042" msgid "Never" msgstr "أبداً" msgctxt "#30045" msgid "Always" msgstr "دائما" msgctxt "#30051" msgid "Login" msgstr "تسجيل الدخول" msgctxt "#30056" msgid "TV" msgstr "ØªÙ„ÙØ§Ø²" msgctxt "#30057" msgid "Radio" msgstr "إذاعة" msgctxt "#30063" msgid "Off" msgstr "تعطيل" msgctxt "#30071" msgid "Recordings" msgstr "التسجيلات" msgctxt "#30085" msgid "OK" msgstr "مواÙÙ‚" msgctxt "#30095" msgid "True" msgstr "صحيح" msgctxt "#30096" msgid "False" msgstr "خطأ" msgctxt "#30430" msgid "Disabled" msgstr "معطلة" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "قطع الاتصال من '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "أعيد الاتصال بـ '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.az_az/000077500000000000000000000000001356012415200273055ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.az_az/strings.po000066400000000000000000000017511356012415200313420ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Azerbaijani (Azerbaijan) (http://www.transifex.com/projects/p/kodi-main/language/az_AZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: az_AZ\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30005" msgid "Connection" msgstr "QoÅŸulma" msgctxt "#30006" msgid "Icons" msgstr "Piktoqramlar" msgctxt "#30018" msgid "General" msgstr "Ümumi" msgctxt "#30019" msgid "Channels" msgstr "Kanallar" msgctxt "#30045" msgid "Always" msgstr "HÉ™miÅŸÉ™" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30085" msgid "OK" msgstr "OK" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.be_by/000077500000000000000000000000001356012415200272615ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.be_by/strings.po000066400000000000000000000052261356012415200313170ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Belarusian (Belarus) (http://www.transifex.com/projects/p/kodi-main/language/be_BY/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: be_BY\n" "Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30003" msgid "Username" msgstr "Username" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Update Interval in minutes" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Folder for channeldata" msgctxt "#30015" msgid "Update interval" msgstr "Прамежак паміж абнаўленнÑмі" msgctxt "#30016" msgid "Check for channel updates" msgstr "Check for channel updates" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Use only the DVB boxes' current recording path" msgctxt "#30018" msgid "General" msgstr "ÐгульныÑ" msgctxt "#30019" msgid "Channels" msgstr "Channels" msgctxt "#30020" msgid "Advanced" msgstr "Advanced" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Recordings / Timer" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Recording folder on the receiver" msgctxt "#30042" msgid "Never" msgstr "Ðіколі" msgctxt "#30045" msgid "Always" msgstr "Заўжды" msgctxt "#30051" msgid "Login" msgstr "Login" msgctxt "#30056" msgid "TV" msgstr "ТВ" msgctxt "#30057" msgid "Radio" msgstr "Радыё" msgctxt "#30063" msgid "Off" msgstr "Ðе" msgctxt "#30071" msgid "Recordings" msgstr "Recordings" msgctxt "#30085" msgid "OK" msgstr "Добра" msgctxt "#30095" msgid "True" msgstr "True" msgctxt "#30096" msgid "False" msgstr "False" msgctxt "#30410" msgid "Automatic" msgstr "Ðўтаматычна " msgctxt "#30430" msgid "Disabled" msgstr "Забаронена" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Disconnected from '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Reconnected to '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.bg_bg/000077500000000000000000000000001356012415200272415ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.bg_bg/strings.po000066400000000000000000000311561356012415200313000ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Bulgarian (Bulgaria) (http://www.transifex.com/projects/p/kodi-main/language/bg_BG/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: bg_BG\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Име на Ñървър или IP Ð°Ð´Ñ€ÐµÑ Ð½Ð° Enigma2" msgctxt "#30002" msgid "Streaming port" msgstr "Порт за поточно излъчване" msgctxt "#30003" msgid "Username" msgstr "Потребител" msgctxt "#30004" 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 "Web interface 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 "Update interval" msgstr "Интервал на обновление" msgctxt "#30016" msgid "Check for channel updates" msgstr "Проверка за промени по каналите" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Използване Ñамо на Ñ‚ÐµÐºÑƒÑ‰Ð¸Ñ Ð¿ÑŠÑ‚ за Ð·Ð°Ð¿Ð¸Ñ Ð½Ð° уÑтройÑтвата" msgctxt "#30018" msgid "General" msgstr "ОÑновни" msgctxt "#30019" msgid "Channels" msgstr "Канали" msgctxt "#30020" msgid "Advanced" msgstr "Допълнителни" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "ЗапиÑи / БроÑч" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Папка за запиÑите на приемника" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "Изпращане на инф. за режима на захранване при изход на добавката" msgctxt "#30025" msgid "TV bouquet fetch mode" msgstr "Режим на изтеглÑне на ТВ-букет" msgctxt "#30026" msgid "TV bouquet" msgstr "ТВ-букет" msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "Получаване на логата на каналите от уеб интерфейÑа" 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 "#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 "Използване на Ñ„Ð°Ð¹Ð»Ð¾Ð²Ð¸Ñ Ñ„Ð¾Ñ€Ð¼Ð° на picons.eu" 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 "ТекÑтови ÑÑŠÐ²Ð¿Ð°Ð´ÐµÐ½Ð¸Ñ Ð½Ð° жанровете от Rytec" msgctxt "#30048" msgid "Enable Rytec genre text mappings" msgstr "Включване на текÑтовите ÑÑŠÐ²Ð¿Ð°Ð´ÐµÐ½Ð¸Ñ Ð½Ð° жанровете от Rytec" msgctxt "#30049" msgid "Rytec genre text mappings file" msgstr "Файл Ñ Ñ‚ÐµÐºÑтови ÑÑŠÐ²Ð¿Ð°Ð´ÐµÐ½Ð¸Ñ Ð½Ð° жанровете от Rytec" msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "ПерÑонализирано време за изчакване на ТВ на живо (0 = по подразбиране)" 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 "Ползване на HTTPS за потоците" msgctxt "#30067" msgid "Use login for streams" msgstr "Използване на потребителÑко име и парола за потоците" msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "ИзтеглÑне на букет Ñ Ð»ÑŽÐ±Ð¸Ð¼Ð¸ ТВ" msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "ИзтеглÑне на букет Ñ Ð»ÑŽÐ±Ð¸Ð¼Ð¸ радиа" 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 "Медиен Ñървър „Enigma2“" 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 "ВерÑÐ¸Ñ Ð½Ð° „WebIf“" 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 "Само броÑчи" msgctxt "#30103" msgid "Use OpenWebIf picon path" msgstr "Използване на Ð¿ÑŠÑ‚Ñ Ð·Ð° picon на OpenWebIf" 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“ Ñе разпадна" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Отново има връзка Ñ â€ž%s“" msgctxt "#30514" msgid "Timeshift buffer path does not exist" msgstr "ПътÑÑ‚ до буфера за измеÑтване във времето не ÑъщеÑтвува" msgctxt "#30515" msgid "Enigma2: Could not reach web interface" msgstr "Enigma2: Уеб-интерфейÑÑŠÑ‚ е недоÑтъпен" msgctxt "#30516" msgid "Enigma2: No channel groups found" msgstr "Enigma2: ÐÑма намерени групи от канали" msgctxt "#30517" msgid "Enigma2: No channels found" msgstr "Enigma2: ÐÑма намерени канали" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.bs_ba/000077500000000000000000000000001356012415200272475ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.bs_ba/strings.po000066400000000000000000000027761356012415200313140ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Bosnian (Bosnia and Herzegovina) (http://www.transifex.com/projects/p/kodi-main/language/bs_BA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: bs_BA\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30003" msgid "Username" msgstr "KorisniÄko ime" msgctxt "#30004" msgid "Password" msgstr "Lozinka" msgctxt "#30006" msgid "Icons" msgstr "Ikone" msgctxt "#30018" msgid "General" msgstr "OpÅ¡te" msgctxt "#30019" msgid "Channels" msgstr "Kanali" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30042" msgid "Never" msgstr "Nikada" msgctxt "#30045" msgid "Always" msgstr "Uvijek" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30063" msgid "Off" msgstr "Isklj." msgctxt "#30071" msgid "Recordings" msgstr "Snimci" msgctxt "#30085" msgid "OK" msgstr "U redu" msgctxt "#30095" msgid "True" msgstr "Ispravno" msgctxt "#30096" msgid "False" msgstr "NetaÄno" msgctxt "#30430" msgid "Disabled" msgstr "Onemogućeno" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ca_es/000077500000000000000000000000001356012415200272535ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ca_es/strings.po000066400000000000000000000062411356012415200313070ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Catalan (Spain) (http://www.transifex.com/projects/p/kodi-main/language/ca_ES/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ca_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Nom d'usuari" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Interval d'actualització en minuts" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Carpeta pel canal de dades" msgctxt "#30015" msgid "Update interval" msgstr "Interval d'actualització" msgctxt "#30016" msgid "Check for channel updates" msgstr "Comprova si hi ha actualitzacions dels canals" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Utilitza únicament el camí a l'enregistrament actual de l'aparell DVB" msgctxt "#30018" msgid "General" msgstr "General" msgctxt "#30019" msgid "Channels" msgstr "Canals" msgctxt "#30020" msgid "Advanced" msgstr "Avançat" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Enregistraments / Temporitzador" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Carpeta d'enregistrament en el receptor" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Ràdio" 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 "#30085" msgid "OK" msgstr "D'acord" msgctxt "#30095" msgid "True" msgstr "Cert" msgctxt "#30096" msgid "False" msgstr "Fals" msgctxt "#30410" msgid "Automatic" msgstr "Automàtic" msgctxt "#30430" msgid "Disabled" msgstr "Inhabilitat" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Desconnectat de '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Reconnectat a '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.cs_cz/000077500000000000000000000000001356012415200273025ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.cs_cz/strings.po000066400000000000000000000226111356012415200313350ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Czech (Czech Republic) (http://www.transifex.com/projects/p/kodi-main/language/cs_CZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: cs_CZ\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Název hostitele nebo IP adresa Enigma2" msgctxt "#30002" msgid "Streaming port" msgstr "Port streamování" msgctxt "#30003" msgid "Username" msgstr "Uživatelské jméno" msgctxt "#30004" 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Ä›" 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 "Web interface 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 "Update interval" msgstr "Interval aktualizace" msgctxt "#30016" msgid "Check for channel updates" msgstr "Kontrolovat aktualizace kanálů" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Používat pouze aktuální cestu nahrávání pÅ™ijímaÄe DVB" msgctxt "#30018" msgid "General" msgstr "Obecné" msgctxt "#30019" msgid "Channels" msgstr "Kanály" msgctxt "#30020" msgid "Advanced" msgstr "Rozšířené" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Nahrávky a ÄasovaÄ" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Složka s nahrávkami na pÅ™ijímaÄi" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "PÅ™i ukonÄení doplňku poslat režim stavu napájení" msgctxt "#30026" msgid "TV bouquet" msgstr "TV buket" msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "NaÄíst ikony kanálů 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 "#30031" msgid "Seasons and Episodes" msgstr "Sezóny a epizody" msgctxt "#30032" msgid "EPG" msgstr "Televizní program" msgctxt "#30033" msgid "Extract season, episode and year info where possible" msgstr "Extrahovat informaci o sezónÄ›, epizodÄ› a roku, kde je to možné" msgctxt "#30034" msgid "Enable autotimers" msgstr "Povolit automatické ÄasovaÄe" msgctxt "#30035" msgid "Use picons.eu file format" msgstr "Používat formát souboru picons.eu" msgctxt "#30036" msgid "Enable generate repeat timers" msgstr "Povolit generování opakujících se ÄasovaÄů" msgctxt "#30038" msgid "Web Interface" msgstr "Webové rozhraní" msgctxt "#30039" msgid "Streaming" msgstr "Streamování" msgctxt "#30040" msgid "Put outline (e.g. sub-title) before plot" msgstr "Umístit struÄné shrnutí (napÅ™. titulky) pÅ™ed obsah dÄ›je" msgctxt "#30041" msgid "Stream read chunk size" msgstr "Velikost bloku dat Ätení streamu" 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 "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "Vlastní Äasový limit živého vysílání (0 pro použití výchozího)" msgctxt "#30051" msgid "Login" msgstr "PÅ™ihlášení" msgctxt "#30052" msgid "Misc" msgstr "Různé" msgctxt "#30053" msgid "Genre ID Mappings" msgstr "Mapování ID žánru" msgctxt "#30054" msgid "Enable genre ID Mappings" msgstr "Povolit mapování ID žánru" msgctxt "#30055" msgid "Genre ID mappings file" msgstr "Soubor mapování ID žánru" msgctxt "#30056" msgid "TV" msgstr "Televize" msgctxt "#30057" msgid "Radio" msgstr "Rádio" msgctxt "#30059" msgid "Radio bouquet" msgstr "Buket rádií" msgctxt "#30060" msgid "Timeshift" msgstr "ÄŒasový posun" msgctxt "#30061" msgid "Enable timeshift" msgstr "Povolit Äasový posun" msgctxt "#30062" msgid "Timeshift buffer path" msgstr "Cesta k 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 "#30066" msgid "Use secure HTTP (https) for streams" msgstr "Použít zabezpeÄené HTTP (https) pro streamy" msgctxt "#30067" msgid "Use login for streams" msgstr "Použít pÅ™ihlášení pro streamy" 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 "#30073" msgid "Number of repeat timers to generate" msgstr "PoÄet opakování ÄasovaÄů ke generování" msgctxt "#30074" msgid "All bouquets" msgstr "VÅ¡echny bukety" msgctxt "#30075" msgid "Only one bouquet" msgstr "Pouze jeden buket" msgctxt "#30076" msgid "As first bouquet" msgstr "Jako první buket" msgctxt "#30077" msgid "As last bouquet" msgstr "Jako poslední buket" msgctxt "#30078" msgid "Favourites group" msgstr "Skupina oblíbených" msgctxt "#30079" msgid "Favourites (TV)" msgstr "Oblíbené (TV)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "Oblíbené (rádio)" msgctxt "#30081" msgid "unknown" msgstr "neznámé" msgctxt "#30082" msgid " (Not connected!)" msgstr "(NepÅ™ipojeno!)" msgctxt "#30083" msgid "addon error" msgstr "chyba doplňku" msgctxt "#30084" msgid "Enigma2 Media Server" msgstr "Server médií Enigma2" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30086" msgid "Backend" msgstr "Podpůrná vrstva" msgctxt "#30087" msgid "Recording Padding" msgstr "Zarovnání nahrávání" msgctxt "#30088" msgid "Global start padding" msgstr "Globální zarovnání zaÄátku" msgctxt "#30089" msgid "Global end padding" msgstr "Globální zarovnání konce" msgctxt "#30090" msgid "Device Info" msgstr "Informace o zařízení" msgctxt "#30091" msgid "WebIf version" msgstr "Verze WebIf" msgctxt "#30092" msgid "AutoTimer tag in timer tags" msgstr "Å títek automatického ÄasovaÄe v Å¡títcích ÄasovaÄů" msgctxt "#30093" msgid "AutoTimer name in timer tags" msgstr "Název automatického ÄasovaÄe v Å¡títcích ÄasovaÄů" msgctxt "#30094" msgid "N/A" msgstr "Nezadáno" msgctxt "#30095" msgid "True" msgstr "Pravda" msgctxt "#30096" msgid "False" msgstr "Nepravda" msgctxt "#30097" msgid "Standby" msgstr "Pohotovostní režim" msgctxt "#30098" msgid "Deep standby" msgstr "Pohotovostní režim s nižší spotÅ™ebou" msgctxt "#30099" msgid "Wakeup, then standby" msgstr "Probudit, pak pohotovostní režim" msgctxt "#30100" msgid "Update mode" msgstr "Režim aktualizace" msgctxt "#30101" msgid "Timers and recordings" msgstr "ÄŒasovaÄe a nahrávání" msgctxt "#30102" msgid "Timers only" msgstr "Pouze ÄasovaÄe" msgctxt "#30103" msgid "Use OpenWebIf picon path" msgstr "Použij OpenWebIf cestu k pikonám" 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 na základÄ› televizního programu)" 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'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Znovu pÅ™ipojeno k '%s'" msgctxt "#30514" msgid "Timeshift buffer path does not exist" msgstr "Cesta k vyrovnávací pamÄ›ti Äasového posunu neexistuje" msgctxt "#30515" msgid "Enigma2: Could not reach web interface" msgstr "Enigma2: Nemohu se spojit s webovým rozhraním" msgctxt "#30516" msgid "Enigma2: No channel groups found" msgstr "Enigma2: Nenalezeny skupiny kanálů" msgctxt "#30517" msgid "Enigma2: No channels found" msgstr "Enigma2: Nenalezeny kanály" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.cy_gb/000077500000000000000000000000001356012415200272645ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.cy_gb/strings.po000066400000000000000000000054751356012415200313300ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Welsh (United Kingdom) (http://www.transifex.com/projects/p/kodi-main/language/cy_GB/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: cy_GB\n" "Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n==2) ? 1 : (n != 8 && n != 11) ? 2 : 3;\n" msgctxt "#30003" msgid "Username" msgstr "Enw defnyddiwr" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Cyfnod diweddaru mewn munudau" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Ffolder ar gyfer data sianel" msgctxt "#30016" msgid "Check for channel updates" msgstr "Gwirio am ddiweddariad sianeli" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Defnyddio llwybr recordio cyfredol y blwch DVB" msgctxt "#30018" msgid "General" msgstr "Cyffredinol" msgctxt "#30019" msgid "Channels" msgstr "Sianeli" msgctxt "#30020" msgid "Advanced" msgstr "Uwch" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Recordiadau / Amserydd" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Ffolder recordio ar y derbynnydd" 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 "#30056" msgid "TV" msgstr "Teledu" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30062" msgid "Timeshift buffer path" msgstr "Llwybr byffro Symud Amser" msgctxt "#30063" msgid "Off" msgstr "Diffodd" msgctxt "#30071" msgid "Recordings" msgstr "Recordiadau" msgctxt "#30085" msgid "OK" msgstr "Iawn" msgctxt "#30094" msgid "N/A" msgstr "Dim ar Gael" msgctxt "#30095" msgid "True" msgstr "Gwir" msgctxt "#30096" msgid "False" msgstr "Gau" msgctxt "#30430" msgid "Disabled" msgstr "Analluogwyd" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Datgysylltwyd o '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Ail gysylltwyd â '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.da_dk/000077500000000000000000000000001356012415200272435ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.da_dk/strings.po000066400000000000000000000061121356012415200312740ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Danish (Denmark) (http://www.transifex.com/projects/p/kodi-main/language/da_DK/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: da_DK\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Brugernavn" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Opdateringsinterval i minutter" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Mappe til kanaldata" msgctxt "#30015" msgid "Update interval" msgstr "Opdateringsinterval" msgctxt "#30016" msgid "Check for channel updates" msgstr "Søg efter kanalopdateringer" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Brug kun DVB-boksens nuværende sti til optagelser" msgctxt "#30018" msgid "General" msgstr "Generelt" msgctxt "#30019" msgid "Channels" msgstr "Kanaler" msgctxt "#30020" msgid "Advanced" msgstr "Avanceret" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Optagelser / Timer" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Optagelsesmappe pÃ¥ modtageren" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "OK" msgctxt "#30094" msgid "N/A" msgstr "N/A" msgctxt "#30095" msgid "True" msgstr "Sandt" msgctxt "#30096" msgid "False" msgstr "Falsk" msgctxt "#30410" msgid "Automatic" msgstr "Automatisk" msgctxt "#30430" msgid "Disabled" msgstr "Deaktiveret" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Forbindelse afbrudt fra '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Forbundet igen til '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.de_de/000077500000000000000000000000001356012415200272415ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.de_de/strings.po000066400000000000000000000106461356012415200313010ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: German (Germany) (http://www.transifex.com/projects/p/kodi-main/language/de_DE/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de_DE\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Benutzername" msgctxt "#30004" 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 "#30009" msgid "Update Interval" msgstr "Aktualisierungsintervall" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Aktualisierungsintervall in Minuten" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Speicherort für Kanaldaten" msgctxt "#30015" msgid "Update interval" msgstr "Aktualisierungsintervall" msgctxt "#30016" msgid "Check for channel updates" msgstr "Überprüfe auf Kanalaktualisierungen" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Nur den aktuellen Box-Aufnahmenpfad nutzen" msgctxt "#30018" msgid "General" msgstr "Allgemein" msgctxt "#30019" msgid "Channels" msgstr "Sender" msgctxt "#30020" msgid "Advanced" msgstr "Erweitert" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Aufnahmen / Timer" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Aufnahmeverzeichnis auf dem Receiver" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "OK" msgctxt "#30094" msgid "N/A" msgstr "N/A" msgctxt "#30095" msgid "True" msgstr "Richtig" msgctxt "#30096" msgid "False" msgstr "Falsch" 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'" msgstr "Verbindung zu '%s' unterbrochen" 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" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.el_gr/000077500000000000000000000000001356012415200272715ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.el_gr/strings.po000066400000000000000000000066161356012415200313330ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Greek (Greece) (http://www.transifex.com/projects/p/kodi-main/language/el_GR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: el_GR\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Όνομα χÏήστη" msgctxt "#30004" msgid "Password" msgstr "Κωδικός Ï€Ïόσβασης" msgctxt "#30005" msgid "Connection" msgstr "ΣÏνδεση" msgctxt "#30006" msgid "Icons" msgstr "Εικονίδια" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "ΧÏόνος απόκÏισης σε δευτεÏόλεπτα" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Διάστημα ΕνημέÏωσης σε λεπτά" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Φάκελος για δεδομένα καναλιών" msgctxt "#30015" msgid "Update interval" msgstr "Διάστημα ενημέÏωσης " msgctxt "#30016" msgid "Check for channel updates" msgstr "Έλεγχος για ενημεÏώσεις καναλιών" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "ΧÏήση μόνο της Ï„Ïέχουσας διαδÏομής εγγÏαφών του DVB" msgctxt "#30018" msgid "General" msgstr "Γενικά" msgctxt "#30019" msgid "Channels" msgstr "Κανάλια" msgctxt "#30020" msgid "Advanced" msgstr "Για Ï€ÏοχωÏημένους" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "ΕγγÏαφές / ΧÏονοδιακόπτης" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Φάκελος εγγÏαφών στο δέκτη" 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 "#30056" msgid "TV" msgstr "ΤηλεόÏαση" msgctxt "#30057" msgid "Radio" 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 "#30085" msgid "OK" msgstr "Εντάξει" msgctxt "#30094" msgid "N/A" msgstr "Α/Α" msgctxt "#30095" msgid "True" msgstr "Αληθές" msgctxt "#30096" msgid "False" msgstr "Ψευδές" msgctxt "#30430" msgid "Disabled" msgstr "ΑνενεÏγή" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "ΑποσÏνδεση από '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "ΕπανασÏνδεση σε '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.en_au/000077500000000000000000000000001356012415200272705ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.en_au/strings.po000066400000000000000000000046501356012415200313260ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: English (Australia) (http://www.transifex.com/projects/p/kodi-main/language/en_AU/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: en_AU\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Username" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Update Interval in minutes" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Folder for channeldata" msgctxt "#30016" msgid "Check for channel updates" msgstr "Check for channel updates" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Use only the DVB boxes' current recording path" msgctxt "#30018" msgid "General" msgstr "General" msgctxt "#30019" msgid "Channels" msgstr "Channels" msgctxt "#30020" msgid "Advanced" msgstr "Advanced" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Recordings / Timer" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Recording folder on the receiver" msgctxt "#30042" msgid "Never" msgstr "Never" msgctxt "#30045" msgid "Always" msgstr "Always" msgctxt "#30051" msgid "Login" msgstr "Login" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30062" msgid "Timeshift buffer path" msgstr "Timeshift buffer path" msgctxt "#30063" msgid "Off" msgstr "Off" msgctxt "#30071" msgid "Recordings" msgstr "Recordings" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30095" msgid "True" msgstr "True" msgctxt "#30096" msgid "False" msgstr "False" msgctxt "#30430" msgid "Disabled" msgstr "Disabled" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Disconnected from '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Reconnected to '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.en_gb/000077500000000000000000000000001356012415200272535ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.en_gb/strings.po000066400000000000000000001126131356012415200313100ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: English (United Kingdom) (http://www.transifex.com/projects/p/kodi-main/language/en_GB/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: en_GB\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" ################### # settings labels # ################### #label: Connection - host msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "" #empty string with id 30001 #label: Connection - streamport msgctxt "#30002" msgid "Streaming port" msgstr "" #label: Connection - user msgctxt "#30003" msgid "Username" msgstr "" #label: Connection - pass msgctxt "#30004" msgid "Password" msgstr "" #label-category: connection msgctxt "#30005" msgid "Connection" msgstr "" #label-group: General - Icons msgctxt "#30006" msgid "Icons" msgstr "" #label-group: General - Program Streams msgctxt "#30007" msgid "Program Streams" msgstr "" #label: General - iconpath msgctxt "#30008" msgid "Icon path" msgstr "" #label-group: General - Update Interval msgctxt "#30009" msgid "Update Interval" msgstr "" #empty string with id 30010 #label: Timers - timerlistcleanup msgctxt "#30011" msgid "Automatic timerlist cleanup" msgstr "" #label: Connection - webport msgctxt "#30012" msgid "Web interface port" msgstr "" #label: Channels - zap msgctxt "#30013" msgid "Zap before channelswitch (i.e. for single tuner boxes)" msgstr "" #label: Channels - setprogramid msgctxt "#30014" msgid "Set program id for live channel or recorded streams" msgstr "" #label: General - updateint msgctxt "#30015" msgid "Update interval" msgstr "" #empty string with id 30016 #label: Recordings - onlycurrent msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "" #label-category: general #label-group: Channels msgctxt "#30018" msgid "General" msgstr "" #label-category: channels msgctxt "#30019" msgid "Channels" msgstr "" #label-category: advanced #label-group: Connection - Advanced msgctxt "#30020" msgid "Advanced" msgstr "" #empty strings from id 30021 to 30022 #label: Recordings - recordingpath msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "" #label: Advanced - powerstatemode msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "" #label: Channels - tvgroupmode msgctxt "#30025" msgid "TV bouquet fetch mode" msgstr "" #label: Channels - onetvgroup msgctxt "#30026" msgid "TV bouquet 1" msgstr "" #label: General - onlinepicons msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "" label: Connection - use_secure msgctxt "#30028" msgid "Use secure HTTP (https)" msgstr "" #label: Connection - autoconfig msgctxt "#30029" msgid "Enable automatic configuration for live streams" msgstr "" #label: Reordings - keepfolders msgctxt "#30030" msgid "Keep folder structure for records" msgstr "" #label-group: EPG - Seasons and Episodes msgctxt "#30031" msgid "Seasons and Episodes" msgstr "" #label-category: epg msgctxt "#30032" msgid "EPG" msgstr "" #label: EPG - extractshowinfoenabled msgctxt "#30033" msgid "Extract season, episode and year info where possible" msgstr "" #label: Timers - enableautotimers msgctxt "#30034" msgid "Enable autotimers" msgstr "" #label: General - usepiconseuformat msgctxt "#30035" msgid "Use picons.eu file format" msgstr "" #label: Timers - enablegenrepeattimers msgctxt "#30036" msgid "Enable generate repeat timers" msgstr "" #label: EPG - logmissinggenremapping msgctxt "#30037" msgid "Log missing genre text mappings" msgstr "" #label-group: Connection - Web Interface msgctxt "#30038" msgid "Web Interface" msgstr "" #label-group: Connection - Streaming msgctxt "#30039" msgid "Streaming" msgstr "" #label: Advanced - prependoutline msgctxt "#30040" msgid "Put outline (e.g. sub-title) before plot" msgstr "" #label: Advanced - streamreadchunksize msgctxt "#30041" msgid "Stream read chunk size" msgstr "" #label - Advanced - prependoutline msgctxt "#30042" msgid "Never" msgstr "" #label - Advanced - prependoutline msgctxt "#30043" msgid "In EPG only" msgstr "" #label - Advanced - prependoutline msgctxt "#30044" msgid "In recordings only" msgstr "" #label - Advanced - prependoutline msgctxt "#30045" msgid "Always" msgstr "" #label: EPG - extractshowinfofile msgctxt "#30046" msgid "Extract show info file" msgstr "" #label-group: EPG - Rytec genre text Mappings msgctxt "#30047" msgid "Rytec genre text Mappings" msgstr "" #label: EPG - rytecgenretextmapenabled msgctxt "#30048" msgid "Enable Rytec genre text mappings" msgstr "" #label: EPG - rytecgenretextmapfile msgctxt "#30049" msgid "Rytec genre text mappings file" msgstr "" #label: Advanced - readtimeout msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "" #label-group: Connection - Login msgctxt "#30051" msgid "Login" msgstr "" #label-group: Advanced - Misc msgctxt "#30052" msgid "Misc" msgstr "" #label-group: EPG - Genre ID Mappings msgctxt "#30053" msgid "Genre ID Mappings" msgstr "" #label: EPG - genreidmapenabled msgctxt "#30054" msgid "Enable genre ID Mappings" msgstr "" #label: EPG - genreidmapfile msgctxt "#30055" msgid "Genre ID mappings file" msgstr "" #label-group: Channels - TV msgctxt "#30056" msgid "TV" msgstr "" #label-group: Channels - Radio msgctxt "#30057" msgid "Radio" msgstr "" #label: Channels - radiogroupmode msgctxt "#30058" msgid "Radio bouquet fetch mode" msgstr "" #label: Channels - oneradiogroup msgctxt "#30059" msgid "Radio bouquet 1" msgstr "" #label-category: timeshift #label-group: Timeshift - Timeshift msgctxt "#30060" msgid "Timeshift" msgstr "" #label: Timeshift - enabletimeshift msgctxt "#30061" msgid "Enable timeshift" msgstr "" #label: Timeshift - timeshiftbufferpath msgctxt "#30062" msgid "Timeshift buffer path" msgstr "" #label-option: Timeshift - enabletimeshift msgctxt "#30063" msgid "Off" msgstr "" #label-option: Timeshift - enabletimeshift msgctxt "#30064" msgid "On playback" msgstr "" #label-option: Timeshift - enabletimeshift msgctxt "#30065" msgid "On pause" msgstr "" #label: Connection - use_secure_stream msgctxt "#30066" msgid "Use secure HTTP (https) for streams" msgstr "" #label: Connection - use_login_stream msgctxt "#30067" msgid "Use login for streams" msgstr "" #label: Channels - tvfavouritesmode msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "" #label: Channels - radiofavouritesmode msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "" #label-category: recordings msgctxt "#30070" msgid "Recordings" msgstr "" #label-group: Recordings - Recordings msgctxt "#30071" msgid "Recordings" msgstr "" #label-category: timers #label-group: Timers - timers msgctxt "#30072" msgid "Timers" msgstr "" #label: Timers - numgenrepeattimers msgctxt "#30073" msgid "Number of repeat timers to generate" msgstr "" #label-option: Channels - tvgroupmode #label-option: Channels - radiogroupmode msgctxt "#30074" msgid "All bouquets" msgstr "" #label-option: Channels - tvgroupmode #label-option: Channels - radiogroupmode msgctxt "#30075" msgid "Some bouquets" msgstr "" #label-option: Channels - tvfavouritesmode #label-option: Channels - radiofavouritesmode msgctxt "#30076" msgid "As first bouquet" msgstr "" #label-option: Channels - tvfavouritesmode #label-option: Channels - radiofavouritesmode msgctxt "#30077" msgid "As last bouquet" msgstr "" #label-option: Channels - tvgroupmode #label-option: Channels - radiogroupmode msgctxt "#30078" msgid "Favourites bouquet" msgstr "" #application: ChannelGroups msgctxt "#30079" msgid "Favourites (TV)" msgstr "" #application: ChannelGroups msgctxt "#30080" msgid "Favourites (Radio)" msgstr "" #application: Client #application: Admin msgctxt "#30081" msgid "unknown" msgstr "" #application: Client msgctxt "#30082" msgid " (Not connected!)" msgstr "" #application: Client msgctxt "#30083" msgid "addon error" msgstr "" #empty strings from id 30084 to 30085 #label-category: backend msgctxt "#30086" msgid "Backend" msgstr "" #label-group: Backend - Recording Padding msgctxt "#30087" msgid "Recording Padding" msgstr "" #label: Backend - globalstartpaddingstb msgctxt "#30088" msgid "Global start padding" msgstr "" #label: Backend - globalendpaddingstb msgctxt "#30089" msgid "Global end padding" msgstr "" #label-group: Backend - Device Info msgctxt "#30090" msgid "Device Info" msgstr "" #label: Backend - webifversion msgctxt "#30091" msgid "WebIf version" msgstr "" #label: Backend - autotimertagintags msgctxt "#30092" msgid "AutoTimer tag in timer tags" msgstr "" #label: Backend - autotimernameintags msgctxt "#30093" msgid "AutoTimer name in timer tags" msgstr "" #application: Admin msgctxt "#30094" msgid "N/A" msgstr "" #application: Admin msgctxt "#30095" msgid "True" msgstr "" #application: Admin msgctxt "#30096" msgid "False" msgstr "" #label-option: Advanced - powerstatemode msgctxt "#30097" msgid "Standby" msgstr "" #label-option: Advanced - powerstatemode msgctxt "#30098" msgid "Deep standby" msgstr "" #label-option: Advanced - powerstatemode msgctxt "#30099" msgid "Wakeup, then standby" msgstr "" #label: General - updatemode msgctxt "#30100" msgid "Update mode" msgstr "" #label-option: General - updatemode msgctxt "#30101" msgid "Timers and recordings" msgstr "" #label-option: General - updatemode msgctxt "#30102" msgid "Timers only" msgstr "" #label: General - useopenwebifpiconpath msgctxt "#30103" msgid "Use OpenWebIf picon path" msgstr "" #label: Advanced - tracedebug msgctxt "#30104" msgid "Enable trace logging in debug mode" msgstr "" #label-group - EPG - Other msgctxt "#30105" msgid "Other" msgstr "" #label: EPG - epgdelayperchannel msgctxt "#30106" msgid "EPG update delay per channel" msgstr "" #label-group: Recordings - Recording EDLs (Edit Decision Lists) msgctxt "#30107" msgid "Recording EDLs (Edit Decision Lists)" msgstr "" #label: Recordings - enablerecordingedls msgctxt "#30108" msgid "Enable EDLs support" msgstr "" #label: Recordings - edlpaddingstart msgctxt "#30109" msgid "EDL start time padding" msgstr "" #label: Recordings - edlpaddingstop msgctxt "#30110" msgid "EDL stop time padding" msgstr "" #label: Advanced - debugnormal msgctxt "#30111" msgid "Enable debug logging in normal mode" msgstr "" #application: ChannelGroups msgctxt "#30112" msgid "Last Scanned (TV)" msgstr "" #application: ChannelGroups msgctxt "#30113" msgid "Last Scanned (Radio)" msgstr "" #label: Channels - excludelastscannedtv #label: Channels - excludelastscannedradio msgctxt "#30114" msgid "Exclude last scanned bouquet" msgstr "" #label: EPG - skipinitialepg msgctxt "#30115" msgid "Skip Initial EPG Load" msgstr "" #label: General - channelandgroupupdatemode msgctxt "#30116" msgid "Channels and groups update mode" msgstr "" #label-option: General - channelandgroupupdatemode msgctxt "#30117" msgid "Disabled" msgstr "" #label-option: General - channelandgroupupdatemode msgctxt "#30118" msgid "Notify on UI and Log" msgstr "" #label-option: General - channelandgroupupdatemode msgctxt "#30119" msgid "Reload Channels and Groups" msgstr "" #label: General - channelandgroupupdatehour msgctxt "#30120" msgid "Channels and groups update hour (24h)" msgstr "" #label: Connection - connectionchecktimeout msgctxt "#30121" msgid "Connection check timeout" msgstr "" #label: Connection - connectioncheckinterval msgctxt "#30122" msgid "Connection check interval" msgstr "" #label: Timers - Autotimers msgctxt "#30123" msgid "Autotimers" msgstr "" #label: Timers - limitanychannelautotimers msgctxt "#30124" msgid "Limit 'Any Channel' autotimers to TV or Radio" msgstr "" #label: Timers - limitanychannelautotimerstogroups msgctxt "#30125" msgid "Limit to groups of original EPG channel" msgstr "" #label: Channels - usestandardserviceref msgctxt "#30126" msgid "Use standard channel service reference" msgstr "" #label: Recordings - storeextrarecordinginfo msgctxt "#30127" msgid "Store last played/play count on the backend" msgstr "" #label: Recordings - sharerecordinglastplayed msgctxt "#30128" msgid "Share last played across:" msgstr "" #label-option: Recordings - sharerecordinglastplayed msgctxt "#30129" msgid "Kodi instances" msgstr "" #label-option: Recordings - sharerecordinglastplayed msgctxt "#30130" msgid "Kodi/E2 instances" msgstr "" #label-option: Channels - tvgroupmode #label-option: Channels - radiogroupmode msgctxt "#30131" msgid "Custom bouquets" msgstr "" #label: Channels - customtvgroupsfile msgctxt "#30132" msgid "Custom TV bouquets file" msgstr "" #label: Channels - customradiogroupsfile msgctxt "#30133" msgid "Custom Radio bouquets file" msgstr "" #label: Channels - numtvgroups msgctxt "#30134" msgid "Number of TV bouquets" msgstr "" #label: Channels - twotvgroup msgctxt "#30135" msgid "TV bouquet 2" msgstr "" #label: Channels - threetvgroup msgctxt "#30136" msgid "TV bouquet 3" msgstr "" #label: Channels - fourtvgroup msgctxt "#30137" msgid "TV bouquet 4" msgstr "" #label: Channels - fivetvgroup msgctxt "#30138" msgid "TV bouquet 5" msgstr "" #label: Channels - numradiogroups msgctxt "#30139" msgid "Number of radio bouquets" msgstr "" #label: Channels - tworadiogroup msgctxt "#30140" msgid "Radio bouquet 2" msgstr "" #label: Channels - threeradiogroup msgctxt "#30141" msgid "Radio bouquet 3" msgstr "" #label: Channels - fourradiogroup msgctxt "#30142" msgid "Radio bouquet 4" msgstr "" #label: Channels - fiveradiogroup msgctxt "#30143" msgid "Radio bouquet 5" msgstr "" #label: Advanced - ignoredebug msgctxt "#30144" msgid "No addon debug logging in Kodi debug mode" msgstr "" #empty strings from id 30145 to 30409 ############### # application # ############### #application: Timers msgctxt "#30410" msgid "Automatic" msgstr "" #empty strings from id 30411 to 30419 #application: Timers msgctxt "#30420" msgid "Once off timer (set by auto guide-based rule)" msgstr "" #application: Timers msgctxt "#30421" msgid "Once off timer (set by repeating time/channel based rule)" msgstr "" #application: Timers msgctxt "#30422" msgid "Once off time/channel based" msgstr "" #application: Timers msgctxt "#30423" msgid "Repeating time/channel based" msgstr "" #application: Timers msgctxt "#30424" msgid "One time guide-based" msgstr "" #application: Timers msgctxt "#30425" msgid "Repeating guide-based" msgstr "" #application: Timers msgctxt "#30426" msgid "Auto guide-based" msgstr "" #empty strings from id 30427 to 30429 #label-option: Channels - tvfavouritesmode #label-option: Channels - radiofavouritesmode #label-option: Advanced - powerstatemode #application: Timers msgctxt "#30430" msgid "Disabled" msgstr "" #application: Timers msgctxt "#30431" msgid "Record if EPG title differs" msgstr "" #application: Timers msgctxt "#30432" msgid "Record if EPG title and short description differs" msgstr "" #application: Timers msgctxt "#30433" msgid "Record if EPG title and all descriptions differ" msgstr "" #empty strings from id 30434 to 30499 ################# # notifications # ################# #empty strings from id 300500 to 30513 #notification: Client msgctxt "#30514" msgid "Timeshift buffer path does not exist" msgstr "" #notification: Enigma2 msgctxt "#30515" msgid "Enigma2: Could not reach web interface" msgstr "" #notification: Enigma2 msgctxt "#30516" msgid "Enigma2: No channel groups found" msgstr "" #notification: Enigma2 msgctxt "#30517" msgid "Enigma2: No channels found" msgstr "" #notification: Enigma2 msgctxt "#30518" msgid "Enigma2: Channel group changes detected, please restart to load changes" msgstr "" #notification: Enigma2 msgctxt "#30519" msgid "Enigma2: Channel changes detected, please restart to load changes" msgstr "" #application: AutoTimer #application: Timer msgctxt "#30520" msgid "Invalid Channel" msgstr "" #notification: Enigma2 msgctxt "#30521" msgid "Enigma2: Channel group changes detected, reloading..." msgstr "" #notification: Enigma2 msgctxt "#30522" msgid "Enigma2: Channel changes detected, reloading..." msgstr "" #empty strings from id 30523 to 30599 ############# # help info # ############# #help info - Connection #help-category: connection msgctxt "#30600" msgid "This category cotains the settings for connecting to the Enigma2 device" msgstr "" #help: Connection - host msgctxt "#30601" msgid "The IP address or hostname of your enigma2 based set-top box." msgstr "" #help: Connection - webport msgctxt "#30602" msgid "The port used to connect to the web interface." msgstr "" #help: Connection - use_secure msgctxt "#30603" msgid "Use https to connect to the web interface." msgstr "" #help: Connection - user msgctxt "#30604" msgid "If the webinterface of the set-top box is protected with a username/password combination this needs to be set in this option." msgstr "" #help: Connection - pass msgctxt "#30605" msgid "If the webinterface of the set-top box is protected with a username/password combination this needs to be set in this option." msgstr "" #help: Connection - autoconfig msgctxt "#30606" msgid "When enabled the stream URL will be read from an M3U8 file. When disabled it is constructed based on the service reference of the channel. This option is rarely required and should not be enbaled unless you have a special use case. If viewing an IPTV Stream this option has no effect on those channels." msgstr "" #help: Connection - streamport msgctxt "#30607" msgid "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." msgstr "" #help: Connection - use_secure_stream msgctxt "#30608" msgid "Use https to connect to streams." msgstr "" #help: Connection - use_login_stream msgctxt "#30609" msgid "Use the login username and password for streams." msgstr "" #help: Connection - connectionchecktimeout msgctxt "#30610" msgid "The value in seconds to wait for a connection check to complete before failure. Useful for tuning on older Enigma2 devices. Note, this setting should rarely need to be changed. It's more likely the `Connection check interval` setting will have the desired effect. Default is 30 seconds." msgstr "" #help: Connection - connectioncheckinterval msgctxt "#30611" msgid "The value in seconds to wait between connection checks. Useful for tuning on older Enigma2 devices. Default is 10 seconds." msgstr "" #empty strings from id 30612 to 30619 #help info - General #help-category: general msgctxt "#30620" msgid "This category cotains the settings whivh generally need to be set by the user" msgstr "" #help: General - onlinepicons msgctxt "#30621" msgid "Fetch the picons straight from the Enigma 2 set-top box." msgstr "" #help: General - useopenwebifpiconpath msgctxt "#30622" msgid "Fetch the picon path from OpenWebIf instead of constructing from ServiceRef. Requires OpenWebIf 1.3.5 or higher. There is no effect if used on a lower version of OpenWebIf." msgstr "" #help: General - usepiconseuformat msgctxt "#30623" msgid "Assume all picons files fetched from the set-top box start with '1_1_1_' and end with '_0_0_0'." msgstr "" #help: General - iconpath msgctxt "#30624" msgid "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." msgstr "" #help: General - updateint msgctxt "#30625" msgid "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. Please note that updating the recordings frequently can keep your receiver and it's harddisk from entering standby automatically." msgstr "" #help: General - updatemode msgctxt "#30626" msgid "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. If it's important to not spin up the HDD on your STB use this option. The HDD should then only spin up when a timer event occurs." msgstr "" #help: General - channelandgroupupdatemode msgctxt "#30627" msgid "The mode used when the hour in the next settings is reached. Choose from one of the following three modes: [Disabled] Never check for channel and group changes; [Notify on UI and Log] Display a notice in the UI and log the fact that a change was detectetd]; [Reload Channels and Groups] Disconnect and reconnect with E2 device to reload channels only if a change is detected." msgstr "" #help: General - channelandgroupupdatehour msgctxt "#30628" msgid "The hour of the day when the check for new channels should occur. Default is 4h as the Auto Bouquet Maker (ABM) on the E2 device defaults to 3AM." msgstr "" #help: Channels - setprogramid msgctxt "#30629" msgid "Some TV Providers (e.g. Nos - Portugal) using MPTS send extra program stream information. Setting the program id allows kodi to select the correct stream and therefore makes the channel/recording playable. Note that it takes approx 33% longer to open any stream with this option enabled." msgstr "" #empty strings from id 30630 to 30639 #help info - Channels #help-category: channels msgctxt "#30640" msgid "This category cotains the settings for channels. 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'." msgstr "" #help: Channels - usestandardserviceref msgctxt "#30641" msgid "Usually service reference's for the channels are in a standard format like '1:0:1:27F6:806:2:11A0000:0:0:0:'. On occasion depending on provider they can be extended with some text e.g. '1:0:1:27F6:806:2:11A0000:0:0:0::UTV' or '1:0:1:27F6:806:2:11A0000:0:0:0::UTV + 1'. If this option is enabled then all read service reference's will be read as standard. This is default behaviour. Functionality like autotimers will always convert to a standard reference." msgstr "" #help: Channels - zap msgctxt "#30642" msgid "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." msgstr "" #help: Channels - tvgroupmode msgctxt "#30643" msgid "Choose from one of the following three modes: [All bouquets] Fetch all TV bouquets from the set-top box; [Some bouquets] Only fetch the bouquets specified in the next options; [Favourites group] Only fetch the system bouquet for TV favourites; [Custom groups] Fetch a set of bouquets from the Set-top box whose names are loaded from an XML file." msgstr "" #help: Channels - onetvgroup #help: Channels - twotvgroup #help: Channels - threetvgroup #help: Channels - fourtvgroup #help: Channels - fivetvgroup msgctxt "#30644" msgid "If the previous option has been has been set to 'Some bouquets' you need to specify a 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." msgstr "" #help: Channels - tvfavouritesmode msgctxt "#30645" msgid "If the fetch mode is 'All bouquets' or 'Some bouquets' 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." msgstr "" #help: Channels - excludelastscannedtv msgctxt "#30646" msgid "Last scanned is a system bouquet containing all the TV and Radio channels found in the last scan. Any TV channels found in the Last Scanned bouquet can be displayed as a group called 'Last Scanned (TV)' in Kodi. For TV this group is excluded by default. Disable this option to exclude this group. Note that if no TV groups are loaded the Last Scanned group for TV will be loaded by default regardless of this setting." msgstr "" #help: Channels - radiogroupmode msgctxt "#30647" msgid "Choose from one of the following three modes: [All bouquets] Fetch all Radio bouquets from the set-top box]; [Some bouquets] Only fetch the bouquets specified in the next options; [Favourites group] Only fetch the system bouquet for Radio favourites; [Custom groups] Fetch a set of bouquets from the Set-top box whose names are loaded from an XML file." msgstr "" #help: Channels - oneradiogroup #help: Channels - tworadiogroup #help: Channels - threeradiogroup #help: Channels - fourradiogroup #help: Channels - fiveradiogroup msgctxt "#30648" msgid "If the previous option has been has been set to 'Some bouquets' you need to specify a 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." msgstr "" #help: Channels - radiofavouritesmode msgctxt "#30649" msgid "If the fetch mode is 'All bouquets' or 'Some bouquets' 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." msgstr "" #help: Channels - excludelastscannedradio msgctxt "#30650" msgid "Last scanned is a system bouquet containing all the TV and Radio channels found in the last scan. Any Radio channels found in the Last Scanned bouquet can be displayed as a group called 'Last Scanned (Radio)' in Kodi. For Radio this group is excluded by default. Disable this option to show this group." msgstr "" #help: Channels - customtvgroupsfile msgctxt "#30651" msgid "The file used to load the custom TV bouquets (groups). If no groups can be matched the channel list will default to 'Last Scanned (TV)'. The default file is `customTVGroups-example.xml`." msgstr "" #help: Channels - customradiogroupsfile msgctxt "#30652" msgid "The file used to load the custom Radio bouquets (groups). If no groups can be matched the channel list will default to 'Last Scanned (Radio)'. The default file is `customRadioGroups-example.xml`." msgstr "" #help: Channels - numtvgroups msgctxt "#30653" msgid "The number of TV bouquets to load when `Some bouquets` is the selected fetch mode. Up to 5 can be chosen. If more than 5 are required the 'Custom bouquets' fetch mode should be used instead." msgstr "" #help: Channels - numradiogroups msgctxt "#30654" msgid "The number of Radio bouquets to load when `Some bouquets` is the selected fetch mode. Up to 5 can be chosen. If more than 5 are required the 'Custom bouquets' fetch mode should be used instead." msgstr "" #empty strings from id 30655 to 30659 #help info - EPG #help-category: epg msgctxt "#30660" msgid "This category cotains the settings for EPG (Electronic Programme Guide). 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." msgstr "" #help: EPG - extractshowinfoenabled msgctxt "#30661" msgid "Check the description fields in the EPG data and attempt to extract season, episode and year info where possible." msgstr "" #help: EPG - extractshowinfofile msgctxt "#30662" msgid "The config used to extract season, episode and year information. The default file is `English-ShowInfo.xml`." msgstr "" #help: EPG - genreidmapenabled msgctxt "#30663" msgid "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." msgstr "" #help: EPG - genreidmapfile msgctxt "#30664" msgid "The config used to map set-top box EPG genre IDs to DVB standard IDs. The default file is `Sky-UK.xml`." msgstr "" #help: EPG - rytecgenretextmapenabled msgctxt "#30665" msgid "If you use Rytec XMLTV EPG data this option can be used to map the text genres to DVB standard IDs." msgstr "" #help: EPG - rytecgenretextmapfile msgctxt "#30666" msgid "The config used to map Rytec Genre Text to DVB IDs. The default file is `Rytec-UK-Ireland.xml`." msgstr "" #help: EPG - logmissinggenremapping msgctxt "#30667" msgid "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]" msgstr "" #help: EPG - epgdelayperchannel msgctxt "#30668" msgid "For older Enigma2 devices EPG updates can effect streaming quality (such as buffer timeouts). A delay of between 250ms and 5000ms can be introduced to improve quality. Only recommended for older devices. Choose the lowest value that avoids buffer timeouts." msgstr "" #help: EPG - skipinitialepg msgctxt "#30669" msgid "Ignore the intial EPG load (now and next). Enabled by default to prevent crash issues on LibreElec/CoreElec." msgstr "" #empty strings from id 30670 to 30679 #help info - Recordings #help-category: recordings msgctxt "#30680" msgid "This category cotains the settings for recordings" msgstr "" #help: Recordings - storeextrarecordinginfo msgctxt "#30681" msgid "Store last played position and count on the backend so they can be shared across kodi instances. Only supported on OpenWebIf version 1.3.6+." msgstr "" #help: Recordings - sharerecordinglastplayed msgctxt "#30682" msgid "The options are: [Kodi instances] Only use the value in kodi and will not affect last played on the E2 device; [Kodi/E2 instances] Use the value across kodi and the E2 device so they stay in sync. Last played will be synced with the E2 device once every 5-10 minutes per recording if the PVR menus are in use. Note that only a single kodi instance is required to have this option enabled." msgstr "" #help: Recordings - recordingpath msgctxt "#30683" msgid "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." msgstr "" #help: Recordings - onlycurrent msgctxt "#30684" msgid "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." msgstr "" #help: Reordings - keepfolders msgctxt "#30685" msgid "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." msgstr "" #help: Recordings - enablerecordingedls msgctxt "#30686" msgid "EDLs are used to define commericals etc. in recordings. If a tool like Comskip is used to generate EDL files enabling this will allow Kodi PVR to use them. E.g. if there is a file called 'my recording.ts' the EDL file should be call 'my recording.edl'. Note: enabling this setting has no effect if the files are not present." msgstr "" #help: Recordings - edlpaddingstart msgctxt "#30687" msgid "Padding to use at an EDL stop. I.e. use a negative number to start the cut earlier and positive to start the cut later. Default 0." msgstr "" #help: Recordings - edlpaddingstop msgctxt "#30688" msgid "Padding to use at an EDL stop. I.e. use a negative number to stop the cut earlier and positive to stop the cut later. Default 0." msgstr "" #empty strings from id 30689 to 30699 #help info - Timers #help-category: timers msgctxt "#30700" msgid "This category cotains the settings for timers (regular and auto)" msgstr "" #help: Timers - enablegenrepeattimers msgctxt "#30701" msgid "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." msgstr "" #help: Timers - numgenrepeattimers msgctxt "#30702" msgid "The number of Kodi PVR timers to generate." msgstr "" #help: Timers - timerlistcleanup msgctxt "#30703" msgid "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." msgstr "" #help: Timers - enableautotimers msgctxt "#30704" msgid "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." msgstr "" #help: Timers - limitanychannelautotimers msgctxt "#30705" msgid "If last scanned groups are excluded attempt to limit new autotimers to either TV or Radio (dependent on channel used to create the autotimer). Note that if last scanned groups are enabled this is not possible and the setting will be ignored." msgstr "" #help: Timers - limitanychannelautotimerstogroups msgctxt "#30706" msgid "For the channel used to create the autotimer limit to channel groups that this channel is a member of." msgstr "" #empty strings from id 30707 to 30719 #help info - Timeshift #help-category: timeshift msgctxt "#30720" msgid "This category cotains the settings for timeshift. Timeshifting allows you to pause live TV as well as move back and forward from your current position similar to playing back a recording. The buffer is deleted each time a channel is changed or stopped." msgstr "" #help: Timeshift - enabletimeshift msgctxt "#30721" msgid "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." msgstr "" #help: Timeshift - timeshiftbufferpath msgctxt "#30722" msgid "The path used to store the timeshift buffer. The default is the `addon_data/pvr.vuplus` folder in userdata." msgstr "" #empty strings from id 30723 to 30739 #help info - Advanced #help-category: advanced msgctxt "#30740" msgid "This category cotains advanced/expert settings" msgstr "" #help: Advanced - prependoutline msgctxt "#30741" msgid "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." msgstr "" #help: Advanced - powerstatemode msgctxt "#30742" msgid "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." msgstr "" #help: Advanced - readtimeout msgctxt "#30743" msgid "The timemout to use when trying to read live streams. Default for live streams is 0. Default for for timeshifting is 10 seconds." msgstr "" #help: Advanced - streamreadchunksize msgctxt "#30744" msgid "The chunk size used by Kodi for streams. Default 0 to leave it to Kodi to decide." msgstr "" #help: Advanced - debugnormal msgctxt "#30745" msgid "Debug log statements will display for the addon even though debug logging may not be enabled in Kodi. Note that all debug log statements will display at NOTICE level." msgstr "" #help: Advanced - tracedebug msgctxt "#30746" msgid "Very detailed and verbose log statements will display in addition to standard debug statements. If enabled along with `Enable debug logging in normal mode` both trace and debug will display without debug logging enabled. In this case both debug and trace log statements will display at NOTICE level." msgstr "" #help: Advanced - ignoredebug msgctxt "#30747" msgid "Debug log statements will not be displayed for the addon even though debug logging is enabled in Kodi. This can be useful when trying to debug an issue in Kodi which is not addon related." msgstr "" #empty strings from id 30748 to 30759 #help info - Backend #help-category: backend msgctxt "#30760" msgid "This category cotains advanced/expert settings" msgstr "" #help: Backend - webifversion msgctxt "#30761" msgid "webifversion" msgstr "" #help: Backend - autotimertagintags msgctxt "#30762" msgid "autotimertagintags" msgstr "" #help: Backend - autotimernameintags msgctxt "#30763" msgid "autotimernameintags" msgstr "" #help: Backend - globalstartpaddingstb msgctxt "#30764" msgid "globalstartpaddingstb" msgstr "" #help: Backend - globalendpaddingstb msgctxt "#30765" msgid "globalendpaddingstb" msgstr ""pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.en_nz/000077500000000000000000000000001356012415200273125ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.en_nz/strings.po000066400000000000000000000060721356012415200313500ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: English (New Zealand) (http://www.transifex.com/projects/p/kodi-main/language/en_NZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: en_NZ\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Username" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Update Interval in minutes" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Folder for channeldata" msgctxt "#30015" msgid "Update interval" msgstr "Update interval" msgctxt "#30016" msgid "Check for channel updates" msgstr "Check for channel updates" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Use only the DVB boxes' current recording path" msgctxt "#30018" msgid "General" msgstr "General" msgctxt "#30019" msgid "Channels" msgstr "Channels" msgctxt "#30020" msgid "Advanced" msgstr "Advanced" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Recordings / Timer" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Recording folder on the receiver" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "OK" msgctxt "#30094" msgid "N/A" msgstr "N/A" msgctxt "#30095" msgid "True" msgstr "True" msgctxt "#30096" msgid "False" msgstr "False" msgctxt "#30410" msgid "Automatic" msgstr "Automatic" msgctxt "#30430" msgid "Disabled" msgstr "Disabled" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Disconnected from '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Reconnected to '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.en_us/000077500000000000000000000000001356012415200273125ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.en_us/strings.po000066400000000000000000000216371356012415200313540ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: English (United States) (http://www.transifex.com/projects/p/kodi-main/language/en_US/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: en_US\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Enigma2 hostname or IP address" msgctxt "#30002" msgid "Streaming port" msgstr "Streaming port" msgctxt "#30003" msgid "Username" msgstr "Username" msgctxt "#30004" 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 "Web interface port" msgstr "Web interface 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 "Update interval" msgstr "Update interval" msgctxt "#30016" msgid "Check for channel updates" msgstr "Check for channel updates" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Use only the DVB boxes' current recording path" msgctxt "#30018" msgid "General" msgstr "General" msgctxt "#30019" msgid "Channels" msgstr "Channels" msgctxt "#30020" msgid "Advanced" msgstr "Advanced" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Recordings / Timer" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Recording folder on the receiver" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "Send powerstate mode on addon exit" msgctxt "#30025" msgid "TV bouquet fetch mode" msgstr "TV bouquet fetch mode" msgctxt "#30026" msgid "TV bouquet" msgstr "TV bouquet" msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "Fetch picons from web interface" 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 "#30031" msgid "Seasons and Episodes" msgstr "Seasons and Episodes" msgctxt "#30032" msgid "EPG" msgstr "EPG" msgctxt "#30033" msgid "Extract season, episode and year info where possible" msgstr "Extract season, episode and year info where possible" msgctxt "#30034" msgid "Enable autotimers" msgstr "Enable autotimers" msgctxt "#30035" msgid "Use picons.eu file format" msgstr "Use picons.eu file format" msgctxt "#30036" msgid "Enable generate repeat timers" msgstr "Enable generate repeat timers" msgctxt "#30037" msgid "Log missing genre text mappings" msgstr "Log missing genre text mappings" msgctxt "#30038" msgid "Web Interface" msgstr "Web Interface" msgctxt "#30039" msgid "Streaming" msgstr "Streaming" msgctxt "#30040" msgid "Put outline (e.g. sub-title) before plot" msgstr "Put outline (e.g. subtitle) before plot" msgctxt "#30041" msgid "Stream read chunk size" msgstr "Stream read chunk size" 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 "#30046" msgid "Extract show info file" msgstr "Extract show info file" msgctxt "#30047" msgid "Rytec genre text Mappings" msgstr "Rytec genre text Mappings" msgctxt "#30048" msgid "Enable Rytec genre text mappings" msgstr "Enable Rytec genre text mappings" msgctxt "#30049" msgid "Rytec genre text mappings file" msgstr "Rytec genre text mappings file" msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "Custom live TV timeout (0 to use default)" msgctxt "#30051" msgid "Login" msgstr "Login" msgctxt "#30052" msgid "Misc" msgstr "Misc" msgctxt "#30053" msgid "Genre ID Mappings" msgstr "Genre ID Mappings" msgctxt "#30054" msgid "Enable genre ID Mappings" msgstr "Enable genre ID Mappings" msgctxt "#30055" msgid "Genre ID mappings file" msgstr "Genre ID mappings file" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30058" msgid "Radio bouquet fetch mode" msgstr "Radio bouquet fetch mode" msgctxt "#30059" msgid "Radio bouquet" msgstr "Radio bouquet" msgctxt "#30060" msgid "Timeshift" msgstr "Timeshift" msgctxt "#30061" msgid "Enable timeshift" msgstr "Enable 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 "#30066" msgid "Use secure HTTP (https) for streams" msgstr "Use secure HTTP (https) for streams" msgctxt "#30067" msgid "Use login for streams" msgstr "Use login for streams" msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "Fetch TV favorites bouquet" msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "Fetch radio favorites bouquet" msgctxt "#30070" msgid "Recordings & Timers" msgstr "Recordings & Timers" msgctxt "#30071" msgid "Recordings" msgstr "Recordings" msgctxt "#30072" msgid "Timers" msgstr "Timers" msgctxt "#30073" msgid "Number of repeat timers to generate" msgstr "Number of repeat timers to generate" msgctxt "#30074" msgid "All bouquets" msgstr "All bouquets" msgctxt "#30075" msgid "Only one bouquet" msgstr "Only one bouquet" msgctxt "#30076" msgid "As first bouquet" msgstr "As first bouquet" msgctxt "#30077" msgid "As last bouquet" msgstr "As last bouquet" msgctxt "#30078" msgid "Favourites group" msgstr "Favorites group" msgctxt "#30079" msgid "Favourites (TV)" msgstr "Favorites (TV)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "Favorites (Radio)" msgctxt "#30081" msgid "unknown" msgstr "unknown" msgctxt "#30082" msgid " (Not connected!)" msgstr " (Not connected!)" msgctxt "#30083" msgid "addon error" msgstr "addon error" msgctxt "#30084" msgid "Enigma2 Media Server" msgstr "Enigma2 Media Server" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30086" msgid "Backend" msgstr "Backend" msgctxt "#30087" msgid "Recording Padding" msgstr "Recording Padding" msgctxt "#30088" msgid "Global start padding" msgstr "Global start padding" msgctxt "#30089" msgid "Global end padding" msgstr "Global end padding" msgctxt "#30090" msgid "Device Info" msgstr "Device Info" msgctxt "#30091" msgid "WebIf version" msgstr "WebIf version" msgctxt "#30092" msgid "AutoTimer tag in timer tags" msgstr "AutoTimer tag in timer tags" msgctxt "#30093" msgid "AutoTimer name in timer tags" msgstr "AutoTimer name in timer tags" msgctxt "#30094" msgid "N/A" msgstr "N/A" msgctxt "#30095" msgid "True" msgstr "True" msgctxt "#30096" msgid "False" msgstr "False" msgctxt "#30097" msgid "Standby" msgstr "Standby" msgctxt "#30098" msgid "Deep standby" msgstr "Deep standby" msgctxt "#30099" msgid "Wakeup, then standby" msgstr "Wakeup, then standby" msgctxt "#30100" msgid "Update mode" msgstr "Update mode" msgctxt "#30101" msgid "Timers and recordings" msgstr "Timers and recordings" msgctxt "#30102" msgid "Timers only" msgstr "Timers only" 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'" msgstr "Disconnected from '%s'" 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" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.eo/000077500000000000000000000000001356012415200266045ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.eo/strings.po000066400000000000000000000017321356012415200306400ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Esperanto (http://www.transifex.com/projects/p/kodi-main/language/eo/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: eo\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Uzulonomo" msgctxt "#30004" msgid "Password" msgstr "pasvorto" msgctxt "#30018" msgid "General" msgstr "Generalo" msgctxt "#30042" msgid "Never" msgstr "Never" msgctxt "#30063" msgid "Off" msgstr "Off" msgctxt "#30085" msgid "OK" msgstr "Bone" msgctxt "#30430" msgid "Disabled" msgstr "Disabled" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.es_ar/000077500000000000000000000000001356012415200272725ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.es_ar/strings.po000066400000000000000000000055671356012415200313400ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Spanish (Argentina) (http://www.transifex.com/projects/p/kodi-main/language/es_AR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es_AR\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Usuario" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Intervalo de actualización en minutos" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Carpeta para canales" msgctxt "#30015" msgid "Update interval" msgstr "Intervalo de actualización" msgctxt "#30016" msgid "Check for channel updates" msgstr "Comprobar actualización de canales" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Utilice sólo ruta de grabación actual de los cuadros DVB" msgctxt "#30018" msgid "General" msgstr "General" msgctxt "#30019" msgid "Channels" msgstr "Canales" msgctxt "#30020" msgid "Advanced" msgstr "Avanzado" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Grabaciones/ Temporizador" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Carpeta de grabaciones en el receptor" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "OK" msgctxt "#30095" msgid "True" msgstr "Sí" msgctxt "#30096" msgid "False" msgstr "Falso" msgctxt "#30410" msgid "Automatic" msgstr "Automático" msgctxt "#30430" msgid "Disabled" msgstr "Deshabilitado" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Desconectado de '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Reconectado a '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.es_es/000077500000000000000000000000001356012415200272775ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.es_es/strings.po000066400000000000000000000236671356012415200313460ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Spanish (Spain) (http://www.transifex.com/projects/p/kodi-main/language/es_ES/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Dirección IP o nombre de equipo Enigma2" msgctxt "#30002" msgid "Streaming port" msgstr "Puerto de emisión" msgctxt "#30003" msgid "Username" msgstr "Usuario" msgctxt "#30004" 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 de 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 "Limpiar automáticamente la lista de programaciones" msgctxt "#30012" msgid "Web interface port" msgstr "Puerto de la interfaz web" msgctxt "#30013" msgid "Zap before channelswitch (i.e. for single tuner boxes)" msgstr "Zap antes de cambio de canal (p.e. para sintonizadores únicos)" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Carpeta para canales" msgctxt "#30015" msgid "Update interval" msgstr "Intervalo de actualización" msgctxt "#30016" msgid "Check for channel updates" msgstr "Comprobar actualizaciones de canales" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Utilice sólo la ruta de grabación actual de los sintonizadores DVB" msgctxt "#30018" msgid "General" msgstr "General" msgctxt "#30019" msgid "Channels" msgstr "Canales" msgctxt "#30020" msgid "Advanced" msgstr "Avanzado" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Grabaciones/Temporizador" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Carpeta de grabaciones en el receptor" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "Enviar apagar al salir del add-on" msgctxt "#30025" msgid "TV bouquet fetch mode" msgstr "Modo de conseguir ramo de TV" msgctxt "#30026" msgid "TV bouquet" msgstr "Ramo TV" msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "Conseguir 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 "#30031" msgid "Seasons and Episodes" msgstr "Temporadas y Capítulos" msgctxt "#30032" msgid "EPG" msgstr "EPG" msgctxt "#30033" msgid "Extract season, episode and year info where possible" msgstr "Extraer información de temporada, episodio y año cuando sea posible" msgctxt "#30034" msgid "Enable autotimers" msgstr "Activar programaciones automáticas" msgctxt "#30035" msgid "Use picons.eu file format" msgstr "Usar formato de archivo picons.eu" msgctxt "#30036" msgid "Enable generate repeat timers" msgstr "Activar generación de programaciones repetidas" msgctxt "#30037" msgid "Log missing genre text mappings" msgstr "Registrar cuando género esté vacío" msgctxt "#30038" msgid "Web Interface" msgstr "Interfaz Web" msgctxt "#30039" msgid "Streaming" msgstr "Streaming" msgctxt "#30040" msgid "Put outline (e.g. sub-title) before plot" msgstr "Poner frase (p.e. subtítulo) antes del argumento" msgctxt "#30041" msgid "Stream read chunk size" msgstr "Tamaño de fragmento de lectura de emisión" 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 "#30046" msgid "Extract show info file" msgstr "Extraer fichero de información del programa" msgctxt "#30047" msgid "Rytec genre text Mappings" msgstr "Mapas Rytec para género" msgctxt "#30048" msgid "Enable Rytec genre text mappings" msgstr "Activa los mapeados de Rytec para el género" msgctxt "#30049" msgid "Rytec genre text mappings file" msgstr "Fichero de mapas Rytec para género" msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "Apagado de TV en directo personalizado (0 por defecto)" msgctxt "#30051" msgid "Login" msgstr "Inicio de sesión" msgctxt "#30052" msgid "Misc" msgstr "Otros" msgctxt "#30053" msgid "Genre ID Mappings" msgstr "Mapas de ID Género" msgctxt "#30054" msgid "Enable genre ID Mappings" msgstr "Activa los mapeados ID para el género" msgctxt "#30055" msgid "Genre ID mappings file" msgstr "Fichero de mapas ID para género" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30058" msgid "Radio bouquet fetch mode" msgstr "Modo de conseguir ramo de radio" msgctxt "#30059" msgid "Radio bouquet" msgstr "Ramo de radio" msgctxt "#30060" msgid "Timeshift" msgstr "Timeshift" msgctxt "#30061" msgid "Enable timeshift" msgstr "Activar 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 "#30066" msgid "Use secure HTTP (https) for streams" msgstr "Usar HTTP seguro (https) para las emisiones" msgctxt "#30067" msgid "Use login for streams" msgstr "Usar usuario para las emisiones" msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "Conseguir ramo de favoritos de TV" msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "Conseguir ramo de favoritos de radio" msgctxt "#30070" msgid "Recordings & Timers" msgstr "Grabaciones y Programaciones" msgctxt "#30071" msgid "Recordings" msgstr "Grabaciones" msgctxt "#30072" msgid "Timers" msgstr "Programaciones" msgctxt "#30073" msgid "Number of repeat timers to generate" msgstr "Número de repeticiones de programación a generar" msgctxt "#30074" msgid "All bouquets" msgstr "Todos los ramos" msgctxt "#30075" msgid "Only one bouquet" msgstr "Solo un ramo" msgctxt "#30076" msgid "As first bouquet" msgstr "Como primer ramo" msgctxt "#30077" msgid "As last bouquet" msgstr "Como último ramo" msgctxt "#30078" msgid "Favourites group" msgstr "Grupo de favoritos" msgctxt "#30079" msgid "Favourites (TV)" msgstr "Favoritos (TV)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "Favoritos (Radio)" msgctxt "#30081" msgid "unknown" msgstr "desconocido" msgctxt "#30082" msgid " (Not connected!)" msgstr "(¡No conectado!)" msgctxt "#30083" msgid "addon error" msgstr "error de add-on" msgctxt "#30084" msgid "Enigma2 Media Server" msgstr "Servidor de Contenido Enigma2" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30086" msgid "Backend" msgstr "Servidor" msgctxt "#30087" msgid "Recording Padding" msgstr "Relleno de Grabación" msgctxt "#30088" msgid "Global start padding" msgstr "Relleno global al empezar" msgctxt "#30089" msgid "Global end padding" msgstr "Relleno global al terminar" msgctxt "#30090" msgid "Device Info" msgstr "Info Dispositivo" msgctxt "#30091" msgid "WebIf version" msgstr "Version WebIf" msgctxt "#30092" msgid "AutoTimer tag in timer tags" msgstr "Etiqueta AutoTimer en etiquetas de programas" msgctxt "#30093" msgid "AutoTimer name in timer tags" msgstr "Nombre AutoTimer en etiquetas de programas" msgctxt "#30094" msgid "N/A" msgstr "N/D" msgctxt "#30095" msgid "True" msgstr "Sí" msgctxt "#30096" msgid "False" msgstr "Falso" msgctxt "#30097" msgid "Standby" msgstr "Modo de espera" msgctxt "#30098" msgid "Deep standby" msgstr "Modo de espera profundo" msgctxt "#30099" msgid "Wakeup, then standby" msgstr "Despertar, después modo de espera" msgctxt "#30100" msgid "Update mode" msgstr "Modo de actualización" msgctxt "#30101" msgid "Timers and recordings" msgstr "Programas y grabaciones" msgctxt "#30102" msgid "Timers only" msgstr "Solo programas" msgctxt "#30103" msgid "Use OpenWebIf picon path" msgstr "Usar ruta OpenWebIf" 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'" msgstr "Desconectado de '%s'" 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" msgctxt "#30515" msgid "Enigma2: Could not reach web interface" msgstr "Enigma2: Interfaz web inalcanzable" msgctxt "#30516" msgid "Enigma2: No channel groups found" msgstr "Enigma2: Ningún grupo de canales encontrado" msgctxt "#30517" msgid "Enigma2: No channels found" msgstr "Enigma2: Ningún canal encontrado" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.es_mx/000077500000000000000000000000001356012415200273145ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.es_mx/strings.po000066400000000000000000000136661356012415200313610ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Spanish (Mexico) (http://www.transifex.com/projects/p/kodi-main/language/es_MX/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: es_MX\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Nombre de host o dirección IP de Enigma2" msgctxt "#30002" msgid "Streaming port" msgstr "Puerto de steaming" msgctxt "#30003" msgid "Username" msgstr "Usuario" msgctxt "#30004" 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 "#30009" msgid "Update Interval" msgstr "Intervalo de actualización" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Intervalo de actualización en minutos" msgctxt "#30012" msgid "Web interface port" msgstr "Puerto para interface web" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Carpeta de datos de canal" msgctxt "#30015" msgid "Update interval" msgstr "Intervalo de actualización." msgctxt "#30016" msgid "Check for channel updates" msgstr "Buscar actualizaciones de canal" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Use sólo la ruta de grabación actual de las cajas DVB" msgctxt "#30018" msgid "General" msgstr "General" msgctxt "#30019" msgid "Channels" msgstr "Canales" msgctxt "#30020" msgid "Advanced" msgstr "Avanzado" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Grabaciones / Temporizador" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Carpeta de grabación en el receptor" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "Envía mode powerstate sobre la salida del complemento" msgctxt "#30028" msgid "Use secure HTTP (https)" msgstr "Usa HTTP seguro (https)" msgctxt "#30029" msgid "Enable automatic configuration for live streams" msgstr "Activa configuración automática para live streams" msgctxt "#30030" msgid "Keep folder structure for records" msgstr "Mantiene estructura de carpetas para grabaciones" msgctxt "#30031" msgid "Seasons and Episodes" msgstr "Temporadas y Episodios" msgctxt "#30032" msgid "EPG" msgstr "EPG" msgctxt "#30033" msgid "Extract season, episode and year info where possible" msgstr "Extrae temporada, episodio e información del año donde sea posible" msgctxt "#30035" msgid "Use picons.eu file format" msgstr "Usa formato de archivo picons.eu" msgctxt "#30038" msgid "Web Interface" msgstr "Interface web" msgctxt "#30039" msgid "Streaming" msgstr "Streaming" 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 "#30046" msgid "Extract show info file" msgstr "Extrae información de la serie del archivo" msgctxt "#30051" msgid "Login" msgstr "iniciar sesión" msgctxt "#30052" msgid "Misc" msgstr "Misc" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30066" msgid "Use secure HTTP (https) for streams" msgstr "Usa HTTPS seguro (https) para streams" msgctxt "#30067" msgid "Use login for streams" msgstr "Usa login para streams" msgctxt "#30071" msgid "Recordings" msgstr "Grabaciones" msgctxt "#30072" msgid "Timers" msgstr "Temporizadores" msgctxt "#30078" msgid "Favourites group" msgstr "Grupo de favoritos" msgctxt "#30079" msgid "Favourites (TV)" msgstr "Favoritos (TV)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "Favoritos (Radio)" msgctxt "#30081" msgid "unknown" msgstr "desconocido" msgctxt "#30082" msgid " (Not connected!)" msgstr "(No conectado!)" msgctxt "#30083" msgid "addon error" msgstr "Error de complemento" msgctxt "#30084" msgid "Enigma2 Media Server" msgstr "Media Server Enigma2" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30090" msgid "Device Info" msgstr "Información del dispositivo" msgctxt "#30091" msgid "WebIf version" msgstr "Versión Weblf" msgctxt "#30094" msgid "N/A" msgstr "N/A" msgctxt "#30095" msgid "True" msgstr "Sí" msgctxt "#30096" msgid "False" msgstr "Falso" msgctxt "#30097" msgid "Standby" msgstr "En espera" msgctxt "#30098" msgid "Deep standby" msgstr "Espera profunda" msgctxt "#30099" msgid "Wakeup, then standby" msgstr "Despertar, entonces en espera" msgctxt "#30100" msgid "Update mode" msgstr "Modo de actualización" msgctxt "#30410" msgid "Automatic" msgstr "Automático" msgctxt "#30430" msgid "Disabled" msgstr "Deshabilitado" msgctxt "#30431" msgid "Record if EPG title differs" msgstr "Graba si los títulos son diferentes" msgctxt "#30432" msgid "Record if EPG title and short description differs" msgstr "Graba si el titulo y la descripción corta del EPG son diferentes" msgctxt "#30433" msgid "Record if EPG title and all descriptions differ" msgstr "Graba si el título y todas las descripciones del EPG son diferentes" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Desconectado desde '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Reconectado a '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.et_ee/000077500000000000000000000000001356012415200272625ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.et_ee/strings.po000066400000000000000000000051431356012415200313160ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Estonian (Estonia) (http://www.transifex.com/projects/p/kodi-main/language/et_EE/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: et_EE\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Kasutajanimi" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Uuendamise intervall minutites" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Kanali info kaust" msgctxt "#30015" msgid "Update interval" msgstr "Uuendamise vahemik" msgctxt "#30016" msgid "Check for channel updates" msgstr "Kontrolli kanali uuendusi" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Kasutage ainult praeguse DVB boksi salvestamisasukohta" msgctxt "#30018" msgid "General" msgstr "Üldine" msgctxt "#30019" msgid "Channels" msgstr "Kanalid" msgctxt "#30020" msgid "Advanced" msgstr "Põhjalikumad seaded" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Salvestamine / ajastus" msgctxt "#30023" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Raadio" 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 "#30085" msgid "OK" msgstr "OK" msgctxt "#30095" msgid "True" msgstr "Nüüd saate lõõgastuda" msgctxt "#30096" msgid "False" msgstr "Ei ole" msgctxt "#30430" msgid "Disabled" msgstr "Keelatud" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "'%s' lahti ühendatud" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "'%s' uuesti ühendatud" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.eu_es/000077500000000000000000000000001356012415200273015ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.eu_es/strings.po000066400000000000000000000034171356012415200313370ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Basque (Spain) (http://www.transifex.com/projects/p/kodi-main/language/eu_ES/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: eu_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Erabiltzailea" msgctxt "#30004" msgid "Password" msgstr "Pasahitza" msgctxt "#30006" msgid "Icons" msgstr "Ikonoak" msgctxt "#30015" msgid "Update interval" msgstr "Eguneraketa denbora-tartea" msgctxt "#30018" msgid "General" msgstr "Orokorra" msgctxt "#30019" msgid "Channels" msgstr "Kateak" msgctxt "#30020" msgid "Advanced" msgstr "Aurreratua" 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 "#30056" msgid "TV" msgstr "TB" msgctxt "#30057" msgid "Radio" msgstr "Irratia" 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 "#30085" msgid "OK" msgstr "Ados" msgctxt "#30095" msgid "True" msgstr "Egia" msgctxt "#30096" msgid "False" msgstr "Gezurra" msgctxt "#30410" msgid "Automatic" msgstr "Automatikoa" msgctxt "#30430" msgid "Disabled" msgstr "Desgaituta" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.fa_af/000077500000000000000000000000001356012415200272355ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.fa_af/strings.po000066400000000000000000000022751356012415200312740ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Persian (Afghanistan) (http://www.transifex.com/projects/p/kodi-main/language/fa_AF/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fa_AF\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30003" msgid "Username" msgstr "نام کاربری" msgctxt "#30004" msgid "Password" msgstr "کلمه عبور" msgctxt "#30005" msgid "Connection" msgstr "اتصال" msgctxt "#30018" msgid "General" msgstr "عمومی" msgctxt "#30020" msgid "Advanced" msgstr "Ù¾ÛŒØ´Ø±ÙØªÙ‡" msgctxt "#30042" msgid "Never" msgstr "هرگز" msgctxt "#30045" msgid "Always" msgstr "همیشه" msgctxt "#30056" msgid "TV" msgstr "تلوزیون" msgctxt "#30063" msgid "Off" msgstr "خاموش" msgctxt "#30430" msgid "Disabled" msgstr "ØºÛŒØ±ÙØ¹Ø§Ù„" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.fa_ir/000077500000000000000000000000001356012415200272615ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.fa_ir/strings.po000066400000000000000000000030441356012415200313130ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Persian (Iran) (http://www.transifex.com/projects/p/kodi-main/language/fa_IR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fa_IR\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30003" msgid "Username" msgstr "نام کاربری" msgctxt "#30004" msgid "Password" msgstr "رمز عبور" msgctxt "#30006" msgid "Icons" msgstr "آیکون" msgctxt "#30018" msgid "General" msgstr "عمومی" msgctxt "#30019" msgid "Channels" msgstr "کانال ها" msgctxt "#30020" msgid "Advanced" msgstr "Ù¾ÛŒØ´Ø±ÙØªÙ‡" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30042" msgid "Never" msgstr "هرگز" msgctxt "#30045" msgid "Always" msgstr "همیشه" msgctxt "#30051" msgid "Login" msgstr "ورود" msgctxt "#30056" msgid "TV" msgstr "تلویزیون" msgctxt "#30057" msgid "Radio" msgstr "رادیو" msgctxt "#30063" msgid "Off" msgstr "خاموش" msgctxt "#30071" msgid "Recordings" msgstr "ضبط شده ها" msgctxt "#30085" msgid "OK" msgstr "تایید" msgctxt "#30095" msgid "True" msgstr "درست" msgctxt "#30430" msgid "Disabled" msgstr "غیر ÙØ¹Ø§Ù„" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.fi_fi/000077500000000000000000000000001356012415200272555ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.fi_fi/strings.po000066400000000000000000000227431356012415200313160ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Finnish (Finland) (http://www.transifex.com/projects/p/kodi-main/language/fi_FI/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fi_FI\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Enigma2-palvelimen nimi tai ip-osoite" msgctxt "#30002" msgid "Streaming port" msgstr "Suoratoistoportti" msgctxt "#30003" msgid "Username" msgstr "Käyttäjänimi" msgctxt "#30004" 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 sijainti" 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 "Ajastuslistan automaattinen puhdistus" msgctxt "#30012" msgid "Web interface port" msgstr "Web-käyttöliittymän portti" msgctxt "#30013" msgid "Zap before channelswitch (i.e. for single tuner boxes)" msgstr "Zap ennen kanavan vaihtoa (yhden virittimen bokseille)" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Kanavadatan kansio" msgctxt "#30015" msgid "Update interval" msgstr "Päivitysväli" msgctxt "#30016" msgid "Check for channel updates" msgstr "Tarkista kanavapäivitykset" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Käytä ainoastaan digiboksin nykyistä tallennuspolkua" msgctxt "#30018" msgid "General" msgstr "Yleiset" msgctxt "#30019" msgid "Channels" msgstr "Kanavat" msgctxt "#30020" msgid "Advanced" msgstr "Lisäasetukset" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Tallenteet / Ajastin" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Vastaanottimen tallennuskansio" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "Lähetä virranhallintakäsky, kun lisäosa suljetaan" msgctxt "#30025" msgid "TV bouquet fetch mode" msgstr "Tv-kanavaryhmien (bouquet) noutotapa" msgctxt "#30026" msgid "TV bouquet" msgstr "Kanavaryhmän nimi (bouquet)" msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "Nouda kanavalogot (picons) 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 "#30031" msgid "Seasons and Episodes" msgstr "Kaudet ja jaksot" msgctxt "#30032" msgid "EPG" msgstr "Ohjelmaopas" msgctxt "#30033" msgid "Extract season, episode and year info where possible" msgstr "Kerää kausi-, jakso- ja vuositiedot, jos mahdollista" msgctxt "#30034" msgid "Enable autotimers" msgstr "Käytä automaattiajastuksia" msgctxt "#30035" msgid "Use picons.eu file format" msgstr "Käytä picons.eu:n tiedostomuotoa" msgctxt "#30036" msgid "Enable generate repeat timers" msgstr "Käytä toistuvia ajastuksia" msgctxt "#30037" msgid "Log missing genre text mappings" msgstr "Kirjaa puuttuvat määritykset lokitiedostoon" msgctxt "#30038" msgid "Web Interface" msgstr "Web-käyttöliittymä" msgctxt "#30039" msgid "Streaming" msgstr "Suoratoisto" msgctxt "#30040" msgid "Put outline (e.g. sub-title) before plot" msgstr "Laita juonitiivistelmä juonen eteen" msgctxt "#30041" msgid "Stream read chunk size" msgstr "Suoratoiston pakettikoko" 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 "#30046" msgid "Extract show info file" msgstr "Extract show info -tiedosto" msgctxt "#30047" msgid "Rytec genre text Mappings" msgstr "Rytecin genremääritykset" msgctxt "#30048" msgid "Enable Rytec genre text mappings" msgstr "Käytä Rytecin genremäärityksiä" msgctxt "#30049" msgid "Rytec genre text mappings file" msgstr "Rytecin genremääritysten tiedosto" msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "Tv-lähetyksen aikakatkaisu (0 on oletusarvo)" msgctxt "#30051" msgid "Login" msgstr "Käyttäjätunnus" msgctxt "#30052" msgid "Misc" msgstr "Muut" msgctxt "#30053" msgid "Genre ID Mappings" msgstr "Genre ID -määritykset" msgctxt "#30054" msgid "Enable genre ID Mappings" msgstr "Käytä genre ID -määrityksiä" msgctxt "#30055" msgid "Genre ID mappings file" msgstr "Genre ID -määritysten tiedosto" msgctxt "#30056" msgid "TV" msgstr "Tv" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30058" msgid "Radio bouquet fetch mode" msgstr "Radion kanavaryhmien (bouquet) noutotapa" msgctxt "#30059" msgid "Radio bouquet" msgstr "Radion kanavaryhmä" msgctxt "#30060" msgid "Timeshift" msgstr "Ajansiirto" msgctxt "#30061" msgid "Enable timeshift" msgstr "Käytä ajansiirtoa" 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 "#30066" msgid "Use secure HTTP (https) for streams" msgstr "Käytä suojattua HTTP:tä (https) suoratoistoon" msgctxt "#30067" msgid "Use login for streams" msgstr "Suojaa suoratoisto käyttäjätunnuksilla" msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "Nouda tv:n suosikkiryhmä" msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "Nouda radion suosikkiryhmä" msgctxt "#30070" msgid "Recordings & Timers" msgstr "Ajastus ja tallennus" msgctxt "#30071" msgid "Recordings" msgstr "Tallenteet" msgctxt "#30072" msgid "Timers" msgstr "Ajastukset" msgctxt "#30073" msgid "Number of repeat timers to generate" msgstr "Toistuvien ajastusten määrä" msgctxt "#30074" msgid "All bouquets" msgstr "Kaikki" msgctxt "#30075" msgid "Only one bouquet" msgstr "Yksi" msgctxt "#30076" msgid "As first bouquet" msgstr "Aseta ensimmäiseksi" msgctxt "#30077" msgid "As last bouquet" msgstr "Aseta viimeiseksi" msgctxt "#30078" msgid "Favourites group" msgstr "Suosikkiryhmä" msgctxt "#30079" msgid "Favourites (TV)" msgstr "Suosikit (Tv)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "Suosikit (Radio)" msgctxt "#30081" msgid "unknown" msgstr "tuntematon" msgctxt "#30082" msgid " (Not connected!)" msgstr "(Ei yhteyttä)" msgctxt "#30083" msgid "addon error" msgstr "lisäosavirhe" msgctxt "#30084" msgid "Enigma2 Media Server" msgstr "Enigma2 Media Server" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30086" msgid "Backend" msgstr "Taustaosa" msgctxt "#30087" msgid "Recording Padding" msgstr "Ajastuksen lisäaika" msgctxt "#30088" msgid "Global start padding" msgstr "Alkuun lisättävä aika" msgctxt "#30089" msgid "Global end padding" msgstr "Loppuun lisättävä aika" msgctxt "#30090" msgid "Device Info" msgstr "Laitetiedot" msgctxt "#30091" msgid "WebIf version" msgstr "Web-käyttöliittymän versio" msgctxt "#30095" msgid "True" msgstr "On" msgctxt "#30096" msgid "False" msgstr "Ei ole" msgctxt "#30097" msgid "Standby" msgstr "Valmiustila" msgctxt "#30098" msgid "Deep standby" msgstr "Horrostila" msgctxt "#30099" msgid "Wakeup, then standby" msgstr "Herätys, jonka jälkeen lepotila" msgctxt "#30100" msgid "Update mode" msgstr "Päivitystapa" msgctxt "#30101" msgid "Timers and recordings" msgstr "Ajastukset ja tallenteet" msgctxt "#30102" msgid "Timers only" msgstr "Vain ajastukset" msgctxt "#30103" msgid "Use OpenWebIf picon path" msgstr "Käytä OpenWebIf:n picon-polkua" 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'" msgstr "Yhteys katkaistu palvelimeen '%s'" 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" msgctxt "#30515" msgid "Enigma2: Could not reach web interface" msgstr "Enigma2: Web-käyttöliittymään ei saatu yhteyttä" msgctxt "#30516" msgid "Enigma2: No channel groups found" msgstr "Enigma2: Kanavaryhmiä ei löytynyt" msgctxt "#30517" msgid "Enigma2: No channels found" msgstr "Enigma2: Kanavia ei löytynyt" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.fo_fo/000077500000000000000000000000001356012415200272715ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.fo_fo/strings.po000066400000000000000000000026001356012415200313200ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Faroese (Faroe Islands) (http://www.transifex.com/projects/p/kodi-main/language/fo_FO/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fo_FO\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Brúkaranavn" msgctxt "#30004" msgid "Password" msgstr "Loyniorð" msgctxt "#30006" msgid "Icons" msgstr "Ãmyndir" msgctxt "#30018" msgid "General" msgstr "Vanligt" msgctxt "#30019" msgid "Channels" msgstr "Rás" msgctxt "#30042" msgid "Never" msgstr "Ongantíð" msgctxt "#30045" msgid "Always" msgstr "Altíð" msgctxt "#30056" msgid "TV" msgstr "Sjónvarp" msgctxt "#30057" msgid "Radio" msgstr "Útvarp" msgctxt "#30063" msgid "Off" msgstr "Sløkk" msgctxt "#30071" msgid "Recordings" msgstr "Upptøkur" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30095" msgid "True" msgstr "Satt" msgctxt "#30096" msgid "False" msgstr "Skeivt" msgctxt "#30430" msgid "Disabled" msgstr "Sløkt" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.fr_ca/000077500000000000000000000000001356012415200272535ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.fr_ca/strings.po000066400000000000000000000250671356012415200313160ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: French (Canada) (http://www.transifex.com/projects/p/kodi-main/language/fr_CA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr_CA\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Non d’hôte ou adresse IP d’Enigma2" msgctxt "#30002" msgid "Streaming port" msgstr "Port de diffusion en continu" msgctxt "#30003" msgid "Username" 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 "Web interface 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 "Update interval" msgstr "Intervalle de mise à jour" msgctxt "#30016" msgid "Check for channel updates" msgstr "Vérifier les mises à jour de chaînes" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Utiliser seulement le chemin d’enregistrement actuel du boîtier DVB" msgctxt "#30018" msgid "General" msgstr "Général" msgctxt "#30019" msgid "Channels" msgstr "Chaînes" msgctxt "#30020" msgid "Advanced" msgstr "Avancé" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr " Enregistrements / minuterie" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Dossier d’enregistrement du récepteur" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "Envoyer le mode d’alimentation en quittant l’addiciel" msgctxt "#30025" msgid "TV bouquet fetch mode" msgstr "Mode de récupération du bouquet télé" msgctxt "#30026" msgid "TV bouquet" msgstr "Bouquet télé" msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "Récupérer les picô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 "#30031" msgid "Seasons and Episodes" msgstr "Saisons et épisodes" msgctxt "#30032" msgid "EPG" msgstr "GÉP" msgctxt "#30033" msgid "Extract season, episode and year info where possible" msgstr "Extraire les renseignements de saison, d’épisode et d’année si possible" msgctxt "#30034" msgid "Enable autotimers" msgstr "Activer les minuteries automatiques" msgctxt "#30035" msgid "Use picons.eu file format" msgstr "Utiliser le format de fichier picons.eu" msgctxt "#30036" msgid "Enable generate repeat timers" msgstr "Activer la génération de minuteries de répétition" msgctxt "#30037" msgid "Log missing genre text mappings" msgstr "Les mappages genre texte sont absents du journal" msgctxt "#30038" msgid "Web Interface" msgstr "Interface Web" msgctxt "#30039" msgid "Streaming" msgstr "Diffusion en continu" msgctxt "#30040" msgid "Put outline (e.g. sub-title) before plot" msgstr "Mettre le contour (p. ex. les sous-titres) avant l’intrigue" msgctxt "#30041" msgid "Stream read chunk size" msgstr "Taille des fragments de lecture du flux" 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 "#30046" msgid "Extract show info file" msgstr "Extraire le fichier d’informations sur l’émission" msgctxt "#30047" msgid "Rytec genre text Mappings" msgstr "Mappages genre texte de Rytec" msgctxt "#30048" msgid "Enable Rytec genre text mappings" msgstr "Activer les mappages genre texte de Rytec" msgctxt "#30049" msgid "Rytec genre text mappings file" msgstr "Fichier des mappages genre texte de Rytec" msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "Temporisation personnalisée de la télé en direct (0 pour la valeur par défaut)" msgctxt "#30051" msgid "Login" msgstr "Connexion" msgctxt "#30052" msgid "Misc" msgstr "Divers" msgctxt "#30053" msgid "Genre ID Mappings" msgstr "Mappages genre ID" msgctxt "#30054" msgid "Enable genre ID Mappings" msgstr "Activer les mappages genre ID" msgctxt "#30055" msgid "Genre ID mappings file" msgstr "Fichier des mappages genre ID" msgctxt "#30056" msgid "TV" msgstr "Télé" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30058" msgid "Radio bouquet fetch mode" msgstr "Mode de récupération du bouquet radio" msgctxt "#30059" msgid "Radio bouquet" msgstr "Bouquet radio" msgctxt "#30060" msgid "Timeshift" msgstr "Décalage temporel" msgctxt "#30061" msgid "Enable timeshift" msgstr "Activer le 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 "#30066" msgid "Use secure HTTP (https) for streams" msgstr "Utiliser le HTTP sécurisé (https) pour les flux" msgctxt "#30067" msgid "Use login for streams" msgstr "Utiliser la connexion pour les flux" msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "Récupérer le bouquet des favoris télé" msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "Récupérer le bouquet des favoris radio" msgctxt "#30070" msgid "Recordings & Timers" msgstr "Enregistrements et minuteries" msgctxt "#30071" msgid "Recordings" msgstr "Enregistrements" msgctxt "#30072" msgid "Timers" msgstr "Minuteries" msgctxt "#30073" msgid "Number of repeat timers to generate" msgstr "Nombre de minuteries de répétition à générer" msgctxt "#30074" msgid "All bouquets" msgstr "Tous les bouquets" msgctxt "#30075" msgid "Only one bouquet" msgstr "Un seul bouquet" msgctxt "#30076" msgid "As first bouquet" msgstr "Comme premier bouquet" msgctxt "#30077" msgid "As last bouquet" msgstr "Comme dernier bouquet" msgctxt "#30078" msgid "Favourites group" msgstr "Groupe de favoris" msgctxt "#30079" msgid "Favourites (TV)" msgstr "Favoris (télé)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "Favoris (radio)" msgctxt "#30081" msgid "unknown" msgstr "inconnu" msgctxt "#30082" msgid " (Not connected!)" msgstr "(Non connecté)" msgctxt "#30083" msgid "addon error" msgstr "Erreur d’addiciel" msgctxt "#30084" msgid "Enigma2 Media Server" msgstr "Serveur multimédia Enigma2" msgctxt "#30085" msgid "OK" msgstr "Valider" msgctxt "#30086" msgid "Backend" msgstr "Dorsale" msgctxt "#30087" msgid "Recording Padding" msgstr "Début/fin de l’enregistrement avant/après la diffusion prévue" msgctxt "#30088" msgid "Global start padding" msgstr "Global — Début de l’enregistrement avant la diffusion prévue" msgctxt "#30089" msgid "Global end padding" msgstr "Global — Fin de l’enregistrement après la diffusion prévue" msgctxt "#30090" msgid "Device Info" msgstr "Informations sur le périphérique" msgctxt "#30091" msgid "WebIf version" msgstr "Version de WebIf" msgctxt "#30092" msgid "AutoTimer tag in timer tags" msgstr "Étiquette de la minuterie automatique dans les étiquettes de minuterie" msgctxt "#30093" msgid "AutoTimer name in timer tags" msgstr "Nom de la minuterie automatique dans les étiquettes de minuterie" msgctxt "#30094" msgid "N/A" msgstr "ND" msgctxt "#30095" msgid "True" msgstr "Vrai" msgctxt "#30096" msgid "False" msgstr "Faux" msgctxt "#30097" msgid "Standby" msgstr "Veille" msgctxt "#30098" msgid "Deep standby" msgstr "Veille prolongée" msgctxt "#30099" msgid "Wakeup, then standby" msgstr "Réveil, puis mise en veille" msgctxt "#30100" msgid "Update mode" msgstr "Mode de mise à jour" msgctxt "#30101" msgid "Timers and recordings" msgstr "Minuteries et enregistrements" msgctxt "#30102" msgid "Timers only" msgstr "Minuteries seulement" msgctxt "#30103" msgid "Use OpenWebIf picon path" msgstr "Utiliser le chemin des picônes d’OpenWebIf" 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'" msgstr "Se déconnecter de « %s »" 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" msgctxt "#30515" msgid "Enigma2: Could not reach web interface" msgstr "Enigma2 : l’interface Web est inaccessible" msgctxt "#30516" msgid "Enigma2: No channel groups found" msgstr "Enigma2 : aucun groupe de chaînes n’a été trouvé" msgctxt "#30517" msgid "Enigma2: No channels found" msgstr "Enigma2 : aucune chaîne n’a été trouvée" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.fr_fr/000077500000000000000000000000001356012415200272775ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.fr_fr/strings.po000066400000000000000000000246221356012415200313360ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: French (France) (http://www.transifex.com/projects/p/kodi-main/language/fr_FR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr_FR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Nom d'hôte Enigma2 ou adresse IP" msgctxt "#30002" msgid "Streaming port" msgstr "Port du flux de diffusion" msgctxt "#30003" msgid "Username" 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 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 "Web interface 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 "Update interval" msgstr "Intervalle de mise à jour" msgctxt "#30016" msgid "Check for channel updates" msgstr "Mettre à jour les chaînes" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Utiliser seulement le chemin d'enregistrement des périphériques DVB" msgctxt "#30018" msgid "General" msgstr "Général" msgctxt "#30019" msgid "Channels" msgstr "Chaînes " msgctxt "#30020" msgid "Advanced" msgstr "Avancé" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Enregistrements / Programmation" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Dossier d'enregistrement du récepteur" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "Envoyer le mode « powerstate » quand une extension quitte" msgctxt "#30025" msgid "TV bouquet fetch mode" msgstr "Mode de récupération du bouquet TV" msgctxt "#30026" msgid "TV bouquet" msgstr "Bouquet TV" msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "Récupérer les icônes depuis 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 la structure des dossiers pour les enregistrements" msgctxt "#30031" msgid "Seasons and Episodes" msgstr "Saisons et épisodes" msgctxt "#30032" msgid "EPG" msgstr "Guide électronique des programmes TV" msgctxt "#30033" msgid "Extract season, episode and year info where possible" msgstr "Extraire les infos de saison, d'épisode et d'année si possible" msgctxt "#30034" msgid "Enable autotimers" msgstr "Activer les programmations auto." msgctxt "#30035" msgid "Use picons.eu file format" msgstr "Utiliser le format de fichier picons.eu" msgctxt "#30036" msgid "Enable generate repeat timers" msgstr "Activer la génération des programmations répétées" msgctxt "#30037" msgid "Log missing genre text mappings" msgstr "Journaliser les mappages manquant de textes de genres" msgctxt "#30038" msgid "Web Interface" msgstr "Interface Web" msgctxt "#30039" msgid "Streaming" msgstr "Diffusion par flux" msgctxt "#30040" msgid "Put outline (e.g. sub-title) before plot" msgstr "Placer le résumé (par ex. les sous-titres) avant l'intrigue" msgctxt "#30041" msgid "Stream read chunk size" msgstr "Taille des blocs de flux de lecture diffusé" 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 "#30046" msgid "Extract show info file" msgstr "Extraire les informations de fichier" msgctxt "#30047" msgid "Rytec genre text Mappings" msgstr "Mappage de textes de genres Rytec" msgctxt "#30048" msgid "Enable Rytec genre text mappings" msgstr "Activer le mappage de textes de genres Rytec" msgctxt "#30049" msgid "Rytec genre text mappings file" msgstr "Fichier de mappage de textes de genres Rytec" msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "Temporisation personnalisée pour la TV en direct (0 pour la valeur prédéfinie)" msgctxt "#30051" msgid "Login" msgstr "Identification" msgctxt "#30052" msgid "Misc" msgstr "Divers" msgctxt "#30053" msgid "Genre ID Mappings" msgstr "Mappage des ID de genres" msgctxt "#30054" msgid "Enable genre ID Mappings" msgstr "Activer le mappage des ID de genres" msgctxt "#30055" msgid "Genre ID mappings file" msgstr "Fichier de mappage des ID de genres" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30058" msgid "Radio bouquet fetch mode" msgstr "Mode de récupération du bouquet radio" msgctxt "#30059" msgid "Radio bouquet" msgstr "Bouquet radio" msgctxt "#30060" msgid "Timeshift" msgstr "Différé" msgctxt "#30061" msgid "Enable timeshift" msgstr "Activer le 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 "#30066" msgid "Use secure HTTP (https) for streams" msgstr "Utiliser le HTTP sécurisé (https) pour la diffusion par flux" msgctxt "#30067" msgid "Use login for streams" msgstr "Utiliser la connexion pour la diffusion par flux" msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "Récupérer le bouquet des favoris TV" msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "Récupérer le bouquet des favoris radio" msgctxt "#30070" msgid "Recordings & Timers" msgstr "Enregistrements et programmation" msgctxt "#30071" msgid "Recordings" msgstr "Enregistrements" msgctxt "#30072" msgid "Timers" msgstr "Programmations" msgctxt "#30073" msgid "Number of repeat timers to generate" msgstr "Nombre de programmations répétées à générer" msgctxt "#30074" msgid "All bouquets" msgstr "Tous les bouquets" msgctxt "#30075" msgid "Only one bouquet" msgstr "Un seul bouquet" msgctxt "#30076" msgid "As first bouquet" msgstr "Comme premier bouquet" msgctxt "#30077" msgid "As last bouquet" msgstr "Comme dernier bouquet" msgctxt "#30078" msgid "Favourites group" msgstr "Groupes des favoris" msgctxt "#30079" msgid "Favourites (TV)" msgstr "Favoris (TV)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "Favoris (radio)" msgctxt "#30081" msgid "unknown" msgstr "inconnu" msgctxt "#30082" msgid " (Not connected!)" msgstr "(Non connecté)" msgctxt "#30083" msgid "addon error" msgstr "erreur de l'extension" msgctxt "#30084" msgid "Enigma2 Media Server" msgstr "Serveur de média Enigma2" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30086" msgid "Backend" msgstr "Serveur" msgctxt "#30087" msgid "Recording Padding" msgstr "Remplissage de l'enregistrement" msgctxt "#30088" msgid "Global start padding" msgstr "Remplissage global de début" msgctxt "#30089" msgid "Global end padding" msgstr "Remplissage global de fin" msgctxt "#30090" msgid "Device Info" msgstr "Infos sur le phériphérique" msgctxt "#30091" msgid "WebIf version" msgstr "Version WebIf" msgctxt "#30092" msgid "AutoTimer tag in timer tags" msgstr "Balise AutoTimer dans les balises de programmation" msgctxt "#30093" msgid "AutoTimer name in timer tags" msgstr "Nom AutoTimer dans les balises de programmation" msgctxt "#30094" msgid "N/A" msgstr "N/D" msgctxt "#30095" msgid "True" msgstr "Vrai" msgctxt "#30096" msgid "False" msgstr "Faux" msgctxt "#30097" msgid "Standby" msgstr "Mise en attente" msgctxt "#30098" msgid "Deep standby" msgstr "Mise en attente profonde" msgctxt "#30099" msgid "Wakeup, then standby" msgstr "Réveil puis mise en attendre" msgctxt "#30100" msgid "Update mode" msgstr "Mode de mise à jour" msgctxt "#30101" msgid "Timers and recordings" msgstr "Programmations et enregistrements" msgctxt "#30102" msgid "Timers only" msgstr "Programmations seules" msgctxt "#30103" msgid "Use OpenWebIf picon path" msgstr "Utiliser le chemin des picon OpenWebIf" 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'" msgstr "Déconnecté de « %s »" 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" msgctxt "#30515" msgid "Enigma2: Could not reach web interface" msgstr "Enigma2 : interface Web introuvable" msgctxt "#30516" msgid "Enigma2: No channel groups found" msgstr "Enigma2 : aucun groupe de chaînes trouvé" msgctxt "#30517" msgid "Enigma2: No channels found" msgstr "Enigma2 : aucune chaîne trouvée" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.gl_es/000077500000000000000000000000001356012415200272725ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.gl_es/strings.po000066400000000000000000000062001356012415200313210ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Galician (Spain) (http://www.transifex.com/projects/p/kodi-main/language/gl_ES/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: gl_ES\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Nome de usuario" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Intervalo de actualización en minutos" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Cartafol para channeldata" msgctxt "#30015" msgid "Update interval" msgstr "Intervalo de actualización" msgctxt "#30016" msgid "Check for channel updates" msgstr "Verificar actualizacións de canles" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Utilizar só o camiño actual das gravacións das caixas DVB" msgctxt "#30018" msgid "General" msgstr "Xeral" msgctxt "#30019" msgid "Channels" msgstr "Canles" msgctxt "#30020" msgid "Advanced" msgstr "Avanzado" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Gravacións/Temporizador" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Cartafol de gravacións no receptor" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "Aceptar" msgctxt "#30094" msgid "N/A" msgstr "N/D" msgctxt "#30095" msgid "True" msgstr "Verdadeiro" msgctxt "#30096" msgid "False" msgstr "Falso" msgctxt "#30410" msgid "Automatic" msgstr "Automático" msgctxt "#30430" msgid "Disabled" msgstr "Desactivado" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Desconectado dende '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Reconectado a '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.he_il/000077500000000000000000000000001356012415200272615ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.he_il/strings.po000066400000000000000000000070541356012415200313200ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Hebrew (Israel) (http://www.transifex.com/projects/p/kodi-main/language/he_IL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: he_IL\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "×©× ×ž×©×ª×ž×©" msgctxt "#30004" msgid "Password" msgstr "סיסמה" msgctxt "#30005" msgid "Connection" msgstr "חיבור" msgctxt "#30006" msgid "Icons" msgstr "סמלי×" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "זמן המתנה מירבי לתגובה בשניות" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "מרווח זמני ×¢×“×›×•× ×™× ×‘×“×§×•×ª" msgctxt "#30014" msgid "Folder for channeldata" msgstr "תיקיית נתוני ערוצי×" msgctxt "#30015" msgid "Update interval" msgstr "מרווח זמני עדכוני×" msgctxt "#30016" msgid "Check for channel updates" msgstr "חיפוש עדכוני ערוץ" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "שימוש בנתיב הקלטה נוכחי של מכשיר ×”Ö¾DVB בלבד" msgctxt "#30018" msgid "General" msgstr "כללי" msgctxt "#30019" msgid "Channels" msgstr "ערוצי×" msgctxt "#30020" msgid "Advanced" msgstr "מתקד×" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "הקלטות / תזמון" msgctxt "#30023" msgid "Recording folder on the receiver" 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 "לוח שידורי×" 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 "#30056" msgid "TV" msgstr "טלוויזיה" msgctxt "#30057" msgid "Radio" 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 "#30085" msgid "OK" msgstr "×ישור" msgctxt "#30095" msgid "True" msgstr "×מת" msgctxt "#30096" msgid "False" msgstr "שקר" msgctxt "#30410" msgid "Automatic" msgstr "×וטומטי" msgctxt "#30430" msgid "Disabled" msgstr "מנוטרל" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "נותק מ־'%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "חובר חזרה ל־'%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.hi_in/000077500000000000000000000000001356012415200272675ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.hi_in/strings.po000066400000000000000000000020741356012415200313230ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Hindi (India) (http://www.transifex.com/projects/p/kodi-main/language/hi_IN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hi_IN\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "उपयोगकरà¥à¤¤à¤¾ नाम" msgctxt "#30006" msgid "Icons" msgstr "पà¥à¤°à¤¤à¥€à¤•" msgctxt "#30018" msgid "General" msgstr "सामानà¥à¤¯" msgctxt "#30020" msgid "Advanced" msgstr "उनà¥à¤¨à¤¤" msgctxt "#30063" msgid "Off" msgstr "से" msgctxt "#30085" msgid "OK" msgstr "टेके" msgctxt "#30430" msgid "Disabled" msgstr "विकलांग" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.hr_hr/000077500000000000000000000000001356012415200273035ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.hr_hr/strings.po000066400000000000000000000071201356012415200313340ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Croatian (Croatia) (http://www.transifex.com/projects/p/kodi-main/language/hr_HR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hr_HR\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" msgctxt "#30003" msgid "Username" msgstr "KorisniÄko ime" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Interval osvježavanja u minutama" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Mapa za podatke programa" msgctxt "#30015" msgid "Update interval" msgstr "Razdoblje nadopune" msgctxt "#30016" msgid "Check for channel updates" msgstr "Provjeri nadopune programa" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Koristi samo za DVB ureÄ‘aje, trenutna putanja snimanja" msgctxt "#30018" msgid "General" msgstr "Općenito" msgctxt "#30019" msgid "Channels" msgstr "Programi" msgctxt "#30020" msgid "Advanced" msgstr "Napredno" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Snimanja / Zakazana snimanja" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Mapa snimanja na prijemniku" 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 "#30056" msgid "TV" msgstr "Televizija" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "U redu" msgctxt "#30094" msgid "N/A" msgstr "N/A" msgctxt "#30095" msgid "True" msgstr "Istina" msgctxt "#30096" msgid "False" msgstr "Nesipravan" msgctxt "#30410" msgid "Automatic" msgstr "Automatski" msgctxt "#30420" msgid "One time (Scheduled by guide-based timer rule)" msgstr "Jednom (zakazano rasporedom EPG vodiÄa)" msgctxt "#30430" msgid "Disabled" msgstr "Onemogućeno" msgctxt "#30431" msgid "Record if EPG title differs" msgstr "Snimi ako se EPG naslov razlikuje" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Odspojen s '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Ponovno povezan s '%s'" msgctxt "#30514" msgid "Timeshift buffer path does not exist" msgstr "Putanja meÄ‘uspremnika premotavanja u vremenu ne postoji" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.hu_hu/000077500000000000000000000000001356012415200273115ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.hu_hu/strings.po000066400000000000000000000242141356012415200313450ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Hungarian (Hungary) (http://www.transifex.com/projects/p/kodi-main/language/hu_HU/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hu_HU\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Enigma2 gazdanév vagy IP cím" msgctxt "#30002" msgid "Streaming port" msgstr "Streaming port" msgctxt "#30003" msgid "Username" msgstr "Felhasználónév" msgctxt "#30004" 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 "Ikon útvonal" msgctxt "#30009" msgid "Update Interval" msgstr "Frissítési intervallum" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Frissítési intervallum percben" msgctxt "#30011" msgid "Automatic timerlist cleanup" msgstr "Automatikus idÅ‘zítÅ‘ lista törlése" msgctxt "#30012" msgid "Web interface port" msgstr "Webes felület port" msgctxt "#30013" msgid "Zap before channelswitch (i.e. for single tuner boxes)" msgstr "Törölje csatornaváltás elÅ‘tt (vagyis egytuneres dobozok esetében)" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Csatornaadat mappa" msgctxt "#30015" msgid "Update interval" msgstr "Frissítési intervallum" msgctxt "#30016" msgid "Check for channel updates" msgstr "Csatorna frissítés keresése" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Csak a DVB box aktuális felvételi útvonalát használja" msgctxt "#30018" msgid "General" msgstr "Ãltalános" msgctxt "#30019" msgid "Channels" msgstr "Csatornák" msgctxt "#30020" msgid "Advanced" msgstr "Haladó" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Felvételek / IdÅ‘zítÅ‘k" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Felvételi mappa a vevÅ‘n" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "Energiaellátási mód küldése kiegészítÅ‘ kilépésekor" msgctxt "#30025" msgid "TV bouquet fetch mode" msgstr "TV-csokor letöltési mód" msgctxt "#30026" msgid "TV bouquet" msgstr "TV csokor" msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "Vegye le a piconokat a webes felületrÅ‘l" msgctxt "#30028" msgid "Use secure HTTP (https)" msgstr "Használjon biztonságos HTTP-t (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 "#30031" msgid "Seasons and Episodes" msgstr "Évadok és epizódok" msgctxt "#30032" msgid "EPG" msgstr "EPG" msgctxt "#30033" msgid "Extract season, episode and year info where possible" msgstr "Másolja ki az évad, epizód és az év adatait, ha lehetséges" msgctxt "#30034" msgid "Enable autotimers" msgstr "Engedélyezze az automatikus idÅ‘zítÅ‘t" msgctxt "#30035" msgid "Use picons.eu file format" msgstr "Használja a picons.eu fájlformátumot" msgctxt "#30036" msgid "Enable generate repeat timers" msgstr "Engedélyezze az ismétlÅ‘dÅ‘ idÅ‘zítÅ‘k létrehozását" msgctxt "#30037" msgid "Log missing genre text mappings" msgstr "Naplózó: hiányzik a műfaj szövegének leképezése" msgctxt "#30038" msgid "Web Interface" msgstr "Webes felület" msgctxt "#30039" msgid "Streaming" msgstr "Adatfolyam" msgctxt "#30040" msgid "Put outline (e.g. sub-title) before plot" msgstr "Vázlat (pl. sub-title) felvétele a megjelenés elÅ‘tt" msgctxt "#30041" msgid "Stream read chunk size" msgstr "Stream olvasott darab méret" 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 "#30046" msgid "Extract show info file" msgstr "Műsorinfo fájl kimásolása" msgctxt "#30047" msgid "Rytec genre text Mappings" msgstr "Rytec műfaj szöveg leképezések" msgctxt "#30048" msgid "Enable Rytec genre text mappings" msgstr "Engedélyezze a Rytec műfaj szövegének leképezését" msgctxt "#30049" msgid "Rytec genre text mappings file" msgstr "Rytec műfaj szöveg leképezés fájl" msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "Egyéni élÅ‘ TV idÅ‘túllépés (0 az alapértelmezett használatához)" msgctxt "#30051" msgid "Login" msgstr "Bejelentkezés" msgctxt "#30052" msgid "Misc" msgstr "Egyéb" msgctxt "#30053" msgid "Genre ID Mappings" msgstr "Műfajazonosító leképezések" msgctxt "#30054" msgid "Enable genre ID Mappings" msgstr "Engedélyezze a műfajazonosító leképezését" msgctxt "#30055" msgid "Genre ID mappings file" msgstr "Műfajazonosító leképezés fájl" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Rádió" msgctxt "#30058" msgid "Radio bouquet fetch mode" msgstr "Rádió csokor letöltési mód" msgctxt "#30059" msgid "Radio bouquet" msgstr "Rádió csokor" msgctxt "#30060" msgid "Timeshift" msgstr "Csúsztatott felvétel" msgctxt "#30061" msgid "Enable timeshift" msgstr "Engedélyezze az idÅ‘csúsztatást" 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 "#30066" msgid "Use secure HTTP (https) for streams" msgstr "Használjon biztonságos HTTP (https) protokollokat" msgctxt "#30067" msgid "Use login for streams" msgstr "Jelentkezzen be a streamekhez" msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "Töltse le a TV-kedvencek csokorát" msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "Töltse le a rádió kedvencek csokorát" msgctxt "#30070" msgid "Recordings & Timers" msgstr "Felvételek és idÅ‘zítÅ‘k" msgctxt "#30071" msgid "Recordings" msgstr "Felvételek" msgctxt "#30072" msgid "Timers" msgstr "IdÅ‘zítÅ‘k" msgctxt "#30073" msgid "Number of repeat timers to generate" msgstr "A létrehozandó ismétlÅ‘dÅ‘ idÅ‘zítÅ‘k száma" msgctxt "#30074" msgid "All bouquets" msgstr "Összes csokor" msgctxt "#30075" msgid "Only one bouquet" msgstr "Egyetlen csokor" msgctxt "#30076" msgid "As first bouquet" msgstr "Az elsÅ‘ csokor" msgctxt "#30077" msgid "As last bouquet" msgstr "Utolsó csokor" msgctxt "#30078" msgid "Favourites group" msgstr "Kedvencek csoport" msgctxt "#30079" msgid "Favourites (TV)" msgstr "Kedvencek (TV)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "Kedvencek (Rádió)" msgctxt "#30081" msgid "unknown" msgstr "ismeretlen" msgctxt "#30082" msgid " (Not connected!)" msgstr " (Nincs csatlakoztatva)" msgctxt "#30083" msgid "addon error" msgstr "KiegészítÅ‘ hiba" msgctxt "#30084" msgid "Enigma2 Media Server" msgstr "Enigma2 Média Szerver" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30086" msgid "Backend" msgstr "Háttér" msgctxt "#30087" msgid "Recording Padding" msgstr "Rögzítés" msgctxt "#30088" msgid "Global start padding" msgstr "Globális kezdeti kitöltés" msgctxt "#30089" msgid "Global end padding" msgstr "Globális végsÅ‘ kitöltés" msgctxt "#30090" msgid "Device Info" msgstr "Eszköz információ" msgctxt "#30091" msgid "WebIf version" msgstr "WebIf verzió" msgctxt "#30092" msgid "AutoTimer tag in timer tags" msgstr "Automatikus idÅ‘zítÅ‘ címke az idÅ‘zítÅ‘ címkékben" msgctxt "#30093" msgid "AutoTimer name in timer tags" msgstr "Automatikus idÅ‘zítÅ‘ neve idÅ‘zítÅ‘ címkékben" msgctxt "#30094" msgid "N/A" msgstr "Nem elérhetÅ‘" msgctxt "#30095" msgid "True" msgstr "Igaz" msgctxt "#30096" msgid "False" msgstr "Hamis" msgctxt "#30097" msgid "Standby" msgstr "Készenléti állapot" msgctxt "#30098" msgid "Deep standby" msgstr "Mély készenléti állapot" msgctxt "#30099" msgid "Wakeup, then standby" msgstr "Ébrestés, majd készenléti állapot" msgctxt "#30100" msgid "Update mode" msgstr "Frissítési mód" msgctxt "#30101" msgid "Timers and recordings" msgstr "IdÅ‘zítÅ‘k és felvételek" msgctxt "#30102" msgid "Timers only" msgstr "Csak idÅ‘zítÅ‘k" msgctxt "#30103" msgid "Use OpenWebIf picon path" msgstr "Használja az OpenWebIf picon útvonalát" msgctxt "#30410" msgid "Automatic" msgstr "Automatikus" msgctxt "#30420" msgid "One time (Scheduled by guide-based timer rule)" msgstr "Egyszeri alkalommal (ütemezett útmutató alapú idÅ‘zítÅ‘ szabály)" msgctxt "#30421" msgid "One time (Scheduled by repeating timer rule)" msgstr "Egyszeri (az idÅ‘zített szabály ismétlése szerint ütemezve)" msgctxt "#30430" msgid "Disabled" msgstr "Letiltva" msgctxt "#30431" msgid "Record if EPG title differs" msgstr "Felvétel ha az EPG cím eltér" msgctxt "#30432" msgid "Record if EPG title and short description differs" msgstr "Felvétel ha az EPG cím és a rövid leírás eltér egymástól" msgctxt "#30433" msgid "Record if EPG title and all descriptions differ" msgstr "Felvétel ha az EPG cím és az összes leírás eltér egymástól" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "'%s': Kapcsolat bontva" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "'%s': Újrakapcsolódva" msgctxt "#30514" msgid "Timeshift buffer path does not exist" msgstr "A Timeshift pufferút nem létezik" msgctxt "#30515" msgid "Enigma2: Could not reach web interface" msgstr "Enigma2: Nem sikerült elérni a webes felületet" msgctxt "#30516" msgid "Enigma2: No channel groups found" msgstr "Enigma2: Nincsenek csatornacsoportok" msgctxt "#30517" msgid "Enigma2: No channels found" msgstr "Enigma2: Csatorna nem található" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.hy_am/000077500000000000000000000000001356012415200272765ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.hy_am/strings.po000066400000000000000000000017301356012415200313300ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Armenian (Armenia) (http://www.transifex.com/projects/p/kodi-main/language/hy_AM/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: hy_AM\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30004" msgid "Password" msgstr "Ô³Õ¡Õ²Õ¿Õ¶Õ¡Õ¢Õ¡Õ¼" msgctxt "#30006" msgid "Icons" msgstr "Õ†Õ·Õ¡Õ¶Õ¶Õ¥Ö€" msgctxt "#30018" msgid "General" msgstr "Ô³Õ¬Õ­Õ¡Õ¾Õ¸Ö€" msgctxt "#30051" msgid "Login" msgstr "Õ„Õ¸Ö‚Õ¿Ö„" msgctxt "#30063" msgid "Off" msgstr "Ô±Õ¶Õ»Õ¡Õ¿Õ¥Õ¬" msgctxt "#30085" msgid "OK" msgstr "Ô¼Õ¡Õ¾" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.id_id/000077500000000000000000000000001356012415200272515ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.id_id/strings.po000066400000000000000000000054271356012415200313120ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Indonesian (Indonesia) (http://www.transifex.com/projects/p/kodi-main/language/id_ID/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: id_ID\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30003" msgid "Username" msgstr "NamaPengguna" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Interval update dalam menit" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Folder untuk data kanal" msgctxt "#30015" msgid "Update interval" msgstr "Interval update" msgctxt "#30016" msgid "Check for channel updates" msgstr "Cek untuk pemuktahiran kanal" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Hanya gunakan path rekaman DVB yang digunakan saat ini" msgctxt "#30018" msgid "General" msgstr "Umum" msgctxt "#30019" msgid "Channels" msgstr "Saluran" msgctxt "#30020" msgid "Advanced" msgstr "Tingkat Lanjut" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Perekaman / Timer" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Folder rekaman di penerima" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "OK" msgctxt "#30095" msgid "True" msgstr "Ya" msgctxt "#30096" msgid "False" msgstr "Salah" msgctxt "#30430" msgid "Disabled" msgstr "Non Aktif" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Terputus dari '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Tersambung lagi pada '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.is_is/000077500000000000000000000000001356012415200273075ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.is_is/strings.po000066400000000000000000000163121356012415200313430ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Icelandic (Iceland) (http://www.transifex.com/projects/p/kodi-main/language/is_IS/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: is_IS\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Nafn eða IP-vistfang á Enigma2" msgctxt "#30002" msgid "Streaming port" msgstr "Gátt streymis" msgctxt "#30003" msgid "Username" msgstr "Notandanafn" msgctxt "#30004" 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 "#30009" msgid "Update Interval" msgstr "Bið milli uppfærslna" 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 "Web interface 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 "Update interval" msgstr "Bið milli uppfærslna" msgctxt "#30016" msgid "Check for channel updates" msgstr "Athuga með uppfærslu rása" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Nota aðeins núverandi upptökuslóð upptökutækja" msgctxt "#30018" msgid "General" msgstr "Almennt" msgctxt "#30019" msgid "Channels" msgstr "Rásir" msgctxt "#30020" msgid "Advanced" msgstr "Ãtarlegt" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Upptökur / Tímatökur" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Upptökumappa á móttakaranum" msgctxt "#30026" msgid "TV bouquet" msgstr "Sjónvarps-knippi" msgctxt "#30027" msgid "Fetch picons from web interface" 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 "#30031" msgid "Seasons and Episodes" msgstr "Þáttaraðir og þættir" msgctxt "#30032" msgid "EPG" msgstr "Rafrænn EPG-sjónvarpsvísir" msgctxt "#30038" msgid "Web Interface" msgstr "Vefviðmót" msgctxt "#30039" msgid "Streaming" msgstr "Streymi" msgctxt "#30040" msgid "Put outline (e.g. sub-title) before plot" msgstr "Setja upplýsingar (t.d. skjátexta) á undan söguþræði" msgctxt "#30041" msgid "Stream read chunk size" msgstr "Stærð lesbúts streymis" 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 "#30046" msgid "Extract show info file" msgstr "Veiða upplýsingar um myndskeið úr skrá" msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "Sérsniðin tímamörk beinnar sjónvarpsútsendingar (0 til að nota sjálfgefið)" msgctxt "#30051" msgid "Login" msgstr "Innskrá" msgctxt "#30052" msgid "Misc" msgstr "Ãmislegt" msgctxt "#30056" msgid "TV" msgstr "Sjónvarp" msgctxt "#30057" msgid "Radio" msgstr "Útvarp" msgctxt "#30059" msgid "Radio bouquet" msgstr "Útvarps-knippi" msgctxt "#30060" msgid "Timeshift" msgstr "Tímaflakk" msgctxt "#30061" msgid "Enable timeshift" msgstr "Virkja 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 "#30066" msgid "Use secure HTTP (https) for streams" msgstr "Nota öruggara HTTP (https) fyrir streymi" msgctxt "#30067" msgid "Use login for streams" msgstr "Nota innskráningu fyrir streymi" msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "Sækja knippi af sjónvarpseftirlætum" msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "Sækja knippi af útvarpseftirlætum" msgctxt "#30070" msgid "Recordings & Timers" msgstr "Upptökur og tímatökur" msgctxt "#30071" msgid "Recordings" msgstr "Upptökur" msgctxt "#30072" msgid "Timers" msgstr "Tímatökur" msgctxt "#30074" msgid "All bouquets" msgstr "Öll knippi" msgctxt "#30075" msgid "Only one bouquet" msgstr "Aðeins eitt knippi" msgctxt "#30076" msgid "As first bouquet" msgstr "Sem fyrsta knippi" msgctxt "#30077" msgid "As last bouquet" msgstr "Sem síðasta knippi" msgctxt "#30078" msgid "Favourites group" msgstr "Eftirlætahópur" msgctxt "#30079" msgid "Favourites (TV)" msgstr "Eftirlæti (sjónvarp)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "Eftirlæti (útvarp)" msgctxt "#30081" msgid "unknown" msgstr "óþekkt" msgctxt "#30082" msgid " (Not connected!)" msgstr "(Engin tenging!)" msgctxt "#30083" msgid "addon error" msgstr "villa í viðbót" msgctxt "#30085" msgid "OK" msgstr "à lagi" msgctxt "#30086" msgid "Backend" msgstr "Bakendi" msgctxt "#30090" msgid "Device Info" msgstr "Upplýsingar um tæki" msgctxt "#30091" msgid "WebIf version" msgstr "Útgáfa WebIf" msgctxt "#30094" msgid "N/A" msgstr "E/T" msgctxt "#30095" msgid "True" msgstr "Satt" msgctxt "#30096" msgid "False" msgstr "Ósatt" msgctxt "#30097" msgid "Standby" msgstr "Biðstaða" 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 "#30421" msgid "One time (Scheduled by repeating timer rule)" msgstr "Eins-skiptis (sett á með endurtekinni tímatökureglu)" 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 "#30432" msgid "Record if EPG title and short description differs" msgstr "Taka upp ef mismunur er á titli og lýsingu í EPG-dagskrárvísi" msgctxt "#30433" msgid "Record if EPG title and all descriptions differ" msgstr "Taka upp ef mismunur er á titli og lýsingum í EPG-dagskrárvísi" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Aftengdur frá '%s'" 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" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.it_it/000077500000000000000000000000001356012415200273115ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.it_it/strings.po000066400000000000000000000065471356012415200313560ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Italian (Italy) (http://www.transifex.com/projects/p/kodi-main/language/it_IT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it_IT\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Nome utente" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Intervallo di aggiornamento in minuti" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Cartella per i dati dei canali" msgctxt "#30015" msgid "Update interval" msgstr "Intervallo aggiornamento" msgctxt "#30016" msgid "Check for channel updates" msgstr "Controlla aggiornamenti dei canali" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Usa solo il percorso di registrazione corrente del dispositivo DVB" msgctxt "#30018" msgid "General" msgstr "Generale" msgctxt "#30019" msgid "Channels" msgstr "Canali" msgctxt "#30020" msgid "Advanced" msgstr "Avanzate" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Registrazioni / Timer" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Cartella per le registrazioni del ricevitore" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "OK" msgctxt "#30094" msgid "N/A" msgstr "N.D" msgctxt "#30095" msgid "True" msgstr "Vero" msgctxt "#30096" msgid "False" msgstr "Falso" msgctxt "#30410" msgid "Automatic" msgstr "Automatico" msgctxt "#30430" msgid "Disabled" msgstr "Disabilitato" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Disconnesso da '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Riconnesso a '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ja_jp/000077500000000000000000000000001356012415200272645ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ja_jp/strings.po000066400000000000000000000052571356012415200313260ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Japanese (Japan) (http://www.transifex.com/projects/p/kodi-main/language/ja_JP/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ja_JP\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30003" msgid "Username" msgstr "ユーザーå" msgctxt "#30004" msgid "Password" msgstr "パスワード" msgctxt "#30005" msgid "Connection" msgstr "接続" msgctxt "#30006" msgid "Icons" msgstr "アイコン" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "レスãƒãƒ³ã‚¹ã®ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆ (ç§’)" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "æ›´æ–°é–“éš” (分)" msgctxt "#30014" msgid "Folder for channeldata" msgstr "ãƒãƒ£ãƒ³ãƒãƒ«ãƒ‡ãƒ¼ã‚¿ã®ãƒ•ォルダー" msgctxt "#30015" msgid "Update interval" msgstr "æ›´æ–°é–“éš”" msgctxt "#30016" msgid "Check for channel updates" msgstr "ãƒãƒ£ãƒ³ãƒãƒ«æ›´æ–°ã‚’確èª" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "DVB ボックスã®ç¾åœ¨ã®éŒ²ç”»ãƒ‘スã®ã¿ä½¿ç”¨" msgctxt "#30018" msgid "General" msgstr "一般" msgctxt "#30019" msgid "Channels" msgstr "ãƒãƒ£ãƒ³ãƒãƒ«" msgctxt "#30020" msgid "Advanced" msgstr "高度ãªè¨­å®š" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "録画/タイマー" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "レシーãƒãƒ¼ã®éŒ²ç”»ãƒ•ォルダー" msgctxt "#30042" msgid "Never" msgstr "使用ã—ãªã„" msgctxt "#30045" msgid "Always" msgstr "常ã«" msgctxt "#30051" msgid "Login" msgstr "ログイン" msgctxt "#30056" msgid "TV" msgstr "テレビ" msgctxt "#30057" msgid "Radio" msgstr "ラジオ" msgctxt "#30062" msgid "Timeshift buffer path" msgstr "タイムシフト用ãƒãƒƒãƒ•ã‚¡ã®ãƒ‘ス" msgctxt "#30063" msgid "Off" msgstr "オフ" msgctxt "#30071" msgid "Recordings" msgstr "録音" msgctxt "#30072" msgid "Timers" msgstr "タイマー" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30095" msgid "True" msgstr "True" msgctxt "#30096" msgid "False" msgstr "False" msgctxt "#30430" msgid "Disabled" msgstr "無効" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "'%s' ã¨ã®æŽ¥ç¶šãŒåˆ‡ã‚Œã¾ã—ãŸ" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "'%s' ã¨ã®æŽ¥ç¶šãŒå¾©æ´»ã—ã¾ã—ãŸ" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ko_kr/000077500000000000000000000000001356012415200273065ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ko_kr/strings.po000066400000000000000000000232641356012415200313460ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Korean (Korea) (http://www.transifex.com/projects/p/kodi-main/language/ko_KR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ko_KR\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Enigma2 호스트명ì´ë‚˜ IP 주소" msgctxt "#30002" msgid "Streaming port" msgstr "ìŠ¤íŠ¸ë¦¬ë° í¬íЏ" msgctxt "#30003" msgid "Username" msgstr "사용ìžëª…" msgctxt "#30004" 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 "Web interface 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 "Update interval" msgstr "ì—…ë°ì´íЏ 주기" msgctxt "#30016" msgid "Check for channel updates" msgstr "ì±„ë„ ì—…ë°ì´íЏ 확ì¸" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "DVB ë°•ìŠ¤ì˜ í˜„ìž¬ 녹화 경로만 사용" msgctxt "#30018" msgid "General" msgstr "ì¼ë°˜" msgctxt "#30019" msgid "Channels" msgstr "채ë„" msgctxt "#30020" msgid "Advanced" msgstr "고급" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "녹화 / 타ì´ë¨¸" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "리시버 녹화 í´ë”" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "ì• ë“œì˜¨ì„ ë‚˜ê°ˆ 때 ì „ì› ìƒíƒœ 모드 보내기" msgctxt "#30025" msgid "TV bouquet fetch mode" msgstr "TV 부케 가져오기 모드" msgctxt "#30026" msgid "TV bouquet" msgstr "TV 부케" msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "웹 ì¸í„°íŽ˜ì´ìФì—서 picons 가져오기" 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 "#30031" msgid "Seasons and Episodes" msgstr "시즌과 ì—피소드" msgctxt "#30032" msgid "EPG" msgstr "EPG" 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 "picons.eu íŒŒì¼ í¬ë§· 사용" 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 "EPGì—서만" 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 "Rytec 장르 í…스트 매핑" msgctxt "#30048" msgid "Enable Rytec genre text mappings" msgstr "Rytec 장르 í…스트 매핑 사용" msgctxt "#30049" msgid "Rytec genre text mappings file" msgstr "Rytec 장르 í…스트 매핑 파ì¼" msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "ì‚¬ìš©ìž ë¼ì´ë¸Œ TV 마침 (0ì€ ê¸°ë³¸ ê°’)" msgctxt "#30051" msgid "Login" msgstr "로그ì¸" msgctxt "#30052" msgid "Misc" msgstr "기타" msgctxt "#30053" msgid "Genre ID Mappings" msgstr "장르 ID 매핑" msgctxt "#30054" msgid "Enable genre ID Mappings" msgstr "장르 ID 매핑 사용" msgctxt "#30055" msgid "Genre ID mappings file" msgstr "장르 ID 매핑 파ì¼" msgctxt "#30056" msgid "TV" msgstr "TV" 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 "ìŠ¤íŠ¸ë¦¼ì— ì•ˆì „í•œ HTTP (https) 사용" msgctxt "#30067" msgid "Use login for streams" msgstr "ìŠ¤íŠ¸ë¦¼ì— ë¡œê·¸ì¸ ì‚¬ìš©" msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "TV ì¦ê²¨ì°¾ê¸° 부케 가져오기" msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "ë¼ë””오 ì¦ê²¨ì°¾ê¸° 부케 가져오기" 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 "ì¦ê²¨ì°¾ê¸° (TV)" 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 "Enigma2 미디어 서버" 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 "WebIf 버전" 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 "타ì´ë¨¸ë§Œ" msgctxt "#30103" msgid "Use OpenWebIf picon path" msgstr "OpenWebIf picon 경로 사용" 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 "EPG ì œëª©ì´ ë‹¤ë¥´ë©´ 녹화" msgctxt "#30432" msgid "Record if EPG title and short description differs" msgstr "EPG 제목과 간략한 개요가 다르면 녹화" msgctxt "#30433" msgid "Record if EPG title and all descriptions differ" msgstr "EPG 제목과 ì „ì²´ 개요가 다르면 녹화" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "'%s'ì—서 ì—°ê²° í•´ì œë¨" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "'%s'ì— ë‹¤ì‹œ ì—°ê²°ë¨" msgctxt "#30514" msgid "Timeshift buffer path does not exist" msgstr "시간차 시청 ë²„í¼ ê²½ë¡œê°€ 없습니다" msgctxt "#30515" msgid "Enigma2: Could not reach web interface" msgstr "Enigma2: 웹 ì¸í„°íŽ˜ì´ìŠ¤ì— ì—°ê²°í•  수 ì—†ìŒ" msgctxt "#30516" msgid "Enigma2: No channel groups found" msgstr "Enigma2: ì±„ë„ ê·¸ë£¹ ì—†ìŒ" msgctxt "#30517" msgid "Enigma2: No channels found" msgstr "Enigma2: ì±„ë„ ì—†ìŒ" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.lt_lt/000077500000000000000000000000001356012415200273175ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.lt_lt/strings.po000066400000000000000000000242421356012415200313540ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Lithuanian (Lithuania) (http://www.transifex.com/projects/p/kodi-main/language/lt_LT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: lt_LT\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Enigma2 kompiuterio vardas arba IP adresas" msgctxt "#30002" msgid "Streaming port" msgstr "Srauto prievadas" msgctxt "#30003" msgid "Username" msgstr "Vartotojo vardas" msgctxt "#30004" 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 iÅ¡valymas" msgctxt "#30012" msgid "Web interface port" msgstr "Žiniatinklio sÄ…sajos prievadas" msgctxt "#30013" msgid "Zap before channelswitch (i.e. for single tuner boxes)" msgstr "Uždaryti prieÅ¡ kanalo perjungimÄ… (pvz., vieno imtuvo priedÄ—liams)" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Aplankas kanalo duomenims" msgctxt "#30015" msgid "Update interval" msgstr "Atnaujinimo intervalas" msgctxt "#30016" msgid "Check for channel updates" msgstr "Patikrinkite kanalo atnaujinimus" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Naudokite tik DVB neužpildyti langeliai 'Esamasis įraÅ¡ymo kelias'" msgctxt "#30018" msgid "General" msgstr "Pagrindinis" msgctxt "#30019" msgid "Channels" msgstr "Kanalai" msgctxt "#30020" msgid "Advanced" msgstr "IÅ¡plÄ—stinis" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Ä®raÅ¡as / Laikmatis" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Ä®raÅ¡ymo aplankas į imtuvÄ…" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "Siųsti maitinimo bÅ«senos režimÄ… iÅ¡jungiant priedÄ…" msgctxt "#30025" msgid "TV bouquet fetch mode" msgstr "TV puokÅ¡tÄ—s gavimo bÅ«das" msgctxt "#30026" msgid "TV bouquet" msgstr "TV puokÅ¡tÄ—" msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "Ä®kelti piktogramas iÅ¡ žiniatinklio 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 "#30031" msgid "Seasons and Episodes" msgstr "Sezonai ir epizodai" msgctxt "#30032" msgid "EPG" msgstr "EPG" msgctxt "#30033" msgid "Extract season, episode and year info where possible" msgstr "IÅ¡gauti sezono, epizodo ir metų informacijÄ…, jei įmanoma" msgctxt "#30034" msgid "Enable autotimers" msgstr "Ä®jungti automatinius laikmaÄius" msgctxt "#30035" msgid "Use picons.eu file format" msgstr "Naudoti picons.eu failo formatÄ…" msgctxt "#30036" msgid "Enable generate repeat timers" msgstr "Ä®jungti pakartotinių laikmaÄių generavimÄ…" msgctxt "#30037" msgid "Log missing genre text mappings" msgstr "Ä®raÅ¡yti į žurnalÄ… trÅ«kstamų žanrų teksto sužymÄ—jimÄ…" msgctxt "#30038" msgid "Web Interface" msgstr "Žiniatinklio sÄ…saja" msgctxt "#30039" msgid "Streaming" msgstr "Transliuojama" msgctxt "#30040" msgid "Put outline (e.g. sub-title) before plot" msgstr "Ä®dÄ—ti pagrindinÄ™ informacijÄ… (pvz., subtitrus) prieÅ¡ siužetÄ…" msgctxt "#30041" msgid "Stream read chunk size" msgstr "Srauto skaitymo dalies dydis" 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 "#30046" msgid "Extract show info file" msgstr "IÅ¡gauti laidos informacijos failÄ…" msgctxt "#30047" msgid "Rytec genre text Mappings" msgstr "Rytec žanrų teksto sužymÄ—jimas" msgctxt "#30048" msgid "Enable Rytec genre text mappings" msgstr "Ä®jungti Rytec žanrų teksto sužymÄ—jimÄ…" msgctxt "#30049" msgid "Rytec genre text mappings file" msgstr "Rytec žanrų teksto sužymÄ—jimo failas" msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "Savas televizijos laukimo laikas (0 norint naudoti numatytÄ…jį)" msgctxt "#30051" msgid "Login" msgstr "Prisijungimo vardas" msgctxt "#30052" msgid "Misc" msgstr "Ä®vairÅ«s" msgctxt "#30053" msgid "Genre ID Mappings" msgstr "Žanrų ID sužymÄ—jimas" msgctxt "#30054" msgid "Enable genre ID Mappings" msgstr "Ä®jungti žanrų ID sužymÄ—jimÄ…" msgctxt "#30055" msgid "Genre ID mappings file" msgstr "Žanrų ID sužymÄ—jimo failas" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radijas" msgctxt "#30058" msgid "Radio bouquet fetch mode" msgstr "Radijo puokÅ¡tÄ—s gavimo bÅ«das" msgctxt "#30059" msgid "Radio bouquet" msgstr "Radijo puokÅ¡tÄ—" msgctxt "#30060" msgid "Timeshift" msgstr "Laiko poslinkis" msgctxt "#30061" msgid "Enable timeshift" msgstr "Ä®jungti laiko poslinkį" 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 "#30066" msgid "Use secure HTTP (https) for streams" msgstr "Naudoti saugų HTTP (https) srautams" msgctxt "#30067" msgid "Use login for streams" msgstr "Naudoti prisijungimÄ… srautams" msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "Gauti TV mÄ—gstamiausiųjų puokÅ¡tÄ™" msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "Gauti radijo mÄ—gstamiausiųjų puokÅ¡tÄ™" 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 "#30073" msgid "Number of repeat timers to generate" msgstr "Kartojimo laikmaÄių skaiÄius generavimui" msgctxt "#30074" msgid "All bouquets" msgstr "Visos puokÅ¡tÄ—s" msgctxt "#30075" msgid "Only one bouquet" msgstr "Tik viena puokÅ¡tÄ—" msgctxt "#30076" msgid "As first bouquet" msgstr "Kaip pirma puokÅ¡tÄ—" msgctxt "#30077" msgid "As last bouquet" msgstr "Kaip paskutinÄ— puokÅ¡tÄ—" msgctxt "#30078" msgid "Favourites group" msgstr "MÄ—gstamiausiųjų grupÄ—" msgctxt "#30079" msgid "Favourites (TV)" msgstr "MÄ—gstamiausieji (TV)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "MÄ—gstamiausieji (radijas)" msgctxt "#30081" msgid "unknown" msgstr "nežinomas" msgctxt "#30082" msgid " (Not connected!)" msgstr "(Neprisijungta!)" msgctxt "#30083" msgid "addon error" msgstr "priedo klaida" msgctxt "#30084" msgid "Enigma2 Media Server" msgstr "Enigma2 medijos serveris" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30086" msgid "Backend" msgstr "PosistemÄ—" msgctxt "#30087" msgid "Recording Padding" msgstr "Ä®raÅ¡o paraÅ¡tÄ—" msgctxt "#30088" msgid "Global start padding" msgstr "Globali pradžios paraÅ¡tÄ—" msgctxt "#30089" msgid "Global end padding" msgstr "Globali pabaigos paraÅ¡tÄ—" msgctxt "#30090" msgid "Device Info" msgstr "Ä®renginio informacija" msgctxt "#30091" msgid "WebIf version" msgstr "WebIf versija" msgctxt "#30092" msgid "AutoTimer tag in timer tags" msgstr "Automatinio laikmaÄio žymÄ— laikmaÄio žymÄ—se" msgctxt "#30093" msgid "AutoTimer name in timer tags" msgstr "Automatinio laikmaÄio pavadinimas laikmaÄio žymÄ—se" msgctxt "#30094" msgid "N/A" msgstr "N/A" msgctxt "#30095" msgid "True" msgstr "Taip" msgctxt "#30096" msgid "False" msgstr "Ne" msgctxt "#30097" msgid "Standby" msgstr "BudÄ—jimo režimas" msgctxt "#30098" msgid "Deep standby" msgstr "Gilus budÄ—jimo režimas" msgctxt "#30099" msgid "Wakeup, then standby" msgstr "Pažadinti, tada pereiti į budÄ—jimo režimÄ…" msgctxt "#30100" msgid "Update mode" msgstr "Atnaujinimo režimas" msgctxt "#30101" msgid "Timers and recordings" msgstr "LaikmaÄiai ir įraÅ¡ai" msgctxt "#30102" msgid "Timers only" msgstr "Tik laikmaÄiai" msgctxt "#30103" msgid "Use OpenWebIf picon path" msgstr "Naudoti OpenWebIf piktogramos keliÄ…" 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'" msgstr "Atjungtas nuo '%s'" 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" msgctxt "#30515" msgid "Enigma2: Could not reach web interface" msgstr "Enigma2: neįmanoma pasiekti žiniatinklio sÄ…sajos" msgctxt "#30516" msgid "Enigma2: No channel groups found" msgstr "Enigma2: kanalų grupių nerasta" msgctxt "#30517" msgid "Enigma2: No channels found" msgstr "Enigma2: kanalų nerasta" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.lv_lv/000077500000000000000000000000001356012415200273235ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.lv_lv/strings.po000066400000000000000000000055021356012415200313560ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Latvian (Latvia) (http://www.transifex.com/projects/p/kodi-main/language/lv_LV/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: lv_LV\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n" msgctxt "#30003" msgid "Username" msgstr "LIetotÄjs" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "AtjauninÄÅ¡anas intervÄls minÅ«tÄ“s" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Mape kanÄldatiem" msgctxt "#30015" msgid "Update interval" msgstr "AtjauninÄjuma intervÄls" msgctxt "#30016" msgid "Check for channel updates" msgstr "PÄrbaudÄ«t kanÄla atjauninÄjumus" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Izmantot tikai DVB pierÄ«ces paÅ¡reizÄ“jo ierakstīšanas ceļu" msgctxt "#30018" msgid "General" msgstr "VispÄrÄ«gi" msgctxt "#30019" msgid "Channels" msgstr "KanÄli" msgctxt "#30020" msgid "Advanced" msgstr "Papildus" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Ieraksti / Taimeris" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Ierakstīšanas mape atskaņotÄjÄ" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "Skaidrs" msgctxt "#30094" msgid "N/A" msgstr "N/P" msgctxt "#30095" msgid "True" msgstr "Patiess" msgctxt "#30096" msgid "False" msgstr "Nepatiess" msgctxt "#30410" msgid "Automatic" msgstr "AutomÄtiski" msgctxt "#30430" msgid "Disabled" msgstr "IzslÄ“gts" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Atvienots no '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Atkal savienots '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.mi/000077500000000000000000000000001356012415200266065ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.mi/strings.po000066400000000000000000000027211356012415200306410ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Maori (http://www.transifex.com/projects/p/kodi-main/language/mi/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: mi\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" msgctxt "#30003" msgid "Username" msgstr "Ingoa kaiwhakamahi" msgctxt "#30004" msgid "Password" msgstr "Kupuhipa" msgctxt "#30006" msgid "Icons" msgstr "Ata" msgctxt "#30018" msgid "General" msgstr "Ä€huawhÄnui" msgctxt "#30019" msgid "Channels" msgstr "NgÄ hongere" msgctxt "#30020" msgid "Advanced" msgstr "ArÄ Atu AnÅ" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30042" msgid "Never" msgstr "Kore rawa" msgctxt "#30045" msgid "Always" msgstr "Tonu" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30063" msgid "Off" msgstr "Weto" msgctxt "#30071" msgid "Recordings" msgstr "NgÄ pÅ«hopu" msgctxt "#30085" msgid "OK" msgstr "Ä€na" msgctxt "#30095" msgid "True" msgstr "Pono" msgctxt "#30096" msgid "False" msgstr "Teka" msgctxt "#30430" msgid "Disabled" msgstr "Kua mono" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.mk_mk/000077500000000000000000000000001356012415200272775ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.mk_mk/strings.po000066400000000000000000000060431356012415200313330ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Macedonian (Macedonia) (http://www.transifex.com/projects/p/kodi-main/language/mk_MK/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: mk_MK\n" "Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" msgctxt "#30003" msgid "Username" msgstr "КориÑничко име" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Интервал на надградби во минути" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Папки за channeldata" msgctxt "#30015" msgid "Update interval" msgstr "Период на оÑвежување" msgctxt "#30016" msgid "Check for channel updates" msgstr "Провери дали има нови канали" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "КориÑти ја патеката за Ñнимање од DVB уредот" msgctxt "#30018" msgid "General" msgstr "Општо" msgctxt "#30019" msgid "Channels" msgstr "Канали" msgctxt "#30020" msgid "Advanced" msgstr "Ðапредно" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Снимки / Тајмер" msgctxt "#30023" msgid "Recording folder on the receiver" 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 "#30056" msgid "TV" msgstr "ТВ" msgctxt "#30057" msgid "Radio" 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 "#30085" msgid "OK" msgstr "Во ред" msgctxt "#30095" msgid "True" msgstr "ВиÑтина" msgctxt "#30096" msgid "False" msgstr "Ðеактивно" msgctxt "#30430" msgid "Disabled" msgstr "ИÑклучено" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Деконектирано од '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Конектирано за '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ml_in/000077500000000000000000000000001356012415200272775ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ml_in/strings.po000066400000000000000000000014061356012415200313310ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Malayalam (India) (http://www.transifex.com/projects/p/kodi-main/language/ml_IN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ml_IN\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30018" msgid "General" msgstr "പോതàµà´µà´¾à´¯à´¤àµ" msgctxt "#30085" msgid "OK" msgstr "à´¶à´°à´¿" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.mn_mn/000077500000000000000000000000001356012415200273055ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.mn_mn/strings.po000066400000000000000000000031601356012415200313360ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Mongolian (Mongolia) (http://www.transifex.com/projects/p/kodi-main/language/mn_MN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: mn_MN\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Ð¥ÑÑ€ÑглÑгчийн нÑÑ€" msgctxt "#30004" msgid "Password" msgstr "Ðууц үг" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Хариу хугацаа Ñ…ÑтрÑлт, ÑекундÑÑÑ€" msgctxt "#30018" msgid "General" msgstr "Ерөнхий" msgctxt "#30019" msgid "Channels" msgstr "Сувгууд" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30056" msgid "TV" msgstr "ТВ" msgctxt "#30057" msgid "Radio" msgstr "Радио" msgctxt "#30063" msgid "Off" msgstr "Хаах" msgctxt "#30071" msgid "Recordings" msgstr "БичлÑгүүд" msgctxt "#30072" msgid "Timers" msgstr "Цагалбарууд" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30430" msgid "Disabled" msgstr "ИдвÑхгүй болÑон" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "'%s'-Ñ Ñалгагдлаа" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "'%s'-д дахин холбогдлоо" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ms_my/000077500000000000000000000000001356012415200273255ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ms_my/strings.po000066400000000000000000000222261356012415200313620ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Malay (Malaysia) (http://www.transifex.com/projects/p/kodi-main/language/ms_MY/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ms_MY\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Namahos atau alamat IP Enigma2 " msgctxt "#30002" msgid "Streaming port" msgstr "Port penstriman" msgctxt "#30003" msgid "Username" msgstr "Nama Pengguna" msgctxt "#30004" 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 "Web interface port" msgstr "Port antaramuka sesawang" 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 "Update interval" msgstr "Kemaskini sela" msgctxt "#30016" msgid "Check for channel updates" msgstr "Semak untuk kemaskini saluran" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Hanya guna laluan rakaman semasa kotak DVB" msgctxt "#30018" msgid "General" msgstr "Am" msgctxt "#30019" msgid "Channels" msgstr "Saluran" msgctxt "#30020" msgid "Advanced" msgstr "Lanjutan" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Rakaman / Pemasa" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Folder rakaman pada penerima" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "Hantar mod keadaan kuasa ketika keluar dari tambahan" msgctxt "#30025" msgid "TV bouquet fetch mode" msgstr "Mod dapatkan jambak TV" msgctxt "#30026" msgid "TV bouquet" msgstr "Jambak TV" msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "Dapatkan picon dari antaramuka sesawang" 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 "#30031" msgid "Seasons and Episodes" msgstr "Musim dan Episod" msgctxt "#30032" msgid "EPG" msgstr "EPG" msgctxt "#30033" msgid "Extract season, episode and year info where possible" msgstr "Ekstrak maklumat musim, episod dan tahun jika ada" msgctxt "#30034" msgid "Enable autotimers" msgstr "Benarkan autopemasa" msgctxt "#30035" msgid "Use picons.eu file format" msgstr "Guna format fail picons.eu" msgctxt "#30036" msgid "Enable generate repeat timers" msgstr "Benarkan jana pemasa berulang" msgctxt "#30037" msgid "Log missing genre text mappings" msgstr "Log pemetaan teks genre yang hilang" msgctxt "#30038" msgid "Web Interface" msgstr "Antaramuka Sesawang" msgctxt "#30039" msgid "Streaming" msgstr "Penstriman" msgctxt "#30040" msgid "Put outline (e.g. sub-title) before plot" msgstr "Letak garis-luar (cth. sarikata) sebelum plot" msgctxt "#30041" msgid "Stream read chunk size" msgstr "Saiz cebisan baca strim" 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 "#30046" msgid "Extract show info file" msgstr "Ekstrak fail maklumat rancangan" msgctxt "#30047" msgid "Rytec genre text Mappings" msgstr "Pemetaan teks genre Rytec" msgctxt "#30048" msgid "Enable Rytec genre text mappings" msgstr "Benarkan pemetaan teks genre Rytec" msgctxt "#30049" msgid "Rytec genre text mappings file" msgstr "Fail pemetaan teks genre Rytec" msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "Had masa tamat TV langsung suai (0 untuk guna lalai)" msgctxt "#30051" msgid "Login" msgstr "Daftar Masuk" msgctxt "#30052" msgid "Misc" msgstr "Pelbagai" msgctxt "#30053" msgid "Genre ID Mappings" msgstr "Pemetaan ID Genre" msgctxt "#30054" msgid "Enable genre ID Mappings" msgstr "Benarkan Pemetaan ID Genre" msgctxt "#30055" msgid "Genre ID mappings file" msgstr "Fail pemetaan ID Genre" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30058" msgid "Radio bouquet fetch mode" msgstr "Mod dapatkan jambak radio" msgctxt "#30059" msgid "Radio bouquet" msgstr "Jambak radio" msgctxt "#30060" msgid "Timeshift" msgstr "Anjak Masa" msgctxt "#30061" msgid "Enable timeshift" msgstr "Benarkan 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 "#30066" msgid "Use secure HTTP (https) for streams" msgstr "Guna HTTP Selamat (https) untuk strim" msgctxt "#30067" msgid "Use login for streams" msgstr "Guna daftar masuk untuk strim" msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "Dapatkan jambak kegemaran TV" msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "Dapatkan jambak kegemaran radio" msgctxt "#30070" msgid "Recordings & Timers" msgstr "Rakaman & Pemasa" msgctxt "#30071" msgid "Recordings" msgstr "Rakaman" msgctxt "#30072" msgid "Timers" msgstr "Pemasa" msgctxt "#30073" msgid "Number of repeat timers to generate" msgstr "Bilangan pemasa ulang untuk dijana" msgctxt "#30074" msgid "All bouquets" msgstr "Semua jambak" msgctxt "#30075" msgid "Only one bouquet" msgstr "Hanya satu jambak" msgctxt "#30076" msgid "As first bouquet" msgstr "Sebagai jambak pertama" msgctxt "#30077" msgid "As last bouquet" msgstr "Sebagai jambak terakhir" msgctxt "#30078" msgid "Favourites group" msgstr "Kumpulan kegemaran" msgctxt "#30079" msgid "Favourites (TV)" msgstr "Kegemaran (TV)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "Kegemaran (Radio)" msgctxt "#30081" msgid "unknown" msgstr "tidak diketahui" msgctxt "#30082" msgid " (Not connected!)" msgstr "(Tidak bersambung)" msgctxt "#30083" msgid "addon error" msgstr "ralat tambahan" msgctxt "#30084" msgid "Enigma2 Media Server" msgstr "Pelayan Media Enigma2" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30086" msgid "Backend" msgstr "Bahagian belakang" msgctxt "#30087" msgid "Recording Padding" msgstr "Pemadatan Rakaman" msgctxt "#30088" msgid "Global start padding" msgstr "Pemadatan mula sejagat" msgctxt "#30089" msgid "Global end padding" msgstr "Pemadatan tamat sejagat" msgctxt "#30090" msgid "Device Info" msgstr "Maklumat Peranti" msgctxt "#30091" msgid "WebIf version" msgstr "Versi Webif" msgctxt "#30092" msgid "AutoTimer tag in timer tags" msgstr "Tag AutoPemasa dalam tag pemasa" msgctxt "#30093" msgid "AutoTimer name in timer tags" msgstr "Nama AutoPemasa dalam tag pemasa" msgctxt "#30094" msgid "N/A" msgstr "T/A" msgctxt "#30095" msgid "True" msgstr "Benar" msgctxt "#30096" msgid "False" msgstr "Palsu" msgctxt "#30097" msgid "Standby" msgstr "Sedia" msgctxt "#30098" msgid "Deep standby" msgstr "Sedia mendalam" msgctxt "#30099" msgid "Wakeup, then standby" msgstr "Bangun, kemudian sedia" msgctxt "#30100" msgid "Update mode" msgstr "Mod kemaskini" msgctxt "#30101" msgid "Timers and recordings" msgstr "Pemasa dan rakaman" msgctxt "#30102" msgid "Timers only" msgstr "Pemasa sahaja" 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'" msgstr "Terputus dari '%s'" 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" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.mt_mt/000077500000000000000000000000001356012415200273215ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.mt_mt/strings.po000066400000000000000000000036571356012415200313650ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Maltese (Malta) (http://www.transifex.com/projects/p/kodi-main/language/mt_MT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: mt_MT\n" "Plural-Forms: nplurals=4; plural=(n==1 ? 0 : n==0 || ( n%100>1 && n%100<11) ? 1 : (n%100>10 && n%100<20 ) ? 2 : 3);\n" msgctxt "#30003" msgid "Username" msgstr "Username" msgctxt "#30004" 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 "#30015" msgid "Update interval" msgstr "Il-ħin bejn l-aġġornamenti" msgctxt "#30018" msgid "General" msgstr "Ä enerali" msgctxt "#30019" msgid "Channels" msgstr "Stazzjonijiet" msgctxt "#30020" msgid "Advanced" msgstr "Avvanzat" 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 "#30056" msgid "TV" msgstr "Televixin" msgctxt "#30057" msgid "Radio" msgstr "Radju" 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 "#30085" msgid "OK" msgstr "OK" msgctxt "#30095" msgid "True" msgstr "Veru" msgctxt "#30096" msgid "False" msgstr "Falz" msgctxt "#30430" msgid "Disabled" msgstr "Mhux attiv" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.my_mm/000077500000000000000000000000001356012415200273175ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.my_mm/strings.po000066400000000000000000000033451356012415200313550ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Burmese (Myanmar) (http://www.transifex.com/projects/p/kodi-main/language/my_MM/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: my_MM\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30003" msgid "Username" msgstr "အသုံးပြုသူအမည်" msgctxt "#30004" msgid "Password" msgstr "စကားá€á€¾á€€á€º" msgctxt "#30005" msgid "Connection" msgstr "ကွန်နက်ရှင်" msgctxt "#30006" msgid "Icons" msgstr "Icons" msgctxt "#30018" msgid "General" msgstr "ယေဘုယျ" msgctxt "#30019" msgid "Channels" msgstr "Channel များ" msgctxt "#30020" msgid "Advanced" msgstr "အဆင့်မြင့်သော" msgctxt "#30042" msgid "Never" msgstr "ဘယ်á€á€±á€¬á€·á€™á€¾" msgctxt "#30045" msgid "Always" msgstr "အမြဲá€á€™á€ºá€¸" msgctxt "#30051" msgid "Login" msgstr "á€á€„်ရန်" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "ရေဒီယို" msgctxt "#30063" msgid "Off" msgstr "ပိá€á€º" msgctxt "#30071" msgid "Recordings" msgstr "အသံသွင်းá€á€¼á€„်း" msgctxt "#30085" msgid "OK" msgstr "အိုကေ" msgctxt "#30095" msgid "True" msgstr "မှန်á" msgctxt "#30430" msgid "Disabled" msgstr "ပိá€á€ºá€‘ားမည်" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.nb_no/000077500000000000000000000000001356012415200272745ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.nb_no/strings.po000066400000000000000000000064111356012415200313270ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Norwegian BokmÃ¥l (Norway) (http://www.transifex.com/projects/p/kodi-main/language/nb_NO/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: nb_NO\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Brukernavn" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Oppdateringsinterval i minutter" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Mappe for kanaldata" msgctxt "#30015" msgid "Update interval" msgstr "Oppdateringsintervall" msgctxt "#30016" msgid "Check for channel updates" msgstr "Se etter kanal oppdateringer" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Bruk bare DVB boksens nÃ¥værende opptakssti" msgctxt "#30018" msgid "General" msgstr "Generelt" msgctxt "#30019" msgid "Channels" msgstr "Kanaler" msgctxt "#30020" msgid "Advanced" msgstr "Avansert" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Opptak / tidsur" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Opptaksmappe pÃ¥ mottaker" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "OK" msgctxt "#30094" msgid "N/A" msgstr "Ikke Tilgjengelig" msgctxt "#30095" msgid "True" msgstr "Sant" msgctxt "#30096" msgid "False" msgstr "Usann" msgctxt "#30410" msgid "Automatic" msgstr "Automatisk" msgctxt "#30430" msgid "Disabled" msgstr "Deaktivert" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Frakoblet fra '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Tilkoblet til '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.nl_nl/000077500000000000000000000000001356012415200273035ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.nl_nl/strings.po000066400000000000000000000166501356012415200313440ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Dutch (Netherlands) (http://www.transifex.com/projects/p/kodi-main/language/nl_NL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: nl_NL\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Enigma2 hostnaam of IP-adres" msgctxt "#30002" msgid "Streaming port" msgstr "Doorvoerpoort" msgctxt "#30003" msgid "Username" msgstr "Gebruikersnaam" msgctxt "#30004" 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 "Iconenpad" msgctxt "#30009" msgid "Update Interval" msgstr "Update-interval" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Update-interval in minuten" msgctxt "#30011" msgid "Automatic timerlist cleanup" msgstr "Automatisch opschonen van de timerlijst" msgctxt "#30012" msgid "Web interface port" msgstr "Webinterface-poort" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Map voor kanaaldata" msgctxt "#30015" msgid "Update interval" msgstr "Updatefrequentie" msgctxt "#30016" msgid "Check for channel updates" msgstr "Zoeken naar kanaal-updates" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Gebruik alleen het huidig opnamepad van de DVB box" msgctxt "#30018" msgid "General" msgstr "Algemeen" msgctxt "#30019" msgid "Channels" msgstr "Kanalen" msgctxt "#30020" msgid "Advanced" msgstr "Geavanceerd" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Opnames / Timer" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Opnamemap op de ontvanger" msgctxt "#30026" msgid "TV bouquet" msgstr "TV bouquet" msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "Picons ophalen van de web-interface" msgctxt "#30028" msgid "Use secure HTTP (https)" msgstr "Gebruik beveiligd 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 "#30031" msgid "Seasons and Episodes" msgstr "Seizoenen en afleveringen" msgctxt "#30032" msgid "EPG" msgstr "EPG" msgctxt "#30033" msgid "Extract season, episode and year info where possible" msgstr "Seizoen-, afleverings- en jaarinformatie ophalen wanneer mogelijk" msgctxt "#30034" msgid "Enable autotimers" msgstr "Inschakelen van autotimers" msgctxt "#30035" msgid "Use picons.eu file format" msgstr "Gebruik picons.eu-bestandsformaat" msgctxt "#30036" msgid "Enable generate repeat timers" msgstr "Activeren van gegenereerde herhaaltimers" msgctxt "#30037" msgid "Log missing genre text mappings" msgstr "Log de afwezige genre-tekstmappings" msgctxt "#30038" msgid "Web Interface" msgstr "Webinterface" msgctxt "#30039" msgid "Streaming" msgstr "Streaming" msgctxt "#30040" msgid "Put outline (e.g. sub-title) before plot" msgstr "Schets het verhaal (bijv. 2e titel) voor de plot" 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 "#30046" msgid "Extract show info file" msgstr "TV-show-informatiebestand ophalen" msgctxt "#30051" msgid "Login" msgstr "Gebruikersnaam" msgctxt "#30052" msgid "Misc" msgstr " Divers" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30059" msgid "Radio bouquet" msgstr "Radio-bouquet" msgctxt "#30060" msgid "Timeshift" msgstr "Timeshift" msgctxt "#30061" msgid "Enable timeshift" msgstr "Timeshift inschakelen" 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 "#30066" msgid "Use secure HTTP (https) for streams" msgstr "Gebruik beveiligde HTTP (https) voor streams" msgctxt "#30070" msgid "Recordings & Timers" msgstr "Opnames en timers" msgctxt "#30071" msgid "Recordings" msgstr "Opnames" msgctxt "#30072" msgid "Timers" msgstr "Timers" msgctxt "#30073" msgid "Number of repeat timers to generate" msgstr "Aantal herhaaltimers te genereren" msgctxt "#30074" msgid "All bouquets" msgstr "Alle bouquets" msgctxt "#30075" msgid "Only one bouquet" msgstr "Slechts één bouquet" msgctxt "#30076" msgid "As first bouquet" msgstr "Als eerste bouquet" msgctxt "#30077" msgid "As last bouquet" msgstr "Als laatste bouquet" msgctxt "#30078" msgid "Favourites group" msgstr "Bladwijzergroep" msgctxt "#30079" msgid "Favourites (TV)" msgstr "Bladwijzers (TV)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "Bladwijzers (Radio)" msgctxt "#30081" msgid "unknown" msgstr "onbekend" msgctxt "#30082" msgid " (Not connected!)" msgstr "(Niet verbonden!)" msgctxt "#30083" msgid "addon error" msgstr "Fout in add-on" msgctxt "#30084" msgid "Enigma2 Media Server" msgstr "Enigma2 Media Server" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30086" msgid "Backend" msgstr "Backend" msgctxt "#30087" msgid "Recording Padding" msgstr "Opname-opvulling" msgctxt "#30088" msgid "Global start padding" msgstr "Globale startopvulling" msgctxt "#30089" msgid "Global end padding" msgstr "Globale eindopvulling" msgctxt "#30090" msgid "Device Info" msgstr "Apparaatinformatie" msgctxt "#30091" msgid "WebIf version" msgstr "WebIf-versie" msgctxt "#30094" msgid "N/A" msgstr "N/B" msgctxt "#30095" msgid "True" msgstr "Waar" msgctxt "#30096" msgid "False" msgstr "Onwaar" msgctxt "#30100" msgid "Update mode" msgstr "Update-modus" msgctxt "#30101" msgid "Timers and recordings" msgstr "Timers en opnames" msgctxt "#30102" msgid "Timers only" msgstr "Alleen 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 "#30421" msgid "One time (Scheduled by repeating timer rule)" msgstr "Eenmaal (ingepland door herhaalde timerregel)" msgctxt "#30430" msgid "Disabled" msgstr "Uitgeschakeld" msgctxt "#30431" msgid "Record if EPG title differs" msgstr "Opname indien EPG-titel afwijkt" msgctxt "#30432" msgid "Record if EPG title and short description differs" msgstr "Opnemen indien er verschillen in de EPG-titel en de korte omschrijving zijn" msgctxt "#30433" msgid "Record if EPG title and all descriptions differ" msgstr "Opnemen indien er verschillen in de EPG-titel en alle korte omschrijvingen zijn" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Verbinding met '%s' verbroken" 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" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.pl_pl/000077500000000000000000000000001356012415200273075ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.pl_pl/strings.po000066400000000000000000000075761356012415200313570ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Polish (Poland) (http://www.transifex.com/projects/p/kodi-main/language/pl_PL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pl_PL\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30003" msgid "Username" msgstr "Użytkownik" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "CzÄ™stotliwość aktualizacji w minutach" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Folder danych kanałów" msgctxt "#30015" msgid "Update interval" msgstr "CzÄ™stotliwość aktualizacji" msgctxt "#30016" msgid "Check for channel updates" msgstr "Sprawdzaj aktualizacje kanałów" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Używaj tylko bieżącego folderu nagrywania dekodera" msgctxt "#30018" msgid "General" msgstr "Ogólne" msgctxt "#30019" msgid "Channels" msgstr "KanaÅ‚y" msgctxt "#30020" msgid "Advanced" msgstr "Zaawansowane" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Nagrania / Harmonogram" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Folder nagrywania na dekoderze" 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 "#30056" msgid "TV" msgstr "TELEWIZJA" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "OK" msgctxt "#30094" msgid "N/A" msgstr "Brak" msgctxt "#30095" msgid "True" msgstr "Prawda" msgctxt "#30096" msgid "False" msgstr "FaÅ‚sz" 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'" msgstr "Rozłączono od '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Połączono ponownie z '%s'" msgctxt "#30514" msgid "Timeshift buffer path does not exist" msgstr "Folderu bufora przesuniÄ™cia czasowego nie istnieje" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.pt_br/000077500000000000000000000000001356012415200273075ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.pt_br/strings.po000066400000000000000000000104111356012415200313350ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/kodi-main/language/pt_BR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pt_BR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" msgctxt "#30003" msgid "Username" msgstr "Nome do usuário" msgctxt "#30004" 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 para o ícone" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Intervalo de atualizações em minutos" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Pasta para dados dos canais" msgctxt "#30015" msgid "Update interval" msgstr "Intervalo de atualização" msgctxt "#30016" msgid "Check for channel updates" msgstr "Verificar atualizações de canal" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Usar somente o caminho de gravação atual do conversor DVB" msgctxt "#30018" msgid "General" msgstr "Geral" msgctxt "#30019" msgid "Channels" msgstr "Canais" msgctxt "#30020" msgid "Advanced" msgstr "Avançado" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Gravações / Agendamentos" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Pasta de gravações no receptor" 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 "#30031" msgid "Seasons and Episodes" msgstr "Temporadas e Episódios" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Rádio" 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 "#30067" msgid "Use login for streams" msgstr "Usar login para streams" msgctxt "#30071" msgid "Recordings" msgstr "Gravações" msgctxt "#30072" msgid "Timers" msgstr "Agendamentos" msgctxt "#30078" msgid "Favourites group" msgstr "Grupo de favoritos" msgctxt "#30079" msgid "Favourites (TV)" msgstr "Favoritos (TV)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "Favoritos (Rádio)" msgctxt "#30081" msgid "unknown" msgstr "desconhecido" msgctxt "#30082" msgid " (Not connected!)" msgstr "(Não conectado!)" msgctxt "#30083" msgid "addon error" msgstr "Erro no add-on" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30090" msgid "Device Info" msgstr "Informações do dispositivo" msgctxt "#30094" msgid "N/A" msgstr "N/D" msgctxt "#30095" msgid "True" msgstr "Verdadeiro" msgctxt "#30096" msgid "False" msgstr "Falso" msgctxt "#30101" msgid "Timers and recordings" msgstr "Agendamentos e gravações" msgctxt "#30102" msgid "Timers only" msgstr "Somente agendamentos" msgctxt "#30410" msgid "Automatic" msgstr "Automático" msgctxt "#30430" msgid "Disabled" msgstr "Desabilitado" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Desconectado de '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Reconectado a '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.pt_pt/000077500000000000000000000000001356012415200273275ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.pt_pt/strings.po000066400000000000000000000061641356012415200313670ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Portuguese (Portugal) (http://www.transifex.com/projects/p/kodi-main/language/pt_PT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pt_PT\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Nome de utilizador" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Intervalo de atualização (minutos)" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Pasta para dados do canais" msgctxt "#30015" msgid "Update interval" msgstr "Intervalo de atualização " msgctxt "#30016" msgid "Check for channel updates" msgstr "Verificar actualizações de canais" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Utilizar apenas o caminho de gravação atual da caixa DVB" msgctxt "#30018" msgid "General" msgstr "Geral" msgctxt "#30019" msgid "Channels" msgstr "Canais" msgctxt "#30020" msgid "Advanced" msgstr "Avançado" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Gravações/Temporizador" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Pasta de gravação no recetor" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Rádio" 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 "#30085" msgid "OK" msgstr "CONFIRMAR" msgctxt "#30095" msgid "True" msgstr "Verdadeiro" msgctxt "#30096" msgid "False" msgstr "Falso" msgctxt "#30410" msgid "Automatic" msgstr "Automático" msgctxt "#30430" msgid "Disabled" msgstr "Desativado" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Desligado de '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Ligado novamente a '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ro_ro/000077500000000000000000000000001356012415200273215ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ro_ro/strings.po000066400000000000000000000064301356012415200313550ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Romanian (Romania) (http://www.transifex.com/projects/p/kodi-main/language/ro_RO/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ro_RO\n" "Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n" msgctxt "#30003" msgid "Username" msgstr "Utilizator" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Intervalul de actualizare în minute" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Dosarul pentru informaÈ›iile canalelor" msgctxt "#30015" msgid "Update interval" msgstr "Interval actualizare" msgctxt "#30016" msgid "Check for channel updates" msgstr "Verifică actualizarea canalului" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Utilizează pentru înregistrare doar adresa decodorului DVB" msgctxt "#30018" msgid "General" msgstr "General" msgctxt "#30019" msgid "Channels" msgstr "Canale" msgctxt "#30020" msgid "Advanced" msgstr "Avansat" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Inregistrari / Cronometru" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Dosarul de înregistrari în decodor" 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 "#30056" msgid "TV" msgstr "Televizor" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "Bine" msgctxt "#30094" msgid "N/A" msgstr "Nedisponibil" msgctxt "#30095" msgid "True" msgstr "Adevărat" msgctxt "#30096" msgid "False" msgstr "Fals" msgctxt "#30410" msgid "Automatic" msgstr "Automat" msgctxt "#30430" msgid "Disabled" msgstr "Dezactivat" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Deconectat de la '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Reconectat la '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ru_ru/000077500000000000000000000000001356012415200273355ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ru_ru/strings.po000066400000000000000000000126711356012415200313750ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Russian (Russia) (http://www.transifex.com/projects/p/kodi-main/language/ru_RU/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ru_RU\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30003" msgid "Username" msgstr "Пользователь" msgctxt "#30004" msgid "Password" msgstr "Пароль" msgctxt "#30005" msgid "Connection" msgstr "Соединение" msgctxt "#30006" msgid "Icons" msgstr "Значки" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Тайм-аут отклика в Ñекундах" msgctxt "#30009" msgid "Update Interval" msgstr "Интервал обновлениÑ" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Интервал Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð² минутах" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Папка Ð´Ð»Ñ Ð´Ð°Ð½Ð½Ñ‹Ñ… о каналах" msgctxt "#30015" msgid "Update interval" msgstr "Интервал обновлениÑ" msgctxt "#30016" msgid "Check for channel updates" msgstr "ПроверÑть Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ ÐºÐ°Ð½Ð°Ð»Ð¾Ð²" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "ИÑпользовать Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи только заданный в DVB путь" msgctxt "#30018" msgid "General" msgstr "ОÑновное" msgctxt "#30019" msgid "Channels" msgstr "Каналы" msgctxt "#30020" msgid "Advanced" msgstr "Дополнительно" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "ЗапиÑи/Таймер" msgctxt "#30023" msgid "Recording folder on the receiver" 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 "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 "#30056" msgid "TV" msgstr "ТВ" msgctxt "#30057" msgid "Radio" 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 "#30083" msgid "addon error" msgstr "ошибка дополнениÑ" msgctxt "#30085" msgid "OK" msgstr "ОК" msgctxt "#30094" msgid "N/A" msgstr "Ðе доÑтупно" msgctxt "#30095" msgid "True" msgstr "Да" msgctxt "#30096" msgid "False" 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'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Подключено к '%s'" msgctxt "#30514" msgid "Timeshift buffer path does not exist" msgstr "ОтÑутÑтвует путь Ð´Ð»Ñ Ð±ÑƒÑ„ÐµÑ€Ð¸Ð·Ð°Ñ†Ð¸Ð¸ отложенного проÑмотра" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.si_lk/000077500000000000000000000000001356012415200273025ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.si_lk/strings.po000066400000000000000000000027221356012415200313360ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Sinhala (Sri Lanka) (http://www.transifex.com/projects/p/kodi-main/language/si_LK/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: si_LK\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "පරිà·à·“ලක නම" msgctxt "#30004" msgid "Password" msgstr "මුරපදය" msgctxt "#30006" msgid "Icons" msgstr "සුරුවම් " msgctxt "#30018" msgid "General" msgstr "à·ƒà·à¶¸à·à¶±à·Šâ€à¶º" msgctxt "#30020" msgid "Advanced" msgstr "උසස්" 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 "#30085" msgid "OK" msgstr "හරි" msgctxt "#30430" msgid "Disabled" msgstr "à¶…à¶šà·Šâ€à¶»à·’ය à¶šà¶» ඇත." pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.sk_sk/000077500000000000000000000000001356012415200273135ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.sk_sk/strings.po000066400000000000000000000074701356012415200313540ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Slovak (Slovakia) (http://www.transifex.com/projects/p/kodi-main/language/sk_SK/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sk_SK\n" "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" msgctxt "#30003" msgid "Username" msgstr "Užívateľské meno" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Interval aktualizácie v minútach" msgctxt "#30014" msgid "Folder for channeldata" msgstr "PrieÄinok pre dáta kanálov" msgctxt "#30015" msgid "Update interval" msgstr "Doba aktualizácie" msgctxt "#30016" msgid "Check for channel updates" msgstr "KontrolovaÅ¥ dostupnosÅ¥ aktualizácií kanálov" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "PoužiÅ¥ iba aktuálny prieÄinok pre nahrávky z DVB prijímaÄa" msgctxt "#30018" msgid "General" msgstr "Hlavné" msgctxt "#30019" msgid "Channels" msgstr "Kanály" msgctxt "#30020" msgid "Advanced" msgstr "PokroÄilé nastavenia" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Nahrávky / ÄasovaÄ" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "PrieÄinok pre nahrávky v prijímaÄi" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Rádio" 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 "#30085" msgid "OK" msgstr "OK" msgctxt "#30094" msgid "N/A" msgstr "N/A" msgctxt "#30095" msgid "True" msgstr "Pravdivé" msgctxt "#30096" msgid "False" msgstr "Nepravdivé" 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'" msgstr "Odpojený od '%s'" 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" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.sl_si/000077500000000000000000000000001356012415200273125ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.sl_si/strings.po000066400000000000000000000060621356012415200313470ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Slovenian (Slovenia) (http://www.transifex.com/projects/p/kodi-main/language/sl_SI/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sl_SI\n" "Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n" msgctxt "#30003" msgid "Username" msgstr "UporabniÅ¡ko ime" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Interval posodabljanja v minutah" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Mapa za podatke o programih" msgctxt "#30015" msgid "Update interval" msgstr "Interval posodabljanja" msgctxt "#30016" msgid "Check for channel updates" msgstr "Preveri za posodobitve programov" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Uporabi le sprejemnikovo trenutno pot snemanja" msgctxt "#30018" msgid "General" msgstr "SploÅ¡no" msgctxt "#30019" msgid "Channels" msgstr "Programi" msgctxt "#30020" msgid "Advanced" msgstr "Napredno" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Posnetki / ÄŒasovniki" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Mapa snemanja na sprejemniku" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "OK" msgctxt "#30095" msgid "True" msgstr "Drži" msgctxt "#30096" msgid "False" msgstr "Nepravilno" msgctxt "#30410" msgid "Automatic" msgstr "Samodejno" msgctxt "#30430" msgid "Disabled" msgstr "OnemogoÄeno" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Povezava prekinjena z '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Povezava vzpostavljena z '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.sq_al/000077500000000000000000000000001356012415200273005ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.sq_al/strings.po000066400000000000000000000045461356012415200313420ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Albanian (Albania) (http://www.transifex.com/projects/p/kodi-main/language/sq_AL/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sq_AL\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Emër-përdoruesi" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Interval i aktualizimit në minuta" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Rregjistri për informacionet të kanaleve" msgctxt "#30016" msgid "Check for channel updates" msgstr "Shikoni për aktualizime të kanaleve" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Përdorni vendndodhjen aktual për regjistrimet të DVB box'it" msgctxt "#30018" msgid "General" msgstr "I përgjithsëm" msgctxt "#30019" msgid "Channels" msgstr "Kanalet" msgctxt "#30020" msgid "Advanced" msgstr "Të shtuar" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Regjistrime / timer" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Regjistër i regjistrimeve në resiverin" msgctxt "#30042" msgid "Never" msgstr "Kurrë" msgctxt "#30045" msgid "Always" msgstr "Gjithnjë" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30063" msgid "Off" msgstr "Hequr" msgctxt "#30071" msgid "Recordings" msgstr "Rregjistrime" msgctxt "#30085" msgid "OK" msgstr "N'RREGULL" msgctxt "#30095" msgid "True" msgstr "Vërtetë" msgctxt "#30096" msgid "False" msgstr "I pavërtetë" msgctxt "#30430" msgid "Disabled" msgstr "Deaktivuar" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "U ndërpre nga '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "U rilidh me '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.sr_rs/000077500000000000000000000000001356012415200273315ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.sr_rs/strings.po000066400000000000000000000072001356012415200313610ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Serbian (Serbia) (http://www.transifex.com/projects/p/kodi-main/language/sr_RS/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sr_RS\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30003" msgid "Username" msgstr "КориÑничко име" msgctxt "#30004" msgid "Password" msgstr "Лозинка" msgctxt "#30005" msgid "Connection" msgstr "Веза" msgctxt "#30006" msgid "Icons" msgstr "Иконе" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "ИÑтек времена за одзив у Ñекундама" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Интервал ажурирања у минутима" msgctxt "#30014" msgid "Folder for channeldata" msgstr "ФаÑцикла за податке канала" msgctxt "#30015" msgid "Update interval" msgstr "Интервал ажурирања" msgctxt "#30016" msgid "Check for channel updates" msgstr "Провери за новије верзије канала" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "КориÑти Ñамо тренутну путању Ñнимања DVB кутија" msgctxt "#30018" msgid "General" msgstr "Опште" msgctxt "#30019" msgid "Channels" msgstr "Канали" msgctxt "#30020" msgid "Advanced" msgstr "Ðапредно" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Снимци / Тајмер" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "ФаÑцикла за Ñнимање на пријемнику" 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 "#30056" msgid "TV" msgstr "ТВ" msgctxt "#30057" msgid "Radio" 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 "#30085" msgid "OK" msgstr "У реду" msgctxt "#30095" msgid "True" msgstr "ИÑправно" msgctxt "#30096" msgid "False" msgstr "Ðетачно" msgctxt "#30410" msgid "Automatic" msgstr "ÐутоматÑки" msgctxt "#30430" msgid "Disabled" msgstr "Онемогућено" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Откачен од '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Поново повезан Ñа '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.sr_rs@latin/000077500000000000000000000000001356012415200304615ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.sr_rs@latin/strings.po000066400000000000000000000063111356012415200325130ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Serbian (Latin) (Serbia) (http://www.transifex.com/projects/p/kodi-main/language/sr_RS@latin/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sr_RS@latin\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30003" msgid "Username" msgstr "KorisniÄko ime" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Interval ažuriranja u minutima" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Fascikla za podatke kanala" msgctxt "#30015" msgid "Update interval" msgstr "Interval ažuriranja" msgctxt "#30016" msgid "Check for channel updates" msgstr "Proveri za novije verzije kanala" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Koristi samo trenutnu putanju snimanja DVB kutija" msgctxt "#30018" msgid "General" msgstr "OpÅ¡te" msgctxt "#30019" msgid "Channels" msgstr "Kanali" msgctxt "#30020" msgid "Advanced" msgstr "Napredno" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Snimci / Tajmer" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Fascikla za snimanje na prijemniku" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "U redu" msgctxt "#30095" msgid "True" msgstr "Ispravno" msgctxt "#30096" msgid "False" msgstr "NetaÄno" msgctxt "#30410" msgid "Automatic" msgstr "Automatski" msgctxt "#30430" msgid "Disabled" msgstr "Onemogućeno" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "OtkaÄen od '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Ponovo povezan sa '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.sv_se/000077500000000000000000000000001356012415200273205ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.sv_se/strings.po000066400000000000000000000231771356012415200313630ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Swedish (Sweden) (http://www.transifex.com/projects/p/kodi-main/language/sv_SE/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: sv_SE\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Enigma2 värdnamn eller IP-adress" msgctxt "#30002" msgid "Streaming port" msgstr "Strömningsport" msgctxt "#30003" msgid "Username" msgstr "Användarnamn" msgctxt "#30004" 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 "Uppdateringsintervall" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Uppdateringsintervall i minuter" msgctxt "#30011" msgid "Automatic timerlist cleanup" msgstr "Automatisk upprensning av timerlista" msgctxt "#30012" msgid "Web interface port" msgstr "Port för webbgränssnitt" msgctxt "#30013" msgid "Zap before channelswitch (i.e. for single tuner boxes)" msgstr "Zappa innan kanalbyte (t.ex. för enskilda mottagarboxar)" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Mapp för kanaldata" msgctxt "#30015" msgid "Update interval" msgstr "Uppdateringsintervall" msgctxt "#30016" msgid "Check for channel updates" msgstr "Kontrollera efter kanaluppdateringar" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Använd endast DVB-boxens nuvarande inspelningssökväg" msgctxt "#30018" msgid "General" msgstr "Allmänt" msgctxt "#30019" msgid "Channels" msgstr "Kanaler" msgctxt "#30020" msgid "Advanced" msgstr "Avancerad" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Inspelningar/Timer" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Inspelningsmapp pÃ¥ mottagaren" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "Sänd energisparläge vid avslutande av tillägget" msgctxt "#30025" msgid "TV bouquet fetch mode" msgstr "TV-bukett hämtningsläge" msgctxt "#30026" msgid "TV bouquet" msgstr "TV-bukett" msgctxt "#30027" msgid "Fetch picons from web interface" msgstr "Hämta 'picons' frÃ¥n webbgränssnittet" 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 "#30031" msgid "Seasons and Episodes" msgstr "Säsonger och Avsnitt" msgctxt "#30032" msgid "EPG" msgstr "EPG" msgctxt "#30033" msgid "Extract season, episode and year info where possible" msgstr "Extrahera säsonger, avsnitt och Ã¥rinformation där det är möjligt" msgctxt "#30034" msgid "Enable autotimers" msgstr "Aktivera automatisk timer" msgctxt "#30035" msgid "Use picons.eu file format" msgstr "Använd picons.eu filformat" msgctxt "#30036" msgid "Enable generate repeat timers" msgstr "Aktivera generera repetitionstimer" msgctxt "#30037" msgid "Log missing genre text mappings" msgstr "Logg saknar genre textmappningar" msgctxt "#30038" msgid "Web Interface" msgstr "Webbgränssnitt" msgctxt "#30039" msgid "Streaming" msgstr "Strömning" msgctxt "#30040" msgid "Put outline (e.g. sub-title) before plot" msgstr "Sätt översikt (t.ex. underrubrik) före handling" msgctxt "#30041" msgid "Stream read chunk size" msgstr "Segmentstorlek pÃ¥ strömläsningar" 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 "#30046" msgid "Extract show info file" msgstr "Extrahera show-infofil" msgctxt "#30047" msgid "Rytec genre text Mappings" msgstr "Rytec genre textmappning" msgctxt "#30048" msgid "Enable Rytec genre text mappings" msgstr "Aktivera Rytec genre textmappningar" msgctxt "#30049" msgid "Rytec genre text mappings file" msgstr "Rytec genre textmappningsfil" msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "Anpassad Live-TV-timeout (0 för att använda standard)" msgctxt "#30051" msgid "Login" msgstr "Logga in" msgctxt "#30052" msgid "Misc" msgstr "Övrigt" msgctxt "#30053" msgid "Genre ID Mappings" msgstr "Genre ID-mappningar" msgctxt "#30054" msgid "Enable genre ID Mappings" msgstr "Aktivera genre ID-mappningar" msgctxt "#30055" msgid "Genre ID mappings file" msgstr "Genre ID-mappningsfil" msgctxt "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30058" msgid "Radio bouquet fetch mode" msgstr "Radio bukett hämtningsläge" msgctxt "#30059" msgid "Radio bouquet" msgstr "Radio bukett" msgctxt "#30060" msgid "Timeshift" msgstr "Tidsskifte" msgctxt "#30061" msgid "Enable timeshift" msgstr "Aktivera 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 "#30066" msgid "Use secure HTTP (https) for streams" msgstr "Använd säker HTTP (https) för strömmar" msgctxt "#30067" msgid "Use login for streams" msgstr "Använd inloggning för strömmar" msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "Hämta TV-favoriter bukett" msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "Hämta radio-favoriter bukett" msgctxt "#30070" msgid "Recordings & Timers" msgstr "Inspelningar & Timers" msgctxt "#30071" msgid "Recordings" msgstr "Inspelningar" msgctxt "#30072" msgid "Timers" msgstr "Timers" msgctxt "#30073" msgid "Number of repeat timers to generate" msgstr "Antalet av repetitionstimers att generera" msgctxt "#30074" msgid "All bouquets" msgstr "Alla buketter" msgctxt "#30075" msgid "Only one bouquet" msgstr "Endast en bukett" msgctxt "#30076" msgid "As first bouquet" msgstr "Som första bukett" msgctxt "#30077" msgid "As last bouquet" msgstr "Som sista bukett" msgctxt "#30078" msgid "Favourites group" msgstr "Favoritgrupp" msgctxt "#30079" msgid "Favourites (TV)" msgstr "Favoriter (TV)" msgctxt "#30080" msgid "Favourites (Radio)" msgstr "Favoriter (Radio)" msgctxt "#30081" msgid "unknown" msgstr "okänd" msgctxt "#30082" msgid " (Not connected!)" msgstr "(Ej ansluten!)" msgctxt "#30083" msgid "addon error" msgstr "tilläggsfel" msgctxt "#30084" msgid "Enigma2 Media Server" msgstr "Enigma2 Media Server" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30086" msgid "Backend" msgstr "Backend" msgctxt "#30087" msgid "Recording Padding" msgstr "Inspelningsutfyllnad" msgctxt "#30088" msgid "Global start padding" msgstr "Global startutfyllnad" msgctxt "#30089" msgid "Global end padding" msgstr "Global slututfyllnad" msgctxt "#30090" msgid "Device Info" msgstr "Enhetsinfo" msgctxt "#30091" msgid "WebIf version" msgstr "WebIf version" msgctxt "#30092" msgid "AutoTimer tag in timer tags" msgstr "AutoTimer tagg i timertaggar" msgctxt "#30093" msgid "AutoTimer name in timer tags" msgstr "AutoTimer namn i timertaggar" msgctxt "#30094" msgid "N/A" msgstr "N/A" msgctxt "#30095" msgid "True" msgstr "Sant" msgctxt "#30096" msgid "False" msgstr "Falskt" msgctxt "#30097" msgid "Standby" msgstr "Standby" msgctxt "#30098" msgid "Deep standby" msgstr "Djup standby" msgctxt "#30099" msgid "Wakeup, then standby" msgstr "Väck, sedan standby" msgctxt "#30100" msgid "Update mode" msgstr "Uppdateringsläge" msgctxt "#30101" msgid "Timers and recordings" msgstr "Timers och inspelningar" msgctxt "#30102" msgid "Timers only" msgstr "Endast timer" msgctxt "#30103" msgid "Use OpenWebIf picon path" msgstr "Använd OpenWebIf picon sökväg" 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 "Avaktiverad" msgctxt "#30431" msgid "Record if EPG title differs" msgstr "Spela in om EPG-titeln skiljer sig Ã¥t" 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'" msgstr "FrÃ¥nkopplad frÃ¥n '%s'" 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" msgctxt "#30515" msgid "Enigma2: Could not reach web interface" msgstr "Enigma2: Kunde inte nÃ¥ webbgränssnitt" msgctxt "#30516" msgid "Enigma2: No channel groups found" msgstr "Enigma2: Inga kanalgrupper funna" msgctxt "#30517" msgid "Enigma2: No channels found" msgstr "Enigma2: Inga kanaler funna" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.szl/000077500000000000000000000000001356012415200270115ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.szl/strings.po000066400000000000000000000057661356012415200310600ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Silesian (http://www.transifex.com/projects/p/kodi-main/language/szl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: szl\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30003" msgid "Username" msgstr "Miano ôd używÅcza" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "FrekwyncyjÅ aktualizacyje we minutach" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Folder datÅw kanaÅ‚Åw" msgctxt "#30015" msgid "Update interval" msgstr "InterwaÅ‚ ôdnÅwianiÅ" msgctxt "#30016" msgid "Check for channel updates" msgstr "Wybaduj aktualizacyje kanaÅ‚Åw" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Używej ino terÅźnygo folderu nagrowaniÅ dekodera" msgctxt "#30018" msgid "General" msgstr "GÅ‚ÅwnÅ" msgctxt "#30019" msgid "Channels" msgstr "KanaÅ‚y" msgctxt "#30020" msgid "Advanced" msgstr "Zaawansowane" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Nagrania / Harmonogram" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Folder nagrowaniÅ na dekoderze" 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 "#30056" msgid "TV" msgstr "TelewizyjÅ" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "OK" msgctxt "#30095" msgid "True" msgstr "PrÅwda" msgctxt "#30096" msgid "False" msgstr "FaÅ‚sz" msgctxt "#30410" msgid "Automatic" msgstr "AutÅmat" msgctxt "#30430" msgid "Disabled" msgstr "ZastawiÅne" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Cwajgniynto byÅ‚o ôd '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "ZaÅ› skuplowano byÅ‚o z '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ta_in/000077500000000000000000000000001356012415200272735ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.ta_in/strings.po000066400000000000000000000036771356012415200313410ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Tamil (India) (http://www.transifex.com/projects/p/kodi-main/language/ta_IN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ta_IN\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "பயனரà¯à®ªà¯†à®¯à®°à¯" msgctxt "#30004" msgid "Password" msgstr "அடையாளச௠சொலà¯" msgctxt "#30006" msgid "Icons" msgstr "சினà¯à®©à®™à¯à®•ளà¯" msgctxt "#30015" msgid "Update interval" msgstr "இடைவேளையை மெரà¯à®•ேறà¯à®±à¯" msgctxt "#30018" msgid "General" msgstr "பொதà¯à®µà®¾à®©à®¤à¯" msgctxt "#30019" msgid "Channels" msgstr "சேனலà¯à®•ளà¯" msgctxt "#30020" msgid "Advanced" msgstr "மேமà¯à®ªà®Ÿà¯à®Ÿ" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30042" msgid "Never" msgstr "à®’à®°à¯à®ªà¯‹à®¤à¯à®®à¯ இலà¯à®²à¯ˆ" msgctxt "#30045" msgid "Always" msgstr "எபà¯à®ªà¯‡à®¾à®¤à¯à®®à¯" msgctxt "#30051" msgid "Login" msgstr "பà¯à®•à¯à®ªà®¤à®¿à®•ை" msgctxt "#30056" msgid "TV" msgstr "தொலைகà¯à®•ாடà¯à®šà®¿" msgctxt "#30057" msgid "Radio" msgstr "வானொலி" msgctxt "#30063" msgid "Off" msgstr "நிறà¯à®¤à¯à®¤à¯" msgctxt "#30071" msgid "Recordings" msgstr "பதிவகளà¯" msgctxt "#30085" msgid "OK" msgstr "சரி" msgctxt "#30095" msgid "True" msgstr "உணà¯à®®à¯ˆ" msgctxt "#30096" msgid "False" msgstr "தவறà¯" msgctxt "#30430" msgid "Disabled" msgstr "à®®à¯à®Ÿà®•à¯à®•பà¯à®ªà®Ÿà¯à®Ÿà®©" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.te_in/000077500000000000000000000000001356012415200272775ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.te_in/strings.po000066400000000000000000000020341356012415200313270ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Telugu (India) (http://www.transifex.com/projects/p/kodi-main/language/te_IN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: te_IN\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "వాడà±à°•à°°à°¿ పేరà±" msgctxt "#30004" msgid "Password" msgstr "సంకేతపదం" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "సెకనà±à°²à°²à±‹ à°¸à±à°ªà°‚దన టైమà±à°…à°µà±à°Ÿà±" msgctxt "#30018" msgid "General" msgstr "సాధారణం" msgctxt "#30085" msgid "OK" msgstr "సరే" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.tg_tj/000077500000000000000000000000001356012415200273105ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.tg_tj/strings.po000066400000000000000000000036741356012415200313530ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Tajik (Tajikistan) (http://www.transifex.com/projects/p/kodi-main/language/tg_TJ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: tg_TJ\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgctxt "#30003" msgid "Username" msgstr "Ðоми корбар" msgctxt "#30004" msgid "Password" msgstr "Парол" msgctxt "#30006" msgid "Icons" msgstr "Ðишонаҳо" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Хотимаи вақти поÑух дар ÑониÑҳо" msgctxt "#30018" msgid "General" msgstr "Умумӣ" msgctxt "#30019" msgid "Channels" msgstr "Шабакаҳо" msgctxt "#30020" msgid "Advanced" msgstr "Иловагӣ" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30042" msgid "Never" msgstr "Ҳеҷ гоҳ" msgctxt "#30045" msgid "Always" msgstr "Ҳамеша" msgctxt "#30051" msgid "Login" msgstr "Вуруд" msgctxt "#30056" msgid "TV" msgstr "ТВ" msgctxt "#30057" msgid "Radio" msgstr "Радио" msgctxt "#30063" msgid "Off" msgstr "Хомӯш" msgctxt "#30071" msgid "Recordings" msgstr "Сабтҳо" msgctxt "#30085" msgid "OK" msgstr "OK" msgctxt "#30095" msgid "True" msgstr "Фаъол" msgctxt "#30096" msgid "False" msgstr "Ғайрифаъол" msgctxt "#30430" msgid "Disabled" msgstr "Ғайрифаъол" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "ПайваÑÑ‚ бо '%s' қатъ шудааÑÑ‚" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "ПайваÑÑ‚ бо '%s' барқарор шудааÑÑ‚" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.th_th/000077500000000000000000000000001356012415200273075ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.th_th/strings.po000066400000000000000000000045711356012415200313470ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Thai (Thailand) (http://www.transifex.com/projects/p/kodi-main/language/th_TH/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: th_TH\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30003" msgid "Username" msgstr "ชื่อผู้ใช้" msgctxt "#30004" msgid "Password" msgstr "รหัสผ่าน" msgctxt "#30005" msgid "Connection" msgstr "à¸à¸²à¸£à¹€à¸Šà¸·à¹ˆà¸­à¸¡à¸•่อ" msgctxt "#30006" msgid "Icons" msgstr "ไอคอน" msgctxt "#30015" msgid "Update interval" msgstr "ช่วงเวลาà¸à¸²à¸£à¸›à¸£à¸±à¸šà¸›à¸£à¸¸à¸‡" msgctxt "#30018" msgid "General" msgstr "ทั่วไป" msgctxt "#30019" msgid "Channels" msgstr "ช่องสัà¸à¸à¸²à¸“" msgctxt "#30020" msgid "Advanced" msgstr "ขั้นสูง" 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 "#30056" msgid "TV" msgstr "ทีวี" msgctxt "#30057" msgid "Radio" 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 "#30085" msgid "OK" msgstr "ตà¸à¸¥à¸‡" msgctxt "#30095" msgid "True" msgstr "จริง" msgctxt "#30096" msgid "False" msgstr "ไม่จริง" msgctxt "#30410" msgid "Automatic" msgstr "อัตโนมัติ" msgctxt "#30430" msgid "Disabled" msgstr "ปิดà¸à¸²à¸£à¹ƒà¸Šà¹‰à¸‡à¸²à¸™" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.tr_tr/000077500000000000000000000000001356012415200273335ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.tr_tr/strings.po000066400000000000000000000057661356012415200314020ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Turkish (Turkey) (http://www.transifex.com/projects/p/kodi-main/language/tr_TR/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: tr_TR\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30003" msgid "Username" msgstr "Kullanıcı adı" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Güncelleme aralığı dakikası" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Kanal verisi için klasör" msgctxt "#30015" msgid "Update interval" msgstr "Güncelleme aralığı" msgctxt "#30016" msgid "Check for channel updates" msgstr "Kanal güncellemelerini denetle" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Sadece DVB kutularının geçerli kayıt yolunu kullan" msgctxt "#30018" msgid "General" msgstr "Genel" msgctxt "#30019" msgid "Channels" msgstr "Kanallar" msgctxt "#30020" msgid "Advanced" msgstr "GeliÅŸmiÅŸ" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Kayıtlar / Zamanlayıcılar" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Alıcıdaki kayıt klasörü" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radyo" 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 "#30085" msgid "OK" msgstr "Tamam" msgctxt "#30095" msgid "True" msgstr "DoÄŸru" msgctxt "#30096" msgid "False" msgstr "Yanlış" msgctxt "#30410" msgid "Automatic" msgstr "Otomatik" msgctxt "#30430" msgid "Disabled" msgstr "Devre dışı" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "'%s' BaÄŸlantı kesilecek" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Tekrar baÄŸlanmaya '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.uk_ua/000077500000000000000000000000001356012415200273055ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.uk_ua/strings.po000066400000000000000000000072361356012415200313460ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Ukrainian (Ukraine) (http://www.transifex.com/projects/p/kodi-main/language/uk_UA/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: uk_UA\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" msgctxt "#30003" msgid "Username" msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача" msgctxt "#30004" msgid "Password" msgstr "Пароль" msgctxt "#30005" msgid "Connection" msgstr "Зв’Ñзок" msgctxt "#30006" msgid "Icons" msgstr "Піктограми" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "Затримка відклику в Ñекундах" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "Інтервал Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð² хвилинах" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Тека Ð´Ð»Ñ Ð´Ð°Ð½Ð¸Ñ… каналів" msgctxt "#30015" msgid "Update interval" msgstr "Інтервал оновлень" msgctxt "#30016" msgid "Check for channel updates" msgstr "Перевірка Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ°Ð½Ð°Ð»Ñ–Ð²" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "ВикориÑтовувати тільки поточний шлÑÑ… запиÑу з DVB приÑтрою" msgctxt "#30018" msgid "General" msgstr "Загальні" msgctxt "#30019" msgid "Channels" msgstr "Канали" msgctxt "#30020" msgid "Advanced" msgstr "Більше" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Ð—Ð°Ð¿Ð¸Ñ / Таймер" msgctxt "#30023" msgid "Recording folder on the receiver" 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 "#30056" msgid "TV" msgstr "ТБ" msgctxt "#30057" msgid "Radio" 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 "#30085" msgid "OK" msgstr "ОК" msgctxt "#30094" msgid "N/A" msgstr "Ð/Д" msgctxt "#30095" msgid "True" msgstr "Так" msgctxt "#30096" msgid "False" msgstr "ÐÑ–" msgctxt "#30410" msgid "Automatic" msgstr "Ðвтоматично" msgctxt "#30430" msgid "Disabled" msgstr "Вимкн." msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Від’єднано від '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Знову з’єднано з '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.uz_uz/000077500000000000000000000000001356012415200273555ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.uz_uz/strings.po000066400000000000000000000024221356012415200314060ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Uzbek (Uzbekistan) (http://www.transifex.com/projects/p/kodi-main/language/uz_UZ/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: uz_UZ\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30003" msgid "Username" msgstr "Foydalanuvchi nomi" msgctxt "#30004" msgid "Password" msgstr "Maxfiy so'z" msgctxt "#30006" msgid "Icons" msgstr "Nishonchalar" msgctxt "#30018" msgid "General" msgstr "Umumiy" msgctxt "#30019" msgid "Channels" msgstr "Kanallar" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" msgctxt "#30063" msgid "Off" msgstr "O'chirilgan" msgctxt "#30085" msgid "OK" msgstr "OK" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.vi_vn/000077500000000000000000000000001356012415200273225ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.vi_vn/strings.po000066400000000000000000000050241356012415200313540ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Vietnamese (Viet Nam) (http://www.transifex.com/projects/p/kodi-main/language/vi_VN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: vi_VN\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30003" msgid "Username" msgstr "Tên truy cập" msgctxt "#30004" 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 "#30010" msgid "Update Interval in minutes" msgstr "Số phút tá»± cập nhật lại" msgctxt "#30014" msgid "Folder for channeldata" msgstr "Thư mục đặt dữ liệu cho kênh" msgctxt "#30016" msgid "Check for channel updates" msgstr "Kiểm tra cập nhật kênh" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "Chỉ sá»­ dụng đương dẫn lưu hiện tại cá»§a DVB box" msgctxt "#30018" msgid "General" msgstr "Tổng Quan" msgctxt "#30019" msgid "Channels" msgstr "Kênh" msgctxt "#30020" msgid "Advanced" msgstr "Nâng cao" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "Thu / Hẹn giá»" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "Thư mục lưu trên thiết bị" 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 "#30056" msgid "TV" msgstr "TV" msgctxt "#30057" msgid "Radio" msgstr "Radio" 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 "#30085" msgid "OK" msgstr "OK" msgctxt "#30095" msgid "True" msgstr "Äúng" msgctxt "#30430" msgid "Disabled" msgstr "Äã tắt" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "Äã ngắt kết nối từ '%s'" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "Äã kết nối lại tá»›i '%s'" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.zh_cn/000077500000000000000000000000001356012415200273025ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.zh_cn/strings.po000066400000000000000000000213361356012415200313400ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Chinese (China) (http://www.transifex.com/projects/p/kodi-main/language/zh_CN/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: zh_CN\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30000" msgid "Enigma2 hostname or IP address" msgstr "Enigma2 æœºå™¨åæˆ– IP 地å€" msgctxt "#30002" msgid "Streaming port" msgstr "æµç«¯å£" msgctxt "#30003" msgid "Username" msgstr "用户å" msgctxt "#30004" 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 "Web interface 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 "Update interval" msgstr "æ›´æ–°é—´éš”" msgctxt "#30016" msgid "Check for channel updates" msgstr "æ£€æŸ¥é¢‘é“æ›´æ–°" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "仅使用 DVB 机顶盒的当å‰å½•åƒè·¯å¾„" msgctxt "#30018" msgid "General" msgstr "常用" msgctxt "#30019" msgid "Channels" msgstr "频é“" msgctxt "#30020" msgid "Advanced" msgstr "高级" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "录åƒ/计时器" msgctxt "#30023" msgid "Recording folder on the receiver" msgstr "æŽ¥æ”¶å™¨ä¸Šçš„å½•åƒæ–‡ä»¶å¤¹" msgctxt "#30024" msgid "Send powerstate mode on addon exit" msgstr "在æ’件退出时å‘é€ç”µæºçŠ¶æ€æ¨¡å¼" msgctxt "#30025" msgid "TV bouquet fetch mode" msgstr "电视频é“ç»„èŽ·å–æ¨¡å¼" msgctxt "#30026" msgid "TV bouquet" msgstr "电视频é“组" msgctxt "#30027" msgid "Fetch picons from web interface" 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 "#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 "使用 picons.eu 文件格å¼" msgctxt "#30036" msgid "Enable generate repeat timers" msgstr "å¯ç”¨ç”Ÿæˆé‡å¤å®šæ—¶å™¨" msgctxt "#30037" msgid "Log missing genre text mappings" msgstr "记录缺少的类型文本映射" msgctxt "#30038" msgid "Web Interface" msgstr "Web 界é¢" msgctxt "#30039" msgid "Streaming" 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 "Rytec 类型文本映射" msgctxt "#30048" msgid "Enable Rytec genre text mappings" msgstr "å¯ç”¨ Rytec 类型文本映射" msgctxt "#30049" msgid "Rytec genre text mappings file" msgstr "Rytec 类型文本映射文件" msgctxt "#30050" msgid "Custom live TV timeout (0 to use default)" msgstr "自定义直播电视超时(0为默认值)" msgctxt "#30051" msgid "Login" msgstr "登录" msgctxt "#30052" msgid "Misc" msgstr "æ‚项" msgctxt "#30053" msgid "Genre ID Mappings" msgstr "类型ID映射" msgctxt "#30054" msgid "Enable genre ID Mappings" msgstr "å¯ç”¨ç±»åž‹ID映射" msgctxt "#30055" msgid "Genre ID mappings file" msgstr "类型 ID 映射文件" 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 "为æµä½¿ç”¨å®‰å…¨è¿žæŽ¥ï¼ˆhttps)" msgctxt "#30067" msgid "Use login for streams" msgstr "登录使用æµ" msgctxt "#30068" msgid "Fetch TV favourites bouquet" msgstr "获å–电视收è—列表" msgctxt "#30069" msgid "Fetch radio favourites bouquet" msgstr "获å–ç”µå°æ”¶è—列表" 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 "Enigma2 媒体æœåС噍" msgctxt "#30085" msgid "OK" msgstr "确定" msgctxt "#30086" msgid "Backend" 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 "WebIf 版本" 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 "ä»…é™å®šæ—¶å™¨" 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â€çš„连接" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "釿–°è¿žæŽ¥åˆ°â€œ%sâ€" msgctxt "#30514" msgid "Timeshift buffer path does not exist" msgstr "时光平移缓存路径ä¸å­˜åœ¨" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.zh_tw/000077500000000000000000000000001356012415200273345ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/language/resource.language.zh_tw/strings.po000066400000000000000000000063751356012415200314000ustar00rootroot00000000000000# Kodi Media Center language file # Addon Name: Enigma2 Client # Addon id: pvr.vuplus # Addon Provider: Joerg Dembski and Ross Nicholson msgid "" msgstr "" "Project-Id-Version: KODI Main\n" "Report-Msgid-Bugs-To: https://github.com/xbmc/xbmc/issues/\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Kodi Translation Team\n" "Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/kodi-main/language/zh_TW/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: zh_TW\n" "Plural-Forms: nplurals=1; plural=0;\n" msgctxt "#30003" msgid "Username" msgstr "帳號" msgctxt "#30004" msgid "Password" msgstr "密碼" msgctxt "#30005" msgid "Connection" msgstr "連接" msgctxt "#30006" msgid "Icons" msgstr "圖示" msgctxt "#30007" msgid "Response timeout in seconds" msgstr "回應逾時 (ç§’)" msgctxt "#30010" msgid "Update Interval in minutes" msgstr "更新頻率 (分)" msgctxt "#30014" msgid "Folder for channeldata" msgstr "channeldata的資料夾" msgctxt "#30015" msgid "Update interval" msgstr "æ›´æ–°é–“éš”" msgctxt "#30016" msgid "Check for channel updates" msgstr "æª¢æŸ¥é »é“æ›´æ–°" msgctxt "#30017" msgid "Use only the DVB boxes' current recording path" msgstr "åªä½¿ç”¨DVBæ•¸ä½æ©Ÿä¸Šç›’ç›®å‰çš„錄影路徑" msgctxt "#30018" msgid "General" msgstr "一般設定" msgctxt "#30019" msgid "Channels" msgstr "é »é“" msgctxt "#30020" msgid "Advanced" msgstr "進階" msgctxt "#30021" msgid "HTTP" msgstr "HTTP" msgctxt "#30022" msgid "Recordings / Timer" msgstr "錄影ï¼å®šæ™‚器" msgctxt "#30023" msgid "Recording folder on the receiver" 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 "é›»å­ç¯€ç›®è¡¨" 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 "#30056" msgid "TV" msgstr "電視" msgctxt "#30057" msgid "Radio" 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 "#30085" msgid "OK" msgstr "確定" msgctxt "#30094" msgid "N/A" msgstr "N/A" msgctxt "#30095" msgid "True" msgstr "真實" msgctxt "#30096" msgid "False" msgstr "錯誤" msgctxt "#30410" msgid "Automatic" msgstr "自動" msgctxt "#30430" msgid "Disabled" msgstr "關閉" msgctxt "#30500" msgid "Disconnected from '%s'" msgstr "從 '%s' 斷開連線" msgctxt "#30501" msgid "Reconnected to '%s'" msgstr "從 '%s' 釿–°é€£ç·š" pvr.vuplus-3.28.9-Leia/pvr.vuplus/resources/settings.xml000066400000000000000000001067001356012415200233740ustar00rootroot00000000000000
0 127.0.0.1 0 80 1 1 65535 1 false 1 true 1 true true 2 false 2 8001 1 1 65535 false 2 false false 2 false false 3 30 10 10 60 true 14045 3 10 1 1 60 true 14045 0 false 0 true 1 false true 0 false 1 true true false 657 1 2 1 1 1440 true 14044 1 0 2 2 2 4 0 1 23 1 2 true 17998 0 false 3 true 0 0 0 1 1 1 5 1 0 true 1 0 true 1 1 0 true 1 2 0 true 1 3 0 true 1 4 0 special://userdata/addon_data/pvr.vuplus/channelGroups/customTVGroups-example.xml false false 3 1033 2 0 0 1 3 true 0 0 0 0 1 1 1 5 1 0 true 1 0 true 1 1 0 true 1 2 0 true 1 3 0 true 1 4 0 special://userdata/addon_data/pvr.vuplus/channelGroups/customRadioGroups-example.xml false false 3 1033 2 0 0 1 3 true 0 0 false 0 special://userdata/addon_data/pvr.vuplus/showInfo/English-ShowInfo.xml false false true 1033 2 false 2 special://userdata/addon_data/pvr.vuplus/genres/genreIdMappings/Sky-UK.xml false false true 1033 2 false 2 special://userdata/addon_data/pvr.vuplus/genres/genreRytecTextMappings/Rytec-UK-Ireland.xml false false true 1033 2 false true 2 0 0 250 5000 true 14046 2 true 0 true 0 0 true 2 true 2 false 2 false 0 false 0 0 -10000 500 10000 true true 14046 0 0 -10000 500 10000 true true 14046 1 true 1 1 1 1 10 true 0 false 0 true 2 true true 2 true true true 0 0 0 special://userdata/addon_data/pvr.vuplus true true 0 657 1 0 1 0 3 0 0 1 60 true 14045 3 0 0 4 128 true 14049 1 false 1 false false 1 false false
pvr.vuplus-3.28.9-Leia/src/000077500000000000000000000000001356012415200154175ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/src/Enigma2.cpp000077500000000000000000000562701356012415200174220ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 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 "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 #include #include #include #include #include #include using namespace ADDON; using namespace P8PLATFORM; using namespace enigma2; using namespace enigma2::data; using namespace enigma2::extract; using namespace enigma2::utilities; Enigma2::Enigma2(PVR_PROPERTIES* pvrProps) : m_epgMaxDays(pvrProps->iEpgMaxDays) { m_timers.AddTimerChangeWatcher(&m_dueRecordingUpdate); connectionManager = new ConnectionManager(*this); } Enigma2::~Enigma2() { if (connectionManager) connectionManager->Stop(); delete connectionManager; } /* ************************************************************************** * Connection * *************************************************************************/ void Enigma2::ConnectionLost() { CLockObject lock(m_mutex); Logger::Log(LEVEL_NOTICE, "%s Lost connection with Enigma2 device...", __FUNCTION__); Logger::Log(LEVEL_DEBUG, "%s Stopping update thread...", __FUNCTION__); StopThread(); m_currentChannel = -1; m_isConnected = false; } void Enigma2::ConnectionEstablished() { CLockObject lock(m_mutex); Logger::Log(LEVEL_DEBUG, "%s Removing internal channels and groups lists...", __FUNCTION__); m_channels.ClearChannels(); m_channelGroups.ClearChannelGroups(); Logger::Log(LEVEL_NOTICE, "%s Connection Established with Enigma2 device...", __FUNCTION__); 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; } } 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__); XBMC->QueueNotification(QUEUE_ERROR, LocalizedString(30515).c_str()); return; } 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()) { Logger::Log(LEVEL_ERROR, "%s No channel groups (bouquets) found, please check the addon channel settings, exiting", __FUNCTION__); XBMC->QueueNotification(QUEUE_ERROR, LocalizedString(30516).c_str()); return; } if (!m_channels.LoadChannels(m_channelGroups)) { Logger::Log(LEVEL_ERROR, "%s No channels found, please check the addon channel settings, exiting", __FUNCTION__); XBMC->QueueNotification(QUEUE_ERROR, LocalizedString(30517).c_str()); return; } } m_skipInitialEpgLoad = m_settings.SkipInitialEpgLoad(); m_epg.Initialise(m_channels, m_channelGroups); m_timers.TimerUpdates(); Logger::Log(LEVEL_INFO, "%s Starting separate client update thread...", __FUNCTION__); CreateThread(); } /* ************************************************************************** * Connection * *************************************************************************/ void Enigma2::OnSleep() { connectionManager->OnSleep(); } void Enigma2::OnWake() { connectionManager->OnWake(); } /*************************************************************************** * Device and helpers **************************************************************************/ bool Enigma2::Start() { CLockObject lock(m_mutex); connectionManager->Start(); return true; } void* Enigma2::Process() { Logger::Log(LEVEL_DEBUG, "%s - starting", __FUNCTION__); // Wait for the initial EPG update to complete int totalWaitSecs = 0; while (totalWaitSecs < INITIAL_EPG_WAIT_SECS) { totalWaitSecs += INITIAL_EPG_STEP_SECS; if (!m_epg.IsInitialEpgCompleted()) Sleep(INITIAL_EPG_STEP_SECS * 1000); } m_skipInitialEpgLoad = false; // Whether or not initial EPG updates occurred now Trigger "Real" EPG updates // This will regard Initial EPG as completed anyway. m_epg.TriggerEpgUpdatesForChannels(); unsigned int updateTimer = 0; time_t lastUpdateTimeSeconds = time(nullptr); int lastUpdateHour = m_settings.GetChannelAndGroupUpdateHour(); //ignore if we start during same hour while (!IsStopped() && m_isConnected) { Sleep(PROCESS_LOOP_WAIT_SECS * 1000); time_t currentUpdateTimeSeconds = time(nullptr); std::tm timeInfo = *std::localtime(¤tUpdateTimeSeconds); updateTimer += static_cast(currentUpdateTimeSeconds - lastUpdateTimeSeconds); lastUpdateTimeSeconds = currentUpdateTimeSeconds; if (m_dueRecordingUpdate || updateTimer >= (m_settings.GetUpdateIntervalMins() * 60)) { updateTimer = 0; // Trigger Timer and Recording updates according to the addon settings CLockObject lock(m_mutex); // We need to check this again in case StopThread is called (in destroying Enigma2) during the sleep, otherwise TimerUpdates could be called after the object is released if (!IsStopped() && m_isConnected) { Logger::Log(LEVEL_INFO, "%s Perform Updates!", __FUNCTION__); if (m_settings.GetAutoTimerListCleanupEnabled()) { m_timers.RunAutoTimerListCleanup(); } m_timers.TimerUpdates(); if (m_dueRecordingUpdate || m_settings.GetUpdateMode() == UpdateMode::TIMERS_AND_RECORDINGS) { m_dueRecordingUpdate = false; PVR->TriggerRecordingUpdate(); } } } if (lastUpdateHour != timeInfo.tm_hour && timeInfo.tm_hour == m_settings.GetChannelAndGroupUpdateHour()) { // Trigger Channel and Group updates according to the addon settings CLockObject lock(m_mutex); // We need to check this again in case StopThread is called (in destroying Enigma2) during the sleep, otherwise TimerUpdates could be called after the object is released if (!IsStopped() && m_isConnected) { if (CheckForChannelAndGroupChanges() != ChannelsChangeState::NO_CHANGE && m_settings.GetChannelAndGroupUpdateMode() == ChannelAndGroupUpdateMode::RELOAD_CHANNELS_AND_GROUPS) { ReloadChannelsGroupsAndEPG(); } } } lastUpdateHour = timeInfo.tm_hour; } //CLockObject lock(m_mutex); m_started.Broadcast(); return nullptr; } ChannelsChangeState Enigma2::CheckForChannelAndGroupChanges() { ChannelsChangeState changeType = ChannelsChangeState::NO_CHANGE; if (m_settings.GetChannelAndGroupUpdateMode() != ChannelAndGroupUpdateMode::DISABLED) { Logger::Log(LEVEL_INFO, "%s Checking for Channel and Group Changes!", __FUNCTION__); //Now check for any channel or group changes ChannelGroups latestChannelGroups; Channels latestChannels; // Load the TV channels - close connection if no channels are found if (latestChannelGroups.LoadChannelGroups()) { if (latestChannels.LoadChannels(latestChannelGroups)) { changeType = m_channels.CheckForChannelAndGroupChanges(latestChannelGroups, latestChannels); if (m_settings.GetChannelAndGroupUpdateMode() == ChannelAndGroupUpdateMode::NOTIFY_AND_LOG) { if (changeType == ChannelsChangeState::CHANNEL_GROUPS_CHANGED) { Logger::Log(LEVEL_NOTICE, "%s Channel group (bouquet) changes detected, please restart to load changes", __FUNCTION__); XBMC->QueueNotification(QUEUE_INFO, LocalizedString(30518).c_str()); } else if (changeType == ChannelsChangeState::CHANNELS_CHANGED) { Logger::Log(LEVEL_NOTICE, "%s Channel changes detected, please restart to load changes", __FUNCTION__); XBMC->QueueNotification(QUEUE_INFO, LocalizedString(30519).c_str()); } } else // RELOAD_CHANNELS_AND_GROUPS { if (changeType == ChannelsChangeState::CHANNEL_GROUPS_CHANGED) { Logger::Log(LEVEL_NOTICE, "%s Channel group (bouquet) changes detected, reloading channels, groups and EPG now", __FUNCTION__); XBMC->QueueNotification(QUEUE_INFO, LocalizedString(30521).c_str()); } else if (changeType == ChannelsChangeState::CHANNELS_CHANGED) { Logger::Log(LEVEL_NOTICE, "%s Channel changes detected, reloading channels, groups and EPG now", __FUNCTION__); XBMC->QueueNotification(QUEUE_INFO, LocalizedString(30522).c_str()); } } } } } return changeType; } void Enigma2::ReloadChannelsGroupsAndEPG() { Logger::Log(LEVEL_DEBUG, "%s Removing internal channels list...", __FUNCTION__); m_channels.ClearChannels(); m_channelGroups.ClearChannelGroups(); m_recordings.ClearLocations(); m_recordings.LoadLocations(); m_channelGroups.LoadChannelGroups(); m_channels.LoadChannels(m_channelGroups); PVR->TriggerChannelGroupsUpdate(); PVR->TriggerChannelUpdate(); m_skipInitialEpgLoad = true; m_epg.Initialise(m_channels, m_channelGroups); m_timers.TimerUpdates(); for (const auto& myChannel : m_channels.GetChannelsList()) PVR->TriggerEpgUpdate(myChannel->GetUniqueId()); PVR->TriggerRecordingUpdate(); } void Enigma2::SendPowerstate() { CLockObject lock(m_mutex); m_admin.SendPowerstate(); } const char* Enigma2::GetServerName() const { return m_admin.GetServerName(); } const char* Enigma2::GetServerVersion() const { return m_admin.GetServerVersion(); } 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) { if (m_epg.IsInitialEpgCompleted() && m_settings.GetEPGDelayPerChannelDelay() != 0) Sleep(m_settings.GetEPGDelayPerChannelDelay()); //Have a lock while getting the channel. Then we don't have to worry about a disconnection while retrieving the EPG data. std::shared_ptr myChannel; { CLockObject lock(m_mutex); 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_SERVER_ERROR; } myChannel = m_channels.GetChannel(channel.iUniqueId); } if (m_skipInitialEpgLoad) { Logger::Log(LEVEL_DEBUG, "%s Skipping Initial EPG for channel: %s", __FUNCTION__, myChannel->GetChannelName().c_str()); m_epg.MarkChannelAsInitialEpgRead(myChannel->GetServiceReference()); return PVR_ERROR_NO_ERROR; } return m_epg.GetEPGForChannel(handle, myChannel->GetServiceReference(), iStart, iEnd); } void Enigma2::SetEPGTimeFrame(int epgMaxDays) { m_epg.SetEPGTimeFrame(epgMaxDays); } /*************************************************************************** * 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; m_lastSignalStatusUpdateSeconds = 0; if (m_settings.GetZapBeforeChannelSwitch()) { // Zapping is set to true, so send the zapping command to the PVR box const std::string strServiceReference = m_channels.GetChannel(channelinfo.iUniqueId)->GetServiceReference().c_str(); const std::string strCmd = StringUtils::Format("web/zap?sRef=%s", WebUtils::URLEncodeInline(strServiceReference).c_str()); std::string strResult; if (!WebUtils::SendSimpleCommand(strCmd, strResult, true)) 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(); } bool Enigma2::IsIptvStream(const PVR_CHANNEL& channelinfo) const { return m_channels.GetChannel(channelinfo.iUniqueId)->IsIptvStream(); } int Enigma2::GetChannelStreamProgramNumber(const PVR_CHANNEL& channelinfo) { return m_channels.GetChannel(channelinfo.iUniqueId)->GetStreamProgramNumber(); } /** * 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) { const std::string strM3U = WebUtils::GetHttpXML(strM3uURL); 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(bool deleted) { return m_recordings.GetNumRecordings(deleted); } PVR_ERROR Enigma2::GetRecordings(ADDON_HANDLE handle, bool deleted) { m_recordings.LoadRecordings(deleted); std::vector recordings; { CLockObject lock(m_mutex); m_recordings.GetRecordings(recordings, deleted); } 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); } PVR_ERROR Enigma2::UndeleteRecording(const PVR_RECORDING& recording) { return m_recordings.UndeleteRecording(recording); } PVR_ERROR Enigma2::DeleteAllRecordingsFromTrash() { return m_recordings.DeleteAllRecordingsFromTrash(); } PVR_ERROR Enigma2::GetRecordingEdl(const PVR_RECORDING& recinfo, PVR_EDL_ENTRY edl[], int* size) { std::vector edlEntries; { CLockObject lock(m_mutex); m_recordings.GetRecordingEdl(recinfo.strRecordingId, edlEntries); } Logger::Log(LEVEL_DEBUG, "%s - recording '%s' has '%d' EDL entries available", __FUNCTION__, recinfo.strTitle, edlEntries.size()); int index = 0; int maxSize = *size; for (auto& edlEntry : edlEntries) { if (index >= maxSize) break; edl[index].start = edlEntry.start; edl[index].end = edlEntry.end; edl[index].type = edlEntry.type; index++; } *size = edlEntries.size(); return PVR_ERROR_NO_ERROR; } RecordingReader* Enigma2::OpenRecordedStream(const PVR_RECORDING& recinfo) { CLockObject lock(m_mutex); std::time_t now = std::time(nullptr), start = 0, end = 0; std::string channelName = recinfo.strChannelName; auto timer = m_timers.GetTimer([&](const Timer &timer) { return timer.IsRunning(&now, &channelName, recinfo.recordingTime); }); if (timer) { start = timer->GetRealStartTime(); end = timer->GetRealEndTime(); } return new RecordingReader(m_recordings.GetRecordingURL(recinfo).c_str(), start, end, recinfo.iDuration); } bool Enigma2::HasRecordingStreamProgramNumber(const PVR_RECORDING& recording) { return m_recordings.HasRecordingStreamProgramNumber(recording); } int Enigma2::GetRecordingStreamProgramNumber(const PVR_RECORDING& recording) { return m_recordings.GetRecordingStreamProgramNumber(recording); } PVR_ERROR Enigma2::RenameRecording(const PVR_RECORDING& recording) { CLockObject lock(m_mutex); return m_recordings.RenameRecording(recording); } PVR_ERROR Enigma2::SetRecordingPlayCount(const PVR_RECORDING& recording, int count) { CLockObject lock(m_mutex); return m_recordings.SetRecordingPlayCount(recording, count); } PVR_ERROR Enigma2::SetRecordingLastPlayedPosition(const PVR_RECORDING& recording, int lastPlayedPosition) { CLockObject lock(m_mutex); return m_recordings.SetRecordingLastPlayedPosition(recording, lastPlayedPosition); } int Enigma2::GetRecordingLastPlayedPosition(const PVR_RECORDING& recording) { CLockObject lock(m_mutex); return m_recordings.GetRecordingLastPlayedPosition(recording); } /*************************************************************************** * 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, "%s Transfered %u timer types", __FUNCTION__, *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) { if (m_admin.GetDeviceHasHDD()) return m_admin.GetDriveSpace(iTotal, iUsed, m_locations); return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR Enigma2::GetTunerSignal(PVR_SIGNAL_STATUS& signalStatus) { if (m_currentChannel >= 0) { const std::shared_ptr channel = m_channels.GetChannel(m_currentChannel); strncpy(signalStatus.strServiceName, channel->GetChannelName().c_str(), sizeof(signalStatus.strServiceName) - 1); strncpy(signalStatus.strProviderName, channel->GetProviderName().c_str(), sizeof(signalStatus.strProviderName) - 1); time_t now = time(nullptr); if ((now - m_lastSignalStatusUpdateSeconds) >= POLL_INTERVAL_SECONDS) { Logger::Log(LEVEL_DEBUG, "%s - Calling backend for Signal Status after interval of %d seconds", __FUNCTION__, POLL_INTERVAL_SECONDS); if (!m_admin.GetTunerSignal(m_signalStatus, channel)) { return PVR_ERROR_SERVER_ERROR; } m_lastSignalStatusUpdateSeconds = now; } } signalStatus.iSNR = m_signalStatus.m_snrPercentage; signalStatus.iBER = m_signalStatus.m_ber; signalStatus.iSignal = m_signalStatus.m_signalStrength; strncpy(signalStatus.strAdapterName, m_signalStatus.m_adapterName.c_str(), sizeof(signalStatus.strAdapterName) - 1); strncpy(signalStatus.strAdapterStatus, m_signalStatus.m_adapterStatus.c_str(), sizeof(signalStatus.strAdapterStatus) - 1); return PVR_ERROR_NO_ERROR; }pvr.vuplus-3.28.9-Leia/src/Enigma2.h000066400000000000000000000130041356012415200170500ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "client.h" #include "enigma2/Admin.h" #include "enigma2/ChannelGroups.h" #include "enigma2/Channels.h" #include "enigma2/ConnectionManager.h" #include "enigma2/Epg.h" #include "enigma2/IConnectionListener.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 "enigma2/utilities/SignalStatus.h" #include "p8-platform/threads/threads.h" #include "tinyxml.h" #include #include // The windows build defines this but it breaks nlohmann/json.hpp's reference to std::snprintf #if defined(snprintf) #undef snprintf #endif class Enigma2 : public P8PLATFORM::CThread, public enigma2::IConnectionListener { public: Enigma2(PVR_PROPERTIES* pvrProps); ~Enigma2(); // IConnectionListener implementation void ConnectionLost() override; void ConnectionEstablished() override; void OnSleep(); void OnWake(); //device and helper functions bool Start(); 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); void SetEPGTimeFrame(int epgMaxDays); //live streams, recordings and Timers bool OpenLiveStream(const PVR_CHANNEL& channelinfo); void CloseLiveStream(); const std::string GetLiveStreamURL(const PVR_CHANNEL& channelinfo); bool IsIptvStream(const PVR_CHANNEL& channelinfo) const; int GetChannelStreamProgramNumber(const PVR_CHANNEL& channelinfo); unsigned int GetRecordingsAmount(bool deleted); PVR_ERROR GetRecordings(ADDON_HANDLE handle, bool deleted); PVR_ERROR DeleteRecording(const PVR_RECORDING& recinfo); PVR_ERROR UndeleteRecording(const PVR_RECORDING& recording); PVR_ERROR DeleteAllRecordingsFromTrash(); bool GetRecordingsFromLocation(std::string strRecordingFolder); PVR_ERROR GetRecordingEdl(const PVR_RECORDING& recinfo, PVR_EDL_ENTRY edl[], int* size); PVR_ERROR RenameRecording(const PVR_RECORDING& recording); PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING& recording, int count); PVR_ERROR SetRecordingLastPlayedPosition(const PVR_RECORDING& recording, int lastplayedposition); int GetRecordingLastPlayedPosition(const PVR_RECORDING& recording); bool HasRecordingStreamProgramNumber(const PVR_RECORDING& recording); int GetRecordingStreamProgramNumber(const PVR_RECORDING& recording); 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); PVR_ERROR GetTunerSignal(PVR_SIGNAL_STATUS& signalStatus); protected: void* Process() override; private: static const int INITIAL_EPG_WAIT_SECS = 60; static const int INITIAL_EPG_STEP_SECS = 5; static const int PROCESS_LOOP_WAIT_SECS = 5; // helper functions std::string GetStreamURL(const std::string& strM3uURL); enigma2::ChannelsChangeState CheckForChannelAndGroupChanges(); void ReloadChannelsGroupsAndEPG(); // members bool m_isConnected = false; int m_currentChannel = -1; std::atomic_bool m_dueRecordingUpdate{true}; time_t m_lastSignalStatusUpdateSeconds; bool m_skipInitialEpgLoad; int m_epgMaxDays; mutable enigma2::Channels m_channels; enigma2::ChannelGroups m_channelGroups; enigma2::Recordings m_recordings{m_channels, m_entryExtractor}; std::vector& m_locations = m_recordings.GetLocations(); enigma2::Epg m_epg{m_entryExtractor, m_epgMaxDays}; enigma2::Timers m_timers{m_channels, m_channelGroups, m_locations, m_epg, m_entryExtractor}; enigma2::Settings& m_settings = enigma2::Settings::GetInstance(); enigma2::Admin m_admin; enigma2::extract::EpgEntryExtractor m_entryExtractor; enigma2::utilities::SignalStatus m_signalStatus; enigma2::ConnectionManager* connectionManager; mutable P8PLATFORM::CMutex m_mutex; P8PLATFORM::CCondition m_started; };pvr.vuplus-3.28.9-Leia/src/client.cpp000077500000000000000000000532151356012415200174120ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 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 "client.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 "kodi/xbmc_pvr_dll.h" #include "p8-platform/util/util.h" #include #include using namespace ADDON; 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" { /*************************************************************************** * Addon Calls **************************************************************************/ ADDON_STATUS ADDON_Create(void* hdl, void* props) { if (!hdl || !props) return m_currentStatus; PVR_PROPERTIES* pvrProps = reinterpret_cast(props); XBMC = new CHelper_libXBMC_addon; if (!XBMC->RegisterMe(hdl)) { SAFE_DELETE(XBMC); m_currentStatus = ADDON_STATUS_PERMANENT_FAILURE; return m_currentStatus; } PVR = new CHelper_libXBMC_pvr; if (!PVR->RegisterMe(hdl)) { SAFE_DELETE(PVR); SAFE_DELETE(XBMC); m_currentStatus = ADDON_STATUS_PERMANENT_FAILURE; return m_currentStatus; } 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) { /* Don't log trace messages unless told so */ if (level == LogLevel::LEVEL_TRACE && !Settings::GetInstance().GetTraceDebug()) return; /* 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; } if (addonLevel == addon_log_t::LOG_DEBUG && Settings::GetInstance().GetNoDebug()) return; if (addonLevel == addon_log_t::LOG_DEBUG && Settings::GetInstance().GetDebugNormal()) addonLevel = addon_log_t::LOG_NOTICE; XBMC->Log(addonLevel, "%s", message); }); Logger::GetInstance().SetPrefix("pvr.vuplus"); Logger::Log(LogLevel::LEVEL_INFO, "%s starting PVR client...", __FUNCTION__); settings.ReadFromAddon(); enigma = new Enigma2(pvrProps); enigma->Start(); m_currentStatus = ADDON_STATUS_OK; m_created = true; return m_currentStatus; } ADDON_STATUS ADDON_GetStatus() { return m_currentStatus; } void ADDON_Destroy() { if (m_created) { m_created = false; } if (enigma) { enigma->SendPowerstate(); } SAFE_DELETE(enigma); SAFE_DELETE(PVR); SAFE_DELETE(XBMC); m_currentStatus = ADDON_STATUS_UNKNOWN; } ADDON_STATUS ADDON_SetSetting(const char* settingName, const void* settingValue) { if (!XBMC || !enigma) return ADDON_STATUS_OK; return settings.SetValue(settingName, settingValue); } /*********************************************************** * PVR Client AddOn specific public library functions ***********************************************************/ void OnSystemSleep() { if (!enigma || !enigma->IsConnected()) return; if (enigma) enigma->OnSleep(); } void OnSystemWake() { if (!enigma || !enigma->IsConnected()) return; if (enigma) enigma->OnWake(); } void OnPowerSavingActivated() {} void OnPowerSavingDeactivated() {} PVR_ERROR GetAddonCapabilities(PVR_ADDON_CAPABILITIES* pCapabilities) { pCapabilities->bSupportsEPG = true; pCapabilities->bSupportsEPGEdl = false; pCapabilities->bSupportsTV = true; pCapabilities->bSupportsRadio = true; pCapabilities->bSupportsRecordings = true; pCapabilities->bSupportsRecordingsUndelete = true; pCapabilities->bSupportsTimers = true; pCapabilities->bSupportsChannelGroups = true; pCapabilities->bSupportsChannelScan = false; pCapabilities->bSupportsChannelSettings = false; pCapabilities->bHandlesInputStream = true; pCapabilities->bHandlesDemuxing = false; pCapabilities->bSupportsRecordingPlayCount = settings.SupportsEditingRecordings() && settings.GetStoreRecordingLastPlayedAndCount(); pCapabilities->bSupportsLastPlayedPosition = settings.SupportsEditingRecordings() && settings.GetStoreRecordingLastPlayedAndCount(); pCapabilities->bSupportsRecordingEdl = true; pCapabilities->bSupportsRecordingsRename = settings.SupportsEditingRecordings(); pCapabilities->bSupportsRecordingsLifetimeChange = false; pCapabilities->bSupportsDescrambleInfo = false; pCapabilities->bSupportsAsyncEPGTransfer = false; return PVR_ERROR_NO_ERROR; } const char* GetBackendName(void) { static const char* backendName = enigma ? enigma->GetServerName() : LocalizedString(30081).c_str(); //unknown return backendName; } const char* GetBackendVersion(void) { static const char* backendVersion = enigma ? enigma->GetServerVersion() : LocalizedString(30081).c_str(); //unknown return backendVersion; } static std::string connectionString; const char* GetConnectionString(void) { if (enigma) connectionString = StringUtils::Format("%s%s", settings.GetHostname().c_str(), enigma->IsConnected() ? "" : LocalizedString(30082).c_str()); // (Not connected!) else connectionString = StringUtils::Format("%s (%s!)", settings.GetHostname().c_str(), LocalizedString(30083).c_str()); //addon error return connectionString.c_str(); } const char* GetBackendHostname(void) { return settings.GetHostname().c_str(); } PVR_ERROR GetDriveSpace(long long* iTotal, long long* iUsed) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; return enigma->GetDriveSpace(iTotal, iUsed); } PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS& signalStatus) { // SNR = Signal to Noise Ratio - which means signal quality // AGC = Automatic Gain Control - which means signal strength // BER = Bit Error Rate - which shows the error rate of the signal. // UNC = There is not notion of UNC on enigma devices // So, SNR and AGC should be as high as possible. // BER should be as low as possible, like 0. It can be higher, if your other values are higher. enigma->GetTunerSignal(signalStatus); Logger::Log(LEVEL_DEBUG, "%s Tuner Details - name: %s, status: %s", __FUNCTION__, signalStatus.strAdapterName, signalStatus.strAdapterStatus); Logger::Log(LEVEL_DEBUG, "%s Service Details - service: %s, provider: %s", __FUNCTION__, signalStatus.strServiceName, signalStatus.strProviderName); // For some reason the iSNR and iSignal values need to multiplied by 655! Logger::Log(LEVEL_DEBUG, "%s Signal - snrPercent: %d, ber: %u, signal strength: %d", __FUNCTION__, signalStatus.iSNR / 655, signalStatus.iBER, signalStatus.iSignal / 655); return PVR_ERROR_NO_ERROR; } /*************************************************************************** * ChannelGroups **************************************************************************/ int GetChannelGroupsAmount(void) { if (!enigma || !enigma->IsConnected()) return 0; 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 SetEPGTimeFrame(int epgMaxDays) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; enigma->SetEPGTimeFrame(epgMaxDays); return PVR_ERROR_NO_ERROR; } PVR_ERROR GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL& channel, time_t iStart, time_t iEnd) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; return enigma->GetEPGForChannel(handle, channel, iStart, iEnd); } int GetChannelsAmount(void) { if (!enigma || !enigma->IsConnected()) return 0; return enigma->GetChannelsAmount(); } PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; return enigma->GetChannels(handle, bRadio); } /*************************************************************************** * Live Streams **************************************************************************/ PVR_ERROR GetChannelStreamProperties(const PVR_CHANNEL* channel, PVR_NAMED_VALUE* properties, unsigned int* iPropertiesCount) { if (!settings.SetStreamProgramID() && !enigma->IsIptvStream(*channel)) return PVR_ERROR_NOT_IMPLEMENTED; // // We only use this function to set the program number which comes with every Enigma2 channel. For providers that // use MPTS it allows the FFMPEG Demux to identify the correct Program/PID. // if (!channel || !properties || !iPropertiesCount) return PVR_ERROR_SERVER_ERROR; if (*iPropertiesCount < 1) return PVR_ERROR_INVALID_PARAMETERS; if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; *iPropertiesCount = 0; if (enigma->IsIptvStream(*channel)) { strncpy(properties[0].strName, PVR_STREAM_PROPERTY_STREAMURL, sizeof(properties[0].strName) - 1); strncpy(properties[0].strValue, enigma->GetLiveStreamURL(*channel).c_str(), sizeof(properties[0].strValue) - 1); (*iPropertiesCount)++; } if (settings.SetStreamProgramID()) { const std::string strStreamProgramNumber = std::to_string(enigma->GetChannelStreamProgramNumber(*channel)); Logger::Log(LEVEL_NOTICE, "%s - for channel: %s, set Stream Program Number to %s - %s", __FUNCTION__, channel->strChannelName, strStreamProgramNumber.c_str(), enigma->GetLiveStreamURL(*channel).c_str()); strncpy(properties[0].strName, "program", sizeof(properties[0].strName) - 1); strncpy(properties[0].strValue, strStreamProgramNumber.c_str(), sizeof(properties[0].strValue) - 1); (*iPropertiesCount)++; } return PVR_ERROR_NO_ERROR; } PVR_ERROR GetStreamReadChunkSize(int* chunksize) { 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; } /* 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()); const 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(); } void CloseLiveStream(void) { if (enigma) enigma->CloseLiveStream(); SAFE_DELETE(streamReader); } bool IsRealTimeStream() { return (streamReader) ? streamReader->IsRealTime() : false; } bool CanPauseStream(void) { if (!enigma || !enigma->IsConnected()) return false; if (settings.GetTimeshift() != Timeshift::OFF && streamReader) return (streamReader->IsTimeshifting() || settings.IsTimeshiftBufferPathValid()); return false; } bool CanSeekStream(void) { if (!enigma || !enigma->IsConnected()) return false; return (settings.GetTimeshift() != Timeshift::OFF); } 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) { 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; } else if (recordingReader) { times->startTime = 0; times->ptsStart = 0; times->ptsBegin = 0; times->ptsEnd = static_cast(recordingReader->CurrentDuration()) * DVD_TIME_BASE; return PVR_ERROR_NO_ERROR; } return PVR_ERROR_NOT_IMPLEMENTED; } void PauseStream(bool paused) { if (!enigma || !enigma->IsConnected()) return; /* 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(); } } /*************************************************************************** * Recordings **************************************************************************/ int GetRecordingsAmount(bool deleted) { if (!enigma || !enigma->IsConnected()) return 0; return enigma->GetRecordingsAmount(deleted); } PVR_ERROR GetRecordings(ADDON_HANDLE handle, bool deleted) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; return enigma->GetRecordings(handle, deleted); } PVR_ERROR DeleteRecording(const PVR_RECORDING& recording) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; return enigma->DeleteRecording(recording); } PVR_ERROR UndeleteRecording(const PVR_RECORDING& recording) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; return enigma->UndeleteRecording(recording); } PVR_ERROR DeleteAllRecordingsFromTrash() { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; return enigma->DeleteAllRecordingsFromTrash(); } PVR_ERROR GetRecordingEdl(const PVR_RECORDING& recinfo, PVR_EDL_ENTRY edl[], int* size) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; if (!settings.GetRecordingEDLsEnabled()) { *size = 0; return PVR_ERROR_NO_ERROR; } return enigma->GetRecordingEdl(recinfo, edl, size); } PVR_ERROR RenameRecording(const PVR_RECORDING& recording) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; return enigma->RenameRecording(recording); } PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING& recording, int count) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; return enigma->SetRecordingPlayCount(recording, count); } PVR_ERROR SetRecordingLastPlayedPosition(const PVR_RECORDING& recording, int lastPlayedPosition) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; return enigma->SetRecordingLastPlayedPosition(recording, lastPlayedPosition); } int GetRecordingLastPlayedPosition(const PVR_RECORDING& recording) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; return enigma->GetRecordingLastPlayedPosition(recording); } /*************************************************************************** * Recording Streams **************************************************************************/ PVR_ERROR GetRecordingStreamProperties(const PVR_RECORDING* recording, PVR_NAMED_VALUE* properties, unsigned int* iPropertiesCount) { if (!settings.SetStreamProgramID()) return PVR_ERROR_NOT_IMPLEMENTED; // // We only use this function to set the program number which may comes with every Enigma2 recording. For providers that // use MPTS it allows the FFMPEG Demux to identify the correct Program/PID. // if (!recording || !properties || !iPropertiesCount) return PVR_ERROR_SERVER_ERROR; if (*iPropertiesCount < 1) return PVR_ERROR_INVALID_PARAMETERS; if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; if (enigma->HasRecordingStreamProgramNumber(*recording)) { const std::string strStreamProgramNumber = std::to_string(enigma->GetRecordingStreamProgramNumber(*recording)); Logger::Log(LEVEL_NOTICE, "%s - for recording for channel: %s, set Stream Program Number to %s - %s", __FUNCTION__, recording->strChannelName, strStreamProgramNumber.c_str(), recording->strRecordingId); strncpy(properties[0].strName, "program", sizeof(properties[0].strName) - 1); strncpy(properties[0].strValue, strStreamProgramNumber.c_str(), sizeof(properties[0].strValue) - 1); *iPropertiesCount = 1; } return PVR_ERROR_NO_ERROR; } bool OpenRecordedStream(const PVR_RECORDING& recording) { if (recordingReader) SAFE_DELETE(recordingReader); if (!enigma || !enigma->IsConnected()) return false; recordingReader = enigma->OpenRecordedStream(recording); return recordingReader->Start(); } void CloseRecordedStream(void) { if (recordingReader) SAFE_DELETE(recordingReader); } int ReadRecordedStream(unsigned char* buffer, unsigned int size) { if (!recordingReader) return 0; return recordingReader->ReadData(buffer, size); } long long SeekRecordedStream(long long position, int whence) { if (!recordingReader) return 0; return recordingReader->Seek(position, whence); } long long LengthRecordedStream(void) { if (!recordingReader) return -1; return recordingReader->Length(); } /*************************************************************************** * 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; } int GetTimersAmount(void) { if (!enigma || !enigma->IsConnected()) return 0; return enigma->GetTimersAmount(); } PVR_ERROR GetTimers(ADDON_HANDLE handle) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; return enigma->GetTimers(handle); } PVR_ERROR AddTimer(const PVR_TIMER& timer) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; return enigma->AddTimer(timer); } PVR_ERROR DeleteTimer(const PVR_TIMER& timer, bool bForceDelete) { if (!enigma || !enigma->IsConnected()) return PVR_ERROR_SERVER_ERROR; return enigma->DeleteTimer(timer); } 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 GetStreamProperties(PVR_STREAM_PROPERTIES* pProperties) { return PVR_ERROR_NOT_IMPLEMENTED; } void DemuxAbort(void) { return; } 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 OpenDialogChannelSettings(const PVR_CHANNEL& channel) { return PVR_ERROR_NOT_IMPLEMENTED; } PVR_ERROR OpenDialogChannelAdd(const PVR_CHANNEL& channel) { return PVR_ERROR_NOT_IMPLEMENTED; } void DemuxReset(void) {} void DemuxFlush(void) {} bool SeekTime(double, bool, double*) { return false; } void SetSpeed(int){}; 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; } } pvr.vuplus-3.28.9-Leia/src/client.h000066400000000000000000000017521356012415200170530ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "kodi/libXBMC_addon.h" #include "kodi/libXBMC_pvr.h" extern ADDON::CHelper_libXBMC_addon* XBMC; extern CHelper_libXBMC_pvr* PVR;pvr.vuplus-3.28.9-Leia/src/enigma2/000077500000000000000000000000001356012415200167415ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/src/enigma2/Admin.cpp000066400000000000000000000603101356012415200204750ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "Admin.h" #include "../Enigma2.h" #include "../client.h" #include "p8-platform/util/StringUtils.h" #include "util/XMLUtils.h" #include "utilities/FileUtils.h" #include "utilities/LocalizedString.h" #include "utilities/Logger.h" #include "utilities/WebUtils.h" #include #include #include using namespace enigma2; using namespace enigma2::data; using namespace enigma2::extract; using namespace enigma2::utilities; using json = nlohmann::json; Admin::Admin() : m_addonVersion(STR(VUPLUS_VERSION)) { m_serverName[0] = '\0'; m_serverVersion[0] = '\0'; }; void Admin::SendPowerstate() { if (Settings::GetInstance().GetPowerstateModeOnAddonExit() != PowerstateMode::DISABLED) { if (Settings::GetInstance().GetPowerstateModeOnAddonExit() == PowerstateMode::WAKEUP_THEN_STANDBY) { const std::string strCmd = StringUtils::Format("web/powerstate?newstate=4"); //Wakeup std::string strResult; WebUtils::SendSimpleCommand(strCmd, strResult, true); } if (Settings::GetInstance().GetPowerstateModeOnAddonExit() == PowerstateMode::STANDBY || Settings::GetInstance().GetPowerstateModeOnAddonExit() == PowerstateMode::WAKEUP_THEN_STANDBY) { const std::string strCmd = StringUtils::Format("web/powerstate?newstate=5"); //Standby std::string strResult; WebUtils::SendSimpleCommand(strCmd, strResult, true); } if (Settings::GetInstance().GetPowerstateModeOnAddonExit() == PowerstateMode::DEEP_STANDBY) { const std::string strCmd = StringUtils::Format("web/powerstate?newstate=1"); //Deep Standby std::string strResult; WebUtils::SendSimpleCommand(strCmd, strResult, true); } } } bool Admin::Initialise() { std::string unknown = LocalizedString(30081).c_str(); SetCharString(m_serverName, unknown); SetCharString(m_serverVersion, unknown); Settings::GetInstance().SetAdmin(this); bool deviceInfoLoaded = LoadDeviceInfo(); if (deviceInfoLoaded) { Settings::GetInstance().SetDeviceInfo(&m_deviceInfo); bool deviceSettingsLoaded = LoadDeviceSettings(); Settings::GetInstance().SetDeviceSettings(&m_deviceSettings); if (deviceSettingsLoaded) { //If OpenWebVersion is new enough to allow the setting of AutoTimer setttings if (Settings::GetInstance().SupportsAutoTimers()) 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_ERROR, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } std::string enigmaVersion; std::string imageVersion; std::string distroName; std::string webIfVersion; std::string deviceName = "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 distroName if (!XMLUtils::GetString(pElem, "e2distroversion", strTmp)) { Logger::Log(LEVEL_NOTICE, "%s Could not parse e2distroversion from result, continuing as not available in all images!", __FUNCTION__); strTmp = LocalizedString(30081); //unknown } else { distroName = strTmp.c_str(); } Logger::Log(LEVEL_NOTICE, "%s - E2DistroName: %s", __FUNCTION__, distroName.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; } deviceName = strTmp.c_str(); Logger::Log(LEVEL_NOTICE, "%s - E2DeviceName: %s", __FUNCTION__, deviceName.c_str()); m_deviceInfo = DeviceInfo(deviceName, enigmaVersion, imageVersion, distroName, webIfVersion, webIfVersionAsNum); std::string version = webIfVersion + " - " + distroName + " (" + imageVersion + "/" + enigmaVersion + ")"; SetCharString(m_serverName, deviceName); SetCharString(m_serverVersion, version); Logger::Log(LEVEL_NOTICE, "%s - ServerVersion: %s", __FUNCTION__, m_serverVersion); Logger::Log(LEVEL_NOTICE, "%s - AddonVersion: %s", __FUNCTION__, m_addonVersion.c_str()); hRoot = TiXmlHandle(pElem); TiXmlElement* pNode = hRoot.FirstChildElement("e2frontends").Element(); if (pNode) { TiXmlElement* tunerNode = pNode->FirstChildElement("e2frontend"); if (tunerNode) { int tunerNumber = 0; for (; tunerNode != nullptr; tunerNode = tunerNode->NextSiblingElement("e2frontend")) { std::string tunerName; std::string tunerModel; XMLUtils::GetString(tunerNode, "e2name", tunerName); XMLUtils::GetString(tunerNode, "e2model", tunerModel); m_tuners.emplace_back(Tuner(tunerNumber, tunerName, tunerModel)); Logger::Log(LEVEL_DEBUG, "%s Tuner Info Loaded - Tuner Number: %d, Tuner Name:%s Tuner Model: %s", __FUNCTION__, tunerNumber, tunerName.c_str(), tunerModel.c_str()); tunerNumber++; } } else { Logger::Log(LEVEL_DEBUG, "%s Could not find element", __FUNCTION__); } } else { Logger::Log(LEVEL_DEBUG, "%s Could not find element", __FUNCTION__); } return true; } unsigned int Admin::ParseWebIfVersion(const std::string& webIfVersion) { unsigned int webIfVersionAsNum = 0; std::regex regex("^.*[0-9]+\\.[0-9]+\\.[0-9].*$"); if (std::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 = std::atoi(i->str().c_str()); webIfVersionAsNum = versionPart << 16; break; case 1: versionPart = std::atoi(i->str().c_str()); webIfVersionAsNum |= versionPart << 8; break; case 2: versionPart = std::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()); 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().SupportsAutoTimers()) { if (LoadAutoTimerSettings()) { 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_ERROR, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem = hDoc.FirstChildElement("e2settings").Element(); if (!pElem) { Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); return false; } TiXmlHandle hRoot = TiXmlHandle(pElem); TiXmlElement* pNode = hRoot.FirstChildElement("e2setting").Element(); if (!pNode) { Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); 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, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem = hDoc.FirstChildElement("e2settings").Element(); if (!pElem) { Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); return false; } TiXmlHandle hRoot = TiXmlHandle(pElem); TiXmlElement* pNode = hRoot.FirstChildElement("e2setting").Element(); if (!pNode) { Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); 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(std::atoi(settingValue.c_str())); readMarginBefore = true; } else if (settingName == "config.recording.margin_after") { m_deviceSettings.SetGlobalRecordingEndMargin(std::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__); const 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); const 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); const 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_ERROR, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return PVR_ERROR_SERVER_ERROR; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem = hDoc.FirstChildElement("e2deviceinfo").Element(); if (!pElem) { Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); return PVR_ERROR_SERVER_ERROR; } TiXmlHandle hRoot = TiXmlHandle(pElem); TiXmlElement* pNode = hRoot.FirstChildElement("e2hdds").Element(); if (!pNode) { Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); return PVR_ERROR_SERVER_ERROR; } TiXmlElement* hddNode = pNode->FirstChildElement("e2hdd"); if (!hddNode) { m_deviceHasHDD = false; Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); 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, "%s Space Total: %lld, Used %lld", __FUNCTION__, *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 (std::regex_match(stringInMbGbTb, regexSize)) { double sizeValue = std::atof(std::regex_replace(stringInMbGbTb, regexReplaceSize, replaceWith).c_str()); sizeInKb += static_cast(sizeValue * multiplier); break; } multiplier = multiplier * 1024; } return sizeInKb; } bool Admin::GetTunerSignal(SignalStatus& signalStatus, const std::shared_ptr& channel) { const std::string url = StringUtils::Format("%s%s", Settings::GetInstance().GetConnectionURL().c_str(), "web/signal"); const std::string strXML = WebUtils::GetHttpXML(url); TiXmlDocument xmlDoc; if (!xmlDoc.Parse(strXML.c_str())) { Logger::Log(LEVEL_ERROR, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } std::string snrDb; std::string snrPercentage; std::string ber; std::string signalStrength; TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem = hDoc.FirstChildElement("e2frontendstatus").Element(); if (!pElem) { Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); return false; } if (!XMLUtils::GetString(pElem, "e2snrdb", snrDb)) { Logger::Log(LEVEL_ERROR, "%s Could not parse e2snrdb from result!", __FUNCTION__); return false; } if (!XMLUtils::GetString(pElem, "e2snr", snrPercentage)) { Logger::Log(LEVEL_ERROR, "%s Could not parse e2snr from result!", __FUNCTION__); return false; } if (!XMLUtils::GetString(pElem, "e2ber", ber)) { Logger::Log(LEVEL_ERROR, "%s Could not parse e2ber from result!", __FUNCTION__); return false; } if (!XMLUtils::GetString(pElem, "e2acg", signalStrength)) { Logger::Log(LEVEL_ERROR, "%s Could not parse e2acg from result!", __FUNCTION__); return false; } std::regex regexReplacePercent(" %"); std::string regexReplace = ""; // For some reason the iSNR and iSignal values need to multiplied by 655! signalStatus.m_snrPercentage = std::atoi(std::regex_replace(snrPercentage, regexReplacePercent, regexReplace).c_str()) * 655; signalStatus.m_ber = std::atol(ber.c_str()); signalStatus.m_signalStrength = std::atoi(std::regex_replace(signalStrength, regexReplacePercent, regexReplace).c_str()) * 655; if (Settings::GetInstance().SupportsTunerDetails()) { //TODO: Cross reference against tuners once OpenWebIf API is updated. //StreamStatus streamStatus = GetStreamDetails(channel); GetTunerDetails(signalStatus, channel); } return true; } StreamStatus Admin::GetStreamDetails(const std::shared_ptr& channel) { StreamStatus streamStatus; const std::string jsonUrl = StringUtils::Format("%s%s", Settings::GetInstance().GetConnectionURL().c_str(), "api/deviceinfo"); const std::string strJson = WebUtils::GetHttpXML(jsonUrl); try { auto jsonDoc = json::parse(strJson); if (!jsonDoc["streams"].empty()) { for (const auto& it : jsonDoc["streams"].items()) { auto jsonStream = it.value(); if (jsonStream["ref"].get() == channel->GetGenericServiceReference() && !jsonStream["ip"].get().empty()) //TODO: Find out Kodi IP and compare { streamStatus.m_ipAddress = jsonStream["ip"].get(); streamStatus.m_serviceReference = channel->GetServiceReference(); streamStatus.m_channelName = channel->GetChannelName(); //Use our channel name as from JSON is unreliable if (jsonStream["type"].get() == "S") streamStatus.m_streamType = StreamType::DIRECTLY_STREAMED; else streamStatus.m_streamType = StreamType::TRANSCODED; break; } Logger::Log(LEVEL_DEBUG, "%s Active Stream IP: %s, ref: %s, name: %s", __FUNCTION__, jsonStream["ip"].get().c_str(), jsonStream["ref"].get().c_str(), jsonStream["name"].get().c_str()); } } if (!streamStatus.m_channelName.empty()) { if (!jsonDoc["tuners"].empty()) { int tunerNumber = 0; for (const auto& it : jsonDoc["tuners"].items()) { auto jsonTuner = it.value(); if (jsonTuner["name"].get() == streamStatus.m_channelName) { //TODO: Complete once API is available break; } tunerNumber++; } } } } catch (nlohmann::detail::parse_error& e) { Logger::Log(LEVEL_ERROR, "%s Invalid JSON received, cannot load extra stream details from OpenWebIf - JSON parse error - message: %s, exception id: %d", __FUNCTION__, e.what(), e.id); } catch (nlohmann::detail::type_error& e) { Logger::Log(LEVEL_ERROR, "%s JSON type error - message: %s, exception id: %d", __FUNCTION__, e.what(), e.id); } return streamStatus; } void Admin::GetTunerDetails(SignalStatus& signalStatus, const std::shared_ptr& channel) { const std::string jsonUrl = StringUtils::Format("%s%s", Settings::GetInstance().GetConnectionURL().c_str(), "api/tunersignal"); const std::string strJson = WebUtils::GetHttpXML(jsonUrl); try { auto jsonDoc = json::parse(strJson); for (const auto& element : jsonDoc.items()) { if (element.key() == "tunernumber") { Logger::Log(LEVEL_DEBUG, "%s Json API - %s : %d", __FUNCTION__, element.key().c_str(), element.value().get()); int tunerNumber = element.value().get(); if (m_tuners.size() > tunerNumber) { Tuner& tuner = m_tuners.at(tunerNumber); signalStatus.m_adapterName = tuner.m_tunerName + " - " + tuner.m_tunerModel; } } else if (element.key() == "tunertype") { Logger::Log(LEVEL_DEBUG, "%s Json API - %s : %s", __FUNCTION__, element.key().c_str(), element.value().get().c_str()); signalStatus.m_adapterStatus = element.value().get(); } } } catch (nlohmann::detail::parse_error& e) { Logger::Log(LEVEL_ERROR, "%s Invalid JSON received, cannot load extra tuner details from OpenWebIf - JSON parse error - message: %s, exception id: %d", __FUNCTION__, e.what(), e.id); } catch (nlohmann::detail::type_error& e) { Logger::Log(LEVEL_ERROR, "%s JSON type error - message: %s, exception id: %d", __FUNCTION__, e.what(), e.id); } } void Admin::SetCharString(char* target, const std::string value) { std::copy(value.begin(), value.end(), target); target[value.size()] = '\0'; } pvr.vuplus-3.28.9-Leia/src/enigma2/Admin.h000066400000000000000000000064511356012415200201500ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "data/Channel.h" #include "utilities/DeviceInfo.h" #include "utilities/DeviceSettings.h" #include "utilities/SignalStatus.h" #include "utilities/StreamStatus.h" #include "utilities/Tuner.h" #include "kodi/libXBMC_pvr.h" #include #include namespace enigma2 { class Admin { public: Admin(); 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 char* GetServerName() const { return m_serverName; } const char* GetServerVersion() const { return m_serverVersion; } const std::string& GetDeviceName() const { return m_deviceInfo.GetServerName(); } const std::string& GetDistroName() const { return m_deviceInfo.GetDistroName(); } 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(); } const std::string& GetAddonVersion() const { return m_addonVersion; } bool GetTunerSignal(utilities::SignalStatus& signalStatus, const std::shared_ptr& channel); bool GetDeviceHasHDD() const { return m_deviceHasHDD; }; private: static void SetCharString(char* target, const std::string value); bool LoadDeviceInfo(); bool LoadAutoTimerSettings(); bool LoadRecordingMarginSettings(); unsigned int ParseWebIfVersion(const std::string& webIfVersion); long long GetKbFromString(const std::string& stringInMbGbTb) const; utilities::StreamStatus GetStreamDetails(const std::shared_ptr& channel); void GetTunerDetails(utilities::SignalStatus& signalStatus, const std::shared_ptr& channel); char m_serverName[256]; char m_serverVersion[256]; bool m_deviceHasHDD = true; const std::string m_addonVersion; enigma2::utilities::DeviceInfo m_deviceInfo; enigma2::utilities::DeviceSettings m_deviceSettings; std::vector m_tuners; }; } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/ChannelGroups.cpp000066400000000000000000000360431356012415200222230ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "ChannelGroups.h" #include "../Enigma2.h" #include "../client.h" #include "p8-platform/util/StringUtils.h" #include "util/XMLUtils.h" #include "utilities/FileUtils.h" #include "utilities/LocalizedString.h" #include "utilities/Logger.h" #include "utilities/WebUtils.h" #include #include using namespace enigma2; using namespace enigma2::data; using namespace enigma2::utilities; using json = nlohmann::json; void ChannelGroups::GetChannelGroups(std::vector& kodiChannelGroups, bool radio) const { Logger::Log(LEVEL_DEBUG, "%s - Starting to get ChannelGroups for PVR", __FUNCTION__); 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 && !channelGroup->IsEmptyGroup()) { PVR_CHANNEL_GROUP kodiChannelGroup = {0}; channelGroup->UpdateTo(kodiChannelGroup); kodiChannelGroups.emplace_back(kodiChannelGroup); } } Logger::Log(LEVEL_DEBUG, "%s - Finished getting ChannelGroups for PVR", __FUNCTION__); } PVR_ERROR ChannelGroups::GetChannelGroupMembers(std::vector& channelGroupMembers, const std::string& groupName) { std::shared_ptr channelGroup = GetChannelGroupUsingName(groupName); if (!channelGroup) { Logger::Log(LEVEL_NOTICE, "%s - Channel Group not found, could not get ChannelGroupsMembers for PVR for group: %s", __FUNCTION__, groupName.c_str()); return PVR_ERROR_NO_ERROR; } else { Logger::Log(LEVEL_DEBUG, "%s - Starting to get ChannelGroupsMembers for PVR for group: %s", __FUNCTION__, groupName.c_str()); } int channelNumberInGroup = 1; for (const auto& channel : channelGroup->GetChannelList()) { PVR_CHANNEL_GROUP_MEMBER tag = {0}; strncpy(tag.strGroupName, groupName.c_str(), sizeof(tag.strGroupName) - 1); tag.iChannelUniqueId = channel->GetUniqueId(); tag.iChannelNumber = channelNumberInGroup; //Keep the channels in list order as per the groups on the STB 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); channelNumberInGroup++; } Logger::Log(LEVEL_DEBUG, "%s - Finished getting ChannelGroupsMembers for PVR for group: %s", __FUNCTION__, groupName.c_str()); return PVR_ERROR_NO_ERROR; } 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(const std::string& groupServiceReference) { const auto channelGroupPair = m_channelGroupsServiceReferenceMap.find(groupServiceReference); if (channelGroupPair != m_channelGroupsServiceReferenceMap.end()) return channelGroupPair->second; return {}; } std::shared_ptr ChannelGroups::GetChannelGroupUsingName(const std::string& groupName) { std::shared_ptr channelGroup; auto channelGroupPair = m_channelGroupsNameMap.find(groupName); if (channelGroupPair != m_channelGroupsNameMap.end()) { channelGroup = channelGroupPair->second; } return channelGroup; } bool ChannelGroups::IsValid(std::string groupName) { return GetChannelGroupUsingName(groupName) != nullptr; } int ChannelGroups::GetNumChannelGroups() const { return m_channelGroups.size(); } void ChannelGroups::ClearChannelGroups() { m_channelGroups.clear(); m_channelGroupsNameMap.clear(); m_channelGroupsServiceReferenceMap.clear(); Settings::GetInstance().SetUsesLastScannedChannelGroup(false); } void ChannelGroups::AddChannelGroup(ChannelGroup& newChannelGroup) { std::shared_ptr foundChannelGroup = GetChannelGroupUsingName(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}); m_channelGroupsServiceReferenceMap.insert({channelGroup->GetServiceReference(), channelGroup}); } } std::vector>& ChannelGroups::GetChannelGroupsList() { return m_channelGroups; } bool ChannelGroups::LoadChannelGroups() { ClearChannelGroups(); bool successful = LoadTVChannelGroups(); if (successful) LoadRadioChannelGroups(); return successful; } bool ChannelGroups::LoadTVChannelGroups() { int tempNumChannelGroups = m_channelGroups.size(); 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) { const std::string strTmp = StringUtils::Format("%sweb/getservices", Settings::GetInstance().GetConnectionURL().c_str()); const std::string strXML = WebUtils::GetHttpXML(strTmp); TiXmlDocument xmlDoc; if (!xmlDoc.Parse(strXML.c_str())) { Logger::Log(LEVEL_ERROR, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem = hDoc.FirstChildElement("e2servicelist").Element(); if (!pElem) { Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); return false; } TiXmlHandle hRoot = TiXmlHandle(pElem); TiXmlElement* pNode = hRoot.FirstChildElement("e2service").Element(); if (!pNode) { Logger::Log(LEVEL_ERROR, "%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()); } } LoadChannelGroupsStartPosition(false); if (Settings::GetInstance().GetTVFavouritesMode() == FavouritesGroupMode::AS_LAST_GROUP && Settings::GetInstance().GetTVChannelGroupMode() != ChannelGroupMode::FAVOURITES_GROUP) { AddTVFavouritesChannelGroup(); } if ((!Settings::GetInstance().ExcludeLastScannedTVGroup() && Settings::GetInstance().GetTVChannelGroupMode() == ChannelGroupMode::ALL_GROUPS) || m_channelGroups.empty()) //If there are no channel groups default to including the last scanned group for TV Only AddTVLastScannedChannelGroup(); Logger::Log(LEVEL_INFO, "%s Loaded %d TV Channelgroups", __FUNCTION__, m_channelGroups.size() - tempNumChannelGroups); return true; } bool ChannelGroups::LoadRadioChannelGroups() { int tempNumChannelGroups = m_channelGroups.size(); 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) { const std::string strTmp = StringUtils::Format("%sweb/getservices?sRef=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline("1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"bouquets.radio\" ORDER BY bouquet").c_str()); const std::string strXML = WebUtils::GetHttpXML(strTmp); TiXmlDocument xmlDoc; if (!xmlDoc.Parse(strXML.c_str())) { Logger::Log(LEVEL_ERROR, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem = hDoc.FirstChildElement("e2servicelist").Element(); if (!pElem) { Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); return false; } TiXmlHandle hRoot = TiXmlHandle(pElem); TiXmlElement* pNode = hRoot.FirstChildElement("e2service").Element(); if (!pNode) { Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); return false; } for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2service")) { ChannelGroup newChannelGroup; if (!newChannelGroup.UpdateFrom(pNode, true)) continue; AddChannelGroup(newChannelGroup); Logger::Log(LEVEL_INFO, "%s Loaded channelgroup: %s", __FUNCTION__, newChannelGroup.GetGroupName().c_str()); } } LoadChannelGroupsStartPosition(true); if (Settings::GetInstance().GetRadioFavouritesMode() == FavouritesGroupMode::AS_LAST_GROUP && Settings::GetInstance().GetRadioChannelGroupMode() != ChannelGroupMode::FAVOURITES_GROUP) { AddRadioFavouritesChannelGroup(); } if (!Settings::GetInstance().ExcludeLastScannedRadioGroup() && Settings::GetInstance().GetRadioChannelGroupMode() == ChannelGroupMode::ALL_GROUPS) AddRadioLastScannedChannelGroup(); Logger::Log(LEVEL_INFO, "%s Loaded %d Radio Channelgroups", __FUNCTION__, m_channelGroups.size() - tempNumChannelGroups); 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()); } void ChannelGroups::AddTVLastScannedChannelGroup() { ChannelGroup newChannelGroup; newChannelGroup.SetRadio(false); newChannelGroup.SetGroupName(LocalizedString(30112)); //Last Scanned (TV) newChannelGroup.SetServiceReference("1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"userbouquet.LastScanned.tv\" ORDER BY bouquet"); newChannelGroup.SetLastScannedGroup(true); AddChannelGroup(newChannelGroup); Settings::GetInstance().SetUsesLastScannedChannelGroup(true); Logger::Log(LEVEL_INFO, "%s Loaded channelgroup: %s", __FUNCTION__, newChannelGroup.GetGroupName().c_str()); } void ChannelGroups::AddRadioLastScannedChannelGroup() { ChannelGroup newChannelGroup; newChannelGroup.SetRadio(true); newChannelGroup.SetGroupName(LocalizedString(30113)); //Last Scanned (Radio) //Hack used here, extra space in service reference so we can spearate TV and Radio, it must be unique newChannelGroup.SetServiceReference("1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"userbouquet.LastScanned.tv\" ORDER BY bouquet"); newChannelGroup.SetLastScannedGroup(true); AddChannelGroup(newChannelGroup); Settings::GetInstance().SetUsesLastScannedChannelGroup(true); Logger::Log(LEVEL_INFO, "%s Loaded channelgroup: %s", __FUNCTION__, newChannelGroup.GetGroupName().c_str()); } void ChannelGroups::LoadChannelGroupsStartPosition(bool radio) { if (Settings::GetInstance().SupportsChannelNumberGroupStartPos()) { //We can use the JSON API so let's supplement the existing groups with start channel numbers std::string jsonURL; if (!radio) { Logger::Log(LEVEL_INFO, "%s loading channel group start channel number for all TV groups", __FUNCTION__); jsonURL = StringUtils::Format("%sapi/getservices", Settings::GetInstance().GetConnectionURL().c_str()); } else { Logger::Log(LEVEL_INFO, "%s loading channel group start channel number for all Radio groups", __FUNCTION__); jsonURL = StringUtils::Format("%sapi/getservices?sRef=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline("1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"bouquets.radio\" ORDER BY bouquet").c_str()); } const std::string strJson = WebUtils::GetHttpXML(jsonURL); try { auto jsonDoc = json::parse(strJson); if (!jsonDoc["services"].empty()) { for (const auto& it : jsonDoc["services"].items()) { auto jsonGroup = it.value(); std::string serviceReference = jsonGroup["servicereference"].get(); // Check whether the current element is not just a label or that it's not a hidden entry if (serviceReference.compare(0, 5, "1:64:") == 0 || serviceReference.compare(0, 6, "1:320:") == 0) continue; auto group = GetChannelGroup(serviceReference); if (group) { if (!jsonGroup["startpos"].empty()) { Logger::Log(LEVEL_DEBUG, "%s For Group %s, set start pos for channel number is %d", __FUNCTION__, jsonGroup["servicename"].get().c_str(), jsonGroup["startpos"].get()); group->SetStartChannelNumber(jsonGroup["startpos"].get()); } } } } } catch (nlohmann::detail::parse_error& e) { Logger::Log(LEVEL_ERROR, "%s Invalid JSON received, cannot load start channel number for group from OpenWebIf - JSON parse error - message: %s, exception id: %d", __FUNCTION__, e.what(), e.id); } catch (nlohmann::detail::type_error& e) { Logger::Log(LEVEL_ERROR, "%s JSON type error - message: %s, exception id: %d", __FUNCTION__, e.what(), e.id); } } } pvr.vuplus-3.28.9-Leia/src/enigma2/ChannelGroups.h000066400000000000000000000047321356012415200216700ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "data/Channel.h" #include "data/ChannelGroup.h" #include "kodi/libXBMC_pvr.h" #include #include #include #include namespace enigma2 { class ChannelGroups { public: void GetChannelGroups(std::vector& channelGroups, bool radio) const; PVR_ERROR GetChannelGroupMembers(std::vector& channelGroupMembers, const std::string& groupName); std::string GetChannelGroupServiceReference(const std::string& groupName); std::shared_ptr GetChannelGroup(const std::string& groupServiceReference); std::shared_ptr GetChannelGroupUsingName(const std::string& groupName); 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 AddTVLastScannedChannelGroup(); void AddRadioLastScannedChannelGroup(); void AddChannelGroup(enigma2::data::ChannelGroup& channelGroup); void LoadChannelGroupsStartPosition(bool radio); std::vector> m_channelGroups; std::unordered_map> m_channelGroupsNameMap; std::unordered_map> m_channelGroupsServiceReferenceMap; }; } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/Channels.cpp000066400000000000000000000312731356012415200212060ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "Channels.h" #include "../Enigma2.h" #include "../client.h" #include "Admin.h" #include "ChannelGroups.h" #include "p8-platform/util/StringUtils.h" #include "util/XMLUtils.h" #include "utilities/Logger.h" #include "utilities/WebUtils.h" #include #include using namespace enigma2; using namespace enigma2::data; using namespace enigma2::utilities; using json = nlohmann::json; namespace { int GenerateChannelUniqueId(const std::string& channelName, const std::string& extendedServiceReference) { std::string concat(channelName); concat.append(extendedServiceReference); const char* calcString = concat.c_str(); int uniqueId = 0; int c; while ((c = *calcString++)) uniqueId = ((uniqueId << 5) + uniqueId) + c; /* iId * 33 + c */ return abs(uniqueId); } } // unnamed namespace 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 = {0}; channel->UpdateTo(kodiChannel); kodiChannels.emplace_back(kodiChannel); } } } int Channels::GetChannelUniqueId(const std::string& channelServiceReference) { std::shared_ptr channel = GetChannel(channelServiceReference); int uniqueId = PVR_CHANNEL_INVALID_UID; if (channel) uniqueId = channel->GetUniqueId(); return uniqueId; } std::shared_ptr Channels::GetChannel(int uniqueId) { auto channelPair = m_channelsUniqueIdMap.find(uniqueId); if (channelPair != m_channelsUniqueIdMap.end()) return channelPair->second; return {}; } std::shared_ptr Channels::GetChannel(const std::string& channelServiceReference) { auto channelPair = m_channelsServiceReferenceMap.find(channelServiceReference); if (channelPair != m_channelsServiceReferenceMap.end()) return channelPair->second; return {}; } std::shared_ptr Channels::GetChannel(const std::string& channelName, bool isRadio) { for (const auto& channel : m_channels) { if (channelName == channel->GetChannelName() && isRadio == channel->IsRadio()) return channel; } return nullptr; } bool Channels::IsValid(int uniqueId) { return GetChannel(uniqueId) != nullptr; } 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(); m_channelsUniqueIdMap.clear(); m_channelsServiceReferenceMap.clear(); } void Channels::AddChannel(Channel& newChannel, std::shared_ptr& channelGroup) { std::shared_ptr foundChannel = GetChannel(newChannel.GetServiceReference()); if (!foundChannel) { newChannel.SetUniqueId(GenerateChannelUniqueId(newChannel.GetChannelName(), newChannel.GetExtendedServiceReference())); 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_channelsUniqueIdMap.insert({channel->GetUniqueId(), channel}); m_channelsServiceReferenceMap.insert({channel->GetServiceReference(), channel}); } else { foundChannel->AddChannelGroup(channelGroup); channelGroup->AddChannel(foundChannel); } } std::vector>& Channels::GetChannelsList() { return m_channels; } std::string Channels::GetChannelIconPath(std::string& channelName) { for (const auto& channel : m_channels) { if (channelName == channel->GetChannelName()) return channel->GetIconPath(); } return ""; } bool Channels::LoadChannels(ChannelGroups& channelGroups) { m_channelGroups = channelGroups; bool bOk = false; ClearChannels(); // Load Channels for (auto& group : channelGroups.GetChannelGroupsList()) { if (LoadChannels(group->GetServiceReference(), group->GetGroupName(), group)) bOk = true; } // Load Channels extra data for groups int tvChannelNumberOffset = 0; int radioChannelNumberOffset = 0; for (const auto& group : channelGroups.GetChannelGroupsList()) { if (group->IsRadio()) radioChannelNumberOffset = LoadChannelsExtraData(group, radioChannelNumberOffset); else tvChannelNumberOffset = LoadChannelsExtraData(group, tvChannelNumberOffset); } 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()); const std::string strTmp = StringUtils::Format("%sweb/getservices?sRef=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(groupServiceReference).c_str()); const std::string strXML = WebUtils::GetHttpXML(strTmp); TiXmlDocument xmlDoc; if (!xmlDoc.Parse(strXML.c_str())) { Logger::Log(LEVEL_ERROR, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem = hDoc.FirstChildElement("e2servicelist").Element(); if (!pElem) { Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); return false; } TiXmlHandle hRoot = TiXmlHandle(pElem); TiXmlElement* pNode = hRoot.FirstChildElement("e2service").Element(); if (!pNode) { Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); return false; } bool emptyGroup = true; for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2service")) { Channel newChannel; newChannel.SetRadio(channelGroup->IsRadio()); if (!newChannel.UpdateFrom(pNode)) continue; else emptyGroup = false; 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()); } channelGroup->SetEmptyGroup(emptyGroup); Logger::Log(LEVEL_INFO, "%s Loaded %d Channels", __FUNCTION__, GetNumChannels()); return true; } int Channels::LoadChannelsExtraData(const std::shared_ptr channelGroup, int lastGroupLatestChannelPosition) { int newChannelPositionOffset = channelGroup->GetStartChannelNumber(); // In case we don't have a start channel number for this group just use the latest if (!channelGroup->HasStartChannelNumber()) newChannelPositionOffset = lastGroupLatestChannelPosition; if (Settings::GetInstance().SupportsProviderNumberAndPiconForChannels()) { Logger::Log(LEVEL_INFO, "%s loading channel group extra data: '%s'", __FUNCTION__, channelGroup->GetGroupName().c_str()); //We can use the JSON API so let's supplement the data with extra information const std::string jsonURL = StringUtils::Format("%sapi/getservices?provider=1&picon=1&sRef=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(channelGroup->GetServiceReference()).c_str()); const std::string strJson = WebUtils::GetHttpXML(jsonURL); try { auto jsonDoc = json::parse(strJson); if (!jsonDoc["services"].empty()) { for (const auto& it : jsonDoc["services"].items()) { auto jsonChannel = it.value(); std::string serviceReference = jsonChannel["servicereference"].get(); // Check whether the current element is not just a label or that it's not a hidden entry if (serviceReference.compare(0, 5, "1:64:") == 0 || serviceReference.compare(0, 6, "1:320:") == 0) continue; if (Settings::GetInstance().UseStandardServiceReference()) { serviceReference = Channel::CreateStandardServiceReference(serviceReference); } auto channel = GetChannel(serviceReference); if (channel) { if (!jsonChannel["provider"].empty()) { Logger::Log(LEVEL_DEBUG, "%s For Channel %s, set provider name to %s", __FUNCTION__, jsonChannel["servicename"].get().c_str(), jsonChannel["provider"].get().c_str()); channel->SetProviderlName(jsonChannel["provider"].get()); } if (!jsonChannel["pos"].empty() && channel->UsingDefaultChannelNumber() && Settings::GetInstance().SupportsChannelNumberGroupStartPos()) { Logger::Log(LEVEL_DEBUG, "%s For Channel %s, set backend channel number to %d", __FUNCTION__, jsonChannel["servicename"].get().c_str(), jsonChannel["pos"].get()); channel->SetChannelNumber(jsonChannel["pos"].get() + lastGroupLatestChannelPosition); channel->SetUsingDefaultChannelNumber(false); } if (Settings::GetInstance().UseOpenWebIfPiconPath()) { if (!jsonChannel["picon"].empty()) { std::string connectionURL = Settings::GetInstance().GetConnectionURL(); connectionURL = connectionURL.substr(0, connectionURL.size() - 1); channel->SetIconPath(StringUtils::Format("%s%s", connectionURL.c_str(), jsonChannel["picon"].get().c_str())); Logger::Log(LEVEL_DEBUG, "%s For Channel %s, using OpenWebPiconPath: %s", __FUNCTION__, jsonChannel["servicename"].get().c_str(), channel->GetIconPath().c_str()); } } } } } if (!jsonDoc["pos"].empty()) { newChannelPositionOffset += jsonDoc["pos"].get(); Logger::Log(LEVEL_DEBUG, "%s For groupName %s, highest backend channel number offset is %d", __FUNCTION__, channelGroup->GetGroupName().c_str(), newChannelPositionOffset); } } catch (nlohmann::detail::parse_error& e) { Logger::Log(LEVEL_ERROR, "%s Invalid JSON received, cannot load provider or picon paths from OpenWebIf - JSON parse error - message: %s, exception id: %d", __FUNCTION__, e.what(), e.id); } catch (nlohmann::detail::type_error& e) { Logger::Log(LEVEL_ERROR, "%s JSON type error - message: %s, exception id: %d", __FUNCTION__, e.what(), e.id); } } return newChannelPositionOffset; } ChannelsChangeState Channels::CheckForChannelAndGroupChanges(enigma2::ChannelGroups& latestChannelGroups, enigma2::Channels& latestChannels) { if (GetNumChannels() != latestChannels.GetNumChannels()) return ChannelsChangeState::CHANNELS_CHANGED; int foundCount = 0; for (const auto& channel : m_channels) { const std::shared_ptr channelPtr = latestChannels.GetChannel(channel->GetServiceReference()); if (channelPtr) { foundCount++; if (*channelPtr != *channel) { return ChannelsChangeState::CHANNELS_CHANGED; } } } if (foundCount != GetNumChannels()) return ChannelsChangeState::CHANNELS_CHANGED; // Now check the groups if (m_channelGroups.GetNumChannelGroups() != latestChannelGroups.GetNumChannelGroups()) return ChannelsChangeState::CHANNEL_GROUPS_CHANGED; foundCount = 0; for (const auto& group : m_channelGroups.GetChannelGroupsList()) { const std::shared_ptr channelGroupPtr = latestChannelGroups.GetChannelGroupUsingName(group->GetGroupName()); if (channelGroupPtr) { foundCount++; if (*channelGroupPtr != *group) { return ChannelsChangeState::CHANNEL_GROUPS_CHANGED; } } } if (foundCount != m_channelGroups.GetNumChannelGroups()) return ChannelsChangeState::CHANNEL_GROUPS_CHANGED; return ChannelsChangeState::NO_CHANGE; } pvr.vuplus-3.28.9-Leia/src/enigma2/Channels.h000066400000000000000000000056621356012415200206560ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "ChannelGroups.h" #include "data/Channel.h" #include "kodi/libXBMC_pvr.h" #include #include #include #include namespace enigma2 { class ChannelGroups; namespace data { class ChannelGroup; } enum class ChannelsChangeState : int // same type as addon settings { NO_CHANGE = 0, CHANNEL_GROUPS_CHANGED, CHANNELS_CHANGED }; 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); std::shared_ptr GetChannel(const std::string& channelName, bool isRadio); bool IsValid(int uniqueId); bool IsValid(const std::string& channelServiceReference); int GetNumChannels() const; void ClearChannels(); std::vector>& GetChannelsList(); std::string GetChannelIconPath(std::string& channelName); bool LoadChannels(enigma2::ChannelGroups& channelGroups); ChannelsChangeState CheckForChannelAndGroupChanges(enigma2::ChannelGroups& latestChannelGroups, enigma2::Channels& latestChannels); 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); int LoadChannelsExtraData(const std::shared_ptr channelGroup, int lastGroupLatestChannelPosition); std::vector> m_channels; std::unordered_map> m_channelsUniqueIdMap; std::unordered_map> m_channelsServiceReferenceMap; ChannelGroups m_channelGroups; }; } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/ConnectionManager.cpp000066400000000000000000000116021356012415200230370ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "ConnectionManager.h" #include "../client.h" #include "IConnectionListener.h" #include "Settings.h" #include "p8-platform/os.h" #include "p8-platform/util/StringUtils.h" #include "utilities/Logger.h" #include "utilities/WebUtils.h" using namespace P8PLATFORM; using namespace enigma2; using namespace enigma2::utilities; /* * Enigma2 Connection handler */ ConnectionManager::ConnectionManager(IConnectionListener& connectionListener) : m_connectionListener(connectionListener), m_suspended(false), m_state(PVR_CONNECTION_STATE_UNKNOWN) { } ConnectionManager::~ConnectionManager() { StopThread(-1); Disconnect(); StopThread(0); } void ConnectionManager::Start() { // Note: "connecting" must only be set one time, before the very first connection attempt, not on every reconnect. SetState(PVR_CONNECTION_STATE_CONNECTING); CreateThread(); } void ConnectionManager::Stop() { StopThread(-1); Disconnect(); } void ConnectionManager::OnSleep() { CLockObject lock(m_mutex); Logger::Log(LogLevel::LEVEL_DEBUG, "%s going to sleep", __FUNCTION__); m_suspended = true; } void ConnectionManager::OnWake() { CLockObject lock(m_mutex); Logger::Log(LogLevel::LEVEL_DEBUG, "%s Waking up", __FUNCTION__); m_suspended = false; } void ConnectionManager::SetState(PVR_CONNECTION_STATE state) { PVR_CONNECTION_STATE prevState(PVR_CONNECTION_STATE_UNKNOWN); PVR_CONNECTION_STATE newState(PVR_CONNECTION_STATE_UNKNOWN); { CLockObject lock(m_mutex); /* No notification if no state change or while suspended. */ if (m_state != state && !m_suspended) { prevState = m_state; newState = state; m_state = newState; Logger::Log(LogLevel::LEVEL_DEBUG, "connection state change (%d -> %d)", prevState, newState); } } if (prevState != newState) { static std::string serverString; if (newState == PVR_CONNECTION_STATE_SERVER_UNREACHABLE) { m_connectionListener.ConnectionLost(); } else if (newState == PVR_CONNECTION_STATE_CONNECTED) { m_connectionListener.ConnectionEstablished(); } /* Notify connection state change (callback!) */ PVR->ConnectionStateChange(Settings::GetInstance().GetConnectionURL().c_str(), newState, NULL); } } void ConnectionManager::Disconnect() { CLockObject lock(m_mutex); m_connectionListener.ConnectionLost(); } void ConnectionManager::Reconnect() { // Setting this state will cause Enigma2 to receive a connetionLost event // The connection manager will then connect again causeing a reload of all state SetState(PVR_CONNECTION_STATE_SERVER_UNREACHABLE); } void* ConnectionManager::Process() { static bool log = false; static unsigned int retryAttempt = 0; int fastReconnectIntervalMs = (Settings::GetInstance().GetConnectioncCheckIntervalSecs() * 1000) / 2; int intervalMs = Settings::GetInstance().GetConnectioncCheckIntervalSecs() * 1000; while (!IsStopped()) { while (m_suspended) { Logger::Log(LogLevel::LEVEL_DEBUG, "%s - suspended, waiting for wakeup...", __FUNCTION__); /* Wait for wakeup */ SteppedSleep(intervalMs); } const std::string url = StringUtils::Format("%s%s", Settings::GetInstance().GetConnectionURL().c_str(), "web/currenttime"); /* Connect */ if (!WebUtils::CheckHttp(url)) { /* Unable to connect */ if (retryAttempt == 0) Logger::Log(LogLevel::LEVEL_ERROR, "%s - unable to connect to: %s", __FUNCTION__, url.c_str()); SetState(PVR_CONNECTION_STATE_SERVER_UNREACHABLE); // Retry a few times with a short interval, after that with the default timeout if (++retryAttempt <= FAST_RECONNECT_ATTEMPTS) SteppedSleep(fastReconnectIntervalMs); else SteppedSleep(intervalMs); continue; } SetState(PVR_CONNECTION_STATE_CONNECTED); retryAttempt = 0; SteppedSleep(intervalMs); } return nullptr; } void ConnectionManager::SteppedSleep(int intervalMs) { int sleepCountMs = 0; while (sleepCountMs <= intervalMs) { if (!IsStopped()) Sleep(SLEEP_INTERVAL_STEP_MS); sleepCountMs += SLEEP_INTERVAL_STEP_MS; } }pvr.vuplus-3.28.9-Leia/src/enigma2/ConnectionManager.h000066400000000000000000000033041356012415200225040ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "kodi/libXBMC_pvr.h" #include "p8-platform/threads/mutex.h" #include "p8-platform/threads/threads.h" #include namespace enigma2 { static const int FAST_RECONNECT_ATTEMPTS = 5; static const int SLEEP_INTERVAL_STEP_MS = 500; class IConnectionListener; class ConnectionManager : public P8PLATFORM::CThread { public: ConnectionManager(IConnectionListener& connectionListener); ~ConnectionManager() override; void Start(); void Stop(); void Disconnect(); void Reconnect(); void OnSleep(); void OnWake(); private: void* Process() override; void SetState(PVR_CONNECTION_STATE state); void SteppedSleep(int intervalMs); IConnectionListener& m_connectionListener; mutable P8PLATFORM::CMutex m_mutex; bool m_suspended; PVR_CONNECTION_STATE m_state; }; } // namespace enigma2 pvr.vuplus-3.28.9-Leia/src/enigma2/Epg.cpp000066400000000000000000000521451356012415200201670ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "Epg.h" #include "../Enigma2.h" #include "../client.h" #include "p8-platform/util/StringUtils.h" #include "util/XMLUtils.h" #include "utilities/Logger.h" #include "utilities/WebUtils.h" #include #include #include #include using namespace enigma2; using namespace enigma2::data; using namespace enigma2::extract; using namespace enigma2::utilities; using namespace P8PLATFORM; using json = nlohmann::json; Epg::Epg(enigma2::extract::EpgEntryExtractor& entryExtractor, int epgMaxDays) : m_entryExtractor(entryExtractor), m_epgMaxDays(epgMaxDays) {} Epg::Epg(const Epg& epg) : m_entryExtractor(epg.m_entryExtractor) {} bool Epg::Initialise(enigma2::Channels& channels, enigma2::ChannelGroups& channelGroups) { SetEPGTimeFrame(m_epgMaxDays); auto started = std::chrono::high_resolution_clock::now(); Logger::Log(LEVEL_DEBUG, "%s Initial EPG Load Start", __FUNCTION__); //clear current data structures m_epgChannels.clear(); m_epgChannelsMap.clear(); m_readInitialEpgChannelsMap.clear(); m_needsInitialEpgChannelsMap.clear(); m_initialEpgReady = false; //add an initial EPG data per channel uId, sref and initial EPG for (auto& channel : channels.GetChannelsList()) { std::shared_ptr newEpgChannel = std::make_shared(); newEpgChannel->SetRadio(channel->IsRadio()); newEpgChannel->SetUniqueId(channel->GetUniqueId()); newEpgChannel->SetChannelName(channel->GetChannelName()); newEpgChannel->SetServiceReference(channel->GetServiceReference()); m_epgChannels.emplace_back(newEpgChannel); m_epgChannelsMap.insert({newEpgChannel->GetServiceReference(), newEpgChannel}); m_readInitialEpgChannelsMap.insert({newEpgChannel->GetServiceReference(), newEpgChannel}); m_needsInitialEpgChannelsMap.insert({newEpgChannel->GetServiceReference(), newEpgChannel}); } int lastScannedIgnoreSuccessCount = std::round((1 - LAST_SCANNED_INITIAL_EPG_SUCCESS_PERCENT) * m_epgChannels.size()); std::vector> groupList; std::shared_ptr newChannelGroup = std::make_shared(); newChannelGroup->SetRadio(false); newChannelGroup->SetGroupName("Last Scanned"); //Name not important newChannelGroup->SetServiceReference("1:7:1:0:0:0:0:0:0:0:FROM BOUQUET \"userbouquet.LastScanned.tv\" ORDER BY bouquet"); newChannelGroup->SetLastScannedGroup(true); groupList.emplace_back(newChannelGroup); for (auto& group : channelGroups.GetChannelGroupsList()) { if (!group->IsLastScannedGroup()) groupList.emplace_back(group); } //load each group and if we don't already have it's intial EPG then load those entries for (auto& group : groupList) { LoadInitialEPGForGroup(group); //Remove channels that now have an initial EPG for (auto& epgChannel : m_epgChannels) { if (epgChannel->GetInitialEPG().size() > 0) InitialEpgLoadedForChannel(epgChannel->GetServiceReference()); } Logger::Log(LEVEL_DEBUG, "%s Initial EPG Progress - Remaining channels %d, Min Channels for completion %d", __FUNCTION__, m_needsInitialEpgChannelsMap.size(), lastScannedIgnoreSuccessCount); for (auto pair : m_needsInitialEpgChannelsMap) Logger::Log(LEVEL_DEBUG, "%s - Initial EPG Progress - Remaining channel: %s - sref: %s", __FUNCTION__, pair.second->GetChannelName().c_str(), pair.first.c_str()); if (group->IsLastScannedGroup() && m_needsInitialEpgChannelsMap.size() <= lastScannedIgnoreSuccessCount) break; } int milliseconds = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - started).count(); Logger::Log(LEVEL_NOTICE, "%s Initial EPG Loaded - %d (ms)", __FUNCTION__, milliseconds); m_initialEpgReady = true; return true; } std::shared_ptr Epg::GetEpgChannel(const std::string& serviceReference) { std::shared_ptr epgChannel = std::make_shared(); auto epgChannelSearch = m_epgChannelsMap.find(serviceReference); if (epgChannelSearch != m_epgChannelsMap.end()) epgChannel = epgChannelSearch->second; return epgChannel; } std::shared_ptr Epg::GetEpgChannelNeedingInitialEpg(const std::string& serviceReference) { std::shared_ptr epgChannel = std::make_shared(); auto initialEpgChannelSearch = m_needsInitialEpgChannelsMap.find(serviceReference); if (initialEpgChannelSearch != m_needsInitialEpgChannelsMap.end()) epgChannel = initialEpgChannelSearch->second; return epgChannel; } bool Epg::ChannelNeedsInitialEpg(const std::string& serviceReference) { auto needsInitialEpgSearch = m_needsInitialEpgChannelsMap.find(serviceReference); return needsInitialEpgSearch != m_needsInitialEpgChannelsMap.end(); } bool Epg::InitialEpgLoadedForChannel(const std::string& serviceReference) { return m_needsInitialEpgChannelsMap.erase(serviceReference) == 1; } bool Epg::IsInitialEpgCompleted() { Logger::Log(LEVEL_DEBUG, "%s Waiting to Get Initial EPG for %d remaining channels", __FUNCTION__, m_readInitialEpgChannelsMap.size()); return m_readInitialEpgChannelsMap.size() == 0; } void Epg::TriggerEpgUpdatesForChannels() { for (auto& epgChannel : m_epgChannels) { //We want to trigger full updates only so let's make sure it's not an initialEpg if (epgChannel->RequiresInitialEpg()) { epgChannel->SetRequiresInitialEpg(false); epgChannel->GetInitialEPG().clear(); m_readInitialEpgChannelsMap.erase(epgChannel->GetServiceReference()); } Logger::Log(LEVEL_DEBUG, "%s - Trigger EPG update for channel: %s (%d)", __FUNCTION__, epgChannel->GetChannelName().c_str(), epgChannel->GetUniqueId()); PVR->TriggerEpgUpdate(epgChannel->GetUniqueId()); } } void Epg::MarkChannelAsInitialEpgRead(const std::string& serviceReference) { std::shared_ptr epgChannel = GetEpgChannel(serviceReference); if (epgChannel->RequiresInitialEpg()) { epgChannel->SetRequiresInitialEpg(false); epgChannel->GetInitialEPG().clear(); m_readInitialEpgChannelsMap.erase(epgChannel->GetServiceReference()); } } PVR_ERROR Epg::GetEPGForChannel(ADDON_HANDLE handle, const std::string& serviceReference, time_t iStart, time_t iEnd) { std::shared_ptr epgChannel = GetEpgChannel(serviceReference); if (epgChannel) { Logger::Log(LEVEL_DEBUG, "%s Getting EPG for channel '%s'", __FUNCTION__, epgChannel->GetChannelName().c_str()); if (epgChannel->RequiresInitialEpg()) { epgChannel->SetRequiresInitialEpg(false); return TransferInitialEPGForChannel(handle, epgChannel, iStart, iEnd); } const std::string url = StringUtils::Format("%s%s%s", Settings::GetInstance().GetConnectionURL().c_str(), "web/epgservice?sRef=", WebUtils::URLEncodeInline(serviceReference).c_str()); const std::string strXML = WebUtils::GetHttpXML(url); int iNumEPG = 0; TiXmlDocument xmlDoc; if (!xmlDoc.Parse(strXML.c_str())) { Logger::Log(LEVEL_ERROR, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return PVR_ERROR_SERVER_ERROR; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem = hDoc.FirstChildElement("e2eventlist").Element(); if (!pElem) { Logger::Log(LEVEL_NOTICE, "%s could not find element!", __FUNCTION__); // Return "NO_ERROR" as the EPG could be empty for this channel return PVR_ERROR_NO_ERROR; } TiXmlHandle hRoot = TiXmlHandle(pElem); TiXmlElement* pNode = hRoot.FirstChildElement("e2event").Element(); if (!pNode) { Logger::Log(LEVEL_NOTICE, "%s Could not find element", __FUNCTION__); // RETURN "NO_ERROR" as the EPG could be empty for this channel return PVR_ERROR_NO_ERROR; } for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2event")) { EpgEntry entry; if (!entry.UpdateFrom(pNode, epgChannel, iStart, iEnd)) continue; if (m_entryExtractor.IsEnabled()) m_entryExtractor.ExtractFromEntry(entry); EPG_TAG broadcast = {0}; entry.UpdateTo(broadcast); PVR->TransferEpgEntry(handle, &broadcast); iNumEPG++; Logger::Log(LEVEL_TRACE, "%s loaded EPG entry '%d:%s' channel '%d' start '%d' end '%d'", __FUNCTION__, broadcast.iUniqueBroadcastId, broadcast.strTitle, entry.GetChannelId(), entry.GetStartTime(), entry.GetEndTime()); } iNumEPG += TransferTimerBasedEntries(handle, epgChannel->GetUniqueId()); Logger::Log(LEVEL_INFO, "%s Loaded %u EPG Entries for channel '%s'", __FUNCTION__, iNumEPG, epgChannel->GetChannelName().c_str()); } else { Logger::Log(LEVEL_NOTICE, "%s EPG requested for unknown channel reference: '%s'", __FUNCTION__, serviceReference.c_str()); } return PVR_ERROR_NO_ERROR; } void Epg::SetEPGTimeFrame(int epgMaxDays) { CLockObject lock(m_mutex); m_epgMaxDays = epgMaxDays; if (m_epgMaxDays > 0) m_epgMaxDaysSeconds = m_epgMaxDays * 24 * 60 * 60; else m_epgMaxDaysSeconds = DEFAULT_EPG_MAX_DAYS * 24 * 60 * 60; } PVR_ERROR Epg::TransferInitialEPGForChannel(ADDON_HANDLE handle, const std::shared_ptr& epgChannel, time_t iStart, time_t iEnd) { for (const auto& entry : epgChannel->GetInitialEPG()) { EPG_TAG broadcast = {0}; entry.UpdateTo(broadcast); PVR->TransferEpgEntry(handle, &broadcast); } epgChannel->GetInitialEPG().clear(); m_readInitialEpgChannelsMap.erase(epgChannel->GetServiceReference()); TransferTimerBasedEntries(handle, epgChannel->GetUniqueId()); return PVR_ERROR_NO_ERROR; } std::string Epg::LoadEPGEntryShortDescription(const std::string& serviceReference, unsigned int epgUid) { std::string shortDescription; const std::string jsonUrl = StringUtils::Format("%sapi/event?sref=%s&idev=%u", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(serviceReference).c_str(), epgUid); const std::string strJson = WebUtils::GetHttpXML(jsonUrl); try { auto jsonDoc = json::parse(strJson); if (!jsonDoc["event"].empty()) { for (const auto& element : jsonDoc["event"].items()) { if (element.key() == "shortdesc") { Logger::Log(LEVEL_DEBUG, "%s Loaded EPG event short description for sref: %s, epgId: %u - '%s'", __FUNCTION__, serviceReference.c_str(), epgUid, element.value().get().c_str()); shortDescription = element.value().get(); } } } } catch (nlohmann::detail::parse_error& e) { Logger::Log(LEVEL_ERROR, "%s Invalid JSON received, cannot load short descrption from OpenWebIf for sref: %s, epgId: %u - JSON parse error - message: %s, exception id: %d", __FUNCTION__, serviceReference.c_str(), epgUid, e.what(), e.id); } catch (nlohmann::detail::type_error& e) { Logger::Log(LEVEL_ERROR, "%s JSON type error - message: %s, exception id: %d", __FUNCTION__, e.what(), e.id); } return shortDescription; } EpgPartialEntry Epg::LoadEPGEntryPartialDetails(const std::string& serviceReference, unsigned int epgUid) { EpgPartialEntry partialEntry; Logger::Log(LEVEL_DEBUG, "%s Looking for EPG event partial details for sref: %s, epgUid: %u", __FUNCTION__, serviceReference.c_str(), epgUid); const std::string jsonUrl = StringUtils::Format("%sapi/event?sref=%s&idev=%u", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(serviceReference).c_str(), epgUid); const std::string strJson = WebUtils::GetHttpXML(jsonUrl); try { auto jsonDoc = json::parse(strJson); if (!jsonDoc["event"].empty()) { for (const auto& element : jsonDoc["event"].items()) { if (element.key() == "shortdesc") partialEntry.SetPlotOutline(element.value().get()); if (element.key() == "longdesc") partialEntry.SetPlot(element.value().get()); else if (element.key() == "title") partialEntry.SetTitle(element.value().get()); else if (element.key() == "id") partialEntry.SetEpgUid(element.value().get()); else if (element.key() == "genreid") { int genreId = element.value().get(); partialEntry.SetGenreType(genreId & 0xF0); partialEntry.SetGenreSubType(genreId & 0x0F); } } if (partialEntry.EntryFound()) { Logger::Log(LEVEL_DEBUG, "%s Loaded EPG event partial details for sref: %s, epgId: %u - title: %s - '%s'", __FUNCTION__, serviceReference.c_str(), epgUid, partialEntry.GetTitle().c_str(), partialEntry.GetPlotOutline().c_str()); } } } catch (nlohmann::detail::parse_error& e) { Logger::Log(LEVEL_ERROR, "%s Invalid JSON received, cannot event details from OpenWebIf for sref: %s, epgId: %u - JSON parse error - message: %s, exception id: %d", __FUNCTION__, serviceReference.c_str(), epgUid, e.what(), e.id); } catch (nlohmann::detail::type_error& e) { Logger::Log(LEVEL_ERROR, "%s JSON type error - message: %s, exception id: %d", __FUNCTION__, e.what(), e.id); } return partialEntry; } EpgPartialEntry Epg::LoadEPGEntryPartialDetails(const std::string& serviceReference, time_t startTime) { EpgPartialEntry partialEntry; Logger::Log(LEVEL_DEBUG, "%s Looking for EPG event partial details for sref: %s, time: %lld", __FUNCTION__, serviceReference.c_str(), static_cast(startTime)); const std::string jsonUrl = StringUtils::Format("%sapi/epgservice?sRef=%s&time=%lld&endTime=1", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(serviceReference).c_str(), static_cast(startTime)); const std::string strJson = WebUtils::GetHttpXML(jsonUrl); try { auto jsonDoc = json::parse(strJson); if (!jsonDoc["events"].empty()) { for (const auto& event : jsonDoc["events"].items()) { for (const auto& element : event.value().items()) { if (element.key() == "shortdesc") partialEntry.SetPlotOutline(element.value().get()); if (element.key() == "longdesc") partialEntry.SetPlot(element.value().get()); else if (element.key() == "title") partialEntry.SetTitle(element.value().get()); else if (element.key() == "id") partialEntry.SetEpgUid(element.value().get()); else if (element.key() == "genreid") { int genreId = element.value().get(); partialEntry.SetGenreType(genreId & 0xF0); partialEntry.SetGenreSubType(genreId & 0x0F); } } if (partialEntry.EntryFound()) Logger::Log(LEVEL_DEBUG, "%s Loaded EPG event partial details for sref: %s, time: %lld - title: %s, epgId: %u - '%s'", __FUNCTION__, serviceReference.c_str(), static_cast(startTime), partialEntry.GetTitle().c_str(), partialEntry.GetEpgUid(), partialEntry.GetPlotOutline().c_str()); break; //We only want first event } } } catch (nlohmann::detail::parse_error& e) { Logger::Log(LEVEL_ERROR, "%s Invalid JSON received, cannot event details from OpenWebIf for sref: %s, time: %lld - JSON parse error - message: %s, exception id: %d", __FUNCTION__, serviceReference.c_str(), static_cast(startTime), e.what(), e.id); } catch (nlohmann::detail::type_error& e) { Logger::Log(LEVEL_ERROR, "%s JSON type error - message: %s, exception id: %d", __FUNCTION__, e.what(), e.id); } return partialEntry; } std::string Epg::FindServiceReference(const std::string& title, int epgUid, time_t startTime, time_t endTime) const { std::string serviceReference; const auto started = std::chrono::high_resolution_clock::now(); const std::string jsonUrl = StringUtils::Format("%sapi/epgsearch?search=%s&endtime=%lld", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(title).c_str(), static_cast(endTime)); const std::string strJson = WebUtils::GetHttpXML(jsonUrl); try { auto jsonDoc = json::parse(strJson); if (!jsonDoc["events"].empty()) { for (const auto& event : jsonDoc["events"].items()) { if (event.value()["title"].get() == title && event.value()["id"].get() == epgUid && event.value()["begin_timestamp"].get() == startTime && event.value()["duration_sec"].get() == (endTime - startTime)) { serviceReference = Channel::NormaliseServiceReference(event.value()["sref"].get()); break; //We only want first event } } } } catch (nlohmann::detail::parse_error& e) { Logger::Log(LEVEL_ERROR, "%s Invalid JSON received, cannot retrieve service reference from OpenWebIf for: %s, epgUid: %d, start time: %lld, end time: %lld - JSON parse error - message: %s, exception id: %d", __FUNCTION__, title.c_str(), epgUid, static_cast(startTime), static_cast(endTime), e.what(), e.id); } catch (nlohmann::detail::type_error& e) { Logger::Log(LEVEL_ERROR, "%s JSON type error - message: %s, exception id: %d", __FUNCTION__, e.what(), e.id); } int milliseconds = std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - started).count(); Logger::Log(LEVEL_DEBUG, "%s Service reference search time - %d (ms)", __FUNCTION__, milliseconds); return serviceReference; } bool Epg::LoadInitialEPGForGroup(const 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_ERROR, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem = hDoc.FirstChildElement("e2eventlist").Element(); if (!pElem) { Logger::Log(LEVEL_NOTICE, "%s could not find element!", __FUNCTION__); // Return "NO_ERROR" as the EPG could be empty for this channel return false; } TiXmlHandle hRoot = TiXmlHandle(pElem); TiXmlElement* pNode = hRoot.FirstChildElement("e2event").Element(); if (!pNode) { Logger::Log(LEVEL_DEBUG, "%s Could not find element", __FUNCTION__); // 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_needsInitialEpgChannelsMap)) continue; std::shared_ptr epgChannel = GetEpgChannelNeedingInitialEpg(entry.GetServiceReference()); if (m_entryExtractor.IsEnabled()) m_entryExtractor.ExtractFromEntry(entry); iNumEPG++; epgChannel->GetInitialEPG().emplace_back(entry); Logger::Log(LEVEL_TRACE, "%s Added Initial EPG Entry for: %s, %d, %s", __FUNCTION__, epgChannel->GetChannelName().c_str(), epgChannel->GetUniqueId(), epgChannel->GetServiceReference().c_str()); } Logger::Log(LEVEL_INFO, "%s Loaded %u EPG Entries for group '%s'", __FUNCTION__, iNumEPG, group->GetGroupName().c_str()); return true; } void Epg::UpdateTimerEPGFallbackEntries(const std::vector& timerBasedEntries) { CLockObject lock(m_mutex); time_t now = time(nullptr); time_t until = now + m_epgMaxDaysSeconds; m_timerBasedEntries.clear(); for (auto& timerBasedEntry : timerBasedEntries) { if (timerBasedEntry.GetEndTime() < now || timerBasedEntry.GetEndTime() > until) m_timerBasedEntries.emplace_back(timerBasedEntry); } } int Epg::TransferTimerBasedEntries(ADDON_HANDLE handle, int epgChannelId) { int numTransferred = 0; CLockObject lock(m_mutex); for (auto& timerBasedEntry : m_timerBasedEntries) { if (epgChannelId == timerBasedEntry.GetChannelId()) { EPG_TAG broadcast = {0}; timerBasedEntry.UpdateTo(broadcast); PVR->TransferEpgEntry(handle, &broadcast); numTransferred++; } } return numTransferred; } pvr.vuplus-3.28.9-Leia/src/enigma2/Epg.h000066400000000000000000000071711356012415200176330ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "ChannelGroups.h" #include "Channels.h" #include "data/EpgChannel.h" #include "data/EpgPartialEntry.h" #include "extract/EpgEntryExtractor.h" #include "kodi/libXBMC_pvr.h" #include "p8-platform/threads/threads.h" #include #include #include #include namespace enigma2 { static const float LAST_SCANNED_INITIAL_EPG_SUCCESS_PERCENT = 0.99f; static const int DEFAULT_EPG_MAX_DAYS = 3; class Epg { public: Epg(enigma2::extract::EpgEntryExtractor& entryExtractor, int epgMaxDays); Epg(const enigma2::Epg& epg); bool Initialise(enigma2::Channels& channels, enigma2::ChannelGroups& channelGroups); bool IsInitialEpgCompleted(); void TriggerEpgUpdatesForChannels(); void MarkChannelAsInitialEpgRead(const std::string& serviceReference); PVR_ERROR GetEPGForChannel(ADDON_HANDLE handle, const std::string& serviceReference, time_t iStart, time_t iEnd); void SetEPGTimeFrame(int epgMaxDays); std::string LoadEPGEntryShortDescription(const std::string& serviceReference, unsigned int epgUid); data::EpgPartialEntry LoadEPGEntryPartialDetails(const std::string& serviceReference, time_t startTime); data::EpgPartialEntry LoadEPGEntryPartialDetails(const std::string& serviceReference, unsigned int epgUid); std::string FindServiceReference(const std::string& title, int epgUid, time_t startTime, time_t endTime) const; void UpdateTimerEPGFallbackEntries(const std::vector& timerBasedEntries); private: PVR_ERROR TransferInitialEPGForChannel(ADDON_HANDLE handle, const std::shared_ptr& epgChannel, time_t iStart, time_t iEnd); std::shared_ptr GetEpgChannel(const std::string& serviceReference); bool LoadInitialEPGForGroup(const std::shared_ptr group); bool ChannelNeedsInitialEpg(const std::string& serviceReference); bool InitialEpgLoadedForChannel(const std::string& serviceReference); bool InitialEpgReadForChannel(const std::string& serviceReference); std::shared_ptr GetEpgChannelNeedingInitialEpg(const std::string& serviceReference); int TransferTimerBasedEntries(ADDON_HANDLE handle, int epgChannelId); enigma2::extract::EpgEntryExtractor& m_entryExtractor; bool m_initialEpgReady = false; int m_epgMaxDays; long m_epgMaxDaysSeconds; std::vector> m_epgChannels; std::map> m_epgChannelsMap; std::map> m_readInitialEpgChannelsMap; std::map> m_needsInitialEpgChannelsMap; std::vector m_timerBasedEntries; mutable P8PLATFORM::CMutex m_mutex; }; } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/IConnectionListener.h000066400000000000000000000020771356012415200230360ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ namespace enigma2 { class IConnectionListener { public: virtual ~IConnectionListener() = default; virtual void ConnectionLost() = 0; virtual void ConnectionEstablished() = 0; }; } // namespace enigma2 pvr.vuplus-3.28.9-Leia/src/enigma2/IStreamReader.h000066400000000000000000000026321356012415200216040ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "kodi/libXBMC_addon.h" #include 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 enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/LocalizedString.h000066400000000000000000000032551356012415200222140ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #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 pvr.vuplus-3.28.9-Leia/src/enigma2/RecordingReader.cpp000066400000000000000000000074641356012415200225170ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "RecordingReader.h" #include "../client.h" #include "p8-platform/threads/mutex.h" #include "utilities/Logger.h" #include using namespace ADDON; using namespace enigma2; using namespace enigma2::utilities; RecordingReader::RecordingReader(const std::string& streamURL, std::time_t start, std::time_t end, int duration) : m_streamURL(streamURL), m_start(start), m_end(end), m_duration(duration) { 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; //If this is an ongoing recording set the duration to the eventual length of the recording if (start > 0 && end > 0) { m_duration = static_cast(end - start); } Logger::Log(LEVEL_DEBUG, "%s RecordingReader: Started - url=%s, start=%u, end=%u, duration=%d", __FUNCTION__, m_streamURL.c_str(), m_start, m_end, m_duration); } RecordingReader::~RecordingReader(void) { if (m_readHandle) XBMC->CloseFile(m_readHandle); Logger::Log(LEVEL_DEBUG, "%s RecordingReader: Stopped", __FUNCTION__); } 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, "%s RecordingReader: Reopening stream...", __FUNCTION__); (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; } int RecordingReader::CurrentDuration() { if (m_end != 0) { time_t now = std::time(nullptr); if (now < m_end) { Logger::Log(LEVEL_DEBUG, "%s RecordingReader - Partial: %d", __FUNCTION__, static_cast(now - m_start)); return now - m_start; } } Logger::Log(LEVEL_DEBUG, "%s RecordingReader - Full: %d", __FUNCTION__, m_duration); return m_duration; } pvr.vuplus-3.28.9-Leia/src/enigma2/RecordingReader.h000066400000000000000000000033431356012415200221540ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "kodi/libXBMC_addon.h" #include #include namespace enigma2 { class RecordingReader { public: RecordingReader(const std::string& streamURL, std::time_t start, std::time_t end, int duration); ~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(); int CurrentDuration(); private: static const int REOPEN_INTERVAL = 30; static const int REOPEN_INTERVAL_FAST = 10; const std::string& m_streamURL; void* m_readHandle; int m_duration; /*!< @brief start and end time of the recording set only in case this an ongoing recording */ std::time_t m_start; std::time_t m_end; std::time_t m_nextReopen; uint64_t m_pos = {0}; uint64_t m_len; }; } // namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/Recordings.cpp000066400000000000000000000626301356012415200215530ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "Recordings.h" #include "../Enigma2.h" #include "../client.h" #include "p8-platform/util/StringUtils.h" #include "util/XMLUtils.h" #include "utilities/Logger.h" #include "utilities/WebUtils.h" #include #include #include #include using namespace enigma2; using namespace enigma2::data; using namespace enigma2::extract; using namespace enigma2::utilities; using json = nlohmann::json; const std::string Recordings::FILE_NOT_FOUND_RESPONSE_SUFFIX = "not found"; Recordings::Recordings(Channels& channels, enigma2::extract::EpgEntryExtractor& entryExtractor) : m_channels(channels), m_entryExtractor(entryExtractor) { std::random_device randomDevice; //Will be used to obtain a seed for the random number engine m_randomGenerator = std::mt19937(randomDevice()); //Standard mersenne_twister_engine seeded with randomDevice() m_randomDistribution = std::uniform_int_distribution<>(E2_DEVICE_LAST_PLAYED_SYNC_INTERVAL_MIN, E2_DEVICE_LAST_PLAYED_SYNC_INTERVAL_MAX); } void Recordings::GetRecordings(std::vector& kodiRecordings, bool deleted) { auto& recordings = (!deleted) ? m_recordings : m_deletedRecordings; for (auto& recording : recordings) { Logger::Log(LEVEL_DEBUG, "%s - Transfer recording '%s', Recording Id '%s'", __FUNCTION__, recording.GetTitle().c_str(), recording.GetRecordingId().c_str()); PVR_RECORDING kodiRecording = {0}; recording.UpdateTo(kodiRecording, m_channels, IsInRecordingFolder(recording.GetTitle(), deleted)); kodiRecordings.emplace_back(kodiRecording); } } int Recordings::GetNumRecordings(bool deleted) const { const auto& recordings = (!deleted) ? m_recordings : m_deletedRecordings; return recordings.size(); } void Recordings::ClearRecordings(bool deleted) { auto& recordings = (!deleted) ? m_recordings : m_deletedRecordings; recordings.clear(); for (auto it = m_recordingsIdMap.begin(); it != m_recordingsIdMap.end();) { if (it->second.IsDeleted() == deleted) it = m_recordingsIdMap.erase(it); else ++it; } } void Recordings::GetRecordingEdl(const std::string& recordingId, std::vector& edlEntries) const { const RecordingEntry recordingEntry = GetRecording(recordingId); if (!recordingEntry.GetEdlURL().empty()) { const std::string edlFile = WebUtils::GetHttp(recordingEntry.GetEdlURL()); if (!StringUtils::EndsWith(edlFile, FILE_NOT_FOUND_RESPONSE_SUFFIX)) { std::istringstream stream(edlFile); std::string line; int lineNumber = 0; while (std::getline(stream, line)) { float start = 0.0f, stop = 0.0f; unsigned int type = PVR_EDL_TYPE_CUT; lineNumber++; if (std::sscanf(line.c_str(), "%f %f %u", &start, &stop, &type) < 2 || type > PVR_EDL_TYPE_COMBREAK) { Logger::Log(LEVEL_NOTICE, "%s Unable to parse EDL entry for recording '%s' at line %d. Skipping.", __FUNCTION__, recordingEntry.GetTitle().c_str(), lineNumber); continue; } start += static_cast(Settings::GetInstance().GetEDLStartTimePadding()) / 1000.0f; stop += static_cast(Settings::GetInstance().GetEDLStopTimePadding()) / 1000.0f; start = std::max(start, 0.0f); stop = std::max(stop, 0.0f); start = std::min(start, stop); stop = std::max(start, stop); Logger::Log(LEVEL_NOTICE, "%s EDL for '%s', line %d - start: %f stop: %f type: %d", __FUNCTION__, recordingEntry.GetTitle().c_str(), lineNumber, start, stop, type); PVR_EDL_ENTRY edlEntry; edlEntry.start = static_cast(start * 1000.0f); edlEntry.end = static_cast(stop * 1000.0f); edlEntry.type = static_cast(type); edlEntries.emplace_back(edlEntry); } } } } RecordingEntry Recordings::GetRecording(const std::string& recordingId) const { RecordingEntry entry; auto recordingPair = m_recordingsIdMap.find(recordingId); if (recordingPair != m_recordingsIdMap.end()) { entry = recordingPair->second; } return entry; } bool Recordings::IsInRecordingFolder(const std::string& recordingFolder, bool deleted) const { const auto& recordings = (!deleted) ? m_recordings : m_deletedRecordings; int iMatches = 0; for (const auto& recording : 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::RenameRecording(const PVR_RECORDING& recording) { auto recordingEntry = GetRecording(recording.strRecordingId); if (!recordingEntry.GetRecordingId().empty()) { Logger::Log(LEVEL_DEBUG, "%s Sending rename command for recording '%s' to '%s'", __FUNCTION__, recordingEntry.GetTitle().c_str(), recording.strTitle); const std::string jsonUrl = StringUtils::Format("%sapi/movieinfo?sref=%s&title=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(recordingEntry.GetRecordingId()).c_str(), WebUtils::URLEncodeInline(recording.strTitle).c_str()); std::string strResult; if (WebUtils::SendSimpleJsonCommand(jsonUrl, strResult)) { PVR->TriggerRecordingUpdate(); return PVR_ERROR_NO_ERROR; } } PVR->TriggerRecordingUpdate(); return PVR_ERROR_SERVER_ERROR; } PVR_ERROR Recordings::SetRecordingPlayCount(const PVR_RECORDING& recording, int count) { auto recordingEntry = GetRecording(recording.strRecordingId); if (!recordingEntry.GetRecordingId().empty()) { if (recording.iPlayCount == count) return PVR_ERROR_NO_ERROR; std::vector oldTags; ReadExtraRecordingPlayCountInfo(recordingEntry, oldTags); std::string addTagsArg = TAG_FOR_PLAY_COUNT + "=" + std::to_string(count); std::string deleteTagsArg; for (std::string& oldTag : oldTags) { if (oldTag != addTagsArg) { if (!deleteTagsArg.empty()) deleteTagsArg += ","; deleteTagsArg += oldTag; } } Logger::Log(LEVEL_DEBUG, "%s Setting playcount for recording '%s' to '%d'", __FUNCTION__, recordingEntry.GetTitle().c_str(), count); const std::string jsonUrl = StringUtils::Format("%sapi/movieinfo?sref=%s&deltag=%s&addtag=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(recordingEntry.GetRecordingId()).c_str(), WebUtils::URLEncodeInline(deleteTagsArg).c_str(), WebUtils::URLEncodeInline(addTagsArg).c_str()); std::string strResult; if (WebUtils::SendSimpleJsonCommand(jsonUrl, strResult)) { PVR->TriggerRecordingUpdate(); return PVR_ERROR_NO_ERROR; } } PVR->TriggerRecordingUpdate(); return PVR_ERROR_SERVER_ERROR; } PVR_ERROR Recordings::SetRecordingLastPlayedPosition(const PVR_RECORDING& recording, int lastPlayedPosition) { auto recordingEntry = GetRecording(recording.strRecordingId); if (!recordingEntry.GetRecordingId().empty()) { if (recording.iLastPlayedPosition == lastPlayedPosition) return PVR_ERROR_NO_ERROR; std::vector> cuts; std::vector oldTags; bool readExtraCutsInfo = ReadExtaRecordingCutsInfo(recordingEntry, cuts, oldTags); std::string cutsArg; bool cutsLastPlayedSet = false; if (readExtraCutsInfo && Settings::GetInstance().GetRecordingLastPlayedMode() == RecordingLastPlayedMode::ACROSS_KODI_AND_E2_INSTANCES) { for (auto cut : cuts) { if (!cutsArg.empty()) cutsArg += ","; if (cut.first == CUTS_LAST_PLAYED_TYPE) { if (!cutsLastPlayedSet) { cutsArg += std::to_string(CUTS_LAST_PLAYED_TYPE) + ":" + std::to_string(PTS_PER_SECOND * lastPlayedPosition); cutsLastPlayedSet = true; } } else { cutsArg += std::to_string(cut.first) + ":" + std::to_string(cut.second); } } if (!cutsLastPlayedSet) { if (!cutsArg.empty()) cutsArg += ","; cutsArg += std::to_string(CUTS_LAST_PLAYED_TYPE) + ":" + std::to_string(PTS_PER_SECOND * lastPlayedPosition); cutsLastPlayedSet = true; } } std::string addTagsArg = TAG_FOR_LAST_PLAYED + "=" + std::to_string(lastPlayedPosition); std::string deleteTagsArg; for (std::string& oldTag : oldTags) { if (oldTag != addTagsArg) { if (!deleteTagsArg.empty()) deleteTagsArg += ","; deleteTagsArg += oldTag; } } addTagsArg += "," + TAG_FOR_NEXT_SYNC_TIME + "=" + std::to_string(std::time(nullptr) + m_randomDistribution(m_randomGenerator)); Logger::Log(LEVEL_DEBUG, "%s Setting last played position for recording '%s' to '%d'", __FUNCTION__, recordingEntry.GetTitle().c_str(), lastPlayedPosition); std::string jsonUrl; if (Settings::GetInstance().GetRecordingLastPlayedMode() == RecordingLastPlayedMode::ACROSS_KODI_INSTANCES || !cutsLastPlayedSet) { jsonUrl = StringUtils::Format("%sapi/movieinfo?sref=%s&deltag=%s&addtag=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(recordingEntry.GetRecordingId()).c_str(), WebUtils::URLEncodeInline(deleteTagsArg).c_str(), WebUtils::URLEncodeInline(addTagsArg).c_str()); } else { jsonUrl = StringUtils::Format("%sapi/movieinfo?sref=%s&deltag=%s&addtag=%s&cuts=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(recordingEntry.GetRecordingId()).c_str(), WebUtils::URLEncodeInline(deleteTagsArg).c_str(), WebUtils::URLEncodeInline(addTagsArg).c_str(), WebUtils::URLEncodeInline(cutsArg).c_str()); } std::string strResult; if (WebUtils::SendSimpleJsonCommand(jsonUrl, strResult)) { PVR->TriggerRecordingUpdate(); return PVR_ERROR_NO_ERROR; } } PVR->TriggerRecordingUpdate(); return PVR_ERROR_SERVER_ERROR; } int Recordings::GetRecordingLastPlayedPosition(const PVR_RECORDING& recording) { auto recordingEntry = GetRecording(recording.strRecordingId); time_t now = std::time(nullptr); time_t newNextSyncTime = now + m_randomDistribution(m_randomGenerator); Logger::Log(LEVEL_DEBUG, "%s Recording: %s - Checking if Next Sync Time: %lld < Now: %lld ", __FUNCTION__, recordingEntry.GetTitle().c_str(), static_cast(recordingEntry.GetNextSyncTime()), static_cast(now)); if (Settings::GetInstance().GetRecordingLastPlayedMode() == RecordingLastPlayedMode::ACROSS_KODI_AND_E2_INSTANCES && recordingEntry.GetNextSyncTime() < now) { //We need to get this value separately as it's not returned by the movielist api //We don't want to call for it everytime as large movie directories would make a lot of calls. //Instead we'll only call out every five to ten mins and store the value so it can be returned by the movielist api. std::vector> cuts; std::vector oldTags; bool readExtraCutsInfo = ReadExtaRecordingCutsInfo(recordingEntry, cuts, oldTags); int lastPlayedPosition = -1; if (readExtraCutsInfo) { for (auto cut : cuts) { if (cut.first == CUTS_LAST_PLAYED_TYPE) { lastPlayedPosition = cut.second / PTS_PER_SECOND; break; } } } if (readExtraCutsInfo && lastPlayedPosition >= 0 && lastPlayedPosition != recordingEntry.GetLastPlayedPosition()) { std::string addTagsArg = TAG_FOR_LAST_PLAYED + "=" + std::to_string(lastPlayedPosition); //then we update it in the tags using movieinfo std::string deleteTagsArg; for (std::string& oldTag : oldTags) { if (oldTag != addTagsArg) { if (!deleteTagsArg.empty()) deleteTagsArg += ","; deleteTagsArg += oldTag; } } addTagsArg += "," + TAG_FOR_NEXT_SYNC_TIME + "=" + std::to_string(newNextSyncTime); Logger::Log(LEVEL_DEBUG, "%s Setting last played position from E2 cuts file to tags for recording '%s' to '%d'", __FUNCTION__, recordingEntry.GetTitle().c_str(), lastPlayedPosition); std::string jsonUrl = StringUtils::Format("%sapi/movieinfo?sref=%s&deltag=%s&addtag=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(recordingEntry.GetRecordingId()).c_str(), WebUtils::URLEncodeInline(deleteTagsArg).c_str(), WebUtils::URLEncodeInline(addTagsArg).c_str()); std::string strResult; if (WebUtils::SendSimpleJsonCommand(jsonUrl, strResult)) { recordingEntry.SetLastPlayedPosition(lastPlayedPosition); recordingEntry.SetNextSyncTime(newNextSyncTime); } } else { //just update the tag for next sync. SetRecordingNextSyncTime(recordingEntry, newNextSyncTime, oldTags); lastPlayedPosition = recordingEntry.GetLastPlayedPosition(); } return lastPlayedPosition; } else { return recordingEntry.GetLastPlayedPosition(); } } void Recordings::SetRecordingNextSyncTime(RecordingEntry& recordingEntry, time_t nextSyncTime, std::vector& oldTags) { Logger::Log(LEVEL_DEBUG, "%s Setting next sync time in tags for recording '%s' to '%lld'", __FUNCTION__, recordingEntry.GetTitle().c_str(), static_cast(nextSyncTime)); std::string addTagsArg = TAG_FOR_NEXT_SYNC_TIME + "=" + std::to_string(nextSyncTime); //then we update it in the tags using movieinfo api std::string deleteTagsArg; for (std::string& oldTag : oldTags) { if (oldTag != addTagsArg && StringUtils::StartsWith(oldTag, TAG_FOR_NEXT_SYNC_TIME + "=")) { if (!deleteTagsArg.empty()) deleteTagsArg += ","; deleteTagsArg += oldTag; } } const std::string jsonUrl = StringUtils::Format("%sapi/movieinfo?sref=%s&deltag=%s&addtag=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(recordingEntry.GetRecordingId()).c_str(), WebUtils::URLEncodeInline(deleteTagsArg).c_str(), WebUtils::URLEncodeInline(addTagsArg).c_str()); std::string strResult; if (!WebUtils::SendSimpleJsonCommand(jsonUrl, strResult)) { recordingEntry.SetNextSyncTime(nextSyncTime); Logger::Log(LEVEL_ERROR, "%s Error setting next sync time for recording '%s' to '%lld'", __FUNCTION__, recordingEntry.GetTitle().c_str(), static_cast(nextSyncTime)); } } PVR_ERROR Recordings::DeleteRecording(const PVR_RECORDING& recinfo) { const 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; // No need to call PVR->TriggerRecordingUpdate() as it is handled by kodi PVR. // In fact when multiple recordings are removed at once, calling it here can cause hanging issues return PVR_ERROR_NO_ERROR; } PVR_ERROR Recordings::UndeleteRecording(const PVR_RECORDING& recording) { auto recordingEntry = GetRecording(recording.strRecordingId); std::regex regex(TRASH_FOLDER); const std::string newRecordingDirectory = std::regex_replace(recordingEntry.GetDirectory(), regex, ""); const std::string strTmp = StringUtils::Format("web/moviemove?sRef=%s&dirname=%s", WebUtils::URLEncodeInline(recordingEntry.GetRecordingId()).c_str(), WebUtils::URLEncodeInline(newRecordingDirectory).c_str()); std::string strResult; if (!WebUtils::SendSimpleCommand(strTmp, strResult)) return PVR_ERROR_FAILED; return PVR_ERROR_NO_ERROR; } PVR_ERROR Recordings::DeleteAllRecordingsFromTrash() { for (const auto& deletedRecording : m_deletedRecordings) { const std::string strTmp = StringUtils::Format("web/moviedelete?sRef=%s", WebUtils::URLEncodeInline(deletedRecording.GetRecordingId()).c_str()); std::string strResult; WebUtils::SendSimpleCommand(strTmp, strResult, true); } return PVR_ERROR_NO_ERROR; } bool Recordings::HasRecordingStreamProgramNumber(const PVR_RECORDING& recording) { return GetRecording(recording.strRecordingId).HasStreamProgramNumber(); } int Recordings::GetRecordingStreamProgramNumber(const PVR_RECORDING& recording) { return GetRecording(recording.strRecordingId).GetStreamProgramNumber(); } const std::string Recordings::GetRecordingURL(const PVR_RECORDING& recinfo) { for (const auto& recording : m_recordings) { if (recinfo.strRecordingId == recording.GetRecordingId()) return recording.GetStreamURL(); } return ""; } bool Recordings::ReadExtaRecordingCutsInfo(const data::RecordingEntry& recordingEntry, std::vector>& cuts, std::vector& tags) { const std::string jsonUrl = StringUtils::Format("%sapi/movieinfo?sref=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(recordingEntry.GetRecordingId()).c_str()); const std::string strJson = WebUtils::GetHttpXML(jsonUrl); try { auto jsonDoc = json::parse(strJson); if (jsonDoc["result"].empty() || !jsonDoc["result"].get()) return false; if (!jsonDoc["cuts"].empty()) { int type; uint64_t position; for (const auto& cut : jsonDoc["cuts"].items()) { for (const auto& element : cut.value().items()) { if (element.key() == "type") type = element.value().get(); if (element.key() == "pos") position = element.value().get(); } cuts.emplace_back(std::make_pair(type, position)); } } if (!jsonDoc["tags"].empty()) { for (const auto& tag : jsonDoc["tags"].items()) { std::string tempTag = tag.value().get(); if (StringUtils::StartsWith(tempTag, TAG_FOR_LAST_PLAYED) || StringUtils::StartsWith(tempTag, TAG_FOR_NEXT_SYNC_TIME)) tags.emplace_back(tempTag); } } return true; } catch (nlohmann::detail::parse_error& e) { Logger::Log(LEVEL_ERROR, "%s Invalid JSON received, cannot find extra recording cuts info from OpenWebIf for recording: %s, ID: %s - JSON parse error - message: %s, exception id: %d", __FUNCTION__, recordingEntry.GetTitle().c_str(), recordingEntry.GetRecordingId().c_str(), e.what(), e.id); } catch (nlohmann::detail::type_error& e) { Logger::Log(LEVEL_ERROR, "%s JSON type error - message: %s, exception id: %d", __FUNCTION__, e.what(), e.id); } return false; } bool Recordings::ReadExtraRecordingPlayCountInfo(const data::RecordingEntry& recordingEntry, std::vector& tags) { const std::string jsonUrl = StringUtils::Format("%sapi/movieinfo?sref=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(recordingEntry.GetRecordingId()).c_str()); const std::string strJson = WebUtils::GetHttpXML(jsonUrl); try { auto jsonDoc = json::parse(strJson); if (jsonDoc["result"].empty() || !jsonDoc["result"].get()) return false; if (!jsonDoc["tags"].empty()) { for (const auto& tag : jsonDoc["tags"].items()) { std::string tempTag = tag.value().get(); if (StringUtils::StartsWith(tempTag, TAG_FOR_PLAY_COUNT)) tags.emplace_back(tempTag); } } return true; } catch (nlohmann::detail::parse_error& e) { Logger::Log(LEVEL_ERROR, "%s Invalid JSON received, cannot find extra recording play count info from OpenWebIf for recording: %s, ID: %s - JSON parse error - message: %s, exception id: %d", __FUNCTION__, recordingEntry.GetTitle().c_str(), recordingEntry.GetRecordingId().c_str(), e.what(), e.id); } catch (nlohmann::detail::type_error& e) { Logger::Log(LEVEL_ERROR, "%s JSON type error - message: %s, exception id: %d", __FUNCTION__, e.what(), e.id); } return false; } 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_ERROR, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem = hDoc.FirstChildElement("e2locations").Element(); if (!pElem) { Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); return false; } TiXmlHandle hRoot = TiXmlHandle(pElem); TiXmlElement* pNode = hRoot.FirstChildElement("e2location").Element(); if (!pNode) { Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); return false; } for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2location")) { const std::string 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(bool deleted) { ClearRecordings(deleted); for (std::string location : m_locations) { if (deleted) location += TRASH_FOLDER; if (!GetRecordingsFromLocation(location, deleted)) { Logger::Log(LEVEL_ERROR, "%s Error fetching lists for folder: '%s'", __FUNCTION__, location.c_str()); } } } bool Recordings::GetRecordingsFromLocation(const std::string recordingLocation, bool deleted) { auto& recordings = (!deleted) ? m_recordings : m_deletedRecordings; 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; } const std::string strXML = WebUtils::GetHttpXML(url); TiXmlDocument xmlDoc; if (!xmlDoc.Parse(strXML.c_str())) { Logger::Log(LEVEL_ERROR, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem = hDoc.FirstChildElement("e2movielist").Element(); if (!pElem) { Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); return false; } TiXmlHandle hRoot = TiXmlHandle(pElem); TiXmlElement* pNode = hRoot.FirstChildElement("e2movie").Element(); int iNumRecordings = 0; if (!pNode) { Logger::Log(LEVEL_DEBUG, "%s Could not find element, no movies at location: %s", directory.c_str(), __FUNCTION__); } else { for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2movie")) { RecordingEntry recordingEntry; if (!recordingEntry.UpdateFrom(pNode, directory, deleted, m_channels)) continue; if (m_entryExtractor.IsEnabled()) m_entryExtractor.ExtractFromEntry(recordingEntry); iNumRecordings++; recordings.emplace_back(recordingEntry); m_recordingsIdMap.insert({recordingEntry.GetRecordingId(), 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; }pvr.vuplus-3.28.9-Leia/src/enigma2/Recordings.h000066400000000000000000000072731356012415200212220ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "Channels.h" #include "data/RecordingEntry.h" #include "extract/EpgEntryExtractor.h" #include "kodi/libXBMC_pvr.h" #include #include #include #include namespace enigma2 { static int64_t PTS_PER_SECOND = 90000; static int CUTS_LAST_PLAYED_TYPE = 3; static int E2_DEVICE_LAST_PLAYED_SYNC_INTERVAL_MIN = 300; static int E2_DEVICE_LAST_PLAYED_SYNC_INTERVAL_MAX = 600; static constexpr const char* TRASH_FOLDER = ".Trash"; class Recordings { public: Recordings(Channels& channels, enigma2::extract::EpgEntryExtractor& entryExtractor); void GetRecordings(std::vector& recordings, bool deleted); int GetNumRecordings(bool deleted) const; void ClearRecordings(bool deleted); void GetRecordingEdl(const std::string& recordingId, std::vector& edlEntries) const; PVR_ERROR RenameRecording(const PVR_RECORDING& recording); PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING& recording, int count); PVR_ERROR SetRecordingLastPlayedPosition(const PVR_RECORDING& recording, int lastplayedposition); int GetRecordingLastPlayedPosition(const PVR_RECORDING& recording); const std::string GetRecordingURL(const PVR_RECORDING& recinfo); PVR_ERROR DeleteRecording(const PVR_RECORDING& recinfo); PVR_ERROR UndeleteRecording(const PVR_RECORDING& recording); PVR_ERROR DeleteAllRecordingsFromTrash(); bool HasRecordingStreamProgramNumber(const PVR_RECORDING& recording); int GetRecordingStreamProgramNumber(const PVR_RECORDING& recording); std::vector& GetLocations(); void ClearLocations(); bool LoadLocations(); void LoadRecordings(bool deleted); private: static const std::string FILE_NOT_FOUND_RESPONSE_SUFFIX; bool GetRecordingsFromLocation(const std::string recordingFolder, bool deleted); data::RecordingEntry GetRecording(const std::string& recordingId) const; bool ReadExtaRecordingCutsInfo(const data::RecordingEntry& recordingEntry, std::vector>& cuts, std::vector& tags); bool ReadExtraRecordingPlayCountInfo(const data::RecordingEntry& recordingEntry, std::vector& tags); void SetRecordingNextSyncTime(data::RecordingEntry& recordingEntry, time_t nextSyncTime, std::vector& oldTags); bool IsInRecordingFolder(const std::string& strRecordingFolder, bool deleted) const; std::mt19937 m_randomGenerator; std::uniform_int_distribution<> m_randomDistribution; std::vector m_recordings; std::vector m_deletedRecordings; std::unordered_map m_recordingsIdMap; std::vector m_locations; Channels& m_channels; enigma2::extract::EpgEntryExtractor& m_entryExtractor; }; } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/Settings.cpp000066400000000000000000000674471356012415200212670ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "Settings.h" #include "../client.h" #include "p8-platform/util/StringUtils.h" #include "tinyxml.h" #include "util/XMLUtils.h" #include "utilities/FileUtils.h" #include "utilities/LocalizedString.h" using namespace ADDON; using namespace enigma2; using namespace enigma2::utilities; /*************************************************************************** * PVR settings **************************************************************************/ void Settings::ReadFromAddon() { FileUtils::CopyDirectory(FileUtils::GetResourceDataPath() + CHANNEL_GROUPS_DIR, CHANNEL_GROUPS_ADDON_DATA_BASE_DIR, true); 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; if (!XBMC->GetSetting("connectionchecktimeout", &m_connectioncCheckTimeoutSecs)) m_connectioncCheckTimeoutSecs = DEFAULT_CONNECTION_CHECK_TIMEOUT_SECS; if (!XBMC->GetSetting("connectioncheckinterval", &m_connectioncCheckIntervalSecs)) m_connectioncCheckIntervalSecs = DEFAULT_CONNECTION_CHECK_INTERVAL_SECS; //General if (!XBMC->GetSetting("setprogramid", &m_setStreamProgramId)) m_setStreamProgramId = false; if (!XBMC->GetSetting("onlinepicons", &m_onlinePicons)) m_onlinePicons = true; if (!XBMC->GetSetting("usepiconseuformat", &m_usePiconsEuFormat)) m_usePiconsEuFormat = false; if (!XBMC->GetSetting("useopenwebifpiconpath", &m_useOpenWebIfPiconPath)) m_useOpenWebIfPiconPath = 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; if (!XBMC->GetSetting("channelandgroupupdatemode", &m_channelAndGroupUpdateMode)) m_channelAndGroupUpdateMode = ChannelAndGroupUpdateMode::RELOAD_CHANNELS_AND_GROUPS; if (!XBMC->GetSetting("channelandgroupupdatehour", &m_channelAndGroupUpdateHour)) m_channelAndGroupUpdateHour = DEFAULT_CHANNEL_AND_GROUP_UPDATE_HOUR; //Channels if (!XBMC->GetSetting("zap", &m_zap)) m_zap = false; if (!XBMC->GetSetting("usestandardserviceref", &m_useStandardServiceReference)) m_useStandardServiceReference = true; if (!XBMC->GetSetting("tvgroupmode", &m_tvChannelGroupMode)) m_tvChannelGroupMode = ChannelGroupMode::ALL_GROUPS; if (!XBMC->GetSetting("numtvgroups", &m_numTVGroups)) m_numTVGroups = DEFAULT_NUM_GROUPS; if (XBMC->GetSetting("onetvgroup", buffer)) m_oneTVGroup = buffer; else m_oneTVGroup = ""; buffer[0] = 0; if (XBMC->GetSetting("twotvgroup", buffer)) m_twoTVGroup = buffer; else m_twoTVGroup = ""; buffer[0] = 0; if (XBMC->GetSetting("threetvgroup", buffer)) m_threeTVGroup = buffer; else m_threeTVGroup = ""; buffer[0] = 0; if (XBMC->GetSetting("fourtvgroup", buffer)) m_fourTVGroup = buffer; else m_fourTVGroup = ""; buffer[0] = 0; if (XBMC->GetSetting("fivetvgroup", buffer)) m_fiveTVGroup = buffer; else m_fiveTVGroup = ""; buffer[0] = 0; if (m_tvChannelGroupMode == ChannelGroupMode::SOME_GROUPS) { m_customTVChannelGroupNameList.clear(); if (!m_oneTVGroup.empty() && m_numTVGroups >= 1) m_customTVChannelGroupNameList.emplace_back(m_oneTVGroup); if (!m_twoTVGroup.empty() && m_numTVGroups >= 2) m_customTVChannelGroupNameList.emplace_back(m_twoTVGroup); if (!m_threeTVGroup.empty() && m_numTVGroups >= 3) m_customTVChannelGroupNameList.emplace_back(m_threeTVGroup); if (!m_fourTVGroup.empty() && m_numTVGroups >= 4) m_customTVChannelGroupNameList.emplace_back(m_fourTVGroup); if (!m_fiveTVGroup.empty() && m_numTVGroups >= 5) m_customTVChannelGroupNameList.emplace_back(m_fiveTVGroup); } if (XBMC->GetSetting("customtvgroupsfile", buffer)) m_customTVGroupsFile = buffer; else m_customTVGroupsFile = DEFAULT_CUSTOM_TV_GROUPS_FILE; buffer[0] = 0; if (m_tvChannelGroupMode == ChannelGroupMode::CUSTOM_GROUPS) LoadCustomChannelGroupFile(m_customTVGroupsFile, m_customTVChannelGroupNameList); if (!XBMC->GetSetting("tvfavouritesmode", &m_tvFavouritesMode)) m_tvFavouritesMode = FavouritesGroupMode::DISABLED; if (!XBMC->GetSetting("excludelastscannedtv", &m_excludeLastScannedTVGroup)) m_excludeLastScannedTVGroup = true; if (!XBMC->GetSetting("radiogroupmode", &m_radioChannelGroupMode)) m_radioChannelGroupMode = ChannelGroupMode::ALL_GROUPS; if (!XBMC->GetSetting("numradiogroups", &m_numRadioGroups)) m_numRadioGroups = DEFAULT_NUM_GROUPS; if (XBMC->GetSetting("oneradiogroup", buffer)) m_oneRadioGroup = buffer; else m_oneRadioGroup = ""; buffer[0] = 0; if (XBMC->GetSetting("tworadiogroup", buffer)) m_twoRadioGroup = buffer; else m_twoRadioGroup = ""; buffer[0] = 0; if (XBMC->GetSetting("threeradiogroup", buffer)) m_threeRadioGroup = buffer; else m_threeRadioGroup = ""; buffer[0] = 0; if (XBMC->GetSetting("fourradiogroup", buffer)) m_fourRadioGroup = buffer; else m_fourRadioGroup = ""; buffer[0] = 0; if (XBMC->GetSetting("fiveradiogroup", buffer)) m_fiveRadioGroup = buffer; else m_fiveRadioGroup = ""; buffer[0] = 0; if (m_radioChannelGroupMode == ChannelGroupMode::SOME_GROUPS) { m_customRadioChannelGroupNameList.clear(); if (!m_oneRadioGroup.empty() && m_numRadioGroups >= 1) m_customRadioChannelGroupNameList.emplace_back(m_oneRadioGroup); if (!m_twoRadioGroup.empty() && m_numRadioGroups >= 2) m_customRadioChannelGroupNameList.emplace_back(m_twoRadioGroup); if (!m_threeRadioGroup.empty() && m_numRadioGroups >= 3) m_customRadioChannelGroupNameList.emplace_back(m_threeRadioGroup); if (!m_fourRadioGroup.empty() && m_numRadioGroups >= 4) m_customRadioChannelGroupNameList.emplace_back(m_fourRadioGroup); if (!m_fiveRadioGroup.empty() && m_numRadioGroups >= 5) m_customRadioChannelGroupNameList.emplace_back(m_fiveRadioGroup); } if (XBMC->GetSetting("customradiogroupsfile", buffer)) m_customRadioGroupsFile = buffer; else m_customRadioGroupsFile = DEFAULT_CUSTOM_RADIO_GROUPS_FILE; buffer[0] = 0; if (m_radioChannelGroupMode == ChannelGroupMode::CUSTOM_GROUPS) LoadCustomChannelGroupFile(m_customRadioGroupsFile, m_customRadioChannelGroupNameList); if (!XBMC->GetSetting("radiofavouritesmode", &m_radioFavouritesMode)) m_radioFavouritesMode = FavouritesGroupMode::DISABLED; if (!XBMC->GetSetting("excludelastscannedradio", &m_excludeLastScannedRadioGroup)) m_excludeLastScannedRadioGroup = true; //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; if (!XBMC->GetSetting("epgdelayperchannel", &m_epgDelayPerChannel)) m_epgDelayPerChannel = 0; if (!XBMC->GetSetting("skipinitialepg", &m_skipInitialEpgLoad)) m_skipInitialEpgLoad = true; //Recording if (!XBMC->GetSetting("storeextrarecordinginfo", &m_storeLastPlayedAndCount)) m_storeLastPlayedAndCount = false; if (!XBMC->GetSetting("sharerecordinglastplayed", &m_recordingLastPlayedMode)) m_recordingLastPlayedMode = RecordingLastPlayedMode::ACROSS_KODI_INSTANCES; 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("enablerecordingedls", &m_enableRecordingEDLs)) m_enableRecordingEDLs = false; if (!XBMC->GetSetting("edlpaddingstart", &m_edlStartTimePadding)) m_edlStartTimePadding = 0; if (!XBMC->GetSetting("edlpaddingstop", &m_edlStopTimePadding)) m_edlStopTimePadding = 0; //Timers 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("timerlistcleanup", &m_automaticTimerlistCleanup)) m_automaticTimerlistCleanup = false; if (!XBMC->GetSetting("enableautotimers", &m_enableAutoTimers)) m_enableAutoTimers = true; if (!XBMC->GetSetting("limitanychannelautotimers", &m_limitAnyChannelAutoTimers)) m_limitAnyChannelAutoTimers = true; if (!XBMC->GetSetting("limitanychannelautotimerstogroups", &m_limitAnyChannelAutoTimersToChannelGroups)) m_limitAnyChannelAutoTimersToChannelGroups = true; //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 = ADDON_DATA_BASE_DIR; 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; if (!XBMC->GetSetting("nodebug", &m_noDebug)) m_noDebug = false; if (!XBMC->GetSetting("debugnormal", &m_debugNormal)) m_debugNormal = false; if (!XBMC->GetSetting("tracedebug", &m_traceDebug)) m_traceDebug = false; // 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); else if (settingName == "connectionchecktimeout") return SetSetting(settingName, settingValue, m_connectioncCheckTimeoutSecs, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "connectioncheckinterval") return SetSetting(settingName, settingValue, m_connectioncCheckIntervalSecs, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); //General else if (settingName == "setprogramid") return SetSetting(settingName, settingValue, m_setStreamProgramId, ADDON_STATUS_OK, ADDON_STATUS_OK); 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 == "useopenwebifpiconpath") return SetSetting(settingName, settingValue, m_useOpenWebIfPiconPath, 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); else if (settingName == "channelandgroupupdatemode") return SetSetting(settingName, settingValue, m_channelAndGroupUpdateMode, ADDON_STATUS_OK, ADDON_STATUS_OK); else if (settingName == "channelandgroupupdatehour") return SetSetting(settingName, settingValue, m_channelAndGroupUpdateHour, 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 == "usestandardserviceref") return SetSetting(settingName, settingValue, m_useStandardServiceReference, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "tvgroupmode") return SetSetting(settingName, settingValue, m_tvChannelGroupMode, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "numtvgroups") return SetSetting(settingName, settingValue, m_numTVGroups, 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 == "twotvgroup") return SetStringSetting(settingName, settingValue, m_twoTVGroup, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "threetvgroup") return SetStringSetting(settingName, settingValue, m_threeTVGroup, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "twotvgroup") return SetStringSetting(settingName, settingValue, m_fourTVGroup, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "fivetvgroup") return SetStringSetting(settingName, settingValue, m_fiveTVGroup, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "customtvgroupsfile") return SetStringSetting(settingName, settingValue, m_customTVGroupsFile, 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 == "excludelastscannedtv") return SetSetting(settingName, settingValue, m_excludeLastScannedTVGroup, 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 == "numradiogroups") return SetSetting(settingName, settingValue, m_numRadioGroups, 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 == "tworadiogroup") return SetStringSetting(settingName, settingValue, m_twoRadioGroup, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "threeradiogroup") return SetStringSetting(settingName, settingValue, m_threeRadioGroup, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "fourradiogroup") return SetStringSetting(settingName, settingValue, m_fourRadioGroup, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "fiveradiogroup") return SetStringSetting(settingName, settingValue, m_fiveRadioGroup, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "customradiogroupsfile") return SetStringSetting(settingName, settingValue, m_customRadioGroupsFile, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "radiofavouritesmode") return SetSetting(settingName, settingValue, m_radioFavouritesMode, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "excludelastscannedradio") return SetSetting(settingName, settingValue, m_excludeLastScannedRadioGroup, 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); else if (settingName == "epgdelayperchannel") return SetSetting(settingName, settingValue, m_epgDelayPerChannel, ADDON_STATUS_OK, ADDON_STATUS_OK); else if (settingName == "skipinitialepg") return SetSetting(settingName, settingValue, m_skipInitialEpgLoad, ADDON_STATUS_OK, ADDON_STATUS_OK); //Recordings else if (settingName == "storeextrarecordinginfo") return SetSetting(settingName, settingValue, m_storeLastPlayedAndCount, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "sharerecordinglastplayed") return SetSetting(settingName, settingValue, m_recordingLastPlayedMode, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); 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 == "enablerecordingedls") return SetSetting(settingName, settingValue, m_enableRecordingEDLs, ADDON_STATUS_NEED_RESTART, ADDON_STATUS_OK); else if (settingName == "edlpaddingstart") return SetSetting(settingName, settingValue, m_edlStartTimePadding, ADDON_STATUS_OK, ADDON_STATUS_OK); else if (settingName == "edlpaddingstop") return SetSetting(settingName, settingValue, m_edlStopTimePadding, ADDON_STATUS_OK, ADDON_STATUS_OK); //Timers 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 == "timerlistcleanup") return SetSetting(settingName, settingValue, m_automaticTimerlistCleanup, 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 == "limitanychannelautotimers") return SetSetting(settingName, settingValue, m_limitAnyChannelAutoTimers, ADDON_STATUS_OK, ADDON_STATUS_OK); else if (settingName == "limitanychannelautotimerstogroups") return SetSetting(settingName, settingValue, m_limitAnyChannelAutoTimersToChannelGroups, 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); else if (settingName == "nodebug") return SetSetting(settingName, settingValue, m_noDebug, ADDON_STATUS_OK, ADDON_STATUS_OK); else if (settingName == "debugnormal") return SetSetting(settingName, settingValue, m_debugNormal, ADDON_STATUS_OK, ADDON_STATUS_OK); else if (settingName == "tracedebug") return SetSetting(settingName, settingValue, m_traceDebug, 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()); } bool Settings::LoadCustomChannelGroupFile(std::string& xmlFile, std::vector& channelGroupNameList) { channelGroupNameList.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()); const 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, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem = hDoc.FirstChildElement("customChannelGroups").Element(); if (!pElem) { Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); return false; } TiXmlHandle hRoot = TiXmlHandle(pElem); TiXmlElement* pNode = hRoot.FirstChildElement("channelGroupName").Element(); if (!pNode) { Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); return false; } for (; pNode != nullptr; pNode = pNode->NextSiblingElement("channelGroupName")) { const std::string channelGroupName = pNode->GetText(); channelGroupNameList.emplace_back(channelGroupName); Logger::Log(LEVEL_TRACE, "%s Read Custom ChannelGroup Name: %s, from file: %s", __FUNCTION__, channelGroupName.c_str(), xmlFile.c_str()); } return true; } pvr.vuplus-3.28.9-Leia/src/enigma2/Settings.h000066400000000000000000000407261356012415200207230ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "Admin.h" #include "utilities/DeviceInfo.h" #include "utilities/DeviceSettings.h" #include "utilities/Logger.h" #include "kodi/xbmc_addon_types.h" #include #include 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_CONNECTION_CHECK_TIMEOUT_SECS = 10; static const int DEFAULT_CONNECTION_CHECK_INTERVAL_SECS = 1; static const int DEFAULT_UPDATE_INTERVAL = 2; static const int DEFAULT_CHANNEL_AND_GROUP_UPDATE_HOUR = 4; static const int DEFAULT_NUM_GROUPS = 1; static const std::string ADDON_DATA_BASE_DIR = "special://userdata/addon_data/pvr.vuplus"; static const std::string DEFAULT_SHOW_INFO_FILE = ADDON_DATA_BASE_DIR + "/showInfo/English-ShowInfo.xml"; static const std::string DEFAULT_GENRE_ID_MAP_FILE = ADDON_DATA_BASE_DIR + "/genres/genreIdMappings/Sky-UK.xml"; static const std::string DEFAULT_GENRE_TEXT_MAP_FILE = ADDON_DATA_BASE_DIR + "/genres/genreRytecTextMappings/Rytec-UK-Ireland.xml"; static const std::string DEFAULT_CUSTOM_TV_GROUPS_FILE = ADDON_DATA_BASE_DIR + "/channelGroups/customRadioGroups-example.xml"; static const std::string DEFAULT_CUSTOM_RADIO_GROUPS_FILE = ADDON_DATA_BASE_DIR + "/channelGroups/customRadioGroups-example.xml"; static const int DEFAULT_NUM_GEN_REPEAT_TIMERS = 1; static const std::string CHANNEL_GROUPS_DIR = "/channelGroups"; static const std::string CHANNEL_GROUPS_ADDON_DATA_BASE_DIR = ADDON_DATA_BASE_DIR + CHANNEL_GROUPS_DIR; enum class UpdateMode : int // same type as addon settings { TIMERS_AND_RECORDINGS = 0, TIMERS_ONLY }; enum class ChannelAndGroupUpdateMode : int // same type as addon settings { DISABLED = 0, NOTIFY_AND_LOG, RELOAD_CHANNELS_AND_GROUPS }; enum class ChannelGroupMode : int // same type as addon settings { ALL_GROUPS = 0, SOME_GROUPS, FAVOURITES_GROUP, CUSTOM_GROUPS }; enum class FavouritesGroupMode : int // same type as addon settings { DISABLED = 0, AS_FIRST_GROUP, AS_LAST_GROUP }; enum class RecordingLastPlayedMode : int // same type as addon settings { ACROSS_KODI_INSTANCES = 0, ACROSS_KODI_AND_E2_INSTANCES }; 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; } int GetConnectioncCheckTimeoutSecs() const { return m_connectioncCheckTimeoutSecs; } int GetConnectioncCheckIntervalSecs() const { return m_connectioncCheckIntervalSecs; } //General bool SetStreamProgramID() const { return m_setStreamProgramId; } bool UseOnlinePicons() const { return m_onlinePicons; } bool UsePiconsEuFormat() const { return m_usePiconsEuFormat; } bool UseOpenWebIfPiconPath() const { return m_useOpenWebIfPiconPath; } const std::string& GetIconPath() const { return m_iconPath; } unsigned int GetUpdateIntervalMins() const { return m_updateInterval; } UpdateMode GetUpdateMode() const { return m_updateMode; } unsigned int GetChannelAndGroupUpdateHour() const { return m_channelAndGroupUpdateHour; } ChannelAndGroupUpdateMode GetChannelAndGroupUpdateMode() const { return m_channelAndGroupUpdateMode; } //Channel bool GetZapBeforeChannelSwitch() const { return m_zap; } bool UseStandardServiceReference() const { return m_useStandardServiceReference; } const ChannelGroupMode& GetTVChannelGroupMode() const { return m_tvChannelGroupMode; } const std::string& GetCustomTVGroupsFile() const { return m_customTVGroupsFile; } const FavouritesGroupMode& GetTVFavouritesMode() const { return m_tvFavouritesMode; } bool ExcludeLastScannedTVGroup() const { return m_excludeLastScannedTVGroup; } const ChannelGroupMode& GetRadioChannelGroupMode() const { return m_radioChannelGroupMode; } const std::string& GetCustomRadioGroupsFile() const { return m_customRadioGroupsFile; } const FavouritesGroupMode& GetRadioFavouritesMode() const { return m_radioFavouritesMode; } bool ExcludeLastScannedRadioGroup() const { return m_excludeLastScannedRadioGroup; } //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; } int GetEPGDelayPerChannelDelay() const { return m_epgDelayPerChannel; } bool SkipInitialEpgLoad() const { return m_skipInitialEpgLoad; } //Recordings bool GetStoreRecordingLastPlayedAndCount() const { return m_storeLastPlayedAndCount; } const RecordingLastPlayedMode& GetRecordingLastPlayedMode() const { return m_recordingLastPlayedMode; } const std::string& GetRecordingPath() const { return m_recordingPath; } bool GetRecordingsFromCurrentLocationOnly() const { return m_onlyCurrentLocation; } bool GetKeepRecordingsFolders() const { return m_keepFolders; } bool GetRecordingEDLsEnabled() const { return m_enableRecordingEDLs; } int GetEDLStartTimePadding() const { return m_edlStartTimePadding; } int GetEDLStopTimePadding() const { return m_edlStopTimePadding; } //Timers bool GetGenRepeatTimersEnabled() const { return m_enableGenRepeatTimers; } int GetNumGenRepeatTimers() const { return m_numGenRepeatTimers; } bool GetAutoTimerListCleanupEnabled() const { return m_automaticTimerlistCleanup; } bool GetAutoTimersEnabled() const { return m_enableAutoTimers; } bool GetLimitAnyChannelAutoTimers() const { return m_limitAnyChannelAutoTimers; } bool GetLimitAnyChannelAutoTimersToChannelGroups() const { return m_limitAnyChannelAutoTimersToChannelGroups; } //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; } bool GetNoDebug() const { return m_noDebug; }; bool GetDebugNormal() const { return m_debugNormal; }; bool GetTraceDebug() const { return m_traceDebug; }; const std::string& GetConnectionURL() const { return m_connectionURL; } unsigned int GetWebIfVersionAsNum() const { return m_deviceInfo->GetWebIfVersionAsNum(); } const std::string& GetWebIfVersion() const { return m_deviceInfo->GetWebIfVersion(); } 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(); m_deviceSettingsSet = true; } void SetAdmin(enigma2::Admin* admin) { m_admin = admin; } inline unsigned int GenerateWebIfVersionAsNum(unsigned int major, unsigned int minor, unsigned int patch) const { return (major << 16 | minor << 8 | patch); }; bool CheckOpenWebIfVersion(unsigned int major, unsigned int minor, unsigned int patch) const { return m_deviceSettingsSet ? GetWebIfVersionAsNum() >= GenerateWebIfVersionAsNum(major, minor, patch) && StringUtils::StartsWith(GetWebIfVersion(), "OWIF") : m_deviceSettingsSet; } bool IsOpenWebIf() const { return StringUtils::StartsWith(GetWebIfVersion(), "OWIF"); } bool SupportsEditingRecordings() const { return CheckOpenWebIfVersion(1, 3, 6); } bool SupportsAutoTimers() const { return CheckOpenWebIfVersion(1, 3, 0); } bool SupportsTunerDetails() const { return CheckOpenWebIfVersion(1, 3, 5); } bool SupportsProviderNumberAndPiconForChannels() const { return CheckOpenWebIfVersion(1, 3, 5); } bool SupportsChannelNumberGroupStartPos() const { return CheckOpenWebIfVersion(1, 3, 7); } bool UsesLastScannedChannelGroup() const { return m_usesLastScannedChannelGroup; } void SetUsesLastScannedChannelGroup(bool value) { m_usesLastScannedChannelGroup = value; } std::vector& GetCustomTVChannelGroupNameList() { return m_customTVChannelGroupNameList; } std::vector& GetCustomRadioChannelGroupNameList() { return m_customRadioChannelGroupNameList; } 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& currentValue, 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; } static bool LoadCustomChannelGroupFile(std::string& file, std::vector& channelGroupNameList); //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; int m_connectioncCheckTimeoutSecs = DEFAULT_CONNECTION_CHECK_TIMEOUT_SECS; int m_connectioncCheckIntervalSecs = DEFAULT_CONNECTION_CHECK_INTERVAL_SECS; //General bool m_setStreamProgramId = false; bool m_onlinePicons = true; bool m_usePiconsEuFormat = false; bool m_useOpenWebIfPiconPath = false; std::string m_iconPath = ""; unsigned int m_updateInterval = DEFAULT_UPDATE_INTERVAL; UpdateMode m_updateMode = UpdateMode::TIMERS_AND_RECORDINGS; ChannelAndGroupUpdateMode m_channelAndGroupUpdateMode = ChannelAndGroupUpdateMode::RELOAD_CHANNELS_AND_GROUPS; unsigned int m_channelAndGroupUpdateHour = DEFAULT_CHANNEL_AND_GROUP_UPDATE_HOUR; //Channel bool m_zap = false; bool m_useStandardServiceReference = true; ChannelGroupMode m_tvChannelGroupMode = ChannelGroupMode::ALL_GROUPS; unsigned int m_numTVGroups = DEFAULT_NUM_GROUPS; std::string m_oneTVGroup = ""; std::string m_twoTVGroup = ""; std::string m_threeTVGroup = ""; std::string m_fourTVGroup = ""; std::string m_fiveTVGroup = ""; std::string m_customTVGroupsFile; FavouritesGroupMode m_tvFavouritesMode = FavouritesGroupMode::DISABLED; bool m_excludeLastScannedTVGroup = true; ChannelGroupMode m_radioChannelGroupMode = ChannelGroupMode::ALL_GROUPS; unsigned int m_numRadioGroups = DEFAULT_NUM_GROUPS; std::string m_oneRadioGroup = ""; std::string m_twoRadioGroup = ""; std::string m_threeRadioGroup = ""; std::string m_fourRadioGroup = ""; std::string m_fiveRadioGroup = ""; std::string m_customRadioGroupsFile; FavouritesGroupMode m_radioFavouritesMode = FavouritesGroupMode::DISABLED; bool m_excludeLastScannedRadioGroup = true; //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; int m_epgDelayPerChannel; bool m_skipInitialEpgLoad = true; //Recordings bool m_storeLastPlayedAndCount = true; RecordingLastPlayedMode m_recordingLastPlayedMode = RecordingLastPlayedMode::ACROSS_KODI_INSTANCES; std::string m_recordingPath = ""; bool m_onlyCurrentLocation = false; bool m_keepFolders = false; bool m_enableRecordingEDLs = false; int m_edlStartTimePadding = 0; int m_edlStopTimePadding = 0; //Timers bool m_enableGenRepeatTimers = true; int m_numGenRepeatTimers = DEFAULT_NUM_GEN_REPEAT_TIMERS; bool m_automaticTimerlistCleanup = false; bool m_enableAutoTimers = true; bool m_limitAnyChannelAutoTimers = true; bool m_limitAnyChannelAutoTimersToChannelGroups = false; //Timeshift Timeshift m_timeshift = Timeshift::OFF; std::string m_timeshiftBufferPath = ADDON_DATA_BASE_DIR; //Advanced PrependOutline m_prependOutline = PrependOutline::IN_EPG; PowerstateMode m_powerstateMode = PowerstateMode::DISABLED; int m_readTimeout = 0; int m_streamReadChunkSize = 0; bool m_noDebug = false; bool m_debugNormal = false; bool m_traceDebug = false; //Backend int m_globalStartPaddingStb = 0; int m_globalEndPaddingStb = 0; //Last Scanned bool m_usesLastScannedChannelGroup = false; std::string m_connectionURL; enigma2::utilities::DeviceInfo* m_deviceInfo; enigma2::utilities::DeviceSettings* m_deviceSettings; enigma2::Admin* m_admin; bool m_deviceSettingsSet = false; std::vector m_customTVChannelGroupNameList; std::vector m_customRadioChannelGroupNameList; //PVR Props std::string m_szUserPath = ""; std::string m_szClientPath = ""; }; } //namespace enigma2 pvr.vuplus-3.28.9-Leia/src/enigma2/StreamReader.cpp000066400000000000000000000044471356012415200220340ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #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 readTimeout) { m_streamHandle = XBMC->CURLCreate(streamURL.c_str()); if (readTimeout > 0) XBMC->CURLAddOption(m_streamHandle, XFILE::CURL_OPTION_PROTOCOL, "connection-timeout", std::to_string(readTimeout).c_str()); Logger::Log(LEVEL_DEBUG, "%s StreamReader: Started; url=%s", __FUNCTION__, streamURL.c_str()); } StreamReader::~StreamReader(void) { if (m_streamHandle) XBMC->CloseFile(m_streamHandle); Logger::Log(LEVEL_DEBUG, "%s StreamReader: Stopped", __FUNCTION__); } 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; } pvr.vuplus-3.28.9-Leia/src/enigma2/StreamReader.h000066400000000000000000000030401356012415200214650ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #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 enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/Timers.cpp000066400000000000000000001340511356012415200207140ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "Timers.h" #include "../Enigma2.h" #include "../client.h" #include "inttypes.h" #include "p8-platform/util/StringUtils.h" #include "util/XMLUtils.h" #include "utilities/LocalizedString.h" #include "utilities/Logger.h" #include "utilities/UpdateState.h" #include "utilities/WebUtils.h" #include #include #include 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_ERROR, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return timers; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem = hDoc.FirstChildElement("e2timerlist").Element(); if (!pElem) { Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); return timers; } TiXmlHandle hRoot = TiXmlHandle(pElem); TiXmlElement* pNode = hRoot.FirstChildElement("e2timer").Element(); if (!pNode) { Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); return timers; } for (; pNode != nullptr; pNode = pNode->NextSiblingElement("e2timer")) { Timer newTimer; if (!newTimer.UpdateFrom(pNode, m_channels)) continue; if (m_entryExtractor.IsEnabled()) m_entryExtractor.ExtractFromEntry(newTimer); 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 '%lld', end '%lld', start padding mins '%u', end padding mins '%u'", __FUNCTION__, newTimer.GetTitle().c_str(), static_cast(newTimer.GetStartTime()), static_cast(newTimer.GetEndTime()), newTimer.GetPaddingStartMins(), newTimer.GetPaddingEndMins()); } 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()); newTimer.SetPaddingStartMins(timer->GetPaddingStartMins()); newTimer.SetPaddingEndMins(timer->GetPaddingEndMins()); time_t now = std::time(nullptr); 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 std::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_ERROR, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return autoTimers; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem = hDoc.FirstChildElement("autotimer").Element(); if (!pElem) { Logger::Log(LEVEL_ERROR, "%s Could not find element!", __FUNCTION__); return autoTimers; } TiXmlHandle hRoot = TiXmlHandle(pElem); TiXmlElement* pNode = hRoot.FirstChildElement("timer").Element(); if (!pNode) { Logger::Log(LEVEL_ERROR, "%s Could not find element", __FUNCTION__); 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 '%lld', end '%lld'", __FUNCTION__, newAutoTimer.GetTitle().c_str(), static_cast(newAutoTimer.GetStartTime()), static_cast(newAutoTimer.GetEndTime())); } Logger::Log(LEVEL_INFO, "%s fetched %u AutoTimer Entries", __FUNCTION__, autoTimers.size()); return autoTimers; } 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 preventDuplicateEpisodesDefault = AutoTimer::DeDup::DISABLED) { int i; memset(this, 0, sizeof(PVR_TIMER_TYPE)); iId = id; iAttributes = attributes; strncpy(strDescription, description.c_str(), sizeof(strDescription) - 1); if ((iRecordingGroupSize = groupValues.size())) iRecordingGroupDefault = groupValues[0].first; i = 0; for (const auto& group : groupValues) { recordingGroup[i].iValue = group.first; strncpy(recordingGroup[i].strDescription, group.second.c_str(), sizeof(recordingGroup[i].strDescription) - 1); i++; } if ((iPreventDuplicateEpisodesSize = deDupValues.size())) iPreventDuplicateEpisodesDefault = preventDuplicateEpisodesDefault; i = 0; for (const auto& deDup : deDupValues) { preventDuplicateEpisodes[i].iValue = deDup.first; strncpy(preventDuplicateEpisodes[i].strDescription, deDup.second.c_str(), sizeof(preventDuplicateEpisodes[i].strDescription) - 1); i++; } } }; /* PVR_Timer.iRecordingGroup values and presentation.*/ std::vector> groupValues = { {0, LocalizedString(30410)}, //automatic }; for (const 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 | PVR_TIMER_TYPE_FORBIDS_EPG_TAG_ON_CREATE, LocalizedString(30422), // Once off time/channel based groupValues); types.emplace_back(*t); delete t; /* One-shot generated by manual repeating timer - note these are completely read only and cannot be edited */ t = new 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), // Once off timer (set by repeating time/channel based rule) groupValues); types.emplace_back(*t); delete 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 | PVR_TIMER_TYPE_FORBIDS_EPG_TAG_ON_CREATE, LocalizedString(30423), // Repeating time/channel based groupValues); types.emplace_back(*t); delete 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, LocalizedString(30424)); // One time guide-based types.emplace_back(*t); delete t; if (!Settings::GetInstance().SupportsAutoTimers() || !m_settings.GetAutoTimersEnabled()) { // Allow this type of timer to be created from kodi if autotimers are not available // as otherwise there is no way to create a repeating EPG timer rule /* Repeating epg based */ t = new TimerType( Timer::Type::EPG_REPEATING, 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, LocalizedString(30425)); // Repeating guide-based types.emplace_back(*t); delete t; } else { // This type can only be created on the Enigma2 device (i.e. not via kodi PVR) if autotimers are used. // In this case this type is superflous and just clutters the UI on creation. /* 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, LocalizedString(30425)); // Repeating guide-based types.emplace_back(*t); delete t; /* 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_TITLE_EPG_MATCH | PVR_TIMER_TYPE_SUPPORTS_FULLTEXT_EPG_MATCH | PVR_TIMER_TYPE_SUPPORTS_RECORDING_GROUP | PVR_TIMER_TYPE_SUPPORTS_RECORD_ONLY_NEW_EPISODES | PVR_TIMER_TYPE_REQUIRES_EPG_TAG_ON_CREATE, LocalizedString(30426), // Auto guide-based groupValues, deDupValues, AutoTimer::DeDup::CHECK_TITLE_AND_ALL_DESCS); types.emplace_back(*t); delete t; /* One-shot created by epg auto search */ t = new 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_READONLY_DELETE | 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 | PVR_TIMER_TYPE_REQUIRES_EPG_TAG_ON_CREATE, LocalizedString(30420), // Once off timer (set by auto guide-based rule) groupValues); types.emplace_back(*t); delete 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 = {0}; 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 = {0}; 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 - Start", __FUNCTION__); const std::string serviceReference = m_channels.GetChannel(timer.iClientChannelUid)->GetServiceReference().c_str(); Tags tags; if (timer.iTimerType == Timer::MANUAL_ONCE || timer.iTimerType == Timer::MANUAL_REPEATING) tags.AddTag(TAG_FOR_MANUAL_TIMER); else tags.AddTag(TAG_FOR_EPG_TIMER); if (m_channels.GetChannel(timer.iClientChannelUid)->IsRadio()) tags.AddTag(TAG_FOR_CHANNEL_TYPE, VALUE_FOR_CHANNEL_TYPE_RADIO); else tags.AddTag(TAG_FOR_CHANNEL_TYPE, VALUE_FOR_CHANNEL_TYPE_TV); tags.AddTag(TAG_FOR_CHANNEL_REFERENCE, serviceReference, true); unsigned int startPadding = timer.iMarginStart; unsigned int endPadding = timer.iMarginEnd; if (startPadding == 0 && endPadding == 0) { startPadding = Settings::GetInstance().GetDeviceSettings()->GetGlobalRecordingStartMargin(); endPadding = Settings::GetInstance().GetDeviceSettings()->GetGlobalRecordingEndMargin(); } bool alreadyStarted = false; time_t startTime, endTime; time_t now = std::time(nullptr); if ((timer.startTime - (startPadding * 60)) < now) { alreadyStarted = true; startTime = now; if (timer.startTime < now) startPadding = 0; else startPadding = (timer.startTime - now) / 60; } else { startTime = timer.startTime - (startPadding * 60); } endTime = timer.endTime + (endPadding * 60); tags.AddTag(TAG_FOR_PADDING, StringUtils::Format("%u,%u", startPadding, endPadding)); std::string title = timer.strTitle; std::string description = timer.strSummary; unsigned int epgUid = timer.iEpgUid; bool foundEntry = false; if (Settings::GetInstance().IsOpenWebIf() && (timer.iTimerType == Timer::EPG_ONCE || timer.iTimerType == Timer::MANUAL_ONCE)) { // We try to find the EPG Entry and use it's details EpgPartialEntry partialEntry = m_epg.LoadEPGEntryPartialDetails(serviceReference, timer.startTime < now ? now : timer.startTime); if (partialEntry.EntryFound()) { foundEntry = true; /* Note that plot (long desc) is automatically written to a timer entry by the backend therefore we only need to send outline as description to preserve both. Once a timer completes, long description will be cleared so if description is not populated we set it to the value of long description */ title = partialEntry.GetTitle(); description = partialEntry.GetPlotOutline(); epgUid = partialEntry.GetEpgUid(); // Very important for providers that only use the plot field. if (description.empty()) description = partialEntry.GetPlot(); tags.AddTag(TAG_FOR_GENRE_ID, StringUtils::Format("0x%02X", partialEntry.GetGenreType() | partialEntry.GetGenreSubType())); } } if (!foundEntry) tags.AddTag(TAG_FOR_GENRE_ID, StringUtils::Format("0x%02X", timer.iGenreType | timer.iGenreSubType)); std::string strTmp; if (!m_settings.GetRecordingPath().empty()) strTmp = StringUtils::Format("web/timeradd?sRef=%s&repeated=%d&begin=%lld&end=%lld&name=%s&description=%s&eit=%d&tags=%s&dirname=&s", WebUtils::URLEncodeInline(serviceReference).c_str(), timer.iWeekdays, static_cast(startTime), static_cast(endTime), WebUtils::URLEncodeInline(title).c_str(), WebUtils::URLEncodeInline(description).c_str(), epgUid, WebUtils::URLEncodeInline(tags.GetTags()).c_str(), WebUtils::URLEncodeInline(m_settings.GetRecordingPath()).c_str()); else strTmp = StringUtils::Format("web/timeradd?sRef=%s&repeated=%d&begin=%lld&end=%lld&name=%s&description=%s&eit=%d&tags=%s", WebUtils::URLEncodeInline(serviceReference).c_str(), timer.iWeekdays, static_cast(startTime), static_cast(endTime), WebUtils::URLEncodeInline(title).c_str(), WebUtils::URLEncodeInline(description).c_str(), epgUid, WebUtils::URLEncodeInline(tags.GetTags()).c_str()); Logger::Log(LEVEL_DEBUG, "%s - Command: %s", __FUNCTION__, strTmp.c_str()); std::string strResult; if (!WebUtils::SendSimpleCommand(strTmp, strResult)) return PVR_ERROR_SERVER_ERROR; Logger::Log(LEVEL_DEBUG, "%s - Updating timers", __FUNCTION__); TimerUpdates(); if (alreadyStarted) { Logger::Log(LEVEL_DEBUG, "%s - Timer started, triggering recording update", __FUNCTION__); PVR->TriggerRecordingUpdate(); } return PVR_ERROR_NO_ERROR; } PVR_ERROR Timers::AddAutoTimer(const PVR_TIMER& timer) { Logger::Log(LEVEL_DEBUG, "%s - Start", __FUNCTION__); std::string 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_DISABLED) 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) { const std::string serviceReference = m_channels.GetChannel(timer.iClientChannelUid)->GetServiceReference(); //single channel strTmp += StringUtils::Format("&services=%s", WebUtils::URLEncodeInline(serviceReference).c_str()); if (m_channels.GetChannel(timer.iClientChannelUid)->IsRadio()) strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s=%s", TAG_FOR_CHANNEL_TYPE.c_str(), VALUE_FOR_CHANNEL_TYPE_RADIO.c_str())).c_str()); else strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s=%s", TAG_FOR_CHANNEL_TYPE.c_str(), VALUE_FOR_CHANNEL_TYPE_TV.c_str())).c_str()); std::string tagValue = serviceReference; std::replace(tagValue.begin(), tagValue.end(), ' ', '_'); strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s=%s", TAG_FOR_CHANNEL_REFERENCE.c_str(), tagValue.c_str())).c_str()); } else { const std::string serviceReference = m_epg.FindServiceReference(timer.strTitle, timer.iEpgUid, timer.startTime, timer.endTime); if (!serviceReference.empty()) { const auto channel = m_channels.GetChannel(serviceReference); if (channel) { bool isRadio = channel->IsRadio(); if (isRadio) strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s=%s", TAG_FOR_CHANNEL_TYPE.c_str(), VALUE_FOR_CHANNEL_TYPE_RADIO.c_str())).c_str()); else strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s=%s", TAG_FOR_CHANNEL_TYPE.c_str(), VALUE_FOR_CHANNEL_TYPE_TV.c_str())).c_str()); std::string tagValue = serviceReference; std::replace(tagValue.begin(), tagValue.end(), ' ', '_'); strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s=%s", TAG_FOR_CHANNEL_REFERENCE.c_str(), tagValue.c_str())).c_str()); if (!m_settings.UsesLastScannedChannelGroup()) strTmp += BuildAddUpdateAutoTimerLimitGroupsParams(channel); } } strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s", TAG_FOR_ANY_CHANNEL.c_str())).c_str()); } strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("GenreId=0x%02X", timer.iGenreType | timer.iGenreSubType)).c_str()); strTmp += Timers::BuildAddUpdateAutoTimerIncludeParams(timer.iWeekdays); Logger::Log(LEVEL_DEBUG, "%s - Command: %s", __FUNCTION__, strTmp.c_str()); std::string strResult; if (!WebUtils::SendSimpleCommand(strTmp, strResult)) return PVR_ERROR_SERVER_ERROR; if (timer.state == PVR_TIMER_STATE_RECORDING) { Logger::Log(LEVEL_DEBUG, "%s - Timer started, triggering recording update", __FUNCTION__); PVR->TriggerRecordingUpdate(); } Logger::Log(LEVEL_DEBUG, "%s - Updating timers", __FUNCTION__); 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); const 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; Logger::Log(LEVEL_DEBUG, "%s old timer channelid '%d'", __FUNCTION__, oldTimer.GetChannelId()); Tags tags(oldTimer.GetTags()); tags.AddTag(TAG_FOR_CHANNEL_REFERENCE, strServiceReference, true); int iDisabled = 0; if (timer.state == PVR_TIMER_STATE_DISABLED) iDisabled = 1; unsigned int startPadding = timer.iMarginStart; unsigned int endPadding = timer.iMarginEnd; if (startPadding == 0 && endPadding == 0) { startPadding = Settings::GetInstance().GetDeviceSettings()->GetGlobalRecordingStartMargin(); endPadding = Settings::GetInstance().GetDeviceSettings()->GetGlobalRecordingEndMargin(); } bool alreadyStarted = false; time_t startTime, endTime; time_t now = std::time(nullptr); if ((timer.startTime - (startPadding * 60)) < now) { alreadyStarted = true; startTime = now; if (timer.startTime < now) startPadding = 0; else startPadding = (timer.startTime - now) / 60; } else { startTime = timer.startTime - (startPadding * 60); } endTime = timer.endTime + (endPadding * 60); tags.AddTag(TAG_FOR_PADDING, StringUtils::Format("%u,%u", startPadding, endPadding)); /* Note that plot (long desc) is automatically written to a timer entry by the backend therefore we only need to send outline as description to preserve both. Once a timer completes, long description will be cleared so if description is not populated we set it to the value of long description. Very important for providers that only use the plot field. */ const std::string& description = !oldTimer.GetPlotOutline().empty() ? oldTimer.GetPlotOutline() : oldTimer.GetPlot(); const std::string strTmp = StringUtils::Format("web/timerchange?sRef=%s&begin=%lld&end=%lld&name=%s&eventID=&description=%s&tags=%s&afterevent=3&eit=0&disabled=%d&justplay=0&repeated=%d&channelOld=%s&beginOld=%lld&endOld=%lld&deleteOldOnSave=1", WebUtils::URLEncodeInline(strServiceReference).c_str(), static_cast(startTime), static_cast(endTime), WebUtils::URLEncodeInline(timer.strTitle).c_str(), WebUtils::URLEncodeInline(description).c_str(), WebUtils::URLEncodeInline(tags.GetTags()).c_str(), iDisabled, timer.iWeekdays, WebUtils::URLEncodeInline(oldTimer.GetServiceReference()).c_str(), static_cast(oldTimer.GetRealStartTime()), static_cast(oldTimer.GetRealEndTime())); std::string strResult; if (!WebUtils::SendSimpleCommand(strTmp, strResult)) return PVR_ERROR_SERVER_ERROR; TimerUpdates(); if (alreadyStarted) PVR->TriggerRecordingUpdate(); return PVR_ERROR_NO_ERROR; } return PVR_ERROR_SERVER_ERROR; } std::string Timers::RemovePaddingTag(std::string tag) { std::regex regex(" Padding=[0-9]+,[0-9]+ *"); std::string replaceWith = ""; return std::regex_replace(tag, regex, replaceWith); } 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_DISABLED) 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 (timer.iClientChannelUid != PVR_TIMER_ANY_CHANNEL && (timerToUpdate.GetAnyChannel() || (!timerToUpdate.GetAnyChannel() && timer.iClientChannelUid != timerToUpdate.GetChannelId()))) { const std::string serviceReference = m_channels.GetChannel(timer.iClientChannelUid)->GetServiceReference(); //move to single channel strTmp += StringUtils::Format("&services=%s", WebUtils::URLEncodeInline(serviceReference).c_str()); //Update tags strTmp += StringUtils::Format("&tag="); if (m_channels.GetChannel(timer.iClientChannelUid)->IsRadio()) strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s=%s", TAG_FOR_CHANNEL_TYPE.c_str(), VALUE_FOR_CHANNEL_TYPE_RADIO.c_str())).c_str()); else strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s=%s", TAG_FOR_CHANNEL_TYPE.c_str(), VALUE_FOR_CHANNEL_TYPE_TV.c_str())).c_str()); std::string tagValue = serviceReference; std::replace(tagValue.begin(), tagValue.end(), ' ', '_'); strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s=%s", TAG_FOR_CHANNEL_REFERENCE.c_str(), tagValue.c_str())).c_str()); if (timerToUpdate.ContainsTag(TAG_FOR_GENRE_ID)) strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s=%s", TAG_FOR_GENRE_ID.c_str(), timerToUpdate.ReadTagValue(TAG_FOR_GENRE_ID).c_str())).c_str()); //Clear bouquets strTmp += "&bouquets="; } else if (!timerToUpdate.GetAnyChannel() && timer.iClientChannelUid == PVR_TIMER_ANY_CHANNEL) { const auto& channel = m_channels.GetChannel(timerToUpdate.GetChannelId()); //Move to any channel strTmp += StringUtils::Format("&services="); //Update tags strTmp += StringUtils::Format("&tag="); if (timerToUpdate.ContainsTag(TAG_FOR_CHANNEL_TYPE)) strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s=%s", TAG_FOR_CHANNEL_TYPE.c_str(), timerToUpdate.ReadTagValue(TAG_FOR_CHANNEL_TYPE).c_str())).c_str()); std::string tagValue = channel->GetServiceReference(); std::replace(tagValue.begin(), tagValue.end(), ' ', '_'); strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s=%s", TAG_FOR_CHANNEL_REFERENCE.c_str(), tagValue.c_str())).c_str()); strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s", TAG_FOR_ANY_CHANNEL.c_str())).c_str()); if (timerToUpdate.ContainsTag(TAG_FOR_GENRE_ID)) strTmp += StringUtils::Format("&tag=%s", WebUtils::URLEncodeInline(StringUtils::Format("%s=%s", TAG_FOR_GENRE_ID.c_str(), timerToUpdate.ReadTagValue(TAG_FOR_GENRE_ID).c_str())).c_str()); //Limit Channel Groups if (!m_settings.UsesLastScannedChannelGroup()) strTmp += BuildAddUpdateAutoTimerLimitGroupsParams(channel); } 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::BuildAddUpdateAutoTimerLimitGroupsParams(const std::shared_ptr& channel) { std::string limitGroupParams; if (m_settings.GetLimitAnyChannelAutoTimers() && channel) { if (m_settings.GetLimitAnyChannelAutoTimersToChannelGroups()) { for (const auto& group : channel->GetChannelGroupList()) limitGroupParams += StringUtils::Format("%s,", group->GetServiceReference().c_str()); } else { for (const auto& group : m_channelGroups.GetChannelGroupsList()) { if (group->IsRadio() == channel->IsRadio()) limitGroupParams += StringUtils::Format("%s,", group->GetServiceReference().c_str()); } } } return StringUtils::Format("&bouquets=%s", WebUtils::URLEncodeInline(limitGroupParams).c_str()); } 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); 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 timerToDelete = *it; const std::string strTmp = StringUtils::Format("web/timerdelete?sRef=%s&begin=%lld&end=%lld", WebUtils::URLEncodeInline(timerToDelete.GetServiceReference()).c_str(), static_cast(timerToDelete.GetRealStartTime()), static_cast(timerToDelete.GetRealEndTime())); 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; } 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; //remove any child timers bool childTimerIsRecording = false; for (const auto& childTimer : m_timers) { if (childTimer.GetParentClientIndex() == timerToDelete.GetClientIndex()) { const std::string strTmp = StringUtils::Format("web/timerdelete?sRef=%s&begin=%lld&end=%lld", WebUtils::URLEncodeInline(childTimer.GetServiceReference()).c_str(), static_cast(childTimer.GetRealStartTime()), static_cast(childTimer.GetRealEndTime())); std::string strResult; WebUtils::SendSimpleCommand(strTmp, strResult, true); if (childTimer.GetState() == PVR_TIMER_STATE_RECORDING) childTimerIsRecording = true; } } const std::string 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 || childTimerIsRecording) 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 (Settings::GetInstance().SupportsAutoTimers() && 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_DEBUG, "%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_DEBUG, "%s No of timers: removed [%d], untouched [%d], updated '%d', new '%d'", __FUNCTION__, iRemoved, iUnchanged, iUpdated, iNew); std::vector timerBaseEntries; for (auto& timer : m_timers) { EpgEntry entry = timer; entry.SetStartTime(timer.GetRealStartTime()); entry.SetEndTime(timer.GetRealEndTime()); timerBaseEntries.emplace_back(entry); } m_epg.UpdateTimerEPGFallbackEntries(timerBaseEntries); 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) { const 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() { const 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__); } pvr.vuplus-3.28.9-Leia/src/enigma2/Timers.h000066400000000000000000000072421356012415200203620ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "Epg.h" #include "data/AutoTimer.h" #include "data/Timer.h" #include "extract/EpgEntryExtractor.h" #include "tinyxml.h" #include "kodi/libXBMC_pvr.h" #include #include #include #include #include #include namespace enigma2 { class Timers { public: Timers(Channels& channels, ChannelGroups& channelGroups, std::vector& locations, Epg& epg, enigma2::extract::EpgEntryExtractor& entryExtractor) : m_channels(channels), m_channelGroups(channelGroups), m_locations(locations), m_epg(epg), m_entryExtractor(entryExtractor) { 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); static std::string RemovePaddingTag(std::string tag); std::vector LoadAutoTimers() const; bool IsAutoTimer(const PVR_TIMER& timer) const; bool TimerUpdatesRegular(); bool TimerUpdatesAuto(); std::string BuildAddUpdateAutoTimerLimitGroupsParams(const std::shared_ptr& channel); static std::string BuildAddUpdateAutoTimerIncludeParams(int weekdays); // members unsigned int m_clientIndexCounter; std::vector m_timerChangeWatchers; enigma2::extract::EpgEntryExtractor& m_entryExtractor; enigma2::Settings& m_settings = enigma2::Settings::GetInstance(); std::vector m_timers; std::vector m_autotimers; Channels& m_channels; ChannelGroups& m_channelGroups; std::vector& m_locations; Epg& m_epg; }; } // namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/TimeshiftBuffer.cpp000066400000000000000000000110041356012415200225270ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "TimeshiftBuffer.h" #include "../client.h" #include "StreamReader.h" #include "p8-platform/util/util.h" #include "utilities/Logger.h" using namespace ADDON; using namespace enigma2; using namespace enigma2::utilities; TimeshiftBuffer::TimeshiftBuffer(IStreamReader* m_streamReader, const std::string& timeshiftBufferPath, const unsigned int readTimeout) : m_streamReader(m_streamReader) { m_bufferPath = timeshiftBufferPath + "/tsbuffer.ts"; m_readTimeout = (readTimeout) ? 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, "%s Timeshift: Stopped", __FUNCTION__); } bool TimeshiftBuffer::Start() { if (m_streamReader == nullptr || m_filebufferWriteHandle == nullptr || m_filebufferReadHandle == nullptr) return false; if (m_running) return true; Logger::Log(LEVEL_INFO, "%s Timeshift: Started", __FUNCTION__); m_start = time(nullptr); m_running = true; m_inputThread = std::thread([&] { DoReadWrite(); }); return true; } void TimeshiftBuffer::DoReadWrite() { Logger::Log(LEVEL_DEBUG, "%s Timeshift: Thread started", __FUNCTION__); 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, "%s Timeshift: Thread stopped", __FUNCTION__); 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, "%s Timeshift: Read timed out; waited %d", __FUNCTION__, 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; } pvr.vuplus-3.28.9-Leia/src/enigma2/TimeshiftBuffer.h000066400000000000000000000041411356012415200222000ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #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 enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/data/000077500000000000000000000000001356012415200176525ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/src/enigma2/data/AutoTimer.cpp000066400000000000000000000213221356012415200222670ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "AutoTimer.h" #include "../utilities/LocalizedString.h" #include "inttypes.h" #include "p8-platform/util/StringUtils.h" #include "util/XMLUtils.h" #include 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 isEqual = (!m_title.compare(right.m_title)); isEqual &= (m_startTime == right.m_startTime); isEqual &= (m_endTime == right.m_endTime); isEqual &= (m_channelId == right.m_channelId); isEqual &= (m_weekdays == right.m_weekdays); isEqual &= (m_searchPhrase == right.m_searchPhrase); isEqual &= (m_searchType == right.m_searchType); isEqual &= (m_searchCase == right.m_searchCase); isEqual &= (m_state == right.m_state); isEqual &= (m_searchFulltext == right.m_searchFulltext); isEqual &= (m_startAnyTime == right.m_startAnyTime); isEqual &= (m_endAnyTime == right.m_endAnyTime); isEqual &= (m_anyChannel == right.m_anyChannel); isEqual &= (m_deDup == right.m_deDup); isEqual &= (m_tags == right.m_tags); return isEqual; } 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; m_tags = right.m_tags; } void AutoTimer::UpdateTo(PVR_TIMER& left) const { strncpy(left.strTitle, m_title.c_str(), sizeof(left.strTitle) - 1); strncpy(left.strEpgSearchString, m_searchPhrase.c_str(), sizeof(left.strEpgSearchString) - 1); 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; 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; m_tags.clear(); if (XMLUtils::GetString(autoTimerNode, "e2tags", strTmp)) m_tags = strTmp; 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_DISABLED; } } 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(Channel::NormaliseServiceReference(strTmp.c_str())); // For 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 // we'll default to any channel (as that is what kodi PVR does) and leave in ERROR state if (m_channelId == PVR_CHANNEL_INVALID_UID) { m_state = PVR_TIMER_STATE_ERROR; Logger::Log(LEVEL_DEBUG, "%s Overriding AutoTimer state as channel not found, state is: ERROR", __FUNCTION__); m_channelName = LocalizedString(30520); // Invalid Channel m_channelId = PVR_TIMER_ANY_CHANNEL; m_anyChannel = true; } else { 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 << std::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; } if (ContainsTag(TAG_FOR_GENRE_ID)) { int genreId = 0; if (std::sscanf(ReadTagValue(TAG_FOR_GENRE_ID).c_str(), "0x%02X", &genreId) == 1) { m_genreType = genreId & 0xF0; m_genreSubType = genreId & 0x0F; } else { m_genreType = 0; m_genreSubType = 0; } } 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); }pvr.vuplus-3.28.9-Leia/src/enigma2/data/AutoTimer.h000066400000000000000000000121001356012415200217260ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "Timer.h" #include "tinyxml.h" #include "kodi/libXBMC_pvr.h" #include #include #include 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 enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/data/BaseChannel.h000066400000000000000000000037431356012415200221750ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "tinyxml.h" #include "kodi/libXBMC_pvr.h" #include #include #include namespace enigma2 { namespace data { class BaseChannel { public: BaseChannel() = default; BaseChannel(const BaseChannel& b) : m_radio(b.IsRadio()), m_uniqueId(b.GetUniqueId()), m_channelName(b.GetChannelName()), m_serviceReference(b.GetServiceReference()) {}; ~BaseChannel() = 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& 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; } protected: bool m_radio; int m_uniqueId = -1; std::string m_channelName; std::string m_serviceReference; }; } //namespace data } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/data/BaseEntry.cpp000066400000000000000000000030531356012415200222530ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #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_plotOutline != "N/A") { m_plot.insert(0, m_plotOutline + "\n"); m_plotOutline.clear(); } } pvr.vuplus-3.28.9-Leia/src/enigma2/data/BaseEntry.h000066400000000000000000000052721356012415200217250ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "../Settings.h" #include 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 enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/data/Channel.cpp000066400000000000000000000204311356012415200217260ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "Channel.h" #include "../Settings.h" #include "../utilities/WebUtils.h" #include "ChannelGroup.h" #include "inttypes.h" #include "p8-platform/util/StringUtils.h" #include "util/XMLUtils.h" #include using namespace enigma2; using namespace enigma2::data; using namespace enigma2::utilities; bool Channel::Like(const Channel& right) const { bool isLike = (m_serviceReference == right.m_serviceReference); isLike &= (m_channelName == right.m_channelName); return isLike; } bool Channel::operator==(const Channel& right) const { bool isEqual = (m_serviceReference == right.m_serviceReference); isEqual &= (m_channelName == right.m_channelName); isEqual &= (m_radio == right.m_radio); isEqual &= (m_genericServiceReference == right.m_genericServiceReference); isEqual &= (m_streamURL == right.m_streamURL); isEqual &= (m_m3uURL == right.m_m3uURL); isEqual &= (m_iconPath == right.m_iconPath); isEqual &= (m_providerName == right.m_providerName); return isEqual; } bool Channel::operator!=(const Channel& right) const { return !(*this == right); } bool Channel::UpdateFrom(TiXmlElement* channelNode) { if (!XMLUtils::GetString(channelNode, "e2servicereference", m_serviceReference)) return false; // Check whether the current element is not just a label or that it's not a hidden entry if (m_serviceReference.compare(0, 5, "1:64:") == 0 || m_serviceReference.compare(0, 6, "1:320:") == 0) return false; if (!XMLUtils::GetString(channelNode, "e2servicename", m_channelName)) return false; m_fuzzyChannelName = m_channelName; m_fuzzyChannelName.erase(std::remove_if(m_fuzzyChannelName.begin(), m_fuzzyChannelName.end(), isspace), m_fuzzyChannelName.end()); if (m_radio != HasRadioServiceType()) return false; m_extendedServiceReference = m_serviceReference; const std::string commonServiceReference = CreateCommonServiceReference(m_serviceReference); m_standardServiceReference = commonServiceReference + ":"; m_genericServiceReference = CreateGenericServiceReference(commonServiceReference); m_iconPath = CreateIconPath(commonServiceReference); const std::string iptvStreamURL = ExtractIptvStreamURL(); Settings& settings = Settings::GetInstance(); if (settings.UseStandardServiceReference()) m_serviceReference = m_standardServiceReference; std::sscanf(m_serviceReference.c_str(), "%*X:%*X:%*X:%X:%*s", &m_streamProgramNumber); Logger::Log(LEVEL_DEBUG, "%s: Loaded Channel: %s, sRef=%s, picon: %s, program number: %d", __FUNCTION__, m_channelName.c_str(), m_serviceReference.c_str(), m_iconPath.c_str(), m_streamProgramNumber); if (m_isIptvStream) { Logger::Log(LEVEL_DEBUG, "%s: Loaded Channel: %s, sRef=%s, IPTV Stream URL: %s", __FUNCTION__, m_channelName.c_str(), m_serviceReference.c_str(), iptvStreamURL.c_str()); } m_m3uURL = StringUtils::Format("%sweb/stream.m3u?ref=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(m_serviceReference).c_str()); if (!m_isIptvStream) { m_streamURL = StringUtils::Format( "http%s://%s%s:%d/%s", settings.UseSecureConnectionStream() ? "s" : "", settings.UseLoginStream() ? StringUtils::Format("%s:%s@", settings.GetUsername().c_str(), settings.GetPassword().c_str()).c_str() : "", settings.GetHostname().c_str(), settings.GetStreamPortNum(), commonServiceReference.c_str() ); } else { m_streamURL = iptvStreamURL; } return true; } std::string Channel::NormaliseServiceReference(const std::string& serviceReference) { if (Settings::GetInstance().UseStandardServiceReference()) return CreateStandardServiceReference(serviceReference); else return serviceReference; } std::string Channel::CreateStandardServiceReference(const std::string& serviceReference) { return CreateCommonServiceReference(serviceReference) + ":"; } std::string Channel::CreateCommonServiceReference(const std::string& serviceReference) { //The common service reference contains only the first 10 groups of digits with colon's in between std::string commonServiceReference = serviceReference; int j = 0; std::string::iterator it = commonServiceReference.begin(); while (j < 10 && it != commonServiceReference.end()) { if (*it == ':') j++; it++; } std::string::size_type index = it - commonServiceReference.begin(); commonServiceReference = commonServiceReference.substr(0, index); it = commonServiceReference.end() - 1; if (*it == ':') { commonServiceReference.erase(it); } return commonServiceReference; } std::string Channel::CreateGenericServiceReference(const std::string& commonServiceReference) { //Same as common service reference but starts with SERVICE_REF_GENERIC_PREFIX and ends with SERVICE_REF_GENERIC_POSTFIX std::regex startPrefixRegex("^\\d+:\\d+:\\d+:"); std::string replaceWith = ""; std::string genericServiceReference = std::regex_replace(commonServiceReference, startPrefixRegex, replaceWith); std::regex endPostfixRegex(":\\d+:\\d+:\\d+$"); genericServiceReference = std::regex_replace(genericServiceReference, endPostfixRegex, replaceWith); genericServiceReference = SERVICE_REF_GENERIC_PREFIX + genericServiceReference + SERVICE_REF_GENERIC_POSTFIX; return genericServiceReference; } std::string Channel::CreateIconPath(const std::string& commonServiceReference) { std::string iconPath = commonServiceReference; if (Settings::GetInstance().UsePiconsEuFormat()) { iconPath = m_genericServiceReference; } std::replace(iconPath.begin(), iconPath.end(), ':', '_'); if (Settings::GetInstance().UseOnlinePicons()) iconPath = StringUtils::Format("%spicon/%s.png", Settings::GetInstance().GetConnectionURL().c_str(), iconPath.c_str()); else iconPath = Settings::GetInstance().GetIconPath().c_str() + iconPath + ".png"; return iconPath; } std::string Channel::ExtractIptvStreamURL() { std::string iptvStreamURL; std::size_t found = m_extendedServiceReference.find(m_standardServiceReference); if (found != std::string::npos) { const std::string possibleIptvStreamURL = m_extendedServiceReference.substr(m_standardServiceReference.length()); found = possibleIptvStreamURL.find("%3a"); //look for an URL encoded colon which means we have an embedded URL if (found != std::string::npos) { m_isIptvStream = true; iptvStreamURL = possibleIptvStreamURL; std::size_t foundColon = iptvStreamURL.find_last_of(":"); if (foundColon != std::string::npos) { iptvStreamURL = iptvStreamURL.substr(0, foundColon); } iptvStreamURL = std::regex_replace(iptvStreamURL, std::regex("%3a"), ":"); } } return iptvStreamURL; } bool Channel::HasRadioServiceType() { std::string radioServiceType = m_serviceReference.substr(4, m_serviceReference.size()); size_t found = radioServiceType.find(':'); if (found != std::string::npos) radioServiceType = radioServiceType.substr(0, found); return radioServiceType == RADIO_SERVICE_TYPE; } 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) - 1); strncpy(left.strInputFormat, "", 0); // unused left.iEncryptionSystem = 0; left.bIsHidden = false; strncpy(left.strIconPath, m_iconPath.c_str(), sizeof(left.strIconPath) - 1); } void Channel::AddChannelGroup(std::shared_ptr& channelGroup) { m_channelGroupList.emplace_back(channelGroup); }pvr.vuplus-3.28.9-Leia/src/enigma2/data/Channel.h000066400000000000000000000124671356012415200214050ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "BaseChannel.h" #include "tinyxml.h" #include "kodi/libXBMC_pvr.h" #include #include #include namespace enigma2 { namespace data { class ChannelGroup; class Channel : public BaseChannel { public: const std::string SERVICE_REF_GENERIC_PREFIX = "1:0:1:"; const std::string SERVICE_REF_GENERIC_POSTFIX = ":0:0:0"; const std::string RADIO_SERVICE_TYPE = "2"; Channel() = default; Channel(const Channel &c) : BaseChannel(c), m_channelNumber(c.GetChannelNumber()), m_standardServiceReference(c.GetStandardServiceReference()), m_extendedServiceReference(c.GetExtendedServiceReference()), m_genericServiceReference(c.GetGenericServiceReference()), m_streamURL(c.GetStreamURL()), m_m3uURL(c.GetM3uURL()), m_iconPath(c.GetIconPath()), m_providerName(c.GetProviderName()), m_fuzzyChannelName(c.GetFuzzyChannelName()), m_streamProgramNumber(c.GetStreamProgramNumber()), m_usingDefaultChannelNumber(c.UsingDefaultChannelNumber()), m_isIptvStream(c.IsIptvStream()) {}; ~Channel() = default; int GetChannelNumber() const { return m_channelNumber; } void SetChannelNumber(int value) { m_channelNumber = value; } const std::string& GetStandardServiceReference() const { return m_standardServiceReference; } void SetStandardServiceReference(const std::string& value) { m_standardServiceReference = value; } const std::string& GetExtendedServiceReference() const { return m_extendedServiceReference; } void SetExtendedServiceReference(const std::string& value) { m_extendedServiceReference = value; } const std::string& GetGenericServiceReference() const { return m_genericServiceReference; } void SetGenericServiceReference(const std::string& value) { m_genericServiceReference = 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; } const std::string& GetProviderName() const { return m_providerName; } void SetProviderlName(const std::string& value) { m_providerName = value; } const std::string& GetFuzzyChannelName() const { return m_fuzzyChannelName; } void SetFuzzyChannelName(const std::string& value) { m_fuzzyChannelName = value; } int GetStreamProgramNumber() const { return m_streamProgramNumber; } void SetStreamProgramNumber(int value) { m_streamProgramNumber = value; } bool UsingDefaultChannelNumber() const { return m_usingDefaultChannelNumber; } void SetUsingDefaultChannelNumber(bool value) { m_usingDefaultChannelNumber = value; } bool IsIptvStream() const { return m_isIptvStream; } bool UpdateFrom(TiXmlElement* channelNode); void UpdateTo(PVR_CHANNEL& left) const; void AddChannelGroup(std::shared_ptr& channelGroup); std::vector> GetChannelGroupList() { return m_channelGroupList; }; bool Like(const Channel& right) const; bool operator==(const Channel& right) const; bool operator!=(const Channel& right) const; static std::string NormaliseServiceReference(const std::string& serviceReference); static std::string CreateStandardServiceReference(const std::string& serviceReference); private: static std::string CreateCommonServiceReference(const std::string& serviceReference); std::string CreateGenericServiceReference(const std::string& commonServiceReference); std::string CreateIconPath(const std::string& commonServiceReference); std::string ExtractIptvStreamURL(); bool HasRadioServiceType(); int m_channelNumber; bool m_usingDefaultChannelNumber = true; bool m_isIptvStream = false; std::string m_standardServiceReference; std::string m_extendedServiceReference; std::string m_genericServiceReference; std::string m_streamURL; std::string m_m3uURL; std::string m_iconPath; std::string m_providerName; std::string m_fuzzyChannelName; int m_streamProgramNumber; std::vector> m_channelGroupList; }; } //namespace data } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/data/ChannelGroup.cpp000066400000000000000000000110561356012415200227460ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "ChannelGroup.h" #include "inttypes.h" #include "p8-platform/util/StringUtils.h" #include "util/XMLUtils.h" using namespace enigma2; using namespace enigma2::data; using namespace enigma2::utilities; bool ChannelGroup::Like(const ChannelGroup& right) const { bool isLike = (m_serviceReference == right.m_serviceReference); isLike &= (m_groupName == right.m_groupName); return isLike; } bool ChannelGroup::operator==(const ChannelGroup& right) const { bool isEqual = (m_serviceReference == right.m_serviceReference); isEqual &= (m_groupName == right.m_groupName); isEqual &= (m_radio == right.m_radio); isEqual &= (m_lastScannedGroup == right.m_lastScannedGroup); for (int i = 0; i < m_channelList.size(); i++) { isEqual &= (*(m_channelList.at(i)) == *(right.m_channelList.at(i))); if (!isEqual) break; } return isEqual; } bool ChannelGroup::operator!=(const ChannelGroup& right) const { return !(*this == right); } 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 or a separator if (groupName == "" || StringUtils::EndsWith(groupName.c_str(), " - Separator")) return false; m_serviceReference = serviceReference; m_groupName = groupName; m_radio = radio; if (!radio && (Settings::GetInstance().GetTVChannelGroupMode() == ChannelGroupMode::SOME_GROUPS || Settings::GetInstance().GetTVChannelGroupMode() == ChannelGroupMode::CUSTOM_GROUPS)) { auto& customGroupNamelist = Settings::GetInstance().GetCustomTVChannelGroupNameList(); auto it = std::find_if(customGroupNamelist.begin(), customGroupNamelist.end(), [&groupName](std::string& customGroupName) { return customGroupName == groupName; }); if (it == customGroupNamelist.end()) return false; else Logger::Log(LEVEL_DEBUG, "%s Custom TV groups are set, current e2servicename '%s' matched", __FUNCTION__, groupName.c_str()); } else if (radio && (Settings::GetInstance().GetRadioChannelGroupMode() == ChannelGroupMode::SOME_GROUPS || Settings::GetInstance().GetRadioChannelGroupMode() == ChannelGroupMode::CUSTOM_GROUPS)) { auto& customGroupNamelist = Settings::GetInstance().GetCustomRadioChannelGroupNameList(); auto it = std::find_if(customGroupNamelist.begin(), customGroupNamelist.end(), [&groupName](std::string& customGroupName) { return customGroupName == groupName; }); if (it == customGroupNamelist.end()) return false; else Logger::Log(LEVEL_DEBUG, "%s Custom Radio groups are set, current e2servicename '%s' matched", __FUNCTION__, groupName.c_str()); } else if (groupName == "Last Scanned") { // Last scanned contains TV and Radio channels mixed, therefore we discard here and handle it separately, // similar to Favourites when loading channel groups. // Note that if Last Scanned is used in only one group for TV we do not discard and only allow it for TV // as it is never supplied as a radio group from Enigma2 return false; } 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) - 1); } void ChannelGroup::AddChannel(std::shared_ptr channel) { m_channelList.emplace_back(channel); }pvr.vuplus-3.28.9-Leia/src/enigma2/data/ChannelGroup.h000066400000000000000000000063341356012415200224160ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "Channel.h" #include "EpgEntry.h" #include "tinyxml.h" #include "kodi/libXBMC_pvr.h" #include #include #include 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()), m_lastScannedGroup(c.IsLastScannedGroup()), m_startChannelNumber(c.GetStartChannelNumber()), m_emptyGroup(c.IsEmptyGroup()) {}; ~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; } bool IsLastScannedGroup() const { return m_lastScannedGroup; } void SetLastScannedGroup(bool value) { m_lastScannedGroup = value; } bool IsEmptyGroup() const { return m_emptyGroup; } void SetEmptyGroup(bool value) { m_emptyGroup = value; } int GetStartChannelNumber() const { return m_startChannelNumber; } void SetStartChannelNumber(int value) { m_startChannelNumber = value; } bool HasStartChannelNumber() const { return m_startChannelNumber >= 0; } void AddChannel(std::shared_ptr channel); bool UpdateFrom(TiXmlElement* groupNode, bool radio); void UpdateTo(PVR_CHANNEL_GROUP& left) const; std::vector> GetChannelList() { return m_channelList; }; bool Like(const ChannelGroup& right) const; bool operator==(const ChannelGroup& right) const; bool operator!=(const ChannelGroup& right) const; private: bool m_radio; int m_uniqueId; std::string m_serviceReference; std::string m_groupName; bool m_lastScannedGroup; bool m_emptyGroup; int m_startChannelNumber = -1; std::vector> m_channelList; }; } //namespace data } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/data/EpgChannel.h000066400000000000000000000031271356012415200220320ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "BaseChannel.h" #include "EpgEntry.h" #include "tinyxml.h" #include "kodi/libXBMC_pvr.h" #include #include #include namespace enigma2 { namespace data { class EpgEntry; class EpgChannel : public BaseChannel { public: EpgChannel() = default; EpgChannel(const EpgChannel& e) : BaseChannel(e){}; ~EpgChannel() = default; bool RequiresInitialEpg() const { return m_requiresInitialEpg; } void SetRequiresInitialEpg(bool value) { m_requiresInitialEpg = value; } std::vector& GetInitialEPG() { return m_initialEPG; } private: bool m_requiresInitialEpg = true; std::vector m_initialEPG; }; } //namespace data } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/data/EpgEntry.cpp000066400000000000000000000113641356012415200221200ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #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_epgId; 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, std::map>& epgChannelsMap) { if (!XMLUtils::GetString(eventNode, "e2eventservicereference", m_serviceReference)) return false; // Check whether the current element is not just a label or that it's not an empty record if (m_serviceReference.compare(0, 5, "1:64:") == 0) return false; m_serviceReference = Channel::NormaliseServiceReference(m_serviceReference); std::shared_ptr epgChannel = std::make_shared(); auto epgChannelSearch = epgChannelsMap.find(m_serviceReference); if (epgChannelSearch != epgChannelsMap.end()) epgChannel = epgChannelSearch->second; if (!epgChannel) { Logger::Log(LEVEL_DEBUG, "%s could not find channel so skipping entry", __FUNCTION__); return false; } m_channelId = epgChannel->GetUniqueId(); return UpdateFrom(eventNode, epgChannel, 0, 0); } bool EpgEntry::UpdateFrom(TiXmlElement* eventNode, const std::shared_ptr& epgChannel, 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_epgId = iTmp; m_channelId = epgChannel->GetUniqueId(); if (!XMLUtils::GetString(eventNode, "e2eventtitle", strTmp)) return false; m_title = strTmp; m_serviceReference = epgChannel->GetServiceReference().c_str(); // Check that it's not an empty record if (m_epgId == 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"); if (genreNode) { int genreId = 0; if (genreNode->QueryIntAttribute("id", &genreId) == TIXML_SUCCESS) { m_genreType = genreId & 0xF0; m_genreSubType = genreId & 0x0F; } } } return true; }pvr.vuplus-3.28.9-Leia/src/enigma2/data/EpgEntry.h000066400000000000000000000042431356012415200215630ustar00rootroot00000000000000#pragma once /* * Copyleft (C) 2005-2019 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 "BaseEntry.h" #include "EpgChannel.h" #include "tinyxml.h" #include "kodi/libXBMC_pvr.h" #include #include namespace enigma2 { namespace data { class EpgEntry : public BaseEntry { public: unsigned int GetEpgId() const { return m_epgId; } void SetEpgId(int value) { m_epgId = 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, std::map>& m_epgChannelsMap); bool UpdateFrom(TiXmlElement* eventNode, const std::shared_ptr& epgChannel, time_t iStart, time_t iEnd); protected: unsigned int m_epgId; std::string m_serviceReference; int m_channelId; time_t m_startTime; time_t m_endTime; }; } //namespace data } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/data/EpgPartialEntry.h000066400000000000000000000024061356012415200230770ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "BaseEntry.h" #include namespace enigma2 { namespace data { class EpgPartialEntry : public BaseEntry { public: unsigned int GetEpgUid() const { return m_epgUid; } void SetEpgUid(unsigned int value) { m_epgUid = value; } bool EntryFound() const { return m_epgUid != 0; }; private: unsigned int m_epgUid = 0; }; } //namespace data } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/data/RecordingEntry.cpp000066400000000000000000000205471356012415200233240ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "RecordingEntry.h" #include "../utilities/WebUtils.h" #include "inttypes.h" #include "p8-platform/util/StringUtils.h" #include "util/XMLUtils.h" #include using namespace enigma2; using namespace enigma2::data; using namespace enigma2::utilities; bool RecordingEntry::UpdateFrom(TiXmlElement* recordingNode, const std::string& directory, bool deleted, Channels& channels) { std::string strTmp; int iTmp; m_directory = directory; m_deleted = deleted; 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; 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)) { m_edlURL = strTmp; strTmp = StringUtils::Format("%sfile?file=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(strTmp).c_str()); m_streamURL = strTmp; m_edlURL = m_edlURL.substr(0, m_edlURL.find_last_of('.')) + ".edl"; m_edlURL = StringUtils::Format("%sfile?file=%s", Settings::GetInstance().GetConnectionURL().c_str(), WebUtils::URLEncodeInline(m_edlURL).c_str()); } ProcessPrependMode(PrependOutline::IN_RECORDINGS); m_tags.clear(); if (XMLUtils::GetString(recordingNode, "e2tags", strTmp)) m_tags = strTmp; if (ContainsTag(TAG_FOR_GENRE_ID)) { int genreId = 0; if (std::sscanf(ReadTagValue(TAG_FOR_GENRE_ID).c_str(), "0x%02X", &genreId) == 1) { m_genreType = genreId & 0xF0; m_genreSubType = genreId & 0x0F; } else { m_genreType = 0; m_genreSubType = 0; } } if (ContainsTag(TAG_FOR_PLAY_COUNT)) { if (std::sscanf(ReadTagValue(TAG_FOR_PLAY_COUNT).c_str(), "%d", &m_playCount) != 1) m_playCount = 0; } if (ContainsTag(TAG_FOR_LAST_PLAYED)) { if (std::sscanf(ReadTagValue(TAG_FOR_LAST_PLAYED).c_str(), "%d", &m_lastPlayedPosition) != 1) m_lastPlayedPosition = 0; } if (ContainsTag(TAG_FOR_NEXT_SYNC_TIME)) { long long scannedTime = 0; if (std::sscanf(ReadTagValue(TAG_FOR_NEXT_SYNC_TIME).c_str(), "%lld", &scannedTime) != 1) m_nextSyncTime = 0; else m_nextSyncTime = static_cast(scannedTime); } auto channel = FindChannel(channels); if (channel) { m_radio = channel->IsRadio(); m_channelUniqueId = channel->GetUniqueId(); m_iconPath = channel->GetIconPath(); m_haveChannelType = true; } return true; } long RecordingEntry::TimeStringToSeconds(const std::string& timeString) { std::vector tokens; std::string s = timeString; const 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 += std::atoi(tokens[0].c_str()) * 60; timeInSecs += std::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) - 1); strncpy(left.strTitle, m_title.c_str(), sizeof(left.strTitle) - 1); strncpy(left.strPlotOutline, m_plotOutline.c_str(), sizeof(left.strPlotOutline) - 1); strncpy(left.strPlot, m_plot.c_str(), sizeof(left.strPlot) - 1); strncpy(left.strChannelName, m_channelName.c_str(), sizeof(left.strChannelName) - 1); strncpy(left.strIconPath, m_iconPath.c_str(), sizeof(left.strIconPath) - 1); 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) - 1); left.bIsDeleted = m_deleted; left.recordingTime = m_startTime; left.iDuration = m_duration; left.iChannelUid = m_channelUniqueId; left.channelType = PVR_RECORDING_CHANNEL_TYPE_UNKNOWN; if (m_haveChannelType) { if (m_radio) left.channelType = PVR_RECORDING_CHANNEL_TYPE_RADIO; else left.channelType = PVR_RECORDING_CHANNEL_TYPE_TV; } left.iPlayCount = m_playCount; left.iLastPlayedPosition = m_lastPlayedPosition; 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) - 1); } std::shared_ptr RecordingEntry::FindChannel(Channels& channels) const { std::shared_ptr channel = GetChannelFromChannelReferenceTag(channels); if (channel) return channel; if (ContainsTag(TAG_FOR_CHANNEL_TYPE)) { m_radio = ReadTagValue(TAG_FOR_CHANNEL_TYPE) == VALUE_FOR_CHANNEL_TYPE_RADIO; m_haveChannelType = true; } m_anyChannelTimerSource = ContainsTag(TAG_FOR_ANY_CHANNEL); channel = GetChannelFromChannelNameSearch(channels); if (channel) { if (!m_hasStreamProgramNumber) { m_streamProgramNumber = channel->GetStreamProgramNumber(); m_hasStreamProgramNumber = true; } return channel; } channel = GetChannelFromChannelNameFuzzySearch(channels); if (channel && !m_hasStreamProgramNumber) { m_streamProgramNumber = channel->GetStreamProgramNumber(); m_hasStreamProgramNumber = true; } return channel; } std::shared_ptr RecordingEntry::GetChannelFromChannelReferenceTag(Channels& channels) const { std::string channelServiceReference; if (ContainsTag(TAG_FOR_CHANNEL_REFERENCE)) { channelServiceReference = Channel::NormaliseServiceReference(ReadTagValue(TAG_FOR_CHANNEL_REFERENCE, true)); std::sscanf(channelServiceReference.c_str(), "%*X:%*X:%*X:%X:%*s", &m_streamProgramNumber); m_hasStreamProgramNumber = true; } return channels.GetChannel(channelServiceReference); } std::shared_ptr RecordingEntry::GetChannelFromChannelNameSearch(Channels& channels) const { //search for channel name using exact match for (const auto& channel : channels.GetChannelsList()) { if (m_channelName == channel->GetChannelName() && (!m_haveChannelType || (channel->IsRadio() == m_radio))) { return channel; } } return nullptr; } std::shared_ptr RecordingEntry::GetChannelFromChannelNameFuzzySearch(Channels& channels) const { std::string fuzzyRecordingChannelName; //search for channel name using fuzzy match for (const auto& channel : channels.GetChannelsList()) { fuzzyRecordingChannelName = m_channelName; fuzzyRecordingChannelName.erase(remove_if(fuzzyRecordingChannelName.begin(), fuzzyRecordingChannelName.end(), isspace), fuzzyRecordingChannelName.end()); if (fuzzyRecordingChannelName == channel->GetFuzzyChannelName() && (!m_haveChannelType || (channel->IsRadio() == m_radio))) { return channel; } } return nullptr; }pvr.vuplus-3.28.9-Leia/src/enigma2/data/RecordingEntry.h000066400000000000000000000112751356012415200227670ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "../Channels.h" #include "BaseEntry.h" #include "Channel.h" #include "Tags.h" #include "tinyxml.h" #include "kodi/libXBMC_pvr.h" #include namespace enigma2 { namespace data { static const std::string TAG_FOR_PLAY_COUNT = "PlayCount"; static const std::string TAG_FOR_LAST_PLAYED = "LastPlayed"; static const std::string TAG_FOR_NEXT_SYNC_TIME = "NextSyncTime"; class RecordingEntry : public BaseEntry, public Tags { 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 GetPlayCount() const { return m_playCount; } void SetPlayCount(int value) { m_playCount = value; } int GetLastPlayedPosition() const { return m_lastPlayedPosition; } void SetLastPlayedPosition(int value) { m_lastPlayedPosition = value; } time_t GetNextSyncTime() const { return m_nextSyncTime; } void SetNextSyncTime(time_t value) { m_nextSyncTime = value; } const std::string& GetStreamURL() const { return m_streamURL; } void SetStreamURL(const std::string& value) { m_streamURL = value; } const std::string& GetEdlURL() const { return m_edlURL; } void SetEdlURL(const std::string& value) { m_edlURL = value; } const std::string& GetChannelName() const { return m_channelName; } void SetChannelName(const std::string& value) { m_channelName = value; } int GetChannelUniqueId() const { return m_channelUniqueId; } void SetChannelUniqueId(int value) { m_channelUniqueId = 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; } int GetStreamProgramNumber() const { return m_streamProgramNumber; } void SetStreamProgramNumber(int value) { m_streamProgramNumber = value; } bool HasStreamProgramNumber() const { return m_hasStreamProgramNumber; } bool IsRadio() const { return m_radio; } void SetRadio(bool value) { m_radio = value; } bool IsDeleted() const { return m_deleted; } void SetDeleted(bool value) { m_deleted = value; } bool UpdateFrom(TiXmlElement* recordingNode, const std::string& directory, bool deleted, enigma2::Channels& channels); void UpdateTo(PVR_RECORDING& left, Channels& channels, bool isInRecordingFolder); private: long TimeStringToSeconds(const std::string& timeString); std::shared_ptr FindChannel(enigma2::Channels& channels) const; std::shared_ptr GetChannelFromChannelReferenceTag(enigma2::Channels& channels) const; std::shared_ptr GetChannelFromChannelNameSearch(enigma2::Channels& channels) const; std::shared_ptr GetChannelFromChannelNameFuzzySearch(enigma2::Channels& channels) const; std::string m_recordingId; time_t m_startTime; int m_duration; int m_playCount = 0; int m_lastPlayedPosition = 0; time_t m_nextSyncTime = 0; std::string m_streamURL; std::string m_edlURL; std::string m_channelName; int m_channelUniqueId = PVR_CHANNEL_INVALID_UID; std::string m_directory; std::string m_iconPath; mutable bool m_radio = false; mutable bool m_haveChannelType = false; mutable bool m_anyChannelTimerSource = false; bool m_deleted = false; mutable int m_streamProgramNumber; mutable bool m_hasStreamProgramNumber = false; }; } //namespace data } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/data/Tags.h000066400000000000000000000062651356012415200207320ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "p8-platform/util/StringUtils.h" #include #include namespace enigma2 { namespace data { static const std::string TAG_FOR_GENRE_ID = "GenreId"; static const std::string TAG_FOR_CHANNEL_REFERENCE = "ChannelRef"; static const std::string TAG_FOR_CHANNEL_TYPE = "ChannelType"; static const std::string TAG_FOR_ANY_CHANNEL = "AnyChannel"; static const std::string VALUE_FOR_CHANNEL_TYPE_TV = "TV"; static const std::string VALUE_FOR_CHANNEL_TYPE_RADIO = "Radio"; class Tags { public: Tags() = default; Tags(const std::string& tags) : m_tags(tags) {}; const std::string& GetTags() const { return m_tags; } void SetTags(const std::string& value) { m_tags = value; } bool ContainsTag(const std::string& tag) const { std::regex regex("^.* ?" + tag + " ?.*$"); return (std::regex_match(m_tags, regex)); } void AddTag(const std::string& tagName, const std::string& tagValue = "", bool replaceUnderscores = false) { RemoveTag(tagName); if (!m_tags.empty()) m_tags.append(" "); m_tags.append(tagName); if (!tagValue.empty()) { std::string val = tagValue; if (replaceUnderscores) std::replace(val.begin(), val.end(), ' ', '_'); m_tags.append(StringUtils::Format("=%s", val.c_str())); } } std::string ReadTagValue(const std::string& tagName, bool replaceUnderscores = false) const { std::string tagValue; size_t found = m_tags.find(tagName + "="); if (found != std::string::npos) { tagValue = m_tags.substr(found + tagName.size() + 1, m_tags.size()); found = tagValue.find(" "); if (found != std::string::npos) tagValue = tagValue.substr(0, found); tagValue = StringUtils::Trim(tagValue); if (replaceUnderscores) std::replace(tagValue.begin(), tagValue.end(), '_', ' '); } return tagValue; } void RemoveTag(const std::string& tagName) { std::regex regex(" *" + tagName + "=?[^\\s-]*"); std::string replaceWith = ""; m_tags = std::regex_replace(m_tags, regex, replaceWith); } protected: std::string m_tags; }; } //namespace data } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/data/Timer.cpp000066400000000000000000000262631356012415200214470ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "Timer.h" #include "../utilities/LocalizedString.h" #include "inttypes.h" #include "p8-platform/util/StringUtils.h" #include "util/XMLUtils.h" #include using namespace enigma2; using namespace enigma2::data; using namespace enigma2::utilities; bool Timer::Like(const Timer& right) const { bool isLike = (m_startTime == right.m_startTime); isLike &= (m_endTime == right.m_endTime); isLike &= (m_channelId == right.m_channelId); isLike &= (m_weekdays == right.m_weekdays); isLike &= (m_epgId == right.m_epgId); return isLike; } bool Timer::operator==(const Timer& right) const { bool isEqual = (m_startTime == right.m_startTime); isEqual &= (m_endTime == right.m_endTime); isEqual &= (m_channelId == right.m_channelId); isEqual &= (m_weekdays == right.m_weekdays); isEqual &= (m_epgId == right.m_epgId); isEqual &= (m_paddingStartMins == right.m_paddingStartMins); isEqual &= (m_paddingEndMins == right.m_paddingEndMins); isEqual &= (m_state == right.m_state); isEqual &= (m_title == right.m_title); isEqual &= (m_plot == right.m_plot); isEqual &= (m_tags == right.m_tags); isEqual &= (m_plotOutline == right.m_plotOutline); isEqual &= (m_plot == right.m_plot); isEqual &= (m_genreType == right.m_genreType); isEqual &= (m_genreSubType == right.m_genreSubType); isEqual &= (m_genreDescription == right.m_genreDescription); isEqual &= (m_episodeNumber == right.m_episodeNumber); isEqual &= (m_episodePartNumber == right.m_episodePartNumber); isEqual &= (m_seasonNumber == right.m_seasonNumber); isEqual &= (m_year == right.m_year); return isEqual; } 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; m_paddingStartMins = right.m_paddingStartMins; m_paddingEndMins = right.m_paddingEndMins; m_plotOutline = right.m_plotOutline; m_plot = right.m_plot; m_genreType = right.m_genreType; m_genreSubType = right.m_genreSubType; m_genreDescription = right.m_genreDescription; m_episodeNumber = right.m_episodeNumber; m_episodePartNumber = right.m_episodePartNumber; m_seasonNumber = right.m_seasonNumber; m_year = right.m_year; } void Timer::UpdateTo(PVR_TIMER& left) const { strncpy(left.strTitle, m_title.c_str(), sizeof(left.strTitle) - 1); strncpy(left.strDirectory, "/", sizeof(left.strDirectory) - 1); // unused strncpy(left.strSummary, m_plot.c_str(), sizeof(left.strSummary) - 1); 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 = m_paddingStartMins; left.iMarginEnd = m_paddingEndMins; 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, std::time_t startTime) const { if (!IsScheduled()) return false; if (now && !(GetRealStartTime() <= *now && *now <= GetRealEndTime())) return false; if (channelName && m_channelName != *channelName) return false; if (GetRealStartTime() != startTime) 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); const 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); const std::string childEndTime = StringUtils::Format("%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min); time = parent.m_startTime; timeinfo = *std::localtime(&time); const std::string parentStartTime = StringUtils::Format("%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min); time = parent.m_endTime; timeinfo = *std::localtime(&time); const 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_paddingStartMins == parent.m_paddingStartMins); isChild = isChild && (m_paddingEndMins == parent.m_paddingEndMins); 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_serviceReference = strTmp; m_channelId = channels.GetChannelUniqueId(Channel::NormaliseServiceReference(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 == PVR_CHANNEL_INVALID_UID) { m_channelName = LocalizedString(30520); // Invalid Channel } else { 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, "e2descriptionextended", strTmp)) m_plot = strTmp; if (XMLUtils::GetString(timerNode, "e2description", strTmp)) m_plotOutline = strTmp; if (m_plot == "N/A") m_plot.clear(); // 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() == PrependOutline::ALWAYS && m_plot != m_plotOutline && !m_plotOutline.empty() && m_plotOutline != "N/A") { m_plot.insert(0, m_plotOutline + "\n"); m_plotOutline.clear(); } 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) { // If a timer is cancelled by the backend mark it as an error so it will show as such in the UI // We don't use CANCELLED or ABORTED as they are synonymous with DISABLED and we won't use them at all // Note there is no user/API action to change to cancelled m_state = PVR_TIMER_STATE_ERROR; Logger::Log(LEVEL_DEBUG, "%s Timer state is: ERROR", __FUNCTION__); } } if (iDisabled == 1) { m_state = PVR_TIMER_STATE_DISABLED; Logger::Log(LEVEL_DEBUG, "%s Timer state is: Disabled", __FUNCTION__); } if (m_state == PVR_TIMER_STATE_NEW) Logger::Log(LEVEL_DEBUG, "%s Timer state is: NEW", __FUNCTION__); if (m_channelId == PVR_CHANNEL_INVALID_UID) { m_state = PVR_TIMER_STATE_ERROR; Logger::Log(LEVEL_DEBUG, "%s Overriding Timer as channel not found, state is: ERROR", __FUNCTION__); } m_tags.clear(); 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; if (!ContainsTag(TAG_FOR_PADDING)) { //We need to add this as these timers are created by the backend so won't have a padding to read m_tags.append(StringUtils::Format(" Padding=%u,%u", Settings::GetInstance().GetDeviceSettings()->GetGlobalRecordingStartMargin(), Settings::GetInstance().GetDeviceSettings()->GetGlobalRecordingEndMargin())); } } else { m_type = Timer::EPG_ONCE; } } } if (ContainsTag(TAG_FOR_PADDING)) { if (std::sscanf(ReadTagValue(TAG_FOR_PADDING).c_str(), "%u,%u", &m_paddingStartMins, &m_paddingEndMins) != 2) { m_paddingStartMins = 0; m_paddingEndMins = 0; } } if (m_paddingStartMins > 0) m_startTime += m_paddingStartMins * 60; if (m_paddingEndMins > 0) m_endTime -= m_paddingEndMins * 60; if (ContainsTag(TAG_FOR_GENRE_ID)) { int genreId = 0; if (std::sscanf(ReadTagValue(TAG_FOR_GENRE_ID).c_str(), "0x%02X", &genreId) == 1) { m_genreType = genreId & 0xF0; m_genreSubType = genreId & 0x0F; } else { m_genreType = 0; m_genreSubType = 0; } } return true; }pvr.vuplus-3.28.9-Leia/src/enigma2/data/Timer.h000066400000000000000000000103231356012415200211020ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "../Channels.h" #include "../utilities/UpdateState.h" #include "BaseEntry.h" #include "Tags.h" #include "tinyxml.h" #include "kodi/libXBMC_pvr.h" #include #include #include 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"; static const std::string TAG_FOR_PADDING = "Padding"; class Timer : public EpgEntry, public Tags { 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& GetChannelName() const { return m_channelName; } void SetChannelName(const std::string& value) { m_channelName = value; } time_t GetRealStartTime() const { return m_startTime - (m_paddingStartMins * 60); } time_t GetRealEndTime() const { return m_endTime + (m_paddingEndMins * 60); } int GetWeekdays() const { return m_weekdays; } void SetWeekdays(int value) { m_weekdays = 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; } int GetPaddingStartMins() const { return m_paddingStartMins; } void SetPaddingStartMins(int value) { m_paddingStartMins = value; } int GetPaddingEndMins() const { return m_paddingEndMins; } void SetPaddingEndMins(int value) { m_paddingEndMins = value; } bool IsScheduled() const; bool IsRunning(std::time_t* now, std::string* channelName, std::time_t startTime) 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); protected: Type m_type = Type::MANUAL_ONCE; std::string m_channelName; int m_weekdays; PVR_TIMER_STATE m_state; int m_updateState; unsigned int m_clientIndex; unsigned int m_parentClientIndex; unsigned int m_paddingStartMins = 0; unsigned int m_paddingEndMins = 0; }; } //namespace data } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/extract/000077500000000000000000000000001356012415200204135ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/src/enigma2/extract/EpgEntryExtractor.cpp000066400000000000000000000042241356012415200245520ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "EpgEntryExtractor.h" #include "../utilities/FileUtils.h" #include "GenreIdMapper.h" #include "GenreRytecTextMapper.h" #include "ShowInfoExtractor.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); FileUtils::CopyDirectory(FileUtils::GetResourceDataPath() + SHOW_INFO_DIR, SHOW_INFO_ADDON_DATA_BASE_DIR, true); if (Settings::GetInstance().GetMapGenreIds()) m_extractors.emplace_back(new GenreIdMapper()); if (Settings::GetInstance().GetMapRytecTextGenres()) m_extractors.emplace_back(new GenreRytecTextMapper()); if (Settings::GetInstance().GetExtractShowInfo()) 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; }pvr.vuplus-3.28.9-Leia/src/enigma2/extract/EpgEntryExtractor.h000066400000000000000000000031741356012415200242220ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "IExtractor.h" #include #include #include namespace enigma2 { namespace extract { static const std::string GENRE_DIR = "/genres"; static const std::string GENRE_ADDON_DATA_BASE_DIR = ADDON_DATA_BASE_DIR + GENRE_DIR; static const std::string SHOW_INFO_DIR = "/showInfo"; static const std::string SHOW_INFO_ADDON_DATA_BASE_DIR = ADDON_DATA_BASE_DIR + SHOW_INFO_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 enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/extract/EpisodeSeasonPattern.h000066400000000000000000000033001356012415200246570ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include namespace enigma2 { namespace extract { struct EpisodeSeasonPattern { EpisodeSeasonPattern(const std::string& masterPattern, const std::string& seasonPattern, const std::string& episodePattern) { m_masterRegex = std::regex(masterPattern); m_seasonRegex = std::regex(seasonPattern); m_episodeRegex = std::regex(episodePattern); m_hasSeasonRegex = true; } EpisodeSeasonPattern(const std::string& masterPattern, const std::string& episodePattern) { m_masterRegex = std::regex(masterPattern); m_episodeRegex = std::regex(episodePattern); m_hasSeasonRegex = false; } std::regex m_masterRegex; std::regex m_seasonRegex; std::regex m_episodeRegex; bool m_hasSeasonRegex; }; } //namespace extract } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/extract/GenreIdMapper.cpp000066400000000000000000000111771356012415200236100ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "GenreIdMapper.h" #include "../utilities/FileUtils.h" #include "tinyxml.h" #include "kodi/libXBMC_pvr.h" #include "util/XMLUtils.h" #include 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 = m_genreIdToDvbIdMap.find(combinedGenreType); if (genreMapSearch != m_genreIdToDvbIdMap.end()) { genreType = genreMapSearch->second; } return genreType; } void GenreIdMapper::LoadGenreIdMapFile() { if (!LoadIdToIdGenreFile(Settings::GetInstance().GetMapGenreIdsFile(), m_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()); const 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, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* 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; TiXmlHandle 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")) { const std::string sourceIdString = pNode->Attribute("sourceId"); const std::string targetIdString = pNode->GetText(); int sourceId = std::strtol(sourceIdString.c_str(), nullptr, 16); int targetId = std::strtol(targetIdString.c_str(), nullptr, 16); map.insert({sourceId, targetId}); Logger::Log(LEVEL_TRACE, "%s Read ID Mapping for: %s, sourceId=%#02X, targetId=%#02X", __FUNCTION__, mapperName.c_str(), sourceId, targetId); } return true; } pvr.vuplus-3.28.9-Leia/src/enigma2/extract/GenreIdMapper.h000066400000000000000000000031321356012415200232450ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #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 m_genreIdToDvbIdMap; }; } //namespace extract } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/extract/GenreRytecTextMapper.cpp000066400000000000000000000152351356012415200252060ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "GenreRytecTextMapper.h" #include "../utilities/FileUtils.h" #include "tinyxml.h" #include "kodi/libXBMC_pvr.h" #include "util/XMLUtils.h" #include using namespace enigma2; using namespace enigma2::data; using namespace enigma2::extract; using namespace enigma2::utilities; GenreRytecTextMapper::GenreRytecTextMapper() : IExtractor() { LoadGenreTextMappingFiles(); for (const auto& genreMapEntry : m_kodiGenreTextToDvbIdMap) { m_kodiDvbIdToGenreTextMap.insert({genreMapEntry.second, genreMapEntry.first}); } m_genrePattern = std::regex(GENRE_PATTERN); m_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(), m_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, m_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 = m_genreMap.find(genreText); if (genreMapSearch != m_genreMap.end()) { genreType = genreMapSearch->second; } else { auto kodiGenreMapSearch = m_kodiGenreTextToDvbIdMap.find(genreText); if (kodiGenreMapSearch != m_kodiGenreTextToDvbIdMap.end()) { genreType = kodiGenreMapSearch->second; } } return genreType; } void GenreRytecTextMapper::LoadGenreTextMappingFiles() { if (!LoadTextToIdGenreFile(GENRE_KODI_DVB_FILEPATH, m_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(), m_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()); const 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, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* 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; TiXmlHandle 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")) { const std::string targetIdString = pNode->Attribute("targetId"); const std::string textMapping = pNode->GetText(); int targetId = std::strtol(targetIdString.c_str(), nullptr, 16); map.insert({textMapping, targetId}); Logger::Log(LEVEL_TRACE, "%s Read Text Mapping for: %s, text=%s, targetId=%#02X", __FUNCTION__, mapperName.c_str(), textMapping.c_str(), targetId); } return true; } pvr.vuplus-3.28.9-Leia/src/enigma2/extract/GenreRytecTextMapper.h000066400000000000000000000044351356012415200246530ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #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 m_genrePattern; std::regex m_genreMajorPattern; std::map m_kodiGenreTextToDvbIdMap; std::map m_kodiDvbIdToGenreTextMap; std::map m_genreMap; }; } //namespace extract } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/extract/IExtractor.h000066400000000000000000000041161356012415200226520ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #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 (std::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 enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/extract/ShowInfoExtractor.cpp000066400000000000000000000156401356012415200245550ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "ShowInfoExtractor.h" #include "../utilities/FileUtils.h" #include "tinyxml.h" #include "util/XMLUtils.h" #include using namespace enigma2; using namespace enigma2::data; using namespace enigma2::extract; using namespace enigma2::utilities; ShowInfoExtractor::ShowInfoExtractor() : IExtractor() { 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) { const std::string masterText = GetMatchedText(entry.GetPlotOutline(), entry.GetPlot(), patternSet.m_masterRegex); if (!masterText.empty()) { if (patternSet.m_hasSeasonRegex && entry.GetSeasonNumber() == 0) { const std::string seasonText = GetMatchTextFromString(masterText, patternSet.m_seasonRegex); if (!seasonText.empty()) { entry.SetSeasonNumber(std::atoi(seasonText.c_str())); } } if (entry.GetEpisodeNumber() == 0) { const std::string episodeText = GetMatchTextFromString(masterText, patternSet.m_episodeRegex); if (!episodeText.empty()) { entry.SetEpisodeNumber(std::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) { const std::string yearText = GetMatchedText(entry.GetPlotOutline(), entry.GetPlot(), pattern); if (!yearText.empty() && entry.GetYear() == 0) { entry.SetYear(std::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()); const 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, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* 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; TiXmlHandle 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) { const std::string masterPattern = childNode->Attribute("pattern"); childNode = pNode->FirstChildElement("episode"); if (childNode) { const std::string episodePattern = childNode->Attribute("pattern"); childNode = pNode->FirstChildElement("season"); if (childNode != nullptr) { const 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")) { const 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; } pvr.vuplus-3.28.9-Leia/src/enigma2/extract/ShowInfoExtractor.h000066400000000000000000000053331356012415200242200ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "EpisodeSeasonPattern.h" #include "IExtractor.h" #include #include #include namespace enigma2 { 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 enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/000077500000000000000000000000001356012415200207545ustar00rootroot00000000000000pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/CurlFile.cpp000066400000000000000000000053021356012415200231650ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 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 "../Settings.h" #include "Logger.h" #include 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_ERROR, "%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_ERROR, "%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; } bool CurlFile::Check(const std::string& strURL) { void* fileHandle = XBMC->CURLCreate(strURL.c_str()); if (!fileHandle) { Logger::Log(LEVEL_ERROR, "%s Unable to create curl handle for %s", __FUNCTION__, strURL.c_str()); return false; } XBMC->CURLAddOption(fileHandle, XFILE::CURL_OPTION_PROTOCOL, "connection-timeout", std::to_string(Settings::GetInstance().GetConnectioncCheckTimeoutSecs()).c_str()); if (!XBMC->CURLOpen(fileHandle, XFILE::READ_NO_CACHE)) { Logger::Log(LEVEL_TRACE, "%s Unable to open url: %s", __FUNCTION__, strURL.c_str()); XBMC->CloseFile(fileHandle); return false; } XBMC->CloseFile(fileHandle); return true; }pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/CurlFile.h000066400000000000000000000023451356012415200226360ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "../../client.h" #include 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); bool Check(const std::string& strURL); }; } // namespace utilities } // namespace enigma2 pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/DeviceInfo.h000066400000000000000000000041651356012415200231460ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #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& distroName, const std::string& webIfVersion, unsigned int webIfVersionAsNum) : m_serverName(serverName), m_enigmaVersion(enigmaVersion), m_imageVersion(imageVersion), m_distroName(distroName), 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& GetDistroName() const { return m_distroName; } 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_distroName; std::string m_webIfVersion; unsigned int m_webIfVersionAsNum; }; } //namespace utilities } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/DeviceSettings.h000066400000000000000000000037421356012415200240530ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #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 enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/FileUtils.cpp000066400000000000000000000126731356012415200233710ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 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 "../../client.h" #include "Logger.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) { const 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; } pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/FileUtils.h000066400000000000000000000033011356012415200230220ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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); }; } // namespace utilities } // namespace enigma2 pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/LocalizedString.h000066400000000000000000000032631356012415200242260ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #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 pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/Logger.cpp000066400000000000000000000034421356012415200227020ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 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 #include "p8-platform/util/StringUtils.h" 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(); std::string logMessage; // Prepend the prefix when set const std::string prefix = logger.m_prefix; if (!prefix.empty()) logMessage = prefix + " - "; logMessage += message; va_list arguments; va_start(arguments, message); logMessage = StringUtils::FormatV(logMessage.c_str(), arguments); va_end(arguments); logger.m_implementation(level, logMessage.c_str()); } void Logger::SetImplementation(LoggerImplementation implementation) { m_implementation = implementation; } void Logger::SetPrefix(const std::string& prefix) { m_prefix = prefix; } pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/Logger.h000066400000000000000000000047441356012415200223550ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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_NOTICE, LEVEL_INFO, LEVEL_DEBUG, LEVEL_TRACE }; /** * Short-hand for a function that acts as the logger implementation */ typedef std::function LoggerImplementation; /** * The logger class. It is a singleton that by default comes with no * underlying implementation. It is up to the user to supply a suitable * implementation as a lambda using SetImplementation(). */ class Logger { public: /** * Returns the singleton instance * @return */ static Logger& GetInstance(); /** * Logs the specified message using the specified log level * @param level the log level * @param message the log message * @param ... parameters for the log message */ static void Log(LogLevel level, const char* message, ...); /** * Configures the logger to use the specified implementation * @param implementation lambda */ void SetImplementation(LoggerImplementation implementation); /** * Sets the prefix to use in log messages * @param prefix */ void SetPrefix(const std::string& prefix); private: Logger(); /** * The logger implementation */ LoggerImplementation m_implementation; /** * The log message prefix */ std::string m_prefix; }; } // namespace utilities } // namespace enigma2 pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/SignalStatus.h000066400000000000000000000022641356012415200235520ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include namespace enigma2 { namespace utilities { static const int POLL_INTERVAL_SECONDS = 10; struct SignalStatus { int m_snrPercentage; long m_ber; int m_signalStrength; std::string m_adapterName; std::string m_adapterStatus; }; } //namespace utilities } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/StreamStatus.h000066400000000000000000000023731356012415200235710ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include namespace enigma2 { namespace utilities { enum class StreamType : int // same type as addon settings { DIRECTLY_STREAMED = 0, TRANSCODED }; struct StreamStatus { std::string m_ipAddress; std::string m_serviceReference; std::string m_channelName; StreamType m_streamType; }; } //namespace utilities } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/Tuner.h000066400000000000000000000023731356012415200222270ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 Team XBMC * http://www.xbmc.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with XBMC; see the file COPYING. If not, write to * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1335, USA. * http://www.gnu.org/copyleft/gpl.html * */ #include namespace enigma2 { namespace utilities { struct Tuner { Tuner(int tunerNumber, const std::string& tunerName, const std::string& tunerModel) : m_tunerNumber(tunerNumber), m_tunerName(tunerName), m_tunerModel(tunerModel){}; int m_tunerNumber; std::string m_tunerName; std::string m_tunerModel; }; } //namespace utilities } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/UpdateState.h000066400000000000000000000022131356012415200233460ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 "../data/BaseEntry.h" #include namespace enigma2 { namespace utilities { typedef enum UPDATE_STATE { UPDATE_STATE_NONE, UPDATE_STATE_FOUND, UPDATE_STATE_UPDATED, UPDATE_STATE_NEW } UPDATE_STATE; } // namespace utilities } //namespace enigma2pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/WebUtils.cpp000066400000000000000000000163301356012415200232210ustar00rootroot00000000000000/* * Copyright (C) 2005-2019 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 "../Settings.h" #include "CurlFile.h" #include "Logger.h" #include "p8-platform/util/StringUtils.h" #include "tinyxml.h" #include "util/XMLUtils.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; } bool WebUtils::CheckHttp(const std::string& url) { Logger::Log(LEVEL_TRACE, "%s Check webAPI with URL: '%s'", __FUNCTION__, url.c_str()); CurlFile http; if (!http.Check(url)) { Logger::Log(LEVEL_TRACE, "%s - Could not open webAPI.", __FUNCTION__); return false; } Logger::Log(LEVEL_TRACE, "%s WebAPI available", __FUNCTION__); return true; } std::string WebUtils::GetHttp(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_ERROR, "%s - Could not open webAPI.", __FUNCTION__); return ""; } Logger::Log(LEVEL_INFO, "%s Got result. Length: %u", __FUNCTION__, strTmp.length()); return strTmp; } std::string WebUtils::GetHttpXML(const std::string& url) { std::string strTmp = GetHttp(url); // 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"; 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_ERROR, "%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()); const std::string strXML = WebUtils::GetHttpXML(url); if (!bIgnoreResult) { TiXmlDocument xmlDoc; if (!xmlDoc.Parse(strXML.c_str())) { Logger::Log(LEVEL_ERROR, "%s Unable to parse XML: %s at line %d", __FUNCTION__, xmlDoc.ErrorDesc(), xmlDoc.ErrorRow()); return false; } TiXmlHandle hDoc(&xmlDoc); TiXmlElement* pElem; TiXmlHandle hRoot(0); pElem = hDoc.FirstChildElement("e2simplexmlresult").Element(); if (!pElem) { Logger::Log(LEVEL_ERROR, "%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::SendSimpleJsonCommand(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()); const std::string strJson = WebUtils::GetHttp(url); if (!bIgnoreResult) { if (strJson.find("\"result\": 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; } 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()); const std::string strJson = WebUtils::PostHttpJson(url); if (!bIgnoreResult) { if (strJson.find("\"result\": 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; }pvr.vuplus-3.28.9-Leia/src/enigma2/utilities/WebUtils.h000066400000000000000000000033711356012415200226670ustar00rootroot00000000000000#pragma once /* * Copyright (C) 2005-2019 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 bool CheckHttp(const std::string& url); static std::string GetHttp(const std::string& url); 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 SendSimpleJsonCommand(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); }; } // namespace utilities } // namespace enigma2