/*
 *  Copyright (C) 2005-2018 Team Kodi
 *  This file is part of Kodi - https://kodi.tv
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 *  See LICENSES/README.md for more information.
 */

#include "GUIInfoManager.h"

#include "FileItem.h"
#include "ServiceBroker.h"
#include "URL.h"
#include "Util.h"
#include "application/ApplicationComponents.h"
#include "application/ApplicationPlayer.h"
#include "cores/DataCacheCore.h"
#include "filesystem/File.h"
#include "games/tags/GameInfoTag.h"
#include "guilib/guiinfo/GUIInfo.h"
#include "guilib/guiinfo/GUIInfoHelper.h"
#include "guilib/guiinfo/GUIInfoLabels.h"
#include "input/WindowTranslator.h"
#include "interfaces/AnnouncementManager.h"
#include "interfaces/info/InfoExpression.h"
#include "messaging/ApplicationMessenger.h"
#include "playlists/PlayListTypes.h"
#include "settings/SkinSettings.h"
#include "utils/CharsetConverter.h"
#include "utils/FileUtils.h"
#include "utils/StringUtils.h"
#include "utils/URIUtils.h"
#include "utils/log.h"

#include <algorithm>
#include <array>
#include <charconv>
#include <cmath>
#include <functional>
#include <iterator>
#include <memory>
#include <mutex>

using namespace KODI::GUILIB;
using namespace KODI::GUILIB::GUIINFO;
using namespace INFO;

bool InfoBoolComparator(const InfoPtr &right, const InfoPtr &left)
{
  return *right < *left;
}

CGUIInfoManager::CGUIInfoManager(void)
: m_currentFile(new CFileItem),
  m_bools(&InfoBoolComparator)
{
}

CGUIInfoManager::~CGUIInfoManager(void)
{
  delete m_currentFile;
}

void CGUIInfoManager::Initialize()
{
  CServiceBroker::GetAppMessenger()->RegisterReceiver(this);
}

/// \brief Translates a string as given by the skin into an int that we use for more
/// efficient retrieval of data. Can handle combined strings on the form
/// Player.Caching + VideoPlayer.IsFullscreen (Logical and)
/// Player.HasVideo | Player.HasAudio (Logical or)
int CGUIInfoManager::TranslateString(const std::string &condition)
{
  // translate $LOCALIZE as required
  std::string strCondition(CGUIInfoLabel::ReplaceLocalize(condition));
  return TranslateSingleString(strCondition);
}

typedef struct
{
  const char *str;
  int  val;
} infomap;

/// \page modules__infolabels_boolean_conditions Infolabels and Boolean conditions
/// \tableofcontents
///
/// \section modules__infolabels_boolean_conditions_Description Description
/// Skins can use boolean conditions with the <b>\<visible\></b> tag or with condition
/// attributes. Scripts can read boolean conditions with
/// <b>xbmc.getCondVisibility(condition)</b>.
///
/// Skins can use infolabels with <b>$INFO[infolabel]</b> or the <b>\<info\></b> tag. Scripts
/// can read infolabels with <b>xbmc.getInfoLabel('infolabel')</b>.
///
/// @todo [docs] Improve the description and create links for functions
/// @todo [docs] Separate boolean conditions from infolabels
/// @todo [docs] Order items alphabetically within subsections for a better search experience
/// @todo [docs] Order subsections alphabetically
/// @todo [docs] Use links instead of bold values for infolabels/bools
/// so we can use a link to point users when providing help
///


/// \page modules__infolabels_boolean_conditions
/// \section modules_list_infolabels_booleans List of Infolabels and Boolean conditions
/// \subsection modules__infolabels_boolean_conditions_GlobalBools Global
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`true`</b>,
///                  \anchor Global_True
///                  _boolean_,
///     @return Always evaluates to **true**.
///     <p>
///   }
///   \table_row3{   <b>`false`</b>,
///                  \anchor Global_False
///                  _boolean_,
///     @return Always evaluates to **false**.
///     <p>
///   }
///   \table_row3{   <b>`yes`</b>,
///                  \anchor Global_Yes
///                  _boolean_,
///     @return same as \link Global_True `true` \endlink.
///     <p>
///   }
///   \table_row3{   <b>`no`</b>,
///                  \anchor Global_No
///                  _boolean_,
///     @return same as \link Global_False `false` \endlink.
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Addon Addon
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`Addon.SettingStr(addon_id\,setting_id)`</b>,
///                  \anchor Addon_SettingString
///                  _string_,
///     @return The string value of the setting `setting_id` belonging to the addon with the id `addon_id`.
///     @param addon_id - the id of the addon
///     @param setting_id - the addon setting
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link Addon_SettingString `Addon.SettingStr(addon_id\,setting_id)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Addon.SettingBool(addon_id\,setting_id)`</b>,
///                  \anchor Addon_SettingBool
///                  _boolean_,
///     @return **True** if the setting `setting_id` belonging to the addon with the id `addon_id` is **True**\, **False** otherwise.
///     @note The provided setting with `setting_id` must be a boolean setting type. Otherwise it will return the boolean info
///     default value (which is **False**).
///     @param addon_id - the id of the addon
///     @param setting_id - the addon setting
///     <p><hr>
///     @skinning_v20 **[New Boolean Condition]** \link Addon_SettingBool `Addon.SettingBool(addon_id\,setting_id)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Addon.SettingInt(addon_id\,setting_id)`</b>,
///                  \anchor Addon_SettingInt
///                  _integer_,
///     @return The integer value of the setting `setting_id` belong to the addon with the id `addon_id`.
///     @note The provided setting with `setting_id` must be an integer setting type. Otherwise it will return the integer info
///     default value (which is 0).
///     @param addon_id - the id of the addon
///     @param setting_id - the addon setting
///     <p><hr>
///     @skinning_v20 **[New Integer Info]** \link Addon_SettingInt `Addon.SettingInt(addon_id\,setting_id)`\endlink
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap addons[] = {
    {"settingstr", ADDON_SETTING_STRING},
    {"settingbool", ADDON_SETTING_BOOL},
    {"settingint", ADDON_SETTING_INT},
};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_String String
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`String.IsEmpty(info)`</b>,
///                  \anchor String_IsEmpty
///                  _boolean_,
///     @return **True** if the info is empty.
///     @param info - infolabel
///     @note **Example of info:** \link ListItem_Title `ListItem.Title` \endlink \,
///     \link ListItem_Genre `ListItem.Genre` \endlink.
///     Please note that string can also be a `$LOCALIZE[]`.
///     Also note that in a panelview or similar this only works on the focused item
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link String_IsEmpty `String.IsEmpty(info)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`String.IsEqual(info\,string)`</b>,
///                  \anchor String_IsEqual
///                  _boolean_,
///     @return **True** if the info is equal to the given string.
///     @param info - infolabel
///     @param string - comparison string
///     @note **Example of info:** \link ListItem_Title `ListItem.Title` \endlink \,
///     \link ListItem_Genre `ListItem.Genre` \endlink.
///     Please note that string can also be a `$LOCALIZE[]`.
///     Also note that in a panelview or similar this only works on the focused item
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link String_IsEqual `String.IsEqual(info\,string)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`String.StartsWith(info\,substring)`</b>,
///                  \anchor String_StartsWith
///                  _boolean_,
///     @return **True** if the info starts with the given substring.
///     @param info - infolabel
///     @param substring - substring to check
///     @note **Example of info:** \link ListItem_Title `ListItem.Title` \endlink \,
///     \link ListItem_Genre `ListItem.Genre` \endlink.
///     Please note that string can also be a `$LOCALIZE[]`.
///     Also note that in a panelview or similar this only works on the focused item
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link String_StartsWith `String.StartsWith(info\,substring)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`String.EndsWith(info\,substring)`</b>,
///                  \anchor String_EndsWith
///                  _boolean_,
///     @return **True** if the info ends with the given substring.
///     @param info - infolabel
///     @param substring - substring to check
///     @note **Example of info:** \link ListItem_Title `ListItem.Title` \endlink \,
///     \link ListItem_Genre `ListItem.Genre` \endlink.
///     Please note that string can also be a `$LOCALIZE[]`.
///     Also note that in a panelview or similar this only works on the focused item
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link String_EndsWith `String.EndsWith(info\,substring)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`String.Contains(info\,substring)`</b>,
///                  \anchor String_Contains
///                  _boolean_,
///     @return **True** if the info contains the given substring.
///     @param info - infolabel
///     @param substring - substring to check
///     @note **Example of info:** \link ListItem_Title `ListItem.Title` \endlink \,
///     \link ListItem_Genre `ListItem.Genre` \endlink.
///     Please note that string can also be a `$LOCALIZE[]`.
///     Also note that in a panelview or similar this only works on the focused item
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link String_Contains `String.Contains(info\,substring)`\endlink
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------


const infomap string_bools[] =   {{ "isempty",          STRING_IS_EMPTY },
                                  { "isequal",          STRING_IS_EQUAL },
                                  { "startswith",       STRING_STARTS_WITH },
                                  { "endswith",         STRING_ENDS_WITH },
                                  { "contains",         STRING_CONTAINS }};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Integer Integer
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`Integer.ValueOf(number)`</b>,
///                  \anchor Integer_ValueOf
///                  _integer_,
///     @return An integer info label that represents the provided number
///     @param number - the number to compute
///     @note **Example:** `Integer.ValueOf(4)` will be evaluated to 4.
///     @note Will return -1 if not able to convert the provided value to an integer. **Example**: `Integer.ValueOf(some string)` will evaluate to -1
///     as the provided argument is not an integer.
///     <p><hr>
///     @skinning_v20 **[New InfoLabel]** \link Integer_ValueOf `Integer.ValueOf(number)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Integer.IsEqual(info\,number)`</b>,
///                  \anchor Integer_IsEqual
///                  _boolean_,
///     @return **True** if the value of the infolabel is equal to the supplied number.
///     @param info - infolabel
///     @param number - number or integer infolabel to compare
///     @note **Example:** `Integer.IsEqual(ListItem.Year\,2000)`
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Integer_IsEqual `Integer.IsEqual(info\,number)`\endlink
///     @skinning_v20 \link Integer_IsEqual `Integer.IsEqual(info\,number)`\endlink now supports comparisons against other integer infos
///     and not just fixed number values.
///     <p>
///   }
///   \table_row3{   <b>`Integer.IsGreater(info\,number)`</b>,
///                  \anchor Integer_IsGreater
///                  _boolean_,
///     @return **True** if the value of the infolabel is greater than to the supplied number.
///     @param info - infolabel
///     @param number - number or integer infolabel to compare
///     @note **Example:** `Integer.IsGreater(ListItem.Year\,2000)`
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Integer_IsGreater `Integer.IsGreater(info\,number)`\endlink
///     @skinning_v20 \link Integer_IsGreater `Integer.IsGreater(info\,number)`\endlink now supports comparisons against other integer infos
///     and not just fixed number values.
///     <p>
///   }
///   \table_row3{   <b>`Integer.IsGreaterOrEqual(info\,number)`</b>,
///                  \anchor Integer_IsGreaterOrEqual
///                  _boolean_,
///     @return **True** if the value of the infolabel is greater or equal to the supplied number.
///     @param info - infolabel
///     @param number - number or integer infolabel to compare
///     @note **Example:** `Integer.IsGreaterOrEqual(ListItem.Year\,2000)`
///     @note **Example2:** `Integer.IsGreaterOrEqual(Container(x).ListItem(1).Year\,Container(x).ListItem(2).Year)`
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Integer_IsGreaterOrEqual `Integer.IsGreaterOrEqual(info\,number)`\endlink
///     @skinning_v20 \link Integer_IsGreaterOrEqual `Integer.IsGreaterOrEqual(info\,number)`\endlink now supports comparisons against other integer infos
///     and not just fixed number values.
///     <p>
///   }
///   \table_row3{   <b>`Integer.IsLess(info\,number)`</b>,
///                  \anchor Integer_IsLess
///                  _boolean_,
///     @return **True** if the value of the infolabel is less than the supplied number.
///     @param info - infolabel
///     @param number - number or integer infolabel to compare
///     @note **Example:** `Integer.IsLess(ListItem.Year\,2000)`
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Integer_IsLess `Integer.IsLess(info\,number)`\endlink
///     @skinning_v20 \link Integer_IsLess `Integer.IsLess(info\,number)`\endlink now supports comparisons against other integer infos
///     and not just fixed number values.
///     <p>
///   }
///   \table_row3{   <b>`Integer.IsLessOrEqual(info\,number)`</b>,
///                  \anchor Integer_IsLessOrEqual
///                  _boolean_,
///     @return **True** if the value of the infolabel is less or equal to the supplied number.
///     @param info - infolabel
///     @param number - number or integer infolabel to compare
///     @note **Example:** `Integer.IsLessOrEqual(ListItem.Year\,2000)`
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Integer_IsLessOrEqual `Integer.IsLessOrEqual(info\,number)`\endlink
///     @skinning_v20 \link Integer_IsLessOrEqual `Integer.IsLessOrEqual(info\,number)`\endlink now supports comparisons against other integer infos
///     and not just fixed number values.
///     <p>
///   }
///   \table_row3{   <b>`Integer.IsEven(info)`</b>,
///                  \anchor Integer_IsEven
///                  _boolean_,
///     @return **True** if the value of the infolabel is odd
///     @param info - infolabel
///     @note **Example:** `Integer.IsEven(ListItem.CurrentItem)`
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \link Integer_IsEven `Integer.IsEven(info)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Integer.IsOdd(info)`</b>,
///                  \anchor Integer_IsOdd
///                  _boolean_,
///     @return **True** if the value of the infolabel is odd
///     @param info - infolabel
///     @note **Example:** `Integer.IsOdd(ListItem.CurrentItem)`
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \link Integer_IsOdd `Integer.IsOdd(info)`\endlink
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------

const infomap integer_bools[] =  {{ "isequal",          INTEGER_IS_EQUAL },
                                  { "isgreater",        INTEGER_GREATER_THAN },
                                  { "isgreaterorequal", INTEGER_GREATER_OR_EQUAL },
                                  { "isless",           INTEGER_LESS_THAN },
                                  { "islessorequal",    INTEGER_LESS_OR_EQUAL },
                                  { "iseven",           INTEGER_EVEN },
                                  { "isodd",            INTEGER_ODD }};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Player Player
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`Player.HasAudio`</b>,
///                  \anchor Player_HasAudio
///                  _boolean_,
///     @return **True** if the player has an audio file.
///     <p>
///   }
///   \table_row3{   <b>`Player.HasGame`</b>,
///                  \anchor Player_HasGame
///                  _boolean_,
///     @return **True** if the player has a game file (RETROPLAYER).
///     <p><hr>
///     @skinning_v18 **[New Boolean Condition]** \link Player_HasGame `Player.HasGame`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.HasMedia`</b>,
///                  \anchor Player_HasMedia
///                  _boolean_,
///     @return **True** if the player has an audio or video file.
///     <p>
///   }
///   \table_row3{   <b>`Player.HasVideo`</b>,
///                  \anchor Player_HasVideo
///                  _boolean_,
///     @return **True** if the player has a video file.
///     <p>
///   }
///   \table_row3{   <b>`Player.Paused`</b>,
///                  \anchor Player_Paused
///                  _boolean_,
///     @return **True** if the player is paused.
///     <p>
///   }
///   \table_row3{   <b>`Player.Playing`</b>,
///                  \anchor Player_Playing
///                  _boolean_,
///     @return **True** if the player is currently playing (i.e. not ffwding\,
///     rewinding or paused.)
///     <p>
///   }
///   \table_row3{   <b>`Player.Rewinding`</b>,
///                  \anchor Player_Rewinding
///                  _boolean_,
///     @return **True** if the player is rewinding.
///     <p>
///   }
///   \table_row3{   <b>`Player.Rewinding2x`</b>,
///                  \anchor Player_Rewinding2x
///                  _boolean_,
///     @return **True** if the player is rewinding at 2x.
///     <p>
///   }
///   \table_row3{   <b>`Player.Rewinding4x`</b>,
///                  \anchor Player_Rewinding4x
///                  _boolean_,
///     @return **True** if the player is rewinding at 4x.
///     <p>
///   }
///   \table_row3{   <b>`Player.Rewinding8x`</b>,
///                  \anchor Player_Rewinding8x
///                  _boolean_,
///     @return **True** if the player is rewinding at 8x.
///     <p>
///   }
///   \table_row3{   <b>`Player.Rewinding16x`</b>,
///                  \anchor Player_Rewinding16x
///                  _boolean_,
///     @return **True** if the player is rewinding at 16x.
///     <p>
///   }
///   \table_row3{   <b>`Player.Rewinding32x`</b>,
///                  \anchor Player_Rewinding32x
///                  _boolean_,
///     @return **True** if the player is rewinding at 32x.
///     <p>
///   }
///   \table_row3{   <b>`Player.Forwarding`</b>,
///                  \anchor Player_Forwarding
///                  _boolean_,
///     @return **True** if the player is fast forwarding.
///     <p>
///   }
///   \table_row3{   <b>`Player.Forwarding2x`</b>,
///                  \anchor Player_Forwarding2x
///                  _boolean_,
///     @return **True** if the player is fast forwarding at 2x.
///     <p>
///   }
///   \table_row3{   <b>`Player.Forwarding4x`</b>,
///                  \anchor Player_Forwarding4x
///                  _boolean_,
///     @return **True** if the player is fast forwarding at 4x.
///     <p>
///   }
///   \table_row3{   <b>`Player.Forwarding8x`</b>,
///                  \anchor Player_Forwarding8x
///                  _boolean_,
///     @return **True** if the player is fast forwarding at 8x.
///     <p>
///   }
///   \table_row3{   <b>`Player.Forwarding16x`</b>,
///                  \anchor Player_Forwarding16x
///                  _boolean_,
///     @return **True** if the player is fast forwarding at 16x.
///     <p>
///   }
///   \table_row3{   <b>`Player.Forwarding32x`</b>,
///                  \anchor Player_Forwarding32x
///                  _boolean_,
///     @return **True** if the player is fast forwarding at 32x.
///     <p>
///   }
///   \table_row3{   <b>`Player.Caching`</b>,
///                  \anchor Player_Caching
///                  _boolean_,
///     @return **True** if the player is current re-caching data (internet based
///     video playback).
///     <p>
///   }
///   \table_row3{   <b>`Player.DisplayAfterSeek`</b>,
///                  \anchor Player_DisplayAfterSeek
///                  _boolean_,
///     @return **True** for the first 2.5 seconds after a seek.
///     <p>
///   }
///   \table_row3{   <b>`Player.Seekbar`</b>,
///                  \anchor Player_Seekbar
///                  _integer_,
///     @return The percentage of one seek to other position.
///     <p>
///   }
///   \table_row3{   <b>`Player.Seeking`</b>,
///                  \anchor Player_Seeking
///                  _boolean_,
///     @return **True** if a seek is in progress.
///     <p>
///   }
///   \table_row3{   <b>`Player.ShowTime`</b>,
///                  \anchor Player_ShowTime
///                  _boolean_,
///     @return **True** if the user has requested the time to show (occurs in video
///     fullscreen).
///     <p>
///   }
///   \table_row3{   <b>`Player.ShowInfo`</b>,
///                  \anchor Player_ShowInfo
///                  _boolean_,
///     @return **True** if the user has requested the song info to show (occurs in
///     visualisation fullscreen and slideshow).
///     <p>
///   }
///   \table_row3{   <b>`Player.Title`</b>,
///                  \anchor Player_Title
///                  _string_,
///     @return The Musicplayer title for audio and the Videoplayer title for
///     video.
///     <p>
///   }
///   \table_row3{   <b>`Player.offset(number).Title`</b>,
///                  \anchor Player_Offset_Title
///                  _string_,
///     @return The title of audio or video which has an offset `number` with respect to the currently playing item.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link Player_Offset_Title `Player.offset(number).Title`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.position(number).Title`</b>,
///                  \anchor Player_Position_Title
///                  _string_,
///     @return The title of the audio or video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link Player_Position_Title `Player.position(number).Title`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Muted`</b>,
///                  \anchor Player_Muted
///                  _boolean_,
///     @return **True** if the volume is muted.
///     <p>
///   }
///   \table_row3{   <b>`Player.HasDuration`</b>,
///                  \anchor Player_HasDuration
///                  _boolean_,
///     @return **True** if Media is not a true stream.
///     <p>
///   }
///   \table_row3{   <b>`Player.Passthrough`</b>,
///                  \anchor Player_Passthrough
///                  _boolean_,
///     @return **True** if the player is using audio passthrough.
///     <p>
///   }
///   \table_row3{   <b>`Player.CacheLevel`</b>,
///                  \anchor Player_CacheLevel
///                  _string_,
///     @return The used cache level as a string with an integer number.
///     <p>
///   }
///   \table_row3{   <b>`Player.Progress`</b>,
///                  \anchor Player_Progress
///                  _integer_ / _string_,
///     @return The progress position as percentage.
///     <p><hr>
///     @skinning_v19 \link Player_Progress `Player.Progress`\endlink infolabel
///     also exposed as a string.
///     <p>
///   }
///   \table_row3{   <b>`Player.ProgressCache`</b>,
///                  \anchor Player_ProgressCache
///                  _integer_ / _string_,
///     @return How much of the file is cached above current play percentage
///     <p><hr>
///     @skinning_v19 \link Player_ProgressCache `Player.ProgressCache`\endlink
///     infolabel also exposed as a string.
///     <p>
///   }
///   \table_row3{   <b>`Player.Volume`</b>,
///                  \anchor Player_Volume
///                  _string_,
///     @return The current player volume with the format `%2.1f` dB
///     <p>
///   }
///   \table_row3{   <b>`Player.SubtitleDelay`</b>,
///                  \anchor Player_SubtitleDelay
///                  _string_,
///     @return The used subtitle delay with the format `%2.3f` s
///     <p>
///   }
///   \table_row3{   <b>`Player.AudioDelay`</b>,
///                  \anchor Player_AudioDelay
///                  _string_,
///     @return The used audio delay with the format `%2.3f` s
///     <p>
///   }
///   \table_row3{   <b>`Player.Chapter`</b>,
///                  \anchor Player_Chapter
///                  _integer_,
///     @return The current chapter of current playing media.
///     <p>
///   }
///   \table_row3{   <b>`Player.ChapterCount`</b>,
///                  \anchor Player_ChapterCount
///                  _integer_,
///     @return The total number of chapters of current playing media.
///     <p>
///   }
///   \table_row3{   <b>`Player.ChapterName`</b>,
///                  \anchor Player_ChapterName
///                  _string_,
///     @return The name of currently used chapter if available.
///     <p>
///   }
///   \table_row3{   <b>`Player.Folderpath`</b>,
///                  \anchor Player_Folderpath
///                  _string_,
///     @return The full path of the currently playing song or movie
///     <p>
///   }
///   \table_row3{   <b>`Player.offset(number).Folderpath`</b>,
///                  \anchor Player_Offset_Folderpath
///                  _string_,
///     @return The full path of the audio or video file which has an offset `number` with respect to the currently playing item.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link Player_Offset_Folderpath `Player.offset(number).Folderpath`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.position(number).Folderpath`</b>,
///                  \anchor Player_Position_Folderpath
///                  _string_,
///     @return The full path of the audio or video file which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link Player_Position_Folderpath `Player.position(number).Folderpath`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.FilenameAndPath`</b>,
///                  \anchor Player_FilenameAndPath
///                  _string_,
///     @return The full path with filename of the currently
///     playing song or movie
///     <p>
///   }
///   \table_row3{   <b>`Player.offset(number).FilenameAndPath`</b>,
///                  \anchor Player_Offset_FilenameAndPath
///                  _string_,
///     @return The full path with filename of audio or video file which has an offset `number` with respect to the currently playing item.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link Player_Offset_FilenameAndPath `Player.offset(number).FilenameAndPath`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.position(number).FilenameAndPath`</b>,
///                  \anchor Player_Position_FilenameAndPath
///                  _string_,
///     @return The full path with filename of the audio or video file which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link Player_Position_FilenameAndPath `Player.position(number).FilenameAndPath`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Filename`</b>,
///                  \anchor Player_Filename
///                  _string_,
///     @return The filename of the currently playing media.
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Player_Filename `Player.Filename`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.offset(number).Filename`</b>,
///                  \anchor Player_Offset_Filename
///                  _string_,
///     @return The filename of audio or video file which has an offset `number` with respect to the currently playing item.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link Player_Offset_Filename `Player.offset(number).Filename`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.position(number).Filename`</b>,
///                  \anchor Player_Position_Filename
///                  _string_,
///     @return The filename of the audio or video file which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link Player_Position_Filename `Player.position(number).Filename`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.IsInternetStream`</b>,
///                  \anchor Player_IsInternetStream
///                  _boolean_,
///     @return **True** if the player is playing an internet stream.
///     <p>
///   }
///   \table_row3{   <b>`Player.PauseEnabled`</b>,
///                  \anchor Player_PauseEnabled
///                  _boolean_,
///     @return **True** if played stream is paused.
///     <p>
///   }
///   \table_row3{   <b>`Player.SeekEnabled`</b>,
///                  \anchor Player_SeekEnabled
///                  _boolean_,
///     @return **True** if seek on playing is enabled.
///     <p>
///   }
///   \table_row3{   <b>`Player.ChannelPreviewActive`</b>,
///                  \anchor Player_ChannelPreviewActive
///                  _boolean_,
///     @return **True** if PVR channel preview is active (used
///     channel tag different from played tag)
///     <p>
///   }
///   \table_row3{   <b>`Player.TempoEnabled`</b>,
///                  \anchor Player_TempoEnabled
///                  _boolean_,
///     @return **True** if player supports tempo (i.e. speed up/down normal
///     playback speed)
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Player_TempoEnabled `Player.TempoEnabled`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.IsTempo`</b>,
///                  \anchor Player_IsTempo
///                  _boolean_,
///     @return **True** if player has tempo (i.e. is playing with a playback speed higher or
///     lower than normal playback speed)
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Player_IsTempo `Player.IsTempo`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.PlaySpeed`</b>,
///                  \anchor Player_PlaySpeed
///                  _string_,
///     @return The player playback speed with the format `%1.2f` (1.00 means normal
///     playback speed).
///     @note For Tempo\, the default range is 0.80 - 1.50 (it can be changed
///     in advanced settings). If \ref Player_PlaySpeed "Player.PlaySpeed" returns a value different from 1.00
///     and \ref Player_IsTempo "Player.IsTempo" is false it means the player is in ff/rw mode.
///     <p>
///   }
///   \table_row3{   <b>`Player.HasResolutions`</b>,
///                  \anchor Player_HasResolutions
///                  _boolean_,
///     @return **True** if the player is allowed to switch resolution and refresh rate
///     (i.e. if whitelist modes are configured in Kodi's System/Display settings)
///     <p><hr>
///     @skinning_v18 **[New Boolean Condition]** \link Player_HasResolutions `Player.HasResolutions`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.HasPrograms`</b>,
///                  \anchor Player_HasPrograms
///                  _boolean_,
///     @return **True** if the media file being played has programs\, i.e. groups of streams.
///     @note Ex: if a media file has multiple streams (quality\, channels\, etc) a program represents
///     a particular stream combo.
///     <p>
///   }
///   \table_row3{   <b>`Player.FrameAdvance`</b>,
///                  \anchor Player_FrameAdvance
///                  _boolean_,
///     @return **True** if player is in frame advance mode.
///     @note Skins should hide seek bar in this mode
///     <p><hr>
///     @skinning_v18 **[New Boolean Condition]** \link Player_FrameAdvance `Player.FrameAdvance`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Icon`</b>,
///                  \anchor Player_Icon
///                  _string_,
///     @return The thumbnail of the currently playing item. If no thumbnail image exists\,
///     the icon will be returned\, if available.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link Player_Icon `Player.Icon`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Cutlist`</b>,
///                  \anchor Player_Cutlist
///                  _string_,
///     @return The cutlist of the currently playing item as csv in the format start1\,end1\,start2\,end2\,...
///     Tokens must have values in the range from 0.0 to 100.0. end token must be less or equal than start token.
///     <p>
///     @deprecated \link Player_Cutlist `Player.Cutlist`\endlink is deprecated and will be removed in the next version.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link Player_Cutlist `Player.Cutlist`\endlink
///     @skinning_v20 \link Player_Cutlist `Player.Cutlist`\endlink is deprecated\, use \link Player_Cuts `Player.Cuts`\endlink instead
///     <p>
///   }
///   \table_row3{   <b>`Player.Editlist`</b>,
///                  \anchor Player_Editlist
///                  _string_,
///     @return The editlist of the currently playing item as csv in the format start1\,end1\,start2\,end2\,...
///     Tokens must have values in the range from 0.0 to 100.0. end token must be less or equal than start token.
///     @note This infolabel does not contain EDL cuts. Edits start and end times are ajusted according to cuts
///     defined for the media item.
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link Player_Editlist `Player.Editlist`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Cuts`</b>,
///                  \anchor Player_Cuts
///                  _string_,
///     @return The EDL cut markers of the currently playing item as csv in the format start1\,end1\,start2\,end2\,...
///     Tokens must have values in the range from 0.0 to 100.0. end token must be less or equal than start token.
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link Player_Cuts `Player.Cuts`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.SceneMarkers`</b>,
///                  \anchor Player_SceneMarkers
///                  _string_,
///     @return The EDL scene markers of the currently playing item as csv in the format start1\,end1\,start2\,end2\,...
///     Tokens must have values in the range from 0.0 to 100.0. end token must be less or equal than start token.
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link Player_SceneMarkers `Player.SceneMarkers`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.HasSceneMarkers`</b>,
///                  \anchor Player_HasSceneMarkers
///                  _boolean_,
///     @return **True** if the item being played has scene markers\, **False** otherwise
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link Player_HasSceneMarkers `Player.HasSceneMarkers`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Chapters`</b>,
///                  \anchor Player_Chapters
///                  _string_,
///     @return The chapters of the currently playing item as csv in the format start1\,end1\,start2\,end2\,...
///     Tokens must have values in the range from 0.0 to 100.0. end token must be less or equal than start token.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link Player_Chapters `Player.Chapters`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.IsExternal`</b>,
///                  \anchor Player_IsExternal
///                  _boolean_,
///     @return **True** if the playing player is an external player\, **False** otherwise
///     <p><hr>
///     @skinning_v21 **[New Boolean Condition]** \link Player_IsExternal `Player.IsExternal`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.IsRemote`</b>,
///                  \anchor Player_IsRemote
///                  _boolean_,
///     @return **True** if the playing player is a remote player (e.g. UPnP)\, **False** otherwise
///     <p><hr>
///     @skinning_v21 **[New Boolean Condition]** \link Player_IsRemote `Player.IsRemote`\endlink
///     <p>
///   }
const infomap player_labels[] = {{"hasmedia", PLAYER_HAS_MEDIA},
                                 {"hasaudio", PLAYER_HAS_AUDIO},
                                 {"hasvideo", PLAYER_HAS_VIDEO},
                                 {"hasgame", PLAYER_HAS_GAME},
                                 {"isexternal", PLAYER_IS_EXTERNAL},
                                 {"isremote", PLAYER_IS_REMOTE},
                                 {"playing", PLAYER_PLAYING},
                                 {"paused", PLAYER_PAUSED},
                                 {"rewinding", PLAYER_REWINDING},
                                 {"forwarding", PLAYER_FORWARDING},
                                 {"rewinding2x", PLAYER_REWINDING_2x},
                                 {"rewinding4x", PLAYER_REWINDING_4x},
                                 {"rewinding8x", PLAYER_REWINDING_8x},
                                 {"rewinding16x", PLAYER_REWINDING_16x},
                                 {"rewinding32x", PLAYER_REWINDING_32x},
                                 {"forwarding2x", PLAYER_FORWARDING_2x},
                                 {"forwarding4x", PLAYER_FORWARDING_4x},
                                 {"forwarding8x", PLAYER_FORWARDING_8x},
                                 {"forwarding16x", PLAYER_FORWARDING_16x},
                                 {"forwarding32x", PLAYER_FORWARDING_32x},
                                 {"caching", PLAYER_CACHING},
                                 {"seekbar", PLAYER_SEEKBAR},
                                 {"seeking", PLAYER_SEEKING},
                                 {"showtime", PLAYER_SHOWTIME},
                                 {"showinfo", PLAYER_SHOWINFO},
                                 {"muted", PLAYER_MUTED},
                                 {"hasduration", PLAYER_HASDURATION},
                                 {"passthrough", PLAYER_PASSTHROUGH},
                                 {"cachelevel", PLAYER_CACHELEVEL},
                                 {"title", PLAYER_TITLE},
                                 {"progress", PLAYER_PROGRESS},
                                 {"progresscache", PLAYER_PROGRESS_CACHE},
                                 {"volume", PLAYER_VOLUME},
                                 {"subtitledelay", PLAYER_SUBTITLE_DELAY},
                                 {"audiodelay", PLAYER_AUDIO_DELAY},
                                 {"chapter", PLAYER_CHAPTER},
                                 {"chaptercount", PLAYER_CHAPTERCOUNT},
                                 {"chaptername", PLAYER_CHAPTERNAME},
                                 {"folderpath", PLAYER_PATH},
                                 {"filenameandpath", PLAYER_FILEPATH},
                                 {"filename", PLAYER_FILENAME},
                                 {"isinternetstream", PLAYER_ISINTERNETSTREAM},
                                 {"pauseenabled", PLAYER_CAN_PAUSE},
                                 {"seekenabled", PLAYER_CAN_SEEK},
                                 {"channelpreviewactive", PLAYER_IS_CHANNEL_PREVIEW_ACTIVE},
                                 {"tempoenabled", PLAYER_SUPPORTS_TEMPO},
                                 {"istempo", PLAYER_IS_TEMPO},
                                 {"playspeed", PLAYER_PLAYSPEED},
                                 {"hasprograms", PLAYER_HAS_PROGRAMS},
                                 {"hasresolutions", PLAYER_HAS_RESOLUTIONS},
                                 {"frameadvance", PLAYER_FRAMEADVANCE},
                                 {"icon", PLAYER_ICON},
                                 {"cutlist", PLAYER_CUTLIST},
                                 {"editlist", PLAYER_EDITLIST},
                                 {"cuts", PLAYER_CUTS},
                                 {"scenemarkers", PLAYER_SCENE_MARKERS},
                                 {"hasscenemarkers", PLAYER_HAS_SCENE_MARKERS},
                                 {"chapters", PLAYER_CHAPTERS}};

/// \page modules__infolabels_boolean_conditions
///   \table_row3{   <b>`Player.Art(type)`</b>,
///                  \anchor Player_Art_type
///                  _string_,
///     @return The Image for the defined art type for the current playing ListItem.
///     @param type - The art type. The type is defined by scripts and scrappers and can have any value.
///     Common example values for type are:
///       - fanart
///       - thumb
///       - poster
///       - banner
///       - clearlogo
///       - tvshow.poster
///       - tvshow.banner
///       - etc
///     @todo get a way of centralize all random art strings used in core so we can point users to them
///     while still making it clear they can have any value.
///     <p>
///   }
///   \table_row3{   <b>`Player.HasPerformedSeek(interval)`</b>,
///                  \anchor Player_HasPerformedSeek
///                  _boolean_,
///     @return **True** if the Player has performed a seek operation in the last provided second `interval`\, **False** otherwise.
///     @param interval - the time interval (in seconds)
///     <p><hr>
///     @skinning_v20 **[New Boolean Condition]** \link Player_HasPerformedSeek `Player.HasPerformedSeek(interval)`\endlink
///     <p>
///   }

const infomap player_param[] = {{"art", PLAYER_ITEM_ART},
                                {"hasperformedseek", PLAYER_HASPERFORMEDSEEK}};

/// \page modules__infolabels_boolean_conditions
///   \table_row3{   <b>`Player.SeekTime`</b>,
///                  \anchor Player_SeekTime
///                  _string_,
///     @return The time to which the user is seeking.
///     <p>
///   }
///   \table_row3{   <b>`Player.SeekOffset([format])`</b>,
///                  \anchor Player_SeekOffset_format
///                  _string_,
///     @return The seek offset after a seek press in a given format.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///     @note **Example:** user presses BigStepForward\, player.seekoffset returns +10:00
///     <p>
///   }
///   \table_row3{   <b>`Player.SeekStepSize`</b>,
///                  \anchor Player_SeekStepSize
///                  _string_,
///     @return The seek step size.
///     <p>
///     <hr>
///     @skinning_v15 **[New Infolabel]** \link Player_SeekStepSize `Player.SeekStepSize`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.TimeRemaining([format])`</b>,
///                  \anchor Player_TimeRemaining_format
///                  _string_,
///     @return The remaining time of current playing media in a given format.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`Player.TimeSpeed`</b>,
///                  \anchor Player_TimeSpeed
///                  _string_,
///     @return The time and the playspeed formatted: "1:23 (2x)".
///     <p>
///   }
///   \table_row3{   <b>`Player.Time([format])`</b>,
///                  \anchor Player_Time_format
///                  _string_,
///     @return The elapsed time of current playing media in a given format.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`Player.Duration([format])`</b>,
///                  \anchor Player_Duration_format
///                  _string_,
///     @return The total duration of the current playing media in a given format.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`Player.FinishTime([format])`</b>,
///                  \anchor Player_FinishTime_format
///                  _string_,
///     @return The time at which the playing media will end (in a specified format).
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`Player.StartTime([format])`</b>,
///                  \anchor Player_StartTime_format
///                  _string_,
///     @return The time at which the playing media began (in a specified format).
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`Player.SeekNumeric([format])`</b>,
///                  \anchor Player_SeekNumeric_format
///                  _string_,
///     @return The time at which the playing media began (in a specified format).
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
const infomap player_times[] =   {{ "seektime",         PLAYER_SEEKTIME },
                                  { "seekoffset",       PLAYER_SEEKOFFSET },
                                  { "seekstepsize",     PLAYER_SEEKSTEPSIZE },
                                  { "timeremaining",    PLAYER_TIME_REMAINING },
                                  { "timespeed",        PLAYER_TIME_SPEED },
                                  { "time",             PLAYER_TIME },
                                  { "duration",         PLAYER_DURATION },
                                  { "finishtime",       PLAYER_FINISH_TIME },
                                  { "starttime",        PLAYER_START_TIME },
                                  { "seeknumeric",      PLAYER_SEEKNUMERIC } };


/// \page modules__infolabels_boolean_conditions
///   \table_row3{   <b>`Player.Process(videohwdecoder)`</b>,
///                  \anchor Player_Process_videohwdecoder
///                  _boolean_,
///     @return **True** if the currently playing video is decoded in hardware.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Player_Process_videohwdecoder `Player.Process(videohwdecoder)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Process(videodecoder)`</b>,
///                  \anchor Player_Process_videodecoder
///                  _string_,
///     @return The videodecoder name of the currently playing video.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Player_Process_videodecoder `Player.Process(videodecoder)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Process(deintmethod)`</b>,
///                  \anchor Player_Process_deintmethod
///                  _string_,
///     @return The deinterlace method of the currently playing video.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Player_Process_deintmethod `Player.Process(deintmethod)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Process(pixformat)`</b>,
///                  \anchor Player_Process_pixformat
///                  _string_,
///     @return The pixel format of the currently playing video.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Player_Process_pixformat `Player.Process(pixformat)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Process(videowidth)`</b>,
///                  \anchor Player_Process_videowidth
///                  _string_,
///     @return The width of the currently playing video.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Player_Process_videowidth `Player.Process(videowidth)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Process(videoheight)`</b>,
///                  \anchor Player_Process_videoheight
///                  _string_,
///     @return The width of the currently playing video.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Player_Process_videoheight `Player.Process(videoheight)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Process(videoscantype)`</b>,
///                  \anchor Player_Process_videoscantype
///                  _string_,
///     @return The scan type identifier of the currently playing video **p** (for progressive) or **i** (for interlaced).
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link Player_Process_videoscantype `Player.Process(videoscantype)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Process(videofps)`</b>,
///                  \anchor Player_Process_videofps
///                  _string_,
///     @return The video framerate of the currently playing video.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Player_Process_videofps `Player.Process(videofps)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Process(videodar)`</b>,
///                  \anchor Player_Process_videodar
///                  _string_,
///     @return The display aspect ratio of the currently playing video.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Player_Process_videodar `Player.Process(videodar)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Process(audiodecoder)`</b>,
///                  \anchor Player_Process_audiodecoder
///                  _string_,
///     @return The audiodecoder name of the currently playing item.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Player_Process_videodar `Player.Process(audiodecoder)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Process(audiochannels)`</b>,
///                  \anchor Player_Process_audiochannels
///                  _string_,
///     @return The audiodecoder name of the currently playing item.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Player_Process_audiochannels `Player.Process(audiochannels)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Process(audiosamplerate)`</b>,
///                  \anchor Player_Process_audiosamplerate
///                  _string_,
///     @return The samplerate of the currently playing item.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Player_Process_audiosamplerate `Player.Process(audiosamplerate)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Player.Process(audiobitspersample)`</b>,
///                  \anchor Player_Process_audiobitspersample
///                  _string_,
///     @return The bits per sample of the currently playing item.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Player_Process_audiobitspersample `Player.Process(audiobitspersample)`\endlink
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------

const infomap player_process[] = {{"videodecoder", PLAYER_PROCESS_VIDEODECODER},
                                  {"deintmethod", PLAYER_PROCESS_DEINTMETHOD},
                                  {"pixformat", PLAYER_PROCESS_PIXELFORMAT},
                                  {"videowidth", PLAYER_PROCESS_VIDEOWIDTH},
                                  {"videoheight", PLAYER_PROCESS_VIDEOHEIGHT},
                                  {"videofps", PLAYER_PROCESS_VIDEOFPS},
                                  {"videodar", PLAYER_PROCESS_VIDEODAR},
                                  {"videohwdecoder", PLAYER_PROCESS_VIDEOHWDECODER},
                                  {"audiodecoder", PLAYER_PROCESS_AUDIODECODER},
                                  {"audiochannels", PLAYER_PROCESS_AUDIOCHANNELS},
                                  {"audiosamplerate", PLAYER_PROCESS_AUDIOSAMPLERATE},
                                  {"audiobitspersample", PLAYER_PROCESS_AUDIOBITSPERSAMPLE},
                                  {"videoscantype", PLAYER_PROCESS_VIDEOSCANTYPE}};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Weather Weather
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`Weather.IsFetched`</b>,
///                  \anchor Weather_IsFetched
///                  _boolean_,
///     @return **True** if the weather data has been downloaded.
///     <p>
///   }
///   \table_row3{   <b>`Weather.Conditions`</b>,
///                  \anchor Weather_Conditions
///                  _string_,
///     @return The current weather conditions as textual description.
///     @note This is looked up in a background process.
///     <p>
///   }
///   \table_row3{   <b>`Weather.ConditionsIcon`</b>,
///                  \anchor Weather_ConditionsIcon
///                  _string_,
///     @return The current weather conditions as an icon.
///     @note This is looked up in a background process.
///     <p>
///   }
///   \table_row3{   <b>`Weather.Temperature`</b>,
///                  \anchor Weather_Temperature
///                  _string_,
///     @return The current weather temperature.
///     <p>
///   }
///   \table_row3{   <b>`Weather.Location`</b>,
///                  \anchor Weather_Location
///                  _string_,
///     @return The city/town which the above two items are for.
///     <p>
///   }
///   \table_row3{   <b>`Weather.Fanartcode`</b>,
///                  \anchor Weather_fanartcode
///                  _string_,
///     @return The current weather fanartcode.
///     <p>
///   }
///   \table_row3{   <b>`Weather.Plugin`</b>,
///                  \anchor Weather_plugin
///                  _string_,
///     @return The current weather plugin.
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap weather[] =        {{ "isfetched",        WEATHER_IS_FETCHED },
                                  { "conditions",       WEATHER_CONDITIONS_TEXT },         // labels from here
                                  { "temperature",      WEATHER_TEMPERATURE },
                                  { "location",         WEATHER_LOCATION },
                                  { "fanartcode",       WEATHER_FANART_CODE },
                                  { "plugin",           WEATHER_PLUGIN },
                                  { "conditionsicon",   WEATHER_CONDITIONS_ICON }};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_System System
/// @todo some values are hardcoded in the middle of the code  - refactor to make it easier to track
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`System.AlarmLessOrEqual(alarmname\,seconds)`</b>,
///                  \anchor System_AlarmLessOrEqual
///                  _boolean_,
///     @return **True** if the alarm with `alarmname` has less or equal to `seconds` left.
///     @param alarmname - The name of the alarm. It can be one of the following:
///       - shutdowntimer
///     @param seconds - Time in seconds to compare with the alarm trigger event
///     @note **Example:** `System.Alarmlessorequal(shutdowntimer\,119)`\,
///     will return true when the shutdowntimer has less then 2 minutes
///     left.
///     <p>
///   }
///   \table_row3{   <b>`System.HasNetwork`</b>,
///                  \anchor System_HasNetwork
///                  _boolean_,
///     @return **True** if the Kodi host has a network available.
///     @note This feature is NOT implemented. Always returns true
///     <p>
///   }
///   \table_row3{   <b>`System.HasMediadvd`</b>,
///                  \anchor System_HasMediadvd
///                  _boolean_,
///     @return **True** if there is a CD or DVD in the DVD-ROM drive.
///     <p>
///   }
///   \table_row3{   <b>`System.HasMediaAudioCD`</b>,
///                  \anchor System_HasMediaAudioCD
///                  _boolean_,
///     @return **True** if there is an audio CD in the optical drive. **False** if no drive
///     available\, empty drive or other medium.
///   <p><hr>
///   @skinning_v18 **[New Boolean Condition]** \link System_HasMediaAudioCD
///   `System.HasMediaAudioCD` \endlink <p>
///   }
///   \table_row3{   <b>`System.DVDReady`</b>,
///                  \anchor System_DVDReady
///                  _boolean_,
///     @return **True** if the disc is ready to use.
///     <p>
///   }
///   \table_row3{   <b>`System.TrayOpen`</b>,
///                  \anchor System_TrayOpen
///                  _boolean_,
///     @return **True** if the disc tray is open.
///     <p>
///   }
///   \table_row3{   <b>`System.HasLocks`</b>,
///                  \anchor System_HasLocks
///                  _boolean_,
///     @return **True** if the system has an active lock mode.
///     <p>
///   }
///   \table_row3{   <b>`System.IsMaster`</b>,
///                  \anchor System_IsMaster
///                  _boolean_,
///     @return **True** if the system is in master mode.
///     <p>
///   }
///   \table_row3{   <b>`System.ShowExitButton`</b>,
///                  \anchor System_ShowExitButton
///                  _boolean_,
///     @return **True** if the exit button should be shown (configurable via advanced settings).
///     <p>
///   }
///   \table_row3{   <b>`System.DPMSActive`</b>,
///                  \anchor System_DPMSActive
///                  _boolean_,
///     @return **True** if DPMS (VESA Display Power Management Signaling) mode is active.
///     <p>
///   }
///   \table_row3{   <b>`System.IsStandalone`</b>,
///                  \anchor System_IsStandalone
///                  _boolean_,
///     @return **True** if Kodi is running in standalone mode.
///     <p>
///   }
///   \table_row3{   <b>`System.IsFullscreen`</b>,
///                  \anchor System_IsFullscreen
///                  _boolean_,
///     @return **True** if Kodi is running fullscreen.
///     <p>
///   }
///   \table_row3{   <b>`System.LoggedOn`</b>,
///                  \anchor System_LoggedOn
///                  _boolean_,
///     @return **True** if a user is currently logged on under a profile.
///     <p>
///   }
///   \table_row3{   <b>`System.HasLoginScreen`</b>,
///                  \anchor System_HasLoginScreen
///                  _boolean_,
///     @return **True** if the profile login screen is enabled.
///     <p>
///   }
///   \table_row3{   <b>`System.HasPVR`</b>,
///                  \anchor System_HasPVR
///                  _boolean_,
///     @return **True** if PVR is supported from Kodi.
///     @note normally always true
///
///   }
///   \table_row3{   <b>`System.HasPVRAddon`</b>,
///                  \anchor System_HasPVRAddon
///                  _boolean_,
///     @return **True** if at least one pvr client addon is installed and enabled.
///     @param id - addon id of the PVR addon
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link System_HasPVRAddon
///     `System.HasPVRAddon`\endlink <p>
///   }
///   \table_row3{   <b>`System.HasCMS`</b>,
///                  \anchor System_HasCMS
///                  _boolean_,
///     @return **True** if colour management is supported from Kodi.
///     @note currently only supported for OpenGL
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link System_HasCMS `System.HasCMS`\endlink
///     <p>
///   }
///   \table_row3{   <b>`System.HasActiveModalDialog`</b>,
///                  \anchor System_HasActiveModalDialog
///                  _boolean_,
///     @return **True** if a modal dialog is active.
///     <p><hr>
///     @skinning_v18 **[New Boolean Condition]** \link System_HasActiveModalDialog
///     `System.HasActiveModalDialog`\endlink <p>
///   }
///   \table_row3{   <b>`System.HasVisibleModalDialog`</b>,
///                  \anchor System_HasVisibleModalDialog
///                  _boolean_,
///     @return **True** if a modal dialog is visible.
///     <p><hr>
///     @skinning_v18 **[New Boolean Condition]** \link System_HasVisibleModalDialog
///     `System.HasVisibleModalDialog`\endlink <p>
///   }
///   \table_row3{   <b>`System.Platform.Linux`</b>,
///                  \anchor System_PlatformLinux
///                  _boolean_,
///     @return **True** if Kodi is running on a linux/unix based computer.
///     <p>
///   }
///   \table_row3{   <b>`System.Platform.Windows`</b>,
///                  \anchor System_PlatformWindows
///                  _boolean_,
///     @return **True** if Kodi is running on a windows based computer.
///     <p>
///   }
///   \table_row3{   <b>`System.Platform.UWP`</b>,
///                  \anchor System_PlatformUWP
///                  _boolean_,
///     @return **True** if Kodi is running on Universal Windows Platform (UWP).
///     <p><hr>
///     @skinning_v18 **[New Boolean Condition]** \link System_PlatformUWP
///     `System.Platform.UWP`\endlink <p>
///   }
///   \table_row3{   <b>`System.Platform.OSX`</b>,
///                  \anchor System_PlatformOSX
///                  _boolean_,
///     @return **True** if Kodi is running on an OSX based computer.
///     <p>
///   }
///   \table_row3{   <b>`System.Platform.IOS`</b>,
///                  \anchor System_PlatformIOS
///                  _boolean_,
///     @return **True** if Kodi is running on an IOS device.
///     <p>
///   }
///   \table_row3{   <b>`System.Platform.TVOS`</b>,
///                  \anchor System_PlatformTVOS
///                  _boolean_,
///     @return **True** if Kodi is running on a tvOS device.
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \link System_PlatformTVOS
///     `System.Platform.TVOS`\endlink <p>
///   }
///   \table_row3{   <b>`System.Platform.Darwin`</b>,
///                  \anchor System_PlatformDarwin
///                  _boolean_,
///     @return **True** if Kodi is running on an OSX or IOS system.
///     <p>
///   }
///   \table_row3{   <b>`System.Platform.Android`</b>,
///                  \anchor System_PlatformAndroid
///                  _boolean_,
///     @return **True** if Kodi is running on an android device.
///     <p>
///   }
///   \table_row3{   <b>`System.Platform.WebOS`</b>,
///                  \anchor System_PlatformWebOS
///                  _boolean_,
///     @return **True** if Kodi is running on a WebOS device.
///     <p><hr>
///     @skinning_v21 **[New Boolean Condition]** \link System_PlatformWebOS
///     `System.Platform.WebOS`\endlink <p>
///   }
///   \table_row3{   <b>`System.CanPowerDown`</b>,
///                  \anchor System_CanPowerDown
///                  _boolean_,
///     @return **True** if Kodi can powerdown the system.
///     <p>
///   }
///   \table_row3{   <b>`System.CanSuspend`</b>,
///                  \anchor System_CanSuspend
///                  _boolean_,
///     @return **True** if Kodi can suspend the system.
///     <p>
///   }
///   \table_row3{   <b>`System.CanHibernate`</b>,
///                  \anchor System_CanHibernate
///                  _boolean_,
///     @return **True** if Kodi can hibernate the system.
///     <p>
///   }
///   \table_row3{   <b>`System.HasHiddenInput`</b>,
///                  \anchor System_HasHiddenInput
///                  _boolean_,
///     @return **True** when to osd keyboard/numeric dialog requests a
///     password/pincode.
///     <p><hr>
///     @skinning_v16 **[New Boolean Condition]** \link System_HasHiddenInput
///     `System.HasHiddenInput`\endlink <p>
///   }
///   \table_row3{   <b>`System.CanReboot`</b>,
///                  \anchor System_CanReboot
///                  _boolean_,
///     @return **True** if Kodi can reboot the system.
///     <p>
///   }
///   \table_row3{   <b>`System.ScreenSaverActive`</b>,
///                  \anchor System_ScreenSaverActive
///                  _boolean_,
///     @return **True** if ScreenSaver is active.
///     <p>
///   }
///   \table_row3{   <b>`System.IdleShutdownInhibited`</b>,
///                  \anchor System_IdleShutdownInhibited
///                  _boolean_,
///     @return **True** when shutdown on idle is disabled.
///     <p>
///   }
///   \table_row3{   <b>`System.HasShutdown`</b>,
///                  \anchor System_HasShutdown
///                  _boolean_,
///     @return **True** if Kodi can shutdown the system.
///     <p>
///   }
///   \table_row3{   <b>`System.Time`</b>,
///                  \anchor System_Time
///                  _string_,
///     @return The current time.
///     <p>
///   }
///   \table_row3{   <b>`System.Time(format)`</b>,
///                  \anchor System_Time_format
///                  _string_,
///     @return The current time in a specified format.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`System.Time(startTime[\,endTime])`</b>,
///                  \anchor System_Time
///                  _boolean_,
///     @return **True** if the current system time is >= `startTime` and < `endTime` (if defined).
///     @param startTime - Start time
///     @param endTime - [opt] End time
///     <p>
///     @note Time must be specified in the format HH:mm\, using
///     a 24 hour clock.
///     <p>
///   }
///   \table_row3{   <b>`System.Date`</b>,
///                  \anchor System_Date
///                  _string_,
///     @return The current date.
///     <p><hr>
///     @skinning_v16 **[Infolabel Updated]** \link System_Date `System.Date`\endlink
///     will now return the full day and month names. old: sat\, jul 18 2015
///     new: saturday\, july 18 2015
///     <p>
///   }
///   \table_row3{   <b>`System.Date(format)`</b>,
///                  \anchor System_Date_format
///                  _string_,
///     @return The current date using a specified format.
///     @param format - the format for the date. It can be one of the following
///     values:
///       - **d** - day of month (1-31)
///       - **dd** - day of month (01-31)
///       - **ddd** - short day of the week Mon-Sun
///       - **DDD** - long day of the week Monday-Sunday
///       - **m** - month (1-12)
///       - **mm** - month (01-12)
///       - **mmm** - short month name Jan-Dec
///       - **MMM** - long month name January-December
///       - **yy** - 2-digit year
///       - **yyyy** - 4-digit year
///     <p>
///   }
///   \table_row3{   <b>`System.Date(startDate[\,endDate])`</b>,
///                  \anchor System_Date
///                  _boolean_,
///     @return **True** if the current system date is >= `startDate` and < `endDate` (if defined).
///     @param startDate - The start date
///     @param endDate - [opt] The end date
///     @note Date must be specified in the format MM-DD or YY-MM-DD.
///     <p>
///   }
///   \table_row3{   <b>`System.AlarmPos`</b>,
///                  \anchor System_AlarmPos
///                  _string_,
///     @return The shutdown Timer position.
///     <p>
///   }
///   \table_row3{   <b>`System.BatteryLevel`</b>,
///                  \anchor System_BatteryLevel
///                  _string_,
///     @return The remaining battery level in range 0-100.
///     <p>
///   }
///   \table_row3{   <b>`System.FreeSpace`</b>,
///                  \anchor System_FreeSpace
///                  _string_,
///     @return The total Freespace on the drive.
///     <p>
///   }
///   \table_row3{   <b>`System.UsedSpace`</b>,
///                  \anchor System_UsedSpace
///                  _string_,
///     @return The total Usedspace on the drive.
///     <p>
///   }
///   \table_row3{   <b>`System.TotalSpace`</b>,
///                  \anchor System_TotalSpace
///                  _string_,
///     @return The total space on the drive.
///     <p>
///   }
///   \table_row3{   <b>`System.UsedSpacePercent`</b>,
///                  \anchor System_UsedSpacePercent
///                  _string_,
///     @return The total Usedspace Percent on the drive.
///     <p>
///   }
///   \table_row3{   <b>`System.FreeSpacePercent`</b>,
///                  \anchor System_FreeSpacePercent
///                  _string_,
///     @return The total Freespace Percent on the drive.
///     <p>
///   }
///   \table_row3{   <b>`System.CPUTemperature`</b>,
///                  \anchor System_CPUTemperature
///                  _string_,
///     @return The current CPU temperature.
///     <p>
///   }
///   \table_row3{   <b>`System.CpuUsage`</b>,
///                  \anchor System_CpuUsage
///                  _string_,
///     @return The the cpu usage for each individual cpu core.
///     <p>
///   }
///   \table_row3{   <b>`System.GPUTemperature`</b>,
///                  \anchor System_GPUTemperature
///                  _string_,
///     @return The current GPU temperature.
///     <p>
///   }
///   \table_row3{   <b>`System.FanSpeed`</b>,
///                  \anchor System_FanSpeed
///                  _string_,
///     @return The current fan speed.
///     <p>
///   }
///   \table_row3{   <b>`System.BuildVersion`</b>,
///                  \anchor System_BuildVersion
///                  _string_,
///     @return The version of build.
///     <p>
///   }
///   \table_row3{   <b>`System.BuildVersionShort`</b>,
///                  \anchor System_BuildVersionShort
///                  _string_,
///     @return The shorter string with version of build.
///     <p>
///   }
///   \table_row3{   <b>`System.BuildDate`</b>,
///                  \anchor System_BuildDate
///                  _string_,
///     @return The date of build.
///     <p>
///   }
///   \table_row3{   <b>`System.BuildVersionCode`</b>,
///                  \anchor System_BuildVersionCode
///                  _string_,
///     @return The version code of build.
///     <p>
///   }
///   \table_row3{   <b>`System.BuildVersionGit`</b>,
///                  \anchor System_BuildVersionGit
///                  _string_,
///     @return The git version of build.
///     <p>
///   }
///   \table_row3{   <b>`System.FriendlyName`</b>,
///                  \anchor System_FriendlyName
///                  _string_,
///     @return The Kodi instance name.
///     @note It will auto append (%hostname%) in case
///     the device name was not changed. eg. "Kodi (htpc)"
///     <p>
///   }
///   \table_row3{   <b>`System.FPS`</b>,
///                  \anchor System_FPS
///                  _string_,
///     @return The current rendering speed (frames per second).
///     <p>
///   }
///   \table_row3{   <b>`System.FreeMemory`</b>,
///                  \anchor System_FreeMemory
///                  _string_,
///     @return The amount of free memory in Mb.
///     <p>
///   }
///   \table_row3{   <b>`System.ScreenMode`</b>,
///                  \anchor System_ScreenMode
///                  _string_,
///     @return The screenmode (eg windowed / fullscreen).
///     <p>
///   }
///   \table_row3{   <b>`System.ScreenWidth`</b>,
///                  \anchor System_ScreenWidth
///                  _string_,
///     @return The width of screen in pixels.
///     <p>
///   }
///   \table_row3{   <b>`System.ScreenHeight`</b>,
///                  \anchor System_ScreenHeight
///                  _string_,
///     @return The height of screen in pixels.
///     <p>
///   }
///   \table_row3{   <b>`System.StartupWindow`</b>,
///                  \anchor System_StartupWindow
///                  _string_,
///     @return The Window Kodi will load on startup.
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link System_StartupWindow `System.StartupWindow`\endlink
///     <p>
///   }
///   \table_row3{   <b>`System.CurrentWindow`</b>,
///                  \anchor System_CurrentWindow
///                  _string_,
///     @return The current Window in use.
///     <p>
///   }
///   \table_row3{   <b>`System.CurrentControl`</b>,
///                  \anchor System_CurrentControl
///                  _string_,
///     @return The current focused control
///     <p>
///   }
///   \table_row3{   <b>`System.CurrentControlId`</b>,
///                  \anchor System_CurrentControlId
///                  _string_,
///     @return The ID of the currently focused control.
///     <p>
///   }
///   \table_row3{   <b>`System.DVDLabel`</b>,
///                  \anchor System_DVDLabel
///                  _string_,
///     @return the label of the disk in the DVD-ROM drive.
///     <p>
///   }
///   \table_row3{   <b>`System.KernelVersion`</b>,
///                  \anchor System_KernelVersion
///                  _string_,
///     @return The System kernel version.
///     <p>
///   }
///   \table_row3{   <b>`System.OSVersionInfo`</b>,
///                  \anchor System_OSVersionInfo
///                  _string_,
///     @return The system name + kernel version.
///     <p>
///   }
///   \table_row3{   <b>`System.Uptime`</b>,
///                  \anchor System_Uptime
///                  _string_,
///     @return The system current uptime.
///     <p>
///   }
///   \table_row3{   <b>`System.TotalUptime`</b>,
///                  \anchor System_TotalUptime
///                  _string_,
///     @return The system total uptime.
///     <p>
///   }
///   \table_row3{   <b>`System.CpuFrequency`</b>,
///                  \anchor System_CpuFrequency
///                  _string_,
///     @return The system cpu frequency.
///     <p>
///   }
///   \table_row3{   <b>`System.ScreenResolution`</b>,
///                  \anchor System_ScreenResolution
///                  _string_,
///     @return The screen resolution.
///     <p>
///   }
///   \table_row3{   <b>`System.VideoEncoderInfo`</b>,
///                  \anchor System_VideoEncoderInfo
///                  _string_,
///     @return The video encoder info.
///     <p>
///   }
///   \table_row3{   <b>`System.InternetState`</b>,
///                  \anchor System_InternetState
///                  _string_,
///     @return The internet state: connected or not connected.
///     @warning Do not use to check status in a pythonscript since it is threaded.
///     <p>
///   }
///   \table_row3{   <b>`System.Language`</b>,
///                  \anchor System_Language
///                  _string_,
///     @return the current language.
///     <p>
///   }
///   \table_row3{   <b>`System.Locale(type)`</b>,
///                  \anchor System_Locale
///                  _string_,
///     @return Locale-specific information depending on the requested type.
///     @param type - Can be one of the following:
///       - <b>timezonecountry</b> The country name for the current time zone.
///       - <b>timezone</b> The full timezone name with country and optional region.
///       - <b>region</b> The currently selected region name within the selected language ( \link System_Language `System.Language` \endlink).
///       - <b>iso</b> The country code of the currently selected region as specified in <a href="https://kodi.wiki/view/Language_support#What_is_langinfo.xml">langinfo.xml</a>.
///     <p><hr>
///     @skinning_v21 **[New Infolabel]** \link System_Locale
///     `System.Locale(type)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`System.ProfileName`</b>,
///                  \anchor System_ProfileName
///                  _string_,
///     @return The user name of the currently logged in Kodi user
///     <p>
///   }
///   \table_row3{   <b>`System.ProfileThumb`</b>,
///                  \anchor System_ProfileThumb
///                  _string_,
///     @return The thumbnail image of the currently logged in Kodi user
///     <p>
///   }
///   \table_row3{   <b>`System.ProfileCount`</b>,
///                  \anchor System_ProfileCount
///                  _string_,
///     @return The number of defined profiles.
///     <p>
///   }
///   \table_row3{   <b>`System.ProfileAutoLogin`</b>,
///                  \anchor System_ProfileAutoLogin
///                  _string_,
///     @return The profile Kodi will auto login to.
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link System_ProfileAutoLogin
///     `System.ProfileAutoLogin`\endlink <p>
///   }
///   \table_row3{   <b>`System.StereoscopicMode`</b>,
///                  \anchor System_StereoscopicMode
///                  _string_,
///     @return The preferred stereoscopic mode.
///     @note Configured in settings > video > playback).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link System_StereoscopicMode
///     `System.StereoscopicMode`\endlink <p>
///   }
///   \table_row3{   <b>`System.TemperatureUnits`</b>,
///                  \anchor System_TemperatureUnits
///                  _string_,
///     @return the Celsius or the Fahrenheit symbol.
///     <p>
///   }
///   \table_row3{   <b>`System.Progressbar`</b>,
///                  \anchor System_Progressbar
///                  _string_,
///     @return The percentage of the currently active progress.
///     <p>
///   }
///   \table_row3{   <b>`System.GetBool(boolean)`</b>,
///                  \anchor System_GetBool
///                  _string_,
///     @return The value of any standard system boolean setting.
///     @note Will not work with settings in advancedsettings.xml
///     <p>
///   }
///   \table_row3{   <b>`System.Memory(type)`</b>,
///                  \anchor System_Memory
///                  _string_,
///     @return The memory value depending on the requested type.
///     @param type - Can be one of the following:
///       - <b>free</b>
///       - <b>free.percent</b>
///       - <b>used</b>
///       - <b>used.percent</b>
///       - <b>total</b>
///     <p>
///   }
///   \table_row3{   <b>`System.AddonTitle(id)`</b>,
///                  \anchor System_AddonTitle
///                  _string_,
///     @return The title of the addon with the given id
///     @param id - the addon id
///     <p>
///   }
///   \table_row3{   <b>`System.AddonVersion(id)`</b>,
///                  \anchor System_AddonVersion
///                  _string_,
///     @return The version of the addon with the given id.
///     @param id - the addon id
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link System_AddonVersion
///     `System.AddonVersion(id)`\endlink <p>
///   }
///   \table_row3{   <b>`System.AddonIcon(id)`</b>,
///                  \anchor System_AddonVersion
///                  _string_,
///     @return The icon of the addon with the given id.
///     @param id - the addon id
///     <p>
///   }
///   \table_row3{   <b>`System.AddonUpdateCount`</b>,
///                  \anchor System_AddonUpdateCount
///                  _string_,
///     @return The number of available addon updates.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link  System_AddonUpdateCount `
///     System.AddonUpdateCount`\endlink <p>
///   }
///   \table_row3{   <b>`System.IdleTime(time)`</b>,
///                  \anchor System_IdleTime
///                  _boolean_,
///     @return **True** if Kodi has had no input for `time` amount of seconds.
///     @param time - elapsed seconds to check for idle activity.
///     <p>
///   }
///   \table_row3{   <b>`System.PrivacyPolicy`</b>,
///                  \anchor System_PrivacyPolicy
///                  _string_,
///     @return The official Kodi privacy policy.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link System_PrivacyPolicy `System.PrivacyPolicy`\endlink
///     <p>
///   }
///   \table_row3{   <b>`System.SupportsCPUUsage`</b>,
///                  \anchor System_SupportsCPUUsage
///                  _boolean_,
///     @return **True** if the system can provide CPU usage information.
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \link  System_SupportsCPUUsage `
///     System.SupportsCPUUsage`\endlink <p>
///   }
///   \table_row3{   <b>`System.SupportedHDRTypes`</b>,
///                  \anchor System_SupportedHDRTypes
///                  _string_,
///     @return The display's supported HDR types.
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link System_SupportedHDRTypes `System.SupportedHDRTypes`\endlink
///     <p>
///   }
///   \table_row3{   <b>`System.IsScreensaverInhibited`</b>,
///                  \anchor System_IsScreensaverInhibited
///                  _boolean_,
///     @return **True** when screensaver on idle is disabled.
///     <p>
///   }
const infomap system_labels[] = {
    {"hasnetwork", SYSTEM_ETHERNET_LINK_ACTIVE},
    {"hasmediadvd", SYSTEM_MEDIA_DVD},
    {"hasmediaaudiocd", SYSTEM_MEDIA_AUDIO_CD},
    {"dvdready", SYSTEM_DVDREADY},
    {"trayopen", SYSTEM_TRAYOPEN},
    {"haslocks", SYSTEM_HASLOCKS},
    {"hashiddeninput", SYSTEM_HAS_INPUT_HIDDEN},
    {"hasloginscreen", SYSTEM_HAS_LOGINSCREEN},
    {"hasactivemodaldialog", SYSTEM_HAS_ACTIVE_MODAL_DIALOG},
    {"hasvisiblemodaldialog", SYSTEM_HAS_VISIBLE_MODAL_DIALOG},
    {"ismaster", SYSTEM_ISMASTER},
    {"isfullscreen", SYSTEM_ISFULLSCREEN},
    {"isstandalone", SYSTEM_ISSTANDALONE},
    {"loggedon", SYSTEM_LOGGEDON},
    {"showexitbutton", SYSTEM_SHOW_EXIT_BUTTON},
    {"canpowerdown", SYSTEM_CAN_POWERDOWN},
    {"cansuspend", SYSTEM_CAN_SUSPEND},
    {"canhibernate", SYSTEM_CAN_HIBERNATE},
    {"canreboot", SYSTEM_CAN_REBOOT},
    {"screensaveractive", SYSTEM_SCREENSAVER_ACTIVE},
    {"dpmsactive", SYSTEM_DPMS_ACTIVE},
    {"cputemperature", SYSTEM_CPU_TEMPERATURE}, // labels from here
    {"cpuusage", SYSTEM_CPU_USAGE},
    {"gputemperature", SYSTEM_GPU_TEMPERATURE},
    {"fanspeed", SYSTEM_FAN_SPEED},
    {"freespace", SYSTEM_FREE_SPACE},
    {"usedspace", SYSTEM_USED_SPACE},
    {"totalspace", SYSTEM_TOTAL_SPACE},
    {"usedspacepercent", SYSTEM_USED_SPACE_PERCENT},
    {"freespacepercent", SYSTEM_FREE_SPACE_PERCENT},
    {"buildversion", SYSTEM_BUILD_VERSION},
    {"buildversionshort", SYSTEM_BUILD_VERSION_SHORT},
    {"buildversioncode", SYSTEM_BUILD_VERSION_CODE},
    {"buildversiongit", SYSTEM_BUILD_VERSION_GIT},
    {"builddate", SYSTEM_BUILD_DATE},
    {"fps", SYSTEM_FPS},
    {"freememory", SYSTEM_FREE_MEMORY},
    {"language", SYSTEM_LANGUAGE},
    {"temperatureunits", SYSTEM_TEMPERATURE_UNITS},
    {"screenmode", SYSTEM_SCREEN_MODE},
    {"screenwidth", SYSTEM_SCREEN_WIDTH},
    {"screenheight", SYSTEM_SCREEN_HEIGHT},
    {"currentwindow", SYSTEM_CURRENT_WINDOW},
    {"currentcontrol", SYSTEM_CURRENT_CONTROL},
    {"currentcontrolid", SYSTEM_CURRENT_CONTROL_ID},
    {"dvdlabel", SYSTEM_DVD_LABEL},
    {"internetstate", SYSTEM_INTERNET_STATE},
    {"osversioninfo", SYSTEM_OS_VERSION_INFO},
    {"kernelversion", SYSTEM_OS_VERSION_INFO}, // old, not correct name
    {"uptime", SYSTEM_UPTIME},
    {"totaluptime", SYSTEM_TOTALUPTIME},
    {"cpufrequency", SYSTEM_CPUFREQUENCY},
    {"screenresolution", SYSTEM_SCREEN_RESOLUTION},
    {"videoencoderinfo", SYSTEM_VIDEO_ENCODER_INFO},
    {"profilename", SYSTEM_PROFILENAME},
    {"profilethumb", SYSTEM_PROFILETHUMB},
    {"profilecount", SYSTEM_PROFILECOUNT},
    {"profileautologin", SYSTEM_PROFILEAUTOLOGIN},
    {"progressbar", SYSTEM_PROGRESS_BAR},
    {"batterylevel", SYSTEM_BATTERY_LEVEL},
    {"friendlyname", SYSTEM_FRIENDLY_NAME},
    {"alarmpos", SYSTEM_ALARM_POS},
    {"isinhibit",
     SYSTEM_IDLE_SHUTDOWN_INHIBITED}, // Deprecated, replaced by "idleshutdowninhibited"
    {"idleshutdowninhibited", SYSTEM_IDLE_SHUTDOWN_INHIBITED},
    {"hasshutdown", SYSTEM_HAS_SHUTDOWN},
    {"haspvr", SYSTEM_HAS_PVR},
    {"startupwindow", SYSTEM_STARTUP_WINDOW},
    {"stereoscopicmode", SYSTEM_STEREOSCOPIC_MODE},
    {"hascms", SYSTEM_HAS_CMS},
    {"privacypolicy", SYSTEM_PRIVACY_POLICY},
    {"haspvraddon", SYSTEM_HAS_PVR_ADDON},
    {"addonupdatecount", SYSTEM_ADDON_UPDATE_COUNT},
    {"supportscpuusage", SYSTEM_SUPPORTS_CPU_USAGE},
    {"supportedhdrtypes", SYSTEM_SUPPORTED_HDR_TYPES},
    {"isscreensaverinhibited", SYSTEM_IS_SCREENSAVER_INHIBITED}};

/// \page modules__infolabels_boolean_conditions
///   \table_row3{   <b>`System.HasAddon(id)`</b>,
///                  \anchor System_HasAddon
///                  _boolean_,
///     @return **True** if the specified addon is installed on the system.
///     @param id - the addon id
///     @skinning_v19 **[Boolean Condition Updated]** \link System_HasAddon `System.HasAddon(id)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`System.AddonIsEnabled(id)`</b>,
///                  \anchor System_AddonIsEnabled
///                  _boolean_,
///     @return **True** if the specified addon is enabled on the system.
///     @param id - The addon Id
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \link System_AddonIsEnabled `System.AddonIsEnabled(id)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`System.HasCoreId(id)`</b>,
///                  \anchor System_HasCoreId
///                  _boolean_,
///     @return **True** if the CPU core with the given 'id' exists.
///     @param id - the id of the CPU core
///     <p>
///   }
///   \table_row3{   <b>`System.HasAlarm(alarm)`</b>,
///                  \anchor System_HasAlarm
///                  _boolean_,
///     @return **True** if the system has the `alarm` alarm set.
///     @param alarm - the name of the alarm
///     <p>
///   }
///   \table_row3{   <b>`System.CoreUsage(id)`</b>,
///                  \anchor System_CoreUsage
///                  _string_,
///     @return the usage of the CPU core with the given 'id'
///     @param id - the id of the CPU core
///     <p>
///   }
///   \table_row3{   <b>`System.Setting(hidewatched)`</b>,
///                  \anchor System_Setting
///                  _boolean_,
///     @return **True** if 'hide watched items' is selected.
///     <p>
///   }
///   \table_row3{   <b>`System.Setting(hideunwatchedepisodethumbs)`</b>,
///                  \anchor System_Setting_HideUnwatchedEpisodeThumbs
///                  _boolean_,
///     @return **True** if 'hide unwatched episode setting is enabled'\, **False** otherwise.
///     <p><hr>
///     @skinning_v20 **[New Boolean Condition]** \link System_Setting_HideUnwatchedEpisodeThumbs `System.Setting(hideunwatchedepisodethumbs)`\endlink
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap system_param[] =   {{ "hasalarm",         SYSTEM_HAS_ALARM },
                                  { "hascoreid",        SYSTEM_HAS_CORE_ID },
                                  { "setting",          SYSTEM_SETTING },
                                  { "hasaddon",         SYSTEM_HAS_ADDON },
                                  { "addonisenabled",   SYSTEM_ADDON_IS_ENABLED },
                                  { "coreusage",        SYSTEM_GET_CORE_USAGE }};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Network Network
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`Network.IsDHCP`</b>,
///                  \anchor Network_IsDHCP
///                  _boolean_,
///     @return **True** if the network type is DHCP.
///     @note Network type can be either DHCP or FIXED
///     <p>
///   }
///   \table_row3{   <b>`Network.IPAddress`</b>,
///                  \anchor Network_IPAddress
///                  _string_,
///     @return The system's IP Address. e.g. 192.168.1.15
///     <p>
///   }
///   \table_row3{   <b>`Network.LinkState`</b>,
///                  \anchor Network_LinkState
///                  _string_,
///     @return The network linkstate e.g. 10mbit/100mbit etc.
///     <p>
///   }
///   \table_row3{   <b>`Network.MacAddress`</b>,
///                  \anchor Network_MacAddress
///                  _string_,
///     @return The system's MAC address.
///     <p>
///   }
///   \table_row3{   <b>`Network.SubnetMask`</b>,
///                  \anchor Network_SubnetMask
///                  _string_,
///     @return The network subnet mask.
///     <p>
///   }
///   \table_row3{   <b>`Network.GatewayAddress`</b>,
///                  \anchor Network_GatewayAddress
///                  _string_,
///     @return The network gateway address.
///     <p>
///   }
///   \table_row3{   <b>`Network.DNS1Address`</b>,
///                  \anchor Network_DNS1Address
///                  _string_,
///     @return The network DNS 1 address.
///     <p>
///   }
///   \table_row3{   <b>`Network.DNS2Address`</b>,
///                  \anchor Network_DNS2Address
///                  _string_,
///     @return The network DNS 2 address.
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
// clang-format off
const infomap network_labels[] = {
    {"isdhcp", NETWORK_IS_DHCP},
    {"ipaddress", NETWORK_IP_ADDRESS}, //labels from here
    {"linkstate", NETWORK_LINK_STATE},
    {"macaddress", NETWORK_MAC_ADDRESS},
    {"subnetmask", NETWORK_SUBNET_MASK},
    {"gatewayaddress", NETWORK_GATEWAY_ADDRESS},
    {"dns1address", NETWORK_DNS1_ADDRESS},
    {"dns2address", NETWORK_DNS2_ADDRESS}
};
// clang-format on

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_musicpartymode Music party mode
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`MusicPartyMode.Enabled`</b>,
///                  \anchor MusicPartyMode_Enabled
///                  _boolean_,
///     @return **True** if Party Mode is enabled.
///     <p>
///   }
///   \table_row3{   <b>`MusicPartyMode.SongsPlayed`</b>,
///                  \anchor MusicPartyMode_SongsPlayed
///                  _string_,
///     @return The number of songs played during Party Mode.
///     <p>
///   }
///   \table_row3{   <b>`MusicPartyMode.MatchingSongs`</b>,
///                  \anchor MusicPartyMode_MatchingSongs
///                  _string_,
///     @return The number of songs available to Party Mode.
///     <p>
///   }
///   \table_row3{   <b>`MusicPartyMode.MatchingSongsPicked`</b>,
///                  \anchor MusicPartyMode_MatchingSongsPicked
///                  _string_,
///     @return The number of songs picked already for Party Mode.
///     <p>
///   }
///   \table_row3{   <b>`MusicPartyMode.MatchingSongsLeft`</b>,
///                  \anchor MusicPartyMode_MatchingSongsLeft
///                  _string_,
///     @return The number of songs left to be picked from for Party Mode.
///     <p>
///   }
///   \table_row3{   <b>`MusicPartyMode.RelaxedSongsPicked`</b>,
///                  \anchor MusicPartyMode_RelaxedSongsPicked
///                  _string_,
///     @todo Not currently used
///     <p>
///   }
///   \table_row3{   <b>`MusicPartyMode.RandomSongsPicked`</b>,
///                  \anchor MusicPartyMode_RandomSongsPicked
///                  _string_,
///     @return The number of unique random songs picked during Party Mode.
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap musicpartymode[] = {{ "enabled",           MUSICPM_ENABLED },
                                  { "songsplayed",       MUSICPM_SONGSPLAYED },
                                  { "matchingsongs",     MUSICPM_MATCHINGSONGS },
                                  { "matchingsongspicked", MUSICPM_MATCHINGSONGSPICKED },
                                  { "matchingsongsleft", MUSICPM_MATCHINGSONGSLEFT },
                                  { "relaxedsongspicked", MUSICPM_RELAXEDSONGSPICKED },
                                  { "randomsongspicked", MUSICPM_RANDOMSONGSPICKED }};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_MusicPlayer Music player
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`MusicPlayer.Offset(number).Exists`</b>,
///                  \anchor MusicPlayer_Offset
///                  _boolean_,
///     @return **True** if the music players playlist has a song queued in
///     position (number).
///     @param number - song position
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Title`</b>,
///                  \anchor MusicPlayer_Title
///                  _string_,
///     @return The title of the currently playing song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.offset(number).Title`</b>,
///                  \anchor MusicPlayer_Offset_Title
///                  _string_,
///     @return The title of the song which has an offset `number` with respect to the
///     current playing song.
///     @param number - the offset number with respect to the current playing song
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Position(number).Title`</b>,
///                  \anchor MusicPlayer_Position_Title
///                  _string_,
///     @return The title of the song which as an offset `number` with respect to the
///     start of the playlist.
///     @param number - the offset number with respect to the start of the playlist
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Album`</b>,
///                  \anchor MusicPlayer_Album
///                  _string_,
///     @return The album from which the current song is from.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.offset(number).Album`</b>,
///                  \anchor MusicPlayer_OffSet_Album
///                  _string_,
///     @return The album from which the song with offset `number` with respect to
///     the current song is from.
///     @param number - the offset number with respect to the current playing song
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Position(number).Album`</b>,
///                  \anchor MusicPlayer_Position_Album
///                  _string_,
///     @return The album from which the song with offset `number` with respect to
///     the start of the playlist is from.
///     @param number - the offset number with respect to the start of the playlist
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Album_Mood)`</b>,
///                  \anchor MusicPlayer_Property_Album_Mood
///                  _string_,
///     @return The moods of the currently playing Album
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Role.Composer)`</b>,
///                  \anchor MusicPlayer_Property_Role_Composer
///                  _string_,
///     @return The name of the person who composed the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_Property_Role_Composer `MusicPlayer.Property(Role.Composer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Role.Conductor)`</b>,
///                  \anchor MusicPlayer_Property_Role_Conductor
///                  _string_,
///     @return The name of the person who conducted the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_Property_Role_Conductor `MusicPlayer.Property(Role.Conductor)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Role.Orchestra)`</b>,
///                  \anchor MusicPlayer_Property_Role_Orchestra
///                  _string_,
///     @return The name of the orchestra performing the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_Property_Role_Orchestra `MusicPlayer.Property(Role.Orchestra)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Role.Lyricist)`</b>,
///                  \anchor MusicPlayer_Property_Role_Lyricist
///                  _string_,
///     @return The name of the person who wrote the lyrics of the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_Property_Role_Lyricist `MusicPlayer.Property(Role.Lyricist)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Role.Remixer)`</b>,
///                  \anchor MusicPlayer_Property_Role_Remixer
///                  _string_,
///     @return The name of the person who remixed the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_Property_Role_Remixer `MusicPlayer.Property(Role.Remixer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Role.Arranger)`</b>,
///                  \anchor MusicPlayer_Property_Role_Arranger
///                  _string_,
///     @return The name of the person who arranged the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_Property_Role_Arranger `MusicPlayer.Property(Role.Arranger)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Role.Engineer)`</b>,
///                  \anchor MusicPlayer_Property_Role_Engineer
///                  _string_,
///     @return The name of the person who was the engineer of the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_Property_Role_Engineer `MusicPlayer.Property(Role.Engineer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Role.Producer)`</b>,
///                  \anchor MusicPlayer_Property_Role_Producer
///                  _string_,
///     @return The name of the person who produced the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_Property_Role_Producer `MusicPlayer.Property(Role.Producer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Role.DJMixer)`</b>,
///                  \anchor MusicPlayer_Property_Role_DJMixer
///                  _string_,
///     @return The name of the dj who remixed the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_Property_Role_DJMixer `MusicPlayer.Property(Role.DJMixer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Role.Mixer)`</b>,
///                  \anchor MusicPlayer_Property_Role_Mixer
///                  _string_,
///     @return The name of the dj who remixed the selected song.
///     @todo So maybe rather than a row each have one entry for Role.XXXXX with composer\, arranger etc. as listed values
///     @note MusicPlayer.Property(Role.any_custom_role) also works\,
///     where any_custom_role could be an instrument violin or some other production activity e.g. sound engineer.
///     The roles listed (composer\, arranger etc.) are standard ones but there are many possible.
///     Music file tagging allows for the musicians and all other people involved in the recording to be added\, Kodi
///     will gathers and stores that data\, and it is available to GUI.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_Property_Role_Mixer `MusicPlayer.Property(Role.Mixer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Album_Mood)`</b>,
///                  \anchor MusicPlayer_Property_Album_Mood
///                  _string_,
///     @return the moods of the currently playing Album
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Album_Style)`</b>,
///                  \anchor MusicPlayer_Property_Album_Style
///                  _string_,
///     @return the styles of the currently playing Album.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Album_Theme)`</b>,
///                  \anchor MusicPlayer_Property_Album_Theme
///                  _string_,
///     @return The themes of the currently playing Album
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Album_Type)`</b>,
///                  \anchor MusicPlayer_Property_Album_Type
///                  _string_,
///     @return The album type (e.g. compilation\, enhanced\, explicit lyrics) of the
///     currently playing album.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Album_Label)`</b>,
///                  \anchor MusicPlayer_Property_Album_Label
///                  _string_,
///     @return The record label of the currently playing album.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Album_Description)`</b>,
///                  \anchor MusicPlayer_Property_Album_Description
///                  _string_,
///     @return A review of the currently playing album
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Artist`</b>,
///                  \anchor MusicPlayer_Artist
///                  _string_,
///     @return Artist(s) of current song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.offset(number).Artist`</b>,
///                  \anchor MusicPlayer_Offset_Artist
///                  _string_,
///     @return Artist(s) of the song which has an offset `number` with respect
///     to the current playing song.
///     @param number - the offset of the song with respect to the current
///     playing song
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Position(number).Artist`</b>,
///                  \anchor MusicPlayer_Position_Artist
///                  _string_,
///     @return Artist(s) of the song which has an offset `number` with respect
///     to the start of the playlist.
///     @param number - the offset of the song with respect to
///     the start of the playlist
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.AlbumArtist`</b>,
///                  \anchor MusicPlayer_AlbumArtist
///                  _string_,
///     @return The album artist of the currently playing song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Cover`</b>,
///                  \anchor MusicPlayer_Cover
///                  _string_,
///     @return The album cover of currently playing song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Artist_Sortname)`</b>,
///                  \anchor MusicPlayer_Property_Artist_Sortname
///                  _string_,
///     @return The sortname of the currently playing Artist.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link MusicPlayer_Property_Artist_Sortname `MusicPlayer.Property(Artist_Sortname)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Artist_Type)`</b>,
///                  \anchor MusicPlayer_Property_Artist_Type
///                  _string_,
///     @return The type of the currently playing Artist - person\,
///     group\, orchestra\, choir etc.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link MusicPlayer_Property_Artist_Type `MusicPlayer.Property(Artist_Type)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Artist_Gender)`</b>,
///                  \anchor MusicPlayer_Property_Artist_Gender
///                  _string_,
///     @return The gender of the currently playing Artist - male\,
///     female\, other.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link MusicPlayer_Property_Artist_Gender `MusicPlayer.Property(Artist_Gender)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Artist_Disambiguation)`</b>,
///                  \anchor MusicPlayer_Property_Artist_Disambiguation
///                  _string_,
///     @return A brief description of the currently playing Artist that differentiates them
///     from others with the same name.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link MusicPlayer_Property_Artist_Disambiguation `MusicPlayer.Property(Artist_Disambiguation)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Artist_Born)`</b>,
///                  \anchor MusicPlayer_Property_Artist_Born
///                  _string_,
///     @return The date of Birth of the currently playing Artist.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Artist_Died)`</b>,
///                  \anchor MusicPlayer_Property_Artist_Died
///                  _string_,
///     @return The date of Death of the currently playing Artist.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Artist_Formed)`</b>,
///                  \anchor MusicPlayer_Property_Artist_Formed
///                  _string_,
///     @return The Formation date of the currently playing Artist/Band.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Artist_Disbanded)`</b>,
///                  \anchor MusicPlayer_Property_Artist_Disbanded
///                  _string_,
///     @return The disbanding date of the currently playing Artist/Band.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Artist_YearsActive)`</b>,
///                  \anchor MusicPlayer_Property_Artist_YearsActive
///                  _string_,
///     @return The years the currently Playing artist has been active.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Artist_Instrument)`</b>,
///                  \anchor MusicPlayer_Property_Artist_Instrument
///                  _string_,
///     @return The instruments played by the currently playing artist.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Artist_Description)`</b>,
///                  \anchor MusicPlayer_Property_Artist_Description
///                  _string_,
///     @return A biography of the currently playing artist.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Artist_Mood)`</b>,
///                  \anchor MusicPlayer_Property_Artist_Mood
///                  _string_,
///     @return The moods of the currently playing artist.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Artist_Style)`</b>,
///                  \anchor MusicPlayer_Property_Artist_Style
///                  _string_,
///     @return The styles of the currently playing artist.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(Artist_Genre)`</b>,
///                  \anchor MusicPlayer_Property_Artist_Genre
///                  _string_,
///     @return The genre of the currently playing artist.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Genre`</b>,
///                  \anchor MusicPlayer_Genre
///                  _string_,
///     @return The genre(s) of current song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.offset(number).Genre`</b>,
///                  \anchor MusicPlayer_OffSet_Genre
///                  _string_,
///     @return The genre(s) of the song with an offset `number` with respect
///     to the current playing song.
///     @param number - the offset song number with respect to the current playing
///     song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Position(number).Genre`</b>,
///                  \anchor MusicPlayer_Position_Genre
///                  _string_,
///     @return The genre(s) of the song with an offset `number` with respect
///     to the start of the playlist.
///     @param number - the offset song number with respect to the start of the
///     playlist
///     song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Lyrics`</b>,
///                  \anchor MusicPlayer_Lyrics
///                  _string_,
///     @return The lyrics of current song stored in ID tag info.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Year`</b>,
///                  \anchor MusicPlayer_Year
///                  _string_,
///     @return The year of release of current song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.offset(number).Year`</b>,
///                  \anchor MusicPlayer_Offset_Year
///                  _string_,
///     @return The year of release of the song with an offset `number` with
///     respect to the current playing song.
///     @param number - the offset number with respect to the current song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Position(number).Year`</b>,
///                  \anchor MusicPlayer_Position_Year
///                  _string_,
///     @return The year of release of the song with an offset `number` with
///     respect to the start of the playlist.
///     @param number - the offset number with respect to the start of the
///     playlist.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Rating`</b>,
///                  \anchor MusicPlayer_Rating
///                  _string_,
///     @return The numeric Rating of current song (1-10).
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.offset(number).Rating`</b>,
///                  \anchor MusicPlayer_OffSet_Rating
///                  _string_,
///     @return The numeric Rating of song with an offset `number` with
///     respect to the current playing song.
///     @param number - the offset with respect to the current playing song
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Position(number).Rating`</b>,
///                  \anchor MusicPlayer_Position_Rating
///                  _string_,
///     @return The numeric Rating of song with an offset `number` with
///     respect to the start of the playlist.
///     @param number - the offset with respect to the start of the playlist
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.RatingAndVotes`</b>,
///                  \anchor MusicPlayer_RatingAndVotes
///                  _string_,
///     @return The scraped rating and votes of currently playing song\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.UserRating`</b>,
///                  \anchor MusicPlayer_UserRating
///                  _string_,
///     @return The scraped rating of the currently playing song (1-10).
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_UserRating `MusicPlayer.UserRating`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Votes`</b>,
///                  \anchor MusicPlayer_Votes
///                  _string_,
///     @return The scraped votes of currently playing song\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.DiscNumber`</b>,
///                  \anchor MusicPlayer_DiscNumber
///                  _string_,
///     @return The Disc Number of current song stored in ID tag info.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.offset(number).DiscNumber`</b>,
///                  \anchor MusicPlayer_Offset_DiscNumber
///                  _string_,
///     @return The Disc Number of current song stored in ID tag info for the
///     song with an offset `number` with respect to the playing song.
///     @param number - The offset value for the song with respect to the
///     playing song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Position(number).DiscNumber`</b>,
///                  \anchor MusicPlayer_Position_DiscNumber
///                  _string_,
///     @return The Disc Number of current song stored in ID tag info for the
///     song with an offset `number` with respect to the start of the playlist.
///     @param number - The offset value for the song with respect to the
///     start of the playlist.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Comment`</b>,
///                  \anchor MusicPlayer_Comment
///                  _string_,
///     @return The Comment of current song stored in ID tag info.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.offset(number).Comment`</b>,
///                  \anchor MusicPlayer_Offset_Comment
///                  _string_,
///     @return The Comment of current song stored in ID tag info for the
///     song with an offset `number` with respect to the playing song.
///     @param number - The offset value for the song with respect to the
///     playing song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Position(number).Comment`</b>,
///                  \anchor MusicPlayer_Position_Comment
///                  _string_,
///     @return The Comment of current song stored in ID tag info for the
///     song with an offset `number` with respect to the start of the playlist.
///     @param number - The offset value for the song with respect to the
///     start of the playlist.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Contributors`</b>,
///                  \anchor MusicPlayer_Contributors
///                  _string_,
///     @return The list of all people who've contributed to the currently playing song
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_Contributors `MusicPlayer.Contributors`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.ContributorAndRole`</b>,
///                  \anchor MusicPlayer_ContributorAndRole
///                  _string_,
///     @return The list of all people and their role who've contributed to the currently playing song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_ContributorAndRole `MusicPlayer.ContributorAndRole`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Mood`</b>,
///                  \anchor MusicPlayer_Mood
///                  _string_,
///     @return The mood of the currently playing song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_Mood `MusicPlayer.Mood`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.PlaylistPlaying`</b>,
///                  \anchor MusicPlayer_PlaylistPlaying
///                  _boolean_,
///     @return **True** if a playlist is currently playing.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Exists(relative\,position)`</b>,
///                  \anchor MusicPlayer_Exists
///                  _boolean_,
///     @return **True** if the currently playing playlist has a song queued at the given position.
///     @param relative - bool - If the position is relative
///     @param position - int - The position of the song
///     @note It is possible to define whether the position is relative or not\, default is false.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.HasPrevious`</b>,
///                  \anchor MusicPlayer_HasPrevious
///                  _boolean_,
///     @return **True** if the music player has a a Previous Song in the Playlist.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.HasNext`</b>,
///                  \anchor MusicPlayer_HasNext
///                  _boolean_,
///     @return **True** if the music player has a next song queued in the Playlist.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.PlayCount`</b>,
///                  \anchor MusicPlayer_PlayCount
///                  _integer_,
///     @return The play count of currently playing song\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.LastPlayed`</b>,
///                  \anchor MusicPlayer_LastPlayed
///                  _string_,
///     @return The last play date of currently playing song\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.TrackNumber`</b>,
///                  \anchor MusicPlayer_TrackNumber
///                  _string_,
///     @return The track number of current song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.offset(number).TrackNumber`</b>,
///                  \anchor MusicPlayer_Offset_TrackNumber
///                  _string_,
///     @return The track number of the song with an offset `number`
///     with respect to the current playing song.
///     @param number - The offset number of the song with respect to the
///     playing song
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Position(number).TrackNumber`</b>,
///                  \anchor MusicPlayer_Position_TrackNumber
///                  _string_,
///     @return The track number of the song with an offset `number`
///     with respect to start of the playlist.
///     @param number - The offset number of the song with respect
///     to start of the playlist
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Duration`</b>,
///                  \anchor MusicPlayer_Duration
///                  _string_,
///     @return The duration of the current song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.offset(number).Duration`</b>,
///                  \anchor MusicPlayer_Offset_Duration
///                  _string_,
///     @return The duration of the song with an offset `number`
///     with respect to the current playing song.
///     @param number - the offset number of the song with respect
///     to the current playing song
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Position(number).Duration`</b>,
///                  \anchor MusicPlayer_Position_Duration
///                  _string_,
///     @return The duration of the song with an offset `number`
///     with respect to the start of the playlist.
///     @param number - the offset number of the song with respect
///     to the start of the playlist
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.BitRate`</b>,
///                  \anchor MusicPlayer_BitRate
///                  _string_,
///     @return The bitrate of current song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Channels`</b>,
///                  \anchor MusicPlayer_Channels
///                  _string_,
///     @return The number of channels of current song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.BitsPerSample`</b>,
///                  \anchor MusicPlayer_BitsPerSample
///                  _string_,
///     @return The number of bits per sample of current song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.SampleRate`</b>,
///                  \anchor MusicPlayer_SampleRate
///                  _string_,
///     @return The samplerate of current playing song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Codec`</b>,
///                  \anchor MusicPlayer_Codec
///                  _string_,
///     @return The codec of current playing song.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.PlaylistPosition`</b>,
///                  \anchor MusicPlayer_PlaylistPosition
///                  _string_,
///     @return The position of the current song in the current music playlist.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.PlaylistLength`</b>,
///                  \anchor MusicPlayer_PlaylistLength
///                  _string_,
///     @return The total size of the current music playlist.
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.ChannelName`</b>,
///                  \anchor MusicPlayer_ChannelName
///                  _string_,
///     @return The channel name of the radio programme that's currently playing (PVR).
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.ChannelNumberLabel`</b>,
///                  \anchor MusicPlayer_ChannelNumberLabel
///                  _string_,
///     @return The channel and subchannel number of the radio channel that's currently
///     playing (PVR).
///     <p><hr>
///     @skinning_v14 **[New Infolabel]** \link MusicPlayer_ChannelNumberLabel `MusicPlayer.ChannelNumberLabel`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.ChannelGroup`</b>,
///                  \anchor MusicPlayer_ChannelGroup
///                  _string_,
///     @return The channel group of the radio programme that's currently playing (PVR).
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Property(propname)`</b>,
///                  \anchor MusicPlayer_Property_Propname
///                  _string_,
///     @return The requested property value of the currently playing item.
///     @param propname - The requested property
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.DBID`</b>,
///                  \anchor MusicPlayer_DBID
///                  _string_,
///     @return The database id of the currently playing song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link MusicPlayer_DBID `MusicPlayer.DBID`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.DiscTitle`</b>,
///                  \anchor MusicPlayer_DiscTitle
///                  _string_,
///     @return The title of the disc currently playing.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link MusicPlayer_DiscTitle `MusicPlayer.DiscTitle`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.ReleaseDate`</b>,
///                  \anchor MusicPlayer_ReleaseDate
///                  _string_,
///     @return The release date of the song currently playing.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link MusicPlayer_ReleaseDate `MusicPlayer.ReleaseDate`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.OriginalDate`</b>,
///                  \anchor MusicPlayer_OriginalDate
///                  _string_,
///     @return The original release date of the song currently playing.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link MusicPlayer_OriginalDate `MusicPlayer.OriginalDate`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.BPM`</b>,
///                  \anchor MusicPlayer_BPM
///                  _string_,
///     @return The bpm of the track currently playing.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link MusicPlayer_BPM `MusicPlayer.BPM`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.IsMultiDisc`</b>,
///                  \anchor MusicPlayer_IsMultiDisc
///                  _boolean_,
///     @return Returns **true** if the album currently playing has more than one disc.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link MusicPlayer_IsMultiDisc `MusicPlayer.IsMultiDisc`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.TotalDiscs`</b>,
///                  \anchor MusicPlayer_TotalDiscs
///                  _string_,
///     @return The number of discs associated with the currently playing album.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link MusicPlayer_TotalDiscs `MusicPlayer.TotalDiscs`\endlink
///     <p>
///   }
///   \table_row3{   <b>`MusicPlayer.Station`</b>,
///                  \anchor MusicPlayer_Station
///                  _string_,
///     @return The name of the radio station currently playing (if available).
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link MusicPlayer_Station `MusicPlayer.Station`\endlink
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap musicplayer[] =    {{ "title",            MUSICPLAYER_TITLE },
                                  { "album",            MUSICPLAYER_ALBUM },
                                  { "artist",           MUSICPLAYER_ARTIST },
                                  { "albumartist",      MUSICPLAYER_ALBUM_ARTIST },
                                  { "year",             MUSICPLAYER_YEAR },
                                  { "genre",            MUSICPLAYER_GENRE },
                                  { "duration",         MUSICPLAYER_DURATION },
                                  { "tracknumber",      MUSICPLAYER_TRACK_NUMBER },
                                  { "cover",            MUSICPLAYER_COVER },
                                  { "bitrate",          MUSICPLAYER_BITRATE },
                                  { "playlistlength",   MUSICPLAYER_PLAYLISTLEN },
                                  { "playlistposition", MUSICPLAYER_PLAYLISTPOS },
                                  { "channels",         MUSICPLAYER_CHANNELS },
                                  { "bitspersample",    MUSICPLAYER_BITSPERSAMPLE },
                                  { "samplerate",       MUSICPLAYER_SAMPLERATE },
                                  { "codec",            MUSICPLAYER_CODEC },
                                  { "discnumber",       MUSICPLAYER_DISC_NUMBER },
                                  { "disctitle",        MUSICPLAYER_DISC_TITLE },
                                  { "rating",           MUSICPLAYER_RATING },
                                  { "ratingandvotes",   MUSICPLAYER_RATING_AND_VOTES },
                                  { "userrating",       MUSICPLAYER_USER_RATING },
                                  { "votes",            MUSICPLAYER_VOTES },
                                  { "comment",          MUSICPLAYER_COMMENT },
                                  { "mood",             MUSICPLAYER_MOOD },
                                  { "contributors",     MUSICPLAYER_CONTRIBUTORS },
                                  { "contributorandrole", MUSICPLAYER_CONTRIBUTOR_AND_ROLE },
                                  { "lyrics",           MUSICPLAYER_LYRICS },
                                  { "playlistplaying",  MUSICPLAYER_PLAYLISTPLAYING },
                                  { "exists",           MUSICPLAYER_EXISTS },
                                  { "hasprevious",      MUSICPLAYER_HASPREVIOUS },
                                  { "hasnext",          MUSICPLAYER_HASNEXT },
                                  { "playcount",        MUSICPLAYER_PLAYCOUNT },
                                  { "lastplayed",       MUSICPLAYER_LASTPLAYED },
                                  { "channelname",      MUSICPLAYER_CHANNEL_NAME },
                                  { "channelnumberlabel", MUSICPLAYER_CHANNEL_NUMBER },
                                  { "channelgroup",     MUSICPLAYER_CHANNEL_GROUP },
                                  { "dbid",             MUSICPLAYER_DBID },
                                  { "property",         MUSICPLAYER_PROPERTY },
                                  { "releasedate",      MUSICPLAYER_RELEASEDATE },
                                  { "originaldate",     MUSICPLAYER_ORIGINALDATE },
                                  { "bpm",              MUSICPLAYER_BPM },
                                  { "ismultidisc",      MUSICPLAYER_ISMULTIDISC },
                                  { "totaldiscs",       MUSICPLAYER_TOTALDISCS },
                                  { "station",          MUSICPLAYER_STATIONNAME }
};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Videoplayer Video player
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`VideoPlayer.UsingOverlays`</b>,
///                  \anchor VideoPlayer_UsingOverlays
///                  _boolean_,
///     @return **True** if the video player is using the hardware overlays render
///     method.
///     @note This is useful\, as with hardware overlays you have no alpha blending to
///     the video image\, so shadows etc. need redoing\, or disabling.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.IsFullscreen`</b>,
///                  \anchor VideoPlayer_IsFullscreen
///                  _boolean_,
///     @return **True** if the video player is in fullscreen mode.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.HasMenu`</b>,
///                  \anchor VideoPlayer_HasMenu
///                  _boolean_,
///     @return **True** if the video player has a menu (ie is playing a DVD).
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.HasInfo`</b>,
///                  \anchor VideoPlayer_HasInfo
///                  _boolean_,
///     @return **True** if the current playing video has information from the
///     library or from a plugin (eg director/plot etc.)
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.HasVideoVersions`</b>,
///                  \anchor VideoPlayer_HasVideoVersions
///                  _boolean_,
///     @return **True** when the played item has multiple video versions.
///     <p><hr>
///     @skinning_v21 **[New Infolabel]** \link VideoPlayer_HasVideoVersions `VideoPlayer.HasVideoVersions`\endlink
///   }
///   \table_row3{   <b>`VideoPlayer.Content(parameter)`</b>,
///                  \anchor VideoPlayer_Content
///                  _boolean_,
///     @return **True** if the current Video you are playing is contained in
///     corresponding Video Library sections. The following values are accepted:
///     - <b>files</b>
///     - <b>movies</b>
///     - <b>episodes</b>
///     - <b>musicvideos</b>
///     - <b>livetv</b>
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.HasSubtitles`</b>,
///                  \anchor VideoPlayer_HasSubtitles
///                  _boolean_,
///     @return **True** if there are subtitles available for video.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.HasTeletext`</b>,
///                  \anchor VideoPlayer_HasTeletext
///                  _boolean_,
///     @return **True** if teletext is usable on played TV channel.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.IsStereoscopic`</b>,
///                  \anchor VideoPlayer_IsStereoscopic
///                  _boolean_,
///     @return **True** when the currently playing video is a 3D (stereoscopic)
///     video.
///     <p><hr>
///     @skinning_v13 **[New Boolean Condition]** \link VideoPlayer_IsStereoscopic `VideoPlayer.IsStereoscopic`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.SubtitlesEnabled`</b>,
///                  \anchor VideoPlayer_SubtitlesEnabled
///                  _boolean_,
///     @return **True** if subtitles are turned on for video.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.HasEpg`</b>,
///                  \anchor VideoPlayer_HasEpg
///                  _boolean_,
///     @return **True** if epg information is available for the currently playing
///     programme (PVR).
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.CanResumeLiveTV`</b>,
///                  \anchor VideoPlayer_CanResumeLiveTV
///                  _boolean_,
///     @return **True** if a in-progress PVR recording is playing an the respective
///     live TV channel is available.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Title`</b>,
///                  \anchor VideoPlayer_Title
///                  _string_,
///     @return The title of currently playing video.
///     @note If it's in the database it will return the database title\, else the filename.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Title`</b>,
///                  \anchor VideoPlayer_Offset_Title
///                  _string_,
///     @return The title of video which has an offset `number` with respect to the currently playing video.
///     @note If it's in the database it will return the database title\, else the filename.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Title `VideoPlayer.offset(number).Title`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Title`</b>,
///                  \anchor VideoPlayer_Position_Title
///                  _string_,
///     @return The title of the video which has an offset `number` with respect to the start of the playlist.
///     @note If it's in the database it will return the database title\, else the filename.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Title `VideoPlayer.position(number).Title`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.OriginalTitle`</b>,
///                  \anchor VideoPlayer_OriginalTitle
///                  _string_,
///     @return The original title of currently playing video. If it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).OriginalTitle`</b>,
///                  \anchor VideoPlayer_Offset_OriginalTitle
///                  _string_,
///     @return The original title of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_OriginalTitle `VideoPlayer.offset(number).OriginalTitle`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).OriginalTitle`</b>,
///                  \anchor VideoPlayer_Position_OriginalTitle
///                  _string_,
///     @return The original title of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_OriginalTitle `VideoPlayer.position(number).OriginalTitle`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.TVShowTitle`</b>,
///                  \anchor VideoPlayer_TVShowTitle
///                  _string_,
///     @return The title of currently playing episode's tvshow name.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).TVShowTitle`</b>,
///                  \anchor VideoPlayer_Offset_TVShowTitle
///                  _string_,
///     @return The title of the episode's tvshow name which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_TVShowTitle `VideoPlayer.offset(number).TVShowTitle`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).TVShowTitle`</b>,
///                  \anchor VideoPlayer_Position_TVShowTitle
///                  _string_,
///     @return The title of the episode's tvshow name which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_TVShowTitle `VideoPlayer.position(number).TVShowTitle`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Season`</b>,
///                  \anchor VideoPlayer_Season
///                  _string_,
///     @return The season number of the currently playing episode\, if it's in the database.
///     <p><hr>
///     @skinning_v15 **[Infolabel Updated]** \link VideoPlayer_Season `VideoPlayer.Season`\endlink
///     also supports EPG.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Season`</b>,
///                  \anchor VideoPlayer_Offset_Season
///                  _string_,
///     @return The season number of the episode which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Season `VideoPlayer.offset(number).Season`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Season`</b>,
///                  \anchor VideoPlayer_Position_Season
///                  _string_,
///     @return The season number of the episode which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Season `VideoPlayer.position(number).Season`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Episode`</b>,
///                  \anchor VideoPlayer_Episode
///                  _string_,
///     @return The episode number of the currently playing episode.
///     <p><hr>
///     @skinning_v15 **[Infolabel Updated]** \link VideoPlayer_Episode `VideoPlayer.Episode`\endlink
///     also supports EPG.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Episode`</b>,
///                  \anchor VideoPlayer_Offset_Episode
///                  _string_,
///     @return The episode number of the episode which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Episode `VideoPlayer.offset(number).Episode`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Episode`</b>,
///                  \anchor VideoPlayer_Position_Episode
///                  _string_,
///     @return The episode number of the episode which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Episode `VideoPlayer.position(number).Episode`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Genre`</b>,
///                  \anchor VideoPlayer_Genre
///                  _string_,
///     @return The genre(s) of current movie\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Genre`</b>,
///                  \anchor VideoPlayer_Offset_Genre
///                  _string_,
///     @return The genre(s) of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Genre `VideoPlayer.offset(number).Genre`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Genre`</b>,
///                  \anchor VideoPlayer_Position_Genre
///                  _string_,
///     @return The genre(s) of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Genre `VideoPlayer.position(number).Genre`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Director`</b>,
///                  \anchor VideoPlayer_Director
///                  _string_,
///     @return The director of current movie\, if it's in the database.
///     <p><hr>
///     @skinning_v15 **[Infolabel Updated]** \link VideoPlayer_Director `VideoPlayer.Director`\endlink
///     also supports EPG.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Director`</b>,
///                  \anchor VideoPlayer_Offset_Director
///                  _string_,
///     @return The director of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Director `VideoPlayer.offset(number).VideoPlayer_Offset_Director`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Director`</b>,
///                  \anchor VideoPlayer_Position_Director
///                  _string_,
///     @return The director of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Director `VideoPlayer.position(number).Director`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Country`</b>,
///                  \anchor VideoPlayer_Country
///                  _string_,
///     @return The production country of current movie\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Country`</b>,
///                  \anchor VideoPlayer_Offset_Country
///                  _string_,
///     @return The production country of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Country `VideoPlayer.offset(number).Country`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Country`</b>,
///                  \anchor VideoPlayer_Position_Country
///                  _string_,
///     @return The production country of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Country `VideoPlayer.position(number).Country`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Year`</b>,
///                  \anchor VideoPlayer_Year
///                  _string_,
///     @return The year of release of current movie\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Year`</b>,
///                  \anchor VideoPlayer_Offset_Year
///                  _string_,
///     @return The year of release of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Year `VideoPlayer.offset(number).Year`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Year`</b>,
///                  \anchor VideoPlayer_Position_Year
///                  _string_,
///     @return The year of release of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Year `VideoPlayer.position(number).Year`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Cover`</b>,
///                  \anchor VideoPlayer_Cover
///                  _string_,
///     @return The cover of currently playing movie.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Cover`</b>,
///                  \anchor VideoPlayer_Offset_Cover
///                  _string_,
///     @return The cover of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Cover `VideoPlayer.offset(number).Cover`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Cover`</b>,
///                  \anchor VideoPlayer_Position_Cover
///                  _string_,
///     @return The cover of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Cover `VideoPlayer.position(number).Cover`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Rating`</b>,
///                  \anchor VideoPlayer_Rating
///                  _string_,
///     @return The scraped rating of current movie\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Rating`</b>,
///                  \anchor VideoPlayer_Offset_Rating
///                  _string_,
///     @return The scraped rating of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Rating `VideoPlayer.offset(number).Rating`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Rating`</b>,
///                  \anchor VideoPlayer_Position_Rating
///                  _string_,
///     @return The scraped rating of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Rating `VideoPlayer.position(number).Rating`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.UserRating`</b>,
///                  \anchor VideoPlayer_UserRating
///                  _string_,
///     @return The user rating of the currently playing item.
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link VideoPlayer_UserRating `VideoPlayer.UserRating`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).UserRating`</b>,
///                  \anchor VideoPlayer_Offset_UserRating
///                  _string_,
///     @return The user rating of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_UserRating `VideoPlayer.offset(number).UserRating`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).UserRating`</b>,
///                  \anchor VideoPlayer_Position_UserRating
///                  _string_,
///     @return The user rating of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_UserRating `VideoPlayer.position(number).UserRating`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Votes`</b>,
///                  \anchor VideoPlayer_Votes
///                  _string_,
///     @return The scraped votes of current movie\, if it's in the database.
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link VideoPlayer_Votes `VideoPlayer.Votes`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Votes`</b>,
///                  \anchor VideoPlayer_Offset_Votes
///                  _string_,
///     @return The scraped votes of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Votes `VideoPlayer.offset(number).Votes`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Votes`</b>,
///                  \anchor VideoPlayer_Position_Votes
///                  _string_,
///     @return The scraped votes of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Votes `VideoPlayer.position(number).Votes`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.RatingAndVotes`</b>,
///                  \anchor VideoPlayer_RatingAndVotes
///                  _string_,
///     @return The scraped rating and votes of current movie\, if it's in the database
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).RatingAndVotes`</b>,
///                  \anchor VideoPlayer_Offset_RatingAndVotes
///                  _string_,
///     @return The scraped rating and votes of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_RatingAndVotes `VideoPlayer.offset(number).RatingAndVotes`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).RatingAndVotes`</b>,
///                  \anchor VideoPlayer_Position_RatingAndVotes
///                  _string_,
///     @return The scraped rating and votes of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_RatingAndVotes `VideoPlayer.position(number).RatingAndVotes`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.mpaa`</b>,
///                  \anchor VideoPlayer_mpaa
///                  _string_,
///     @return The MPAA rating of current movie\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).mpaa`</b>,
///                  \anchor VideoPlayer_Offset_mpaa
///                  _string_,
///     @return The MPAA rating of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_mpaa `VideoPlayer.offset(number).mpaa`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).mpaa`</b>,
///                  \anchor VideoPlayer_Position_mpaa
///                  _string_,
///     @return The MPAA rating of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_mpaa `VideoPlayer.position(number).mpaa`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Art(type)`</b>,
///                  \anchor VideoPlayer_art
///                  _string_,
///     @return The art path for the requested arttype and for the currently playing video.
///     @param type - can virtually be anything\, refers to the art type keyword in the art map (poster\, fanart\, banner\, thumb\, etc)
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link VideoPlayer_art `VideoPlayer.Art(type)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Art(type)`</b>,
///                  \anchor VideoPlayer_Offset_art
///                  _string_,
///     @return The art path for the requested arttype and for the video which has an offset `number` with respect to the currently playing video.
///     @param number - the offset with respect to the start of the playlist
///     @param type - can virtually be anything\, refers to the art type keyword in the art map (poster\, fanart\, banner\, thumb\, etc)
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link VideoPlayer_Offset_mpaa `VideoPlayer.offset(number).Art(type)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Art(type)`</b>,
///                  \anchor VideoPlayer_position_art
///                  _string_,
///     @return The art path for the requested arttype and for the video which has an offset `number` with respect to the start of the playlist.
///     @param number - the offset with respect to the start of the playlist
///     @param type - can virtually be anything\, refers to the art type keyword in the art map (poster\, fanart\, banner\, thumb\, etc)
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link VideoPlayer_position_art `VideoPlayer.position(number).Art(type)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.IMDBNumber`</b>,
///                  \anchor VideoPlayer_IMDBNumber
///                  _string_,
///     @return The IMDb ID of the current movie\, if it's in the database.
///     <p><hr>
///     @skinning_v15 **[New Infolabel]** \link VideoPlayer_IMDBNumber `VideoPlayer.IMDBNumber`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).IMDBNumber`</b>,
///                  \anchor VideoPlayer_Offset_IMDBNumber
///                  _string_,
///     @return The IMDb ID of the the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_IMDBNumber `VideoPlayer.offset(number).IMDBNumber`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).IMDBNumber`</b>,
///                  \anchor VideoPlayer_Position_IMDBNumber
///                  _string_,
///     @return The IMDb ID of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_IMDBNumber `VideoPlayer.position(number).IMDBNumber`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Top250`</b>,
///                  \anchor VideoPlayer_Top250
///                  _string_,
///     @return The IMDb Top250 position of the currently playing movie\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Top250`</b>,
///                  \anchor VideoPlayer_Offset_Top250
///                  _string_,
///     @return The IMDb Top250 position of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Top250 `VideoPlayer.offset(number).Top250`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Top250`</b>,
///                  \anchor VideoPlayer_Position_Top250
///                  _string_,
///     @return The IMDb Top250 position of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Top250 `VideoPlayer.position(number).Top250`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.EpisodeName`</b>,
///                  \anchor VideoPlayer_EpisodeName
///                  _string_,
///     @return The name of the episode if the playing video is a TV Show\,
///     if it's in the database (PVR).
///     <p><hr>
///     @skinning_v15 **[New Infolabel]** \link VideoPlayer_EpisodeName `VideoPlayer.EpisodeName`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.PlaylistPosition`</b>,
///                  \anchor VideoPlayer_PlaylistPosition
///                  _string_,
///     @return The position of the current song in the current video playlist.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.PlaylistLength`</b>,
///                  \anchor VideoPlayer_PlaylistLength
///                  _string_,
///     @return The total size of the current video playlist.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Cast`</b>,
///                  \anchor VideoPlayer_Cast
///                  _string_,
///     @return A concatenated string of cast members of the current movie\, if it's in
///     the database.
///     <p><hr>
///     @skinning_v15 **[Infolabel Updated]** \link VideoPlayer_Cast `VideoPlayer.Cast`\endlink
///     also supports EPG.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.CastAndRole`</b>,
///                  \anchor VideoPlayer_CastAndRole
///                  _string_,
///     @return A concatenated string of cast members and roles of the current movie\,
///     if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Album`</b>,
///                  \anchor VideoPlayer_Album
///                  _string_,
///     @return The album from which the current Music Video is from\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Album`</b>,
///                  \anchor VideoPlayer_Offset_Album
///                  _string_,
///     @return The album from which the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Album `VideoPlayer.offset(number).Album`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Album`</b>,
///                  \anchor VideoPlayer_Position_Album
///                  _string_,
///     @return The album from which the music video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Album `VideoPlayer.position(number).Album`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Artist`</b>,
///                  \anchor VideoPlayer_Artist
///                  _string_,
///     @return The artist(s) of current Music Video\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Artist`</b>,
///                  \anchor VideoPlayer_Offset_Artist
///                  _string_,
///     @return The artist(s) of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Artist `VideoPlayer.offset(number).Artist`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Artist`</b>,
///                  \anchor VideoPlayer_Position_Artist
///                  _string_,
///     @return The artist(s) of the music video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Artist `VideoPlayer.position(number).Artist`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Studio`</b>,
///                  \anchor VideoPlayer_Studio
///                  _string_,
///     @return The studio of current Music Video\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Studio`</b>,
///                  \anchor VideoPlayer_Offset_Studio
///                  _string_,
///     @return The studio of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Studio `VideoPlayer.offset(number).Studio`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Studio`</b>,
///                  \anchor VideoPlayer_Position_Studio
///                  _string_,
///     @return The studio of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Studio `VideoPlayer.position(number).Studio`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Writer`</b>,
///                  \anchor VideoPlayer_Writer
///                  _string_,
///     @return The name of Writer of current playing Video\, if it's in the database.
///     <p><hr>
///     @skinning_v15 **[Infolabel Updated]** \link VideoPlayer_Writer `VideoPlayer.Writer`\endlink
///     also supports EPG.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Writer`</b>,
///                  \anchor VideoPlayer_Offset_Writer
///                  _string_,
///     @return The name of Writer of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Writer `VideoPlayer.offset(number).Writer`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Writer`</b>,
///                  \anchor VideoPlayer_Position_Writer
///                  _string_,
///     @return The name of Writer of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Writer `VideoPlayer.position(number).Writer`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Tagline`</b>,
///                  \anchor VideoPlayer_Tagline
///                  _string_,
///     @return The small Summary of current playing Video\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Tagline`</b>,
///                  \anchor VideoPlayer_Offset_Tagline
///                  _string_,
///     @return The small Summary of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Tagline `VideoPlayer.offset(number).Tagline`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Tagline`</b>,
///                  \anchor VideoPlayer_Position_Tagline
///                  _string_,
///     @return The small Summary of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Tagline `VideoPlayer.position(number).Tagline`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.PlotOutline`</b>,
///                  \anchor VideoPlayer_PlotOutline
///                  _string_,
///     @return The small Summary of current playing Video\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).PlotOutline`</b>,
///                  \anchor VideoPlayer_Offset_PlotOutline
///                  _string_,
///     @return The small Summary of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_PlotOutline `VideoPlayer.offset(number).PlotOutline`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).PlotOutline`</b>,
///                  \anchor VideoPlayer_Position_PlotOutline
///                  _string_,
///     @return The small Summary of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_PlotOutline `VideoPlayer.position(number).PlotOutline`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Plot`</b>,
///                  \anchor VideoPlayer_Plot
///                  _string_,
///     @return The complete Text Summary of current playing Video\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Plot`</b>,
///                  \anchor VideoPlayer_Offset_Plot
///                  _string_,
///     @return The complete Text Summary of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Plot `VideoPlayer.offset(number).Plot`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Plot`</b>,
///                  \anchor VideoPlayer_Position_Plot
///                  _string_,
///     @return The complete Text Summary of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Plot `VideoPlayer.position(number).Plot`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Premiered`</b>,
///                  \anchor VideoPlayer_Premiered
///                  _string_,
///     @return The release or aired date of the currently playing episode\, show\, movie or EPG item\,
///     if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Premiered`</b>,
///                  \anchor VideoPlayer_Offset_Premiered
///                  _string_,
///     @return The release or aired date of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Premiered `VideoPlayer.offset(number).Premiered`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Premiered`</b>,
///                  \anchor VideoPlayer_Position_Premiered
///                  _string_,
///     @return The release or aired date of the video which has an offset `number` with respect to the start of the playlist.
///     if it's in the database.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Premiered `VideoPlayer.position(number).Premiered`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.Trailer`</b>,
///                  \anchor VideoPlayer_Trailer
///                  _string_,
///     @return The path to the trailer of the currently playing movie\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).Trailer`</b>,
///                  \anchor VideoPlayer_Offset_Trailer
///                  _string_,
///     @return The path to the trailer of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_Trailer `VideoPlayer.offset(number).Title`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).Trailer`</b>,
///                  \anchor VideoPlayer_Position_Trailer
///                  _string_,
///     @return The path to the trailer of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_Trailer `VideoPlayer.position(number).Trailer`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.LastPlayed`</b>,
///                  \anchor VideoPlayer_LastPlayed
///                  _string_,
///     @return The last play date of current playing Video\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).LastPlayed`</b>,
///                  \anchor VideoPlayer_Offset_LastPlayed
///                  _string_,
///     @return The last play date of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_LastPlayed `VideoPlayer.offset(number).LastPlayed`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).LastPlayed`</b>,
///                  \anchor VideoPlayer_Position_LastPlayed
///                  _string_,
///     @return The last play date of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_LastPlayed `VideoPlayer.position(number).LastPlayed`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.PlayCount`</b>,
///                  \anchor VideoPlayer_PlayCount
///                  _string_,
///     @return The playcount of current playing Video\, if it's in the database.
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).PlayCount`</b>,
///                  \anchor VideoPlayer_Offset_PlayCount
///                  _string_,
///     @return The playcount of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_PlayCount `VideoPlayer.offset(number).PlayCount`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).PlayCount`</b>,
///                  \anchor VideoPlayer_Position_PlayCount
///                  _string_,
///     @return The playcount of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_PlayCount `VideoPlayer.position(number).PlayCount`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.VideoCodec`</b>,
///                  \anchor VideoPlayer_VideoCodec
///                  _string_,
///     @return The video codec of the currently playing video (common values: see
///     \ref ListItem_VideoCodec "ListItem.VideoCodec").
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.VideoResolution`</b>,
///                  \anchor VideoPlayer_VideoResolution
///                  _string_,
///     @return The video resolution of the currently playing video (possible
///     values: see \ref ListItem_VideoResolution "ListItem.VideoResolution").
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.VideoAspect`</b>,
///                  \anchor VideoPlayer_VideoAspect
///                  _string_,
///     @return The aspect ratio of the currently playing video (possible values:
///     see \ref ListItem_VideoAspect "ListItem.VideoAspect").
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.AudioCodec`</b>,
///                  \anchor VideoPlayer_AudioCodec
///                  _string_,
///     @return The audio codec of the currently playing video\, optionally 'n'
///     defines the number of the audiostream (common values: see
///     \ref ListItem_AudioCodec "ListItem.AudioCodec").
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.AudioChannels`</b>,
///                  \anchor VideoPlayer_AudioChannels
///                  _string_,
///     @return The number of audio channels of the currently playing video
///     (possible values: see \ref ListItem_AudioChannels "ListItem.AudioChannels").
///     <p><hr>
///     @skinning_v16 **[Infolabel Updated]** \link VideoPlayer_AudioChannels `VideoPlayer.AudioChannels`\endlink
///     if a video contains no audio\, these infolabels will now return empty.
///     (they used to return 0)
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.AudioLanguage`</b>,
///                  \anchor VideoPlayer_AudioLanguage
///                  _string_,
///     @return The language of the audio of the currently playing video(possible
///     values: see \ref ListItem_AudioLanguage "ListItem.AudioLanguage").
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link VideoPlayer_AudioLanguage `VideoPlayer.AudioLanguage`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.SubtitlesLanguage`</b>,
///                  \anchor VideoPlayer_SubtitlesLanguage
///                  _string_,
///     @return The language of the subtitle of the currently playing video
///     (possible values: see \ref ListItem_SubtitleLanguage "ListItem.SubtitleLanguage").
///     @note `VideoPlayer.SubtitlesLanguage` holds the language of the next available
///     subtitle stream if subtitles are disabled in the player
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link VideoPlayer_SubtitlesLanguage `VideoPlayer.SubtitlesLanguage`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.StereoscopicMode`</b>,
///                  \anchor VideoPlayer_StereoscopicMode
///                  _string_,
///     @return The stereoscopic mode of the currently playing video (possible
///     values: see \ref ListItem_StereoscopicMode "ListItem.StereoscopicMode").
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link VideoPlayer_StereoscopicMode `VideoPlayer.StereoscopicMode`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.StartTime`</b>,
///                  \anchor VideoPlayer_StartTime
///                  _string_,
///     @return The start date and time of the currently playing epg event or recording (PVR).
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.EndTime`</b>,
///                  \anchor VideoPlayer_EndTime
///                  _string_,
///     @return The end date and time of the currently playing epg event or recording (PVR).
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.NextTitle`</b>,
///                  \anchor VideoPlayer_NextTitle
///                  _string_,
///     @return The title of the programme that will be played next (PVR).
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.NextGenre`</b>,
///                  \anchor VideoPlayer_NextGenre
///                  _string_,
///     @return The genre of the programme that will be played next (PVR).
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.NextPlot`</b>,
///                  \anchor VideoPlayer_NextPlot
///                  _string_,
///     @return The plot of the programme that will be played next (PVR).
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.NextPlotOutline`</b>,
///                  \anchor VideoPlayer_NextPlotOutline
///                  _string_,
///     @return The plot outline of the programme that will be played next (PVR).
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.NextStartTime`</b>,
///                  \anchor VideoPlayer_NextStartTime
///                  _string_,
///     @return The start time of the programme that will be played next (PVR).
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.NextEndTime`</b>,
///                  \anchor VideoPlayer_NextEndTime
///                  _string_,
///     @return The end time of the programme that will be played next (PVR).
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.NextDuration`</b>,
///                  \anchor VideoPlayer_NextDuration
///                  _string_,
///     @return The duration of the programme that will be played next (PVR).
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.ChannelName`</b>,
///                  \anchor VideoPlayer_ChannelName
///                  _string_,
///     @return The name of the currently tuned channel (PVR).
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.ChannelNumberLabel`</b>,
///                  \anchor VideoPlayer_ChannelNumberLabel
///                  _string_,
///     @return The channel and subchannel number of the tv channel that's currently playing (PVR).
///     <p><hr>
///     @skinning_v14 **[New Infolabel]** \link VideoPlayer_ChannelNumberLabel `VideoPlayer.ChannelNumberLabel`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.ChannelGroup`</b>,
///                  \anchor VideoPlayer_ChannelGroup
///                  _string_,
///     @return The group of the currently tuned channel (PVR).
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.ParentalRating`</b>,
///                  \anchor VideoPlayer_ParentalRating
///                  _string_,
///     @return The parental rating of the currently playing programme (PVR).
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.DBID`</b>,
///                  \anchor VideoPlayer_DBID
///                  _string_,
///     @return The database id of the currently playing video
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link VideoPlayer_DBID `VideoPlayer.DBID`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.offset(number).DBID`</b>,
///                  \anchor VideoPlayer_Offset_DBID
///                  _string_,
///     @return The database id of the video which has an offset `number` with respect to the currently playing video.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Offset_DBID `VideoPlayer.offset(number).DBID`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.position(number).DBID`</b>,
///                  \anchor VideoPlayer_Position_DBID
///                  _string_,
///     @return The database id of the video which has an offset `number` with respect to the start of the playlist.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_Position_DBID `VideoPlayer.position(number).DBID`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.UniqueID(name)`</b>,
///                  \anchor VideoPlayer_UniqueID
///                  _string_,
///     @return The scraped metadata id of current movie\, if it's in the database.
///     @param name - the name of the metadata provider.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_UniqueID `VideoPlayer.UniqueID(name)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.TvShowDBID`</b>,
///                  \anchor VideoPlayer_TvShowDBID
///                  _string_,
///     @return The database id of the TvShow for the currently playing Episode
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link VideoPlayer_TvShowDBID `VideoPlayer.TvShowDBID`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.AudioStreamCount`</b>,
///                  \anchor VideoPlayer_AudioStreamCount
///                  _integer_,
///     @return The number of audio streams of the currently playing video.
///     @note If the video contains no audio streams it returns 0.
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link VideoPlayer_AudioStreamCount `VideoPlayer.AudioStreamCount`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.HdrType`</b>,
///                  \anchor VideoPlayer_HdrType
///                  _string_,
///     @return String containing the name of the detected HDR type or empty if not HDR. See \ref StreamHdrType for the list of possible values.
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link VideoPlayer_HdrType `VideoPlayer.HdrType`\endlink
///     <p>
///   }
///   \table_row3{   <b>`VideoPlayer.VideoVersionName`</b>,
///                  \anchor VideoPlayer_VideoVersionName
///                  _string_,
///     @return String containing the version name of the currently playing video (movie) - empty if not a movie, version name is not set or not a version
///     <p><hr>
///     @skinning_v21 **[New Infolabel]** \link VideoPlayer_VideoVersionName `VideoPlayer.VideoVersionName`\endlink
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
// clang-format off
const infomap videoplayer[] =    {{ "title",            VIDEOPLAYER_TITLE },
                                  { "genre",            VIDEOPLAYER_GENRE },
                                  { "country",          VIDEOPLAYER_COUNTRY },
                                  { "originaltitle",    VIDEOPLAYER_ORIGINALTITLE },
                                  { "director",         VIDEOPLAYER_DIRECTOR },
                                  { "year",             VIDEOPLAYER_YEAR },
                                  { "cover",            VIDEOPLAYER_COVER },
                                  { "usingoverlays",    VIDEOPLAYER_USING_OVERLAYS },
                                  { "isfullscreen",     VIDEOPLAYER_ISFULLSCREEN },
                                  { "hasmenu",          VIDEOPLAYER_HASMENU },
                                  { "playlistlength",   VIDEOPLAYER_PLAYLISTLEN },
                                  { "playlistposition", VIDEOPLAYER_PLAYLISTPOS },
                                  { "plot",             VIDEOPLAYER_PLOT },
                                  { "plotoutline",      VIDEOPLAYER_PLOT_OUTLINE },
                                  { "episode",          VIDEOPLAYER_EPISODE },
                                  { "season",           VIDEOPLAYER_SEASON },
                                  { "rating",           VIDEOPLAYER_RATING },
                                  { "ratingandvotes",   VIDEOPLAYER_RATING_AND_VOTES },
                                  { "userrating",       VIDEOPLAYER_USER_RATING },
                                  { "votes",            VIDEOPLAYER_VOTES },
                                  { "tvshowtitle",      VIDEOPLAYER_TVSHOW },
                                  { "premiered",        VIDEOPLAYER_PREMIERED },
                                  { "studio",           VIDEOPLAYER_STUDIO },
                                  { "mpaa",             VIDEOPLAYER_MPAA },
                                  { "top250",           VIDEOPLAYER_TOP250 },
                                  { "cast",             VIDEOPLAYER_CAST },
                                  { "castandrole",      VIDEOPLAYER_CAST_AND_ROLE },
                                  { "artist",           VIDEOPLAYER_ARTIST },
                                  { "album",            VIDEOPLAYER_ALBUM },
                                  { "writer",           VIDEOPLAYER_WRITER },
                                  { "tagline",          VIDEOPLAYER_TAGLINE },
                                  { "hasinfo",          VIDEOPLAYER_HAS_INFO },
                                  { "trailer",          VIDEOPLAYER_TRAILER },
                                  { "videocodec",       VIDEOPLAYER_VIDEO_CODEC },
                                  { "videoresolution",  VIDEOPLAYER_VIDEO_RESOLUTION },
                                  { "videoaspect",      VIDEOPLAYER_VIDEO_ASPECT },
                                  { "videobitrate",     VIDEOPLAYER_VIDEO_BITRATE },
                                  { "audiocodec",       VIDEOPLAYER_AUDIO_CODEC },
                                  { "audiochannels",    VIDEOPLAYER_AUDIO_CHANNELS },
                                  { "audiobitrate",     VIDEOPLAYER_AUDIO_BITRATE },
                                  { "audiolanguage",    VIDEOPLAYER_AUDIO_LANG },
                                  { "hasteletext",      VIDEOPLAYER_HASTELETEXT },
                                  { "lastplayed",       VIDEOPLAYER_LASTPLAYED },
                                  { "playcount",        VIDEOPLAYER_PLAYCOUNT },
                                  { "hassubtitles",     VIDEOPLAYER_HASSUBTITLES },
                                  { "subtitlesenabled", VIDEOPLAYER_SUBTITLESENABLED },
                                  { "subtitleslanguage",VIDEOPLAYER_SUBTITLES_LANG },
                                  { "starttime",        VIDEOPLAYER_STARTTIME },
                                  { "endtime",          VIDEOPLAYER_ENDTIME },
                                  { "nexttitle",        VIDEOPLAYER_NEXT_TITLE },
                                  { "nextgenre",        VIDEOPLAYER_NEXT_GENRE },
                                  { "nextplot",         VIDEOPLAYER_NEXT_PLOT },
                                  { "nextplotoutline",  VIDEOPLAYER_NEXT_PLOT_OUTLINE },
                                  { "nextstarttime",    VIDEOPLAYER_NEXT_STARTTIME },
                                  { "nextendtime",      VIDEOPLAYER_NEXT_ENDTIME },
                                  { "nextduration",     VIDEOPLAYER_NEXT_DURATION },
                                  { "channelname",      VIDEOPLAYER_CHANNEL_NAME },
                                  { "channelnumberlabel", VIDEOPLAYER_CHANNEL_NUMBER },
                                  { "channelgroup",     VIDEOPLAYER_CHANNEL_GROUP },
                                  { "hasepg",           VIDEOPLAYER_HAS_EPG },
                                  { "parentalrating",   VIDEOPLAYER_PARENTAL_RATING },
                                  { "isstereoscopic",   VIDEOPLAYER_IS_STEREOSCOPIC },
                                  { "stereoscopicmode", VIDEOPLAYER_STEREOSCOPIC_MODE },
                                  { "canresumelivetv",  VIDEOPLAYER_CAN_RESUME_LIVE_TV },
                                  { "imdbnumber",       VIDEOPLAYER_IMDBNUMBER },
                                  { "episodename",      VIDEOPLAYER_EPISODENAME },
                                  { "dbid",             VIDEOPLAYER_DBID },
                                  { "uniqueid",         VIDEOPLAYER_UNIQUEID },
                                  { "tvshowdbid",       VIDEOPLAYER_TVSHOWDBID },
                                  { "audiostreamcount", VIDEOPLAYER_AUDIOSTREAMCOUNT },
                                  { "hdrtype",          VIDEOPLAYER_HDR_TYPE },
                                  { "art",              VIDEOPLAYER_ART},
                                  { "videoversionname", VIDEOPLAYER_VIDEOVERSION_NAME},
                                  { "hasvideoversions", VIDEOPLAYER_HAS_VIDEOVERSIONS}
};
// clang-format on

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_RetroPlayer RetroPlayer
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`RetroPlayer.VideoFilter`</b>,
///                  \anchor RetroPlayer_VideoFilter
///                  _string_,
///     @return The video filter of the currently-playing game.
///     The following values are possible:
///       - <b>`nearest`</b> (Nearest neighbor\, i.e. pixelate)
///       - <b>`linear`</b> (Bilinear filtering\, i.e. smooth blur)
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link RetroPlayer_VideoFilter `RetroPlayer.VideoFilter`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RetroPlayer.StretchMode`</b>,
///                  \anchor RetroPlayer_StretchMode
///                  _string_,
///     @return The stretch mode of the currently-playing game.
///     The following values are possible:
///       - <b>`normal`</b> (Show the game normally)
///       - <b>`4:3`</b> (Stretch to a 4:3 aspect ratio)
///       - <b>`fullscreen`</b> (Stretch to the full viewing area)
///       - <b>`original`</b> (Shrink to the original resolution)
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link RetroPlayer_StretchMode `RetroPlayer.StretchMode`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RetroPlayer.VideoRotation`</b>,
///                  \anchor RetroPlayer_VideoRotation
///                  _integer_,
///     @return The video rotation of the currently-playing game
///     in degrees counter-clockwise.
///     The following values are possible:
///       - <b>`0`</b>
///       - <b>`90`</b> (Shown in the GUI as 270 degrees)
///       - <b>`180`</b>
///       - <b>`270`</b> (Shown in the GUI as 90 degrees)
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link RetroPlayer_VideoRotation `RetroPlayer.VideoRotation`\endlink
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap retroplayer[] =
{
  { "videofilter",            RETROPLAYER_VIDEO_FILTER},
  { "stretchmode",            RETROPLAYER_STRETCH_MODE},
  { "videorotation",          RETROPLAYER_VIDEO_ROTATION},
};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Container Container
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`Container.HasFiles`</b>,
///                  \anchor Container_HasFiles
///                  _boolean_,
///     @return **True** if the container contains files.
///     <p>
///   }
///   \table_row3{   <b>`Container.HasFolders`</b>,
///                  \anchor Container_HasFolders
///                  _boolean_,
///     @return **True** if the container contains folders.
///     <p>
///   }
///   \table_row3{   <b>`Container.IsStacked`</b>,
///                  \anchor Container_IsStacked
///                  _boolean_,
///     @return **True** if the container is currently in stacked mode.
///     <p>
///   }
///   \table_row3{   <b>`Container.FolderPath`</b>,
///                  \anchor Container_FolderPath
///                  _string_,
///     @return The complete path of currently displayed folder.
///     <p>
///   }
///   \table_row3{   <b>`Container.FolderName`</b>,
///                  \anchor Container_FolderName
///                  _string_,
///     @return The top most folder in currently displayed folder.
///     <p>
///   }
///   \table_row3{   <b>`Container.PluginName`</b>,
///                  \anchor Container_PluginName
///                  _string_,
///     @return The current plugins base folder name.
///     <p>
///   }
///   \table_row3{   <b>`Container.PluginCategory`</b>,
///                  \anchor Container_PluginCategory
///                  _string_,
///     @return The current plugins category (set by the scripter).
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Container_PluginCategory `Container.PluginCategory`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Container.Viewmode`</b>,
///                  \anchor Container_Viewmode
///                  _string_,
///     @return The current viewmode (list\, icons etc).
///     <p>
///   }
///   \table_row3{   <b>`Container.ViewCount`</b>,
///                  \anchor Container_ViewCount
///                  _integer_,
///     @return The number of available skin view modes for the current container listing.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Container_ViewCount `Container.ViewCount`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Container.Totaltime`</b>,
///                  \anchor Container_Totaltime
///                  _string_,
///     @return The total time of all items in the current container.
///     <p>
///   }
///   \table_row3{   <b>`Container.TotalWatched`</b>,
///                  \anchor Container_TotalWatched
///                  _string_,
///     @return The number of watched items in the container.
///     @param id - [opt] if not supplied the current container will be used.
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link Container_TotalWatched `Container(id).TotalWatched`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Container.TotalUnWatched`</b>,
///                  \anchor Container_TotalUnWatched
///                  _string_,
///     @return The number of unwatched items in the container.
///     @param id - [opt] if not supplied the current container will be used.
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link Container_TotalUnWatched `Container(id).TotalUnWatched`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Container.HasThumb`</b>,
///                  \anchor Container_HasThumb
///                  _boolean_,
///     @return **True** if the current container you are in has a thumb assigned
///     to it.
///     <p>
///   }
///   \table_row3{   <b>`Container.SortOrder`</b>,
///                  \anchor Container_SortOrder
///                  _string_,
///     @return The current sort order (Ascending/Descending).
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link Container_SortOrder `Container.SortOrder`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Container.CanFilter`</b>,
///                  \anchor Container_CanFilter
///                  _boolean_,
///     @return **True** when the current container can be filtered.
///     <p>
///   }
///   \table_row3{   <b>`Container.CanFilterAdvanced`</b>,
///                  \anchor Container_CanFilterAdvanced
///                  _boolean_,
///     @return **True** when advanced filtering can be applied to the current container.
///     <p>
///   }
///   \table_row3{   <b>`Container.Filtered`</b>,
///                  \anchor Container_Filtered
///                  _boolean_,
///     @return **True** when a mediafilter is applied to the current container.
///     <p>
///   }
///   \table_row3{   <b>`Container.ShowPlot`</b>,
///                  \anchor Container_ShowPlot
///                  _string_,
///     @return The TV Show plot of the current container and can be used at
///     season and episode level.
///     <p>
///   }
///   \table_row3{   <b>`Container.ShowTitle`</b>,
///                  \anchor Container_ShowTitle
///                  _string_,
///     @return The TV Show title of the current container and can be used at
///     season and episode level.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Container_ShowTitle `Container.ShowTitle`\endlink
///     <p>
///   }
const infomap mediacontainer[] = {{ "hasfiles",         CONTAINER_HASFILES },
                                  { "hasfolders",       CONTAINER_HASFOLDERS },
                                  { "isstacked",        CONTAINER_STACKED },
                                  { "folderpath",       CONTAINER_FOLDERPATH },
                                  { "foldername",       CONTAINER_FOLDERNAME },
                                  { "pluginname",       CONTAINER_PLUGINNAME },
                                  { "plugincategory",   CONTAINER_PLUGINCATEGORY },
                                  { "viewmode",         CONTAINER_VIEWMODE },
                                  { "viewcount",        CONTAINER_VIEWCOUNT },
                                  { "totaltime",        CONTAINER_TOTALTIME },
                                  { "totalwatched",     CONTAINER_TOTALWATCHED },
                                  { "totalunwatched",   CONTAINER_TOTALUNWATCHED },
                                  { "hasthumb",         CONTAINER_HAS_THUMB },
                                  { "sortorder",        CONTAINER_SORT_ORDER },
                                  { "canfilter",        CONTAINER_CAN_FILTER },
                                  { "canfilteradvanced",CONTAINER_CAN_FILTERADVANCED },
                                  { "filtered",         CONTAINER_FILTERED },
                                  { "showplot",         CONTAINER_SHOWPLOT },
                                  { "showtitle",        CONTAINER_SHOWTITLE }};

/// \page modules__infolabels_boolean_conditions
///   \table_row3{   <b>`Container(id).OnNext`</b>,
///                  \anchor Container_OnNext
///                  _boolean_,
///     @return **True** if the container with id (or current container if id is
///     omitted) is moving to the next item. Allows views to be
///     custom-designed (such as 3D coverviews etc.)
///     <p>
///   }
///   \table_row3{   <b>`Container(id).OnScrollNext`</b>,
///                  \anchor Container_OnScrollNext
///                  _boolean_,
///     @return **True** if the container with id (or current container if id is
///     omitted) is scrolling to the next item. Differs from \ref Container_OnNext "OnNext" in that
///     \ref Container_OnNext "OnNext" triggers on movement even if there is no scroll involved.
///     <p>
///   }
///   \table_row3{   <b>`Container(id).OnPrevious`</b>,
///                  \anchor Container_OnPrevious
///                  _boolean_,
///     @return **True** if the container with id (or current container if id is
///     omitted) is moving to the previous item. Allows views to be
///     custom-designed (such as 3D coverviews etc).
///     <p>
///   }
///   \table_row3{   <b>`Container(id).OnScrollPrevious`</b>,
///                  \anchor Container_OnScrollPrevious
///                  _boolean_,
///     @return **True** if the container with id (or current container if id is
///     omitted) is scrolling to the previous item. Differs from \ref Container_OnPrevious "OnPrevious" in
///     that \ref Container_OnPrevious "OnPrevious" triggers on movement even if there is no scroll involved.
///     <p>
///   }
///   \table_row3{   <b>`Container(id).NumPages`</b>,
///                  \anchor Container_NumPages
///                  _integer_,
///     @return The number of pages in the container with given id. If no id is specified it
///     grabs the current container.
///     <p>
///   }
///   \table_row3{   <b>`Container(id).NumItems`</b>,
///                  \anchor Container_NumItems
///                  _integer_,
///     @return The number of items in the container or grouplist with given id excluding parent folder item.
///     @note If no id is specified it grabs the current container.
///     <p>
///   }
///   \table_row3{   <b>`Container(id).NumAllItems`</b>,
///                  \anchor Container_NumAllItems
///                  _integer_,
///     @return The number of all items in the container or grouplist with given id including parent folder item.
///     @note If no id is specified it grabs the current container.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link Container_NumAllItems `Container(id).NumAllItems`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Container(id).NumNonFolderItems`</b>,
///                  \anchor Container_NumNonFolderItems
///                  _integer_,
///     @return The Number of items in the container or grouplist with given id excluding all folder items.
///     @note **Example:** pvr recordings folders\, parent ".." folder).
///     If no id is specified it grabs the current container.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link Container_NumNonFolderItems `Container(id).NumNonFolderItems`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Container(id).CurrentPage`</b>,
///                  \anchor Container_CurrentPage
///                  _string_,
///     @return THe current page in the container with given id.
///     @note If no id is specified it grabs the current container.
///     <p>
///   }
///   \table_row3{   <b>`Container(id).CurrentItem`</b>,
///                  \anchor Container_CurrentItem
///                  _integer_,
///     @return The current item in the container or grouplist with given id.
///     @note If no id is specified it grabs the current container.
///     <p><hr>
///     @skinning_v15 **[New Infolabel]** \link Container_CurrentItem `Container(id).CurrentItem`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Container(id).Scrolling`</b>,
///                  \anchor Container_Scrolling
///                  _boolean_,
///     @return **True** if the user is currently scrolling through the container
///     with id (or current container if id is omitted).
///     @note This is slightly delayed from the actual scroll start. Use
///     \ref Container_OnScrollNext "Container(id).OnScrollNext" or
///     \ref Container_OnScrollPrevious "Container(id).OnScrollPrevious" to trigger animations
///     immediately on scroll.
///     <p>
///   }
///   \table_row3{   <b>`Container(id).HasNext`</b>,
///                  \anchor Container_HasNext
///                  _boolean_,
///     @return **True** if the container or textbox with id (id) has a next page.
///     <p>
///   }
///   \table_row3{   <b>`Container(id).HasParent`</b>,
///                  \anchor Container_HasParent
///                  _boolean_,
///     @return **True** when the container with given id contains a parent ('..') item.
///     @note If no id is specified it grabs the current container.
///     <p><hr>
///     @skinning_v16 **[New Boolean Condition]** \link Container_HasParent `Container.HasParent`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Container(id).HasPrevious`</b>,
///                  \anchor Container_HasPrevious
///                  _boolean_,
///     @return **True** if the container or textbox with id (id) has a previous page.
///     <p>
///   }
///   \table_row3{   <b>`Container(id).IsUpdating`</b>,
///                  \anchor Container_IsUpdating
///                  _boolean_,
///     @return **True** if the container with dynamic list content is currently updating.
///   }
const infomap container_bools[] ={{ "onnext",           CONTAINER_MOVE_NEXT },
                                  { "onprevious",       CONTAINER_MOVE_PREVIOUS },
                                  { "onscrollnext",     CONTAINER_SCROLL_NEXT },
                                  { "onscrollprevious", CONTAINER_SCROLL_PREVIOUS },
                                  { "numpages",         CONTAINER_NUM_PAGES },
                                  { "numitems",         CONTAINER_NUM_ITEMS },
                                  { "numnonfolderitems", CONTAINER_NUM_NONFOLDER_ITEMS },
                                  { "numallitems",      CONTAINER_NUM_ALL_ITEMS },
                                  { "currentpage",      CONTAINER_CURRENT_PAGE },
                                  { "currentitem",      CONTAINER_CURRENT_ITEM },
                                  { "scrolling",        CONTAINER_SCROLLING },
                                  { "hasnext",          CONTAINER_HAS_NEXT },
                                  { "hasparent",        CONTAINER_HAS_PARENT_ITEM },
                                  { "hasprevious",      CONTAINER_HAS_PREVIOUS },
                                  { "isupdating",       CONTAINER_ISUPDATING }};

/// \page modules__infolabels_boolean_conditions
///   \table_row3{   <b>`Container(id).Row`</b>,
///                  \anchor Container_Row
///                  _integer_,
///     @return The row number of the focused position in a panel container.
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link Container_Row `Container(id).Row`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Container(id).Row(parameter)`</b>,
///                  \anchor Container_Row_parameter
///                  _boolean_,
///     @return **True** if the row number of the focused position matches the specified parameter.
///     <p>
///   }
///   \table_row3{   <b>`Container(id).Column`</b>,
///                  \anchor Container_Column
///                  _integer_,
///     @return The column number of the focused position in a panel container.
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link Container_Column `Container(id).Column`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Container(id).Column(parameter)`</b>,
///                  \anchor Container_Column_parameter
///                  _boolean_,
///     @return **True** if the column number of the focused position matches the specified parameter.
///     <p>
///   }
///   \table_row3{   <b>`Container(id).Position`</b>,
///                  \anchor Container_Position
///                  _integer_,
///     @return The current focused position of container / grouplist (id) as a
///     numeric label.
///     <p><hr>
///     @skinning_v16 **[Infolabel Updated]** \link Container_Position `Container(id).Position`\endlink
///     now also returns the position for items inside a grouplist.
///     <p>
///   }
///   \table_row3{   <b>`Container(id).Position(parameter)`</b>,
///                  \anchor Container_Position_parameter
///                  _boolean_,
///     @return **True** if the container with id (or current container if id is omitted) is focused on the specified position.
///     <p>
///   }
///   \table_row3{   <b>`Container(id).SubItem(item_number)`</b>,
///                  \anchor Container_SubItem
///                  _boolean_,
///     @return **True** if the container with id (or current container if id is omitted) is focused on the specified subitem.
///     @note If no id is specified it grabs the current container.
///     <p>
///   }
///   \table_row3{   <b>`Container(id).HasFocus(item_number)`</b>,
///                  \anchor Container_HasFocus
///                  _boolean_,
///     @return **True** if the container with id (or current container if id is
///     omitted) has static content and is focused on the item with id
///     item_number.
///     <p>
///   }
///   \table_row3{   <b>`Container.SortMethod`</b>,
///                  \anchor Container_SortMethod
///                  _string_,
///     @return The current sort method (returns a localized value).
///     <p>
///   }
///   \table_row3{   <b>`Container.SortMethod(sortid)`</b>,
///                  \anchor Container_SortMethod_sortid
///                  _boolean_,
///     @return **True** if the current sort method matches the specified SortID (see \ref List_of_sort_methods "SortUtils").
///     <p>
///   }
const infomap container_ints[] = {{ "row",              CONTAINER_ROW },
                                  { "column",           CONTAINER_COLUMN },
                                  { "position",         CONTAINER_POSITION },
                                  { "subitem",          CONTAINER_SUBITEM },
                                  { "hasfocus",         CONTAINER_HAS_FOCUS },
                                  { "sortmethod",       CONTAINER_SORT_METHOD },
};

/// \page modules__infolabels_boolean_conditions
///   \table_row3{   <b>`Container.Property(addoncategory)`</b>,
///                  \anchor Container_Property_addoncategory
///                  _string_,
///     @return The current add-on category.
///     <p>
///   }
///   \table_row3{   <b>`Container.Property(reponame)`</b>,
///                  \anchor Container_Property_reponame
///                  _string_,
///     @return The current add-on repository name.
///     <p>
///   }
///   \table_row3{   <b>`Container.Content`</b>,
///                  \anchor Container_Content
///                  _string_,
///     @return The content of the current container.
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link Container_Content `Container.Content`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Container(id).ListItem(offset).Property`</b>,
///                  \anchor Container_ListItem_property
///                  _string_,
///     @return the property of the ListItem with a given offset.
///     @param offset - The offset for the listitem.
///     @note `Property` has to be replaced with `Label`\, `Label2`\, `Icon` etc.
///     @note **Example:** `Container(50).Listitem(2).Label `
///     <p>
///   }
///   \table_row3{   <b>`Container(id).ListItemNoWrap(offset).Property`</b>,
///                  \anchor Container_ListItemNoWrap
///                  _string_,
///     @return the same as \link Container_ListItem_property `Container(id).ListItem(offset).Property` \endlink
///     but it won't wrap.
///     @param offset - The offset for the listitem.
///     @note That means if the last item of a list is focused\, `ListItemNoWrap(1)`
///     will be empty while `ListItem(1)` will return the first item of the list.
///     `Property` has to be replaced with `Label`\, `Label2`\, `Icon` etc.
///     @note **Example:** `Container(50).ListitemNoWrap(1).Plot`
///     <p>
///   }
///   \table_row3{   <b>`Container(id).ListItemPosition(x).[infolabel]`</b>,
///                  \anchor Container_ListItemPosition
///                  _string_,
///     @return The infolabel for an item in a Container.
///     @param x - the position in the container relative to the cursor position.
///     @note **Example:** `Container(50).ListItemPosition(4).Genre`
///     <p>
///   }
///   \table_row3{   <b>`Container(id).ListItemAbsolute(x).[infolabel]`</b>,
///                  \anchor Container_ListItemAbsolute
///                  _string_,
///     @return The infolabel for an item in a Container.
///     @param x - the absolute position in the container.
///     @note **Example:** `Container(50).ListItemAbsolute(4).Genre`
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link Container_ListItemAbsolute `Container(id).ListItemAbsolute(x).[infolabel]`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Container.Content(parameter)`</b>,
///                  \anchor Container_Content_parameter
///                  _string_,
///     @return **True** if the current container you are in contains the following:
///       - <b>files</b>
///       - <b>songs</b>
///       - <b>artists</b>
///       - <b>albums</b>
///       - <b>movies</b>
///       - <b>tvshows</b>
///       - <b>seasons</b>
///       - <b>episodes</b>
///       - <b>musicvideos</b>
///       - <b>genres</b>
///       - <b>years</b>
///       - <b>actors</b>
///       - <b>playlists</b>
///       - <b>plugins</b>
///       - <b>studios</b>
///       - <b>directors</b>
///       - <b>sets</b>
///       - <b>tags</b>
///     @note These currently only work in the Video and Music
///     Library or unless a Plugin has set the value) also available are
///     Addons true when a list of add-ons is shown LiveTV true when a
///     htsp (tvheadend) directory is shown
///     <p>
///   }
///   \table_row3{   <b>`Container.Art(type)`</b>,
///                  \anchor Container_Art
///                  _string_,
///     @return The path to the art image file for the given type of the current container.
///     @param type - the art type to request.
///     @todo List of all art types
///     <p><hr>
///     @skinning_v16 **[Infolabel Updated]** \link Container_Art `Container.Art(type)`\endlink
///     <b>set.fanart</b> as possible type value.
///     @skinning_v15 **[New Infolabel]** \link Container_Art `Container.Art(type)`\endlink
///     <p>
///   }
///
const infomap container_str[]  = {{ "property",         CONTAINER_PROPERTY },
                                  { "content",          CONTAINER_CONTENT },
                                  { "art",              CONTAINER_ART }};

/// \page modules__infolabels_boolean_conditions
///   \table_row3{   <b>`Container.SortDirection(direction)`</b>,
///                  \anchor Container_SortDirection
///                  _boolean_,
///     @return **True** if the sort direction of a container equals direction.
///     @param direction - The direction to check. It can be:
///       - <b>ascending</b>
///       - <b>descending</b>
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_ListItem ListItem
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`ListItem.Thumb`</b>,
///                  \anchor ListItem_Thumb
///                  _string_,
///     @return The thumbnail (if it exists) of the currently selected item
///     in a list or thumb control.
///     @deprecated but still available\, returns
///     the same as \ref ListItem_Art_Type "ListItem.Art(thumb)"
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Icon`</b>,
///                  \anchor ListItem_Icon
///                  _string_,
///     @return The thumbnail (if it exists) of the currently selected item in a list or thumb control.
///     @note If no thumbnail image exists\, it will show the icon.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.ActualIcon`</b>,
///                  \anchor ListItem_ActualIcon
///                  _string_,
///     @return The icon of the currently selected item in a list or thumb control.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Overlay`</b>,
///                  \anchor ListItem_Overlay
///                  _string_,
///     @return The overlay icon status of the currently selected item in a list or thumb control.
///       - compressed file -- OverlayRAR.png
///       - watched -- OverlayWatched.png
///       - unwatched -- OverlayUnwatched.png
///       - locked -- OverlayLocked.png
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsFolder`</b>,
///                  \anchor ListItem_IsFolder
///                  _boolean_,
///     @return **True** if the current ListItem is a folder.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsPlaying`</b>,
///                  \anchor ListItem_IsPlaying
///                  _boolean_,
///     @return **True** if the current ListItem.* info labels and images are
///     currently Playing media.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsResumable`</b>,
///                  \anchor ListItem_IsResumable
///                  _boolean_,
///     @return **True** when the current ListItem has been partially played.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsCollection`</b>,
///                  \anchor ListItem_IsCollection
///                  _boolean_,
///     @return **True** when the current ListItem is a movie set.
///     <p><hr>
///     @skinning_v15 **[New Boolean Condition]** \link ListItem_IsCollection `ListItem.IsCollection`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsSelected`</b>,
///                  \anchor ListItem_IsSelected
///                  _boolean_,
///     @return **True** if the current ListItem is selected (f.e. currently playing
///     in playlist window).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.HasEpg`</b>,
///                  \anchor ListItem_HasEpg
///                  _boolean_,
///     @return **True** when the selected programme has epg info (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.HasTimer`</b>,
///                  \anchor ListItem_HasTimer
///                  _boolean_,
///     @return **True** when a recording timer has been set for the selected
///     programme (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsRecording`</b>,
///                  \anchor ListItem_IsRecording
///                  _boolean_,
///     @return **True** when the selected programme is being recorded (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsPlayable`</b>,
///                  \anchor ListItem_IsPlayable
///                  _boolean_,
///     @return **True** when the selected programme can be played (PVR)
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \link ListItem_IsPlayable `ListItem.IsPlayable`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.HasArchive`</b>,
///                  \anchor ListItem_HasArchive
///                  _boolean_,
///     @return **True** when the selected channel has a server-side back buffer (PVR)
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \link ListItem_HasArchive `ListItem.HasArchive`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsEncrypted`</b>,
///                  \anchor ListItem_IsEncrypted
///                  _boolean_,
///     @return **True** when the selected programme is encrypted (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsStereoscopic`</b>,
///                  \anchor ListItem_IsStereoscopic
///                  _boolean_,
///     @return **True** when the selected video is a 3D (stereoscopic) video.
///     <p><hr>
///     @skinning_v13 **[New Boolean Condition]** \link ListItem_IsStereoscopic `ListItem.IsStereoscopic`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(IsSpecial)`</b>,
///                  \anchor ListItem_Property_IsSpecial
///                  _boolean_,
///     @return **True** if the current Season/Episode is a Special.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(DateLabel)`</b>,
///                  \anchor ListItem_Property_DateLabel
///                  _boolean_,
///     @return **True** if the item is a date label\, returns false if the item is a time label.
///     @note Can be used in the rulerlayout of the epggrid control.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Addon.IsEnabled)`</b>,
///                  \anchor ListItem_Property_AddonIsEnabled
///                  _boolean_,
///     @return **True** when the selected addon is enabled (for use in the addon
///     info dialog only).
///     <p><hr>
///     @skinning_v17 **[Boolean Condition Updated]** \link ListItem_Property_AddonIsEnabled `ListItem.Property(Addon.IsEnabled)`\endlink
///     replaces `ListItem.Property(Addon.Enabled)`.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Addon.IsInstalled)`</b>,
///                  \anchor ListItem_Property_AddonIsInstalled
///                  _boolean_,
///     @return **True** when the selected addon is installed (for use in the addon
///     info dialog only).
///     <p><hr>
///     @skinning_v17 **[Boolean Condition Updated]** \link ListItem_Property_AddonIsInstalled `ListItem.Property(Addon.IsInstalled)`\endlink
///     replaces `ListItem.Property(Addon.Installed)`.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Addon.HasUpdate)`</b>,
///                  \anchor ListItem_Property_AddonHasUpdate
///                  _boolean_,
///     @return **True** when there's an update available for the selected addon.
///     <p><hr>
///     @skinning_v17 **[Boolean Condition Updated]** \link ListItem_Property_AddonHasUpdate `ListItem.Property(Addon.HasUpdate)`\endlink
///     replaces `ListItem.Property(Addon.UpdateAvail)`.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsAutoUpdateable`</b>,
///                  \anchor ListItem_IsAutoUpdateable
///                  _boolean_,
///     @return **True** if this add-on can be updated automatically.
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \link ListItem_IsAutoUpdateable `ListItem.IsAutoUpdateable`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Addon.IsFromOfficialRepo)`</b>,
///                  \anchor ListItem_Property_AddonIsFromOfficialRepo
///                  _boolean_,
///     @return **True** if this add-on is from an official repository.
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \link ListItem_Property_AddonIsFromOfficialRepo `ListItem.Property(Addon.IsFromOfficialRepo)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Addon.IsBinary)`</b>,
///                  \anchor ListItem_Property_AddonIsBinary
///                  _boolean_,
///     @return **True** if this add-on is a binary addon.
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \link ListItem_Property_AddonIsBinary `ListItem.Property(Addon.IsBinary)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Addon.IsUpdate)`</b>,
///                  \anchor ListItem_Property_AddonIsUpdate
///                  _boolean_,
///     @return **True** if this add-on is a valid update of an installed outdated add-on.
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \link ListItem_Property_AddonIsUpdate `ListItem.Property(Addon.IsUpdate)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Addon.ValidUpdateOrigin)`</b>,
///                  \anchor ListItem_Property_ValidUpdateOrigin
///                  _string_,
///     @return The origin string of a valid update for the addon. Empty string if there is no valid update available.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_Property_ValidUpdateOrigin `ListItem.Property(Addon.ValidUpdateOrigin)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Addon.ValidUpdateVersion)`</b>,
///                  \anchor ListItem_Property_ValidUpdateVersion
///                  _string_,
///     @return The version string of a valid update for the addon. Empty string if there is no valid update available.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_Property_ValidUpdateVersion `ListItem.Property(Addon.ValidUpdateVersion)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Label`</b>,
///                  \anchor ListItem_Label
///                  _string_,
///     @return The left label of the currently selected item in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Label2`</b>,
///                  \anchor ListItem_Label2
///                  _string_,
///     @return The right label of the currently selected item in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Title`</b>,
///                  \anchor ListItem_Title
///                  _string_,
///     @return The title of the currently selected song\, movie\, game in a container.
///     <p><hr>
///     @skinning_v18 **[Infolabel Updated]** \link ListItem_Title `ListItem.Title`\endlink extended
///     to support games
///     <p>
///   }
///   \table_row3{   <b>`ListItem.OriginalTitle`</b>,
///                  \anchor ListItem_OriginalTitle
///                  _string_,
///     @return The original title of the currently selected movie in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.SortLetter`</b>,
///                  \anchor ListItem_SortLetter
///                  _string_,
///     @return The first letter of the current file in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.TrackNumber`</b>,
///                  \anchor ListItem_TrackNumber
///                  _string_,
///     @return The track number of the currently selected song in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Artist`</b>,
///                  \anchor ListItem_Artist
///                  _string_,
///     @return The artist of the currently selected song in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AlbumArtist`</b>,
///                  \anchor ListItem_AlbumArtist
///                  _string_,
///     @return The artist of the currently selected album in a list.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Artist_Sortname)`</b>,
///                  \anchor ListItem_Property_Artist_Sortname
///                  _string_,
///     @return The sortname of the currently selected Artist.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_Property_Artist_Sortname `ListItem.Property(Artist_Sortname)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Artist_Type)`</b>,
///                  \anchor ListItem_Property_Artist_Type
///                  _string_,
///     @return The type of the currently selected Artist - person\, group\, orchestra\, choir etc.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_Property_Artist_Type `ListItem.Property(Artist_Type)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Artist_Gender)`</b>,
///                  \anchor ListItem_Property_Artist_Gender
///                  _string_,
///     @return The Gender of the currently selected Artist - male\, female\, other.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_Property_Artist_Gender `ListItem.Property(Artist_Gender)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Artist_Disambiguation)`</b>,
///                  \anchor ListItem_Property_Artist_Disambiguation
///                  _string_,
///     @return A Brief description of the currently selected Artist that differentiates them
///     from others with the same name.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_Property_Artist_Disambiguation `ListItem.Property(Artist_Disambiguation)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Artist_Born)`</b>,
///                  \anchor ListItem_Property_Artist_Born
///                  _string_,
///     @return The date of Birth of the currently selected Artist.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Artist_Died)`</b>,
///                  \anchor ListItem_Property_Artist_Died
///                  _string_,
///     @return The date of Death of the currently selected Artist.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Artist_Formed)`</b>,
///                  \anchor ListItem_Property_Artist_Formed
///                  _string_,
///     @return The formation date of the currently selected Band.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Artist_Disbanded)`</b>,
///                  \anchor ListItem_Property_Artist_Disbanded
///                  _string_,
///     @return The disbanding date of the currently selected Band.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Artist_YearsActive)`</b>,
///                  \anchor ListItem_Property_Artist_YearsActive
///                  _string_,
///     @return The years the currently selected artist has been active.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Artist_Instrument)`</b>,
///                  \anchor ListItem_Property_Artist_Instrument
///                  _string_,
///     @return The instruments played by the currently selected artist.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Artist_Description)`</b>,
///                  \anchor ListItem_Property_Artist_Description
///                  _string_,
///     @return A biography of the currently selected artist.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Artist_Mood)`</b>,
///                  \anchor ListItem_Property_Artist_Mood
///                  _string_,
///     @return The moods of the currently selected artist.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Artist_Style)`</b>,
///                  \anchor ListItem_Property_Artist_Style
///                  _string_,
///     @return The styles of the currently selected artist.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Artist_Genre)`</b>,
///                  \anchor ListItem_Property_Artist_Genre
///                  _string_,
///     @return The genre of the currently selected artist.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Album`</b>,
///                  \anchor ListItem_Album
///                  _string_,
///     @return The album of the currently selected song in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Album_Mood)`</b>,
///                  \anchor ListItem_Property_Album_Mood
///                  _string_,
///     @return The moods of the currently selected Album.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Album_Style)`</b>,
///                  \anchor ListItem_Property_Album_Style
///                  _string_,
///     @return The styles of the currently selected Album.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Album_Theme)`</b>,
///                  \anchor ListItem_Property_Album_Theme
///                  _string_,
///     @return The themes of the currently selected Album.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Album_Type)`</b>,
///                  \anchor ListItem_Property_Album_Type
///                  _string_,
///     @return The Album Type (e.g. compilation\, enhanced\, explicit lyrics) of
///     the currently selected Album.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Album_Label)`</b>,
///                  \anchor ListItem_Property_Album_Label
///                  _string_,
///     @return The record label of the currently selected Album.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Album_Description)`</b>,
///                  \anchor ListItem_Property_Album_Description
///                  _string_,
///     @return A review of the currently selected Album.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Album_Totaldiscs)`</b>,
///                  \anchor ListItem_Property_Album_Totaldiscs
///                  _string_,
///     @return The total number of discs belonging to an album.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem.Property(Album_Totaldiscs) `ListItem.Property(Album_Totaldiscs)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Album_Isboxset)`</b>,
///                  \anchor ListItem_Property_Album_Isboxset
///                  _string_,
///     @return **True** if the album is a boxset.
///     <p><hr>
///     @skinning_v19 **[New Infobool]** \link ListItem.Property(Album_Isboxset) `ListItem.Property(Album_Isboxset)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Album_Duration)`</b>,
///                  \anchor ListItem_Property_Album_Duration
///                  _string_,
///     @return The duration of the album in HH:MM:SS.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_Property_Album_Duration `ListItem.Property(Album_Duration)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.DiscNumber`</b>,
///                  \anchor ListItem_DiscNumber
///                  _string_,
///     @return The disc number of the currently selected song in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Year`</b>,
///                  \anchor ListItem_Year
///                  _string_,
///     @return The year of the currently selected song\, album\, movie\, game  in a
///     container.
///     <p><hr>
///     @skinning_v18 **[Infolabel Updated]** \link ListItem_Title `ListItem.Title`\endlink extended
///     to support games
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Premiered`</b>,
///                  \anchor ListItem_Premiered
///                  _string_,
///     @return The release/aired date of the currently selected episode\, show\,
///     movie or EPG item in a container.
///     <p><hr>
///     @skinning_v15 **[Infolabel Updated]** \link ListItem_Premiered `ListItem.Premiered`\endlink
///     now also available for EPG items.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Genre`</b>,
///                  \anchor ListItem_Genre
///                  _string_,
///     @return The genre of the currently selected song\, album or movie in a
///     container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Contributors`</b>,
///                  \anchor ListItem_Contributors
///                  _string_,
///     @return The list of all people who've contributed to the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Contributors `ListItem.Contributors`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.ContributorAndRole`</b>,
///                  \anchor ListItem_ContributorAndRole
///                  _string_,
///     @return The list of all people and their role who've contributed to the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_ContributorAndRole `ListItem.ContributorAndRole`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Director`</b>,
///                  \anchor ListItem_Director
///                  _string_,
///     @return The director of the currently selected movie in a container.
///     <p><hr>
///     @skinning_v15 **[Infolabel Updated]** \link ListItem_Director `ListItem.Director`\endlink
///     also supports EPG.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Country`</b>,
///                  \anchor ListItem_Country
///                  _string_,
///     @return The production country of the currently selected movie in a
///     container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Episode`</b>,
///                  \anchor ListItem_Episode
///                  _string_,
///     @return The episode number value for the currently selected episode. It
///     also returns the number of total\, watched or unwatched episodes for the
///     currently selected tvshow or season\, based on the the current watched
///     filter.
///     <p><hr>
///     @skinning_v15 **[Infolabel Updated]** \link ListItem_Episode `ListItem.Episode`\endlink
///     also supports EPG.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Season`</b>,
///                  \anchor ListItem_Season
///                  _string_,
///     @return The season value for the currently selected tvshow.
///     <p><hr>
///     @skinning_v15 **[Infolabel Updated]** \link ListItem_Season `ListItem.Season`\endlink
///     also supports EPG.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.TVShowTitle`</b>,
///                  \anchor ListItem_TVShowTitle
///                  _string_,
///     @return The name value for the currently selected tvshow in the season and
///     episode depth of the video library.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(TotalSeasons)`</b>,
///                  \anchor ListItem_Property_TotalSeasons
///                  _string_,
///     @return The total number of seasons for the currently selected tvshow.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(TotalEpisodes)`</b>,
///                  \anchor ListItem_Property_TotalEpisodes
///                  _string_,
///     @return the total number of episodes for the currently selected tvshow or
///     season.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(WatchedEpisodes)`</b>,
///                  \anchor ListItem_Property_WatchedEpisodes
///                  _string_,
///     @return The number of watched episodes for the currently selected tvshow
///     or season.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(UnWatchedEpisodes)`</b>,
///                  \anchor ListItem_Property_UnWatchedEpisodes
///                  _string_,
///     @return The number of unwatched episodes for the currently selected tvshow
///     or season.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(NumEpisodes)`</b>,
///                  \anchor ListItem_Property_NumEpisodes
///                  _string_,
///     @return The number of total\, watched or unwatched episodes for the
///     currently selected tvshow or season\, based on the the current watched filter.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(WatchedEpisodePercent)`</b>,
///                  \anchor ListItem_Property_WatchedEpisodePercent
///                  _string_,
///     @return The percentage of watched episodes in the tvshow (watched/total*100) or season.
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link ListItem_Property_WatchedEpisodePercent `ListItem.Property(WatchedEpisodePercent)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureAperture`</b>,
///                  \anchor ListItem_PictureAperture
///                  _string_,
///     @return The F-stop used to take the selected picture.
///     @note This is the value of the EXIF FNumber tag (hex code 0x829D).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureAuthor`</b>,
///                  \anchor ListItem_PictureAuthor
///                  _string_,
///     @return The name of the person involved in writing about the selected picture.
///     @note This is the value of the IPTC Writer tag (hex code 0x7A).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureAuthor `ListItem.PictureAuthor`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureByline`</b>,
///                  \anchor ListItem_PictureByline
///                  _string_,
///     @return The name of the person who created the selected picture.
///     @note This is the value of the IPTC Byline tag (hex code 0x50).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureByline `ListItem.PictureByline`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureBylineTitle`</b>,
///                  \anchor ListItem_PictureBylineTitle
///                  _string_,
///     @return The title of the person who created the selected picture.
///     @note This is the value of the IPTC BylineTitle tag (hex code 0x55).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureBylineTitle `ListItem.PictureBylineTitle`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureCamMake`</b>,
///                  \anchor ListItem_PictureCamMake
///                  _string_,
///     @return The manufacturer of the camera used to take the selected picture.
///     @note This is the value of the EXIF Make tag (hex code 0x010F).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureCamModel`</b>,
///                  \anchor ListItem_PictureCamModel
///                  _string_,
///     @return The manufacturer's model name or number of the camera used to take
///     the selected picture.
///     @note This is the value of the EXIF Model tag (hex code 0x0110).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureCaption`</b>,
///                  \anchor ListItem_PictureCaption
///                  _string_,
///     @return A description of the selected picture.
///     @note This is the value of the IPTC Caption tag (hex code 0x78).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureCategory`</b>,
///                  \anchor ListItem_PictureCategory
///                  _string_,
///     @return The subject of the selected picture as a category code.
///     @note This is the value of the IPTC Category tag (hex code 0x0F).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureCategory `ListItem.PictureCategory`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureCCDWidth`</b>,
///                  \anchor ListItem_PictureCCDWidth
///                  _string_,
///     @return The width of the CCD in the camera used to take the selected
///     picture.
///     @note This is calculated from three EXIF tags (0xA002 * 0xA210 / 0xA20e).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureCCDWidth `ListItem.PictureCCDWidth`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureCity`</b>,
///                  \anchor ListItem_PictureCity
///                  _string_,
///     @return The city where the selected picture was taken.
///     @note This is the value of the IPTC City tag (hex code 0x5A).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureCity `ListItem.PictureCity`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureColour`</b>,
///                  \anchor ListItem_PictureColour
///                  _string_,
///     @return Whether the selected picture is "Colour" or "Black and White".
///     <p>
///     @deprecated \link ListItem_PictureColour `ListItem.PictureColour`\endlink is deprecated and will be removed in future Kodi versions
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureColour `ListItem.PictureColour`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureComment`</b>,
///                  \anchor ListItem_PictureComment
///                  _string_,
///     @return A description of the selected picture.
///     @note This is the value of the
///     EXIF User Comment tag (hex code 0x9286). This is the same value as
///     \ref Slideshow_SlideComment "Slideshow.SlideComment".
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureCopyrightNotice`</b>,
///                  \anchor ListItem_PictureCopyrightNotice
///                  _string_,
///     @return The copyright notice of the selected picture.
///     @note This is the value of the IPTC Copyright tag (hex code 0x74).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureCopyrightNotice `ListItem.PictureCopyrightNotice`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureCountry`</b>,
///                  \anchor ListItem_PictureCountry
///                  _string_,
///     @return The full name of the country where the selected picture was taken.
///     @note This is the value of the IPTC CountryName tag (hex code 0x65).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureCountry `ListItem.PictureCountry`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureCountryCode`</b>,
///                  \anchor ListItem_PictureCountryCode
///                  _string_,
///     @return The country code of the country where the selected picture was
///     taken.
///     @note This is the value of the IPTC CountryCode tag (hex code 0x64).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureCountryCode `ListItem.PictureCountryCode`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureCredit`</b>,
///                  \anchor ListItem_PictureCredit
///                  _string_,
///     @return Who provided the selected picture.
///     @note This is the value of the IPTC Credit tag (hex code 0x6E).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureCredit `ListItem.PictureCredit`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureDate`</b>,
///                  \anchor ListItem_PictureDate
///                  _string_,
///     @return The localized date of the selected picture. The short form of the
///     date is used.
///     @note The value of the EXIF DateTimeOriginal tag (hex code 0x9003)
///     is preferred. If the DateTimeOriginal tag is not found\, the value of
///     DateTimeDigitized (hex code 0x9004) or of DateTime (hex code 0x0132) might
///     be used.
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureDate `ListItem.PictureDate`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureDatetime`</b>,
///                  \anchor ListItem_PictureDatetime
///                  _string_,
///     @return The date/timestamp of the selected picture. The localized short form
///     of the date and time is used.
///     @note The value of the EXIF DateTimeOriginal tag (hex code 0x9003) is preferred.
///     If the DateTimeOriginal tag is not found\, the value of DateTimeDigitized
///     (hex code 0x9004) or of DateTime (hex code 0x0132) might be used.
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureDatetime `ListItem.PictureDatetime`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureDesc`</b>,
///                  \anchor ListItem_PictureDesc
///                  _string_,
///     @return A short description of the selected picture. The SlideComment\,
///     EXIFComment\, or Caption values might contain a longer description.
///     @note This is the value of the EXIF ImageDescription tag (hex code 0x010E).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureDigitalZoom`</b>,
///                  \anchor ListItem_PictureDigitalZoom
///                  _string_,
///     @return The digital zoom ratio when the selected picture was taken.
///     @note This is the value of the EXIF DigitalZoomRatio tag (hex code 0xA404).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureDigitalZoom `ListItem.PictureDigitalZoom`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureExpMode`</b>,
///                  \anchor ListItem_PictureExpMode
///                  _string_,
///     @return The exposure mode of the selected picture.
///     The possible values are:
///       - <b>"Automatic"</b>
///       - <b>"Manual"</b>
///       - <b>"Auto bracketing"</b>
///     @note This is the value of the EXIF ExposureMode tag (hex code 0xA402).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureExposure`</b>,
///                  \anchor ListItem_PictureExposure
///                  _string_,
///     @return The class of the program used by the camera to set exposure when
///     the selected picture was taken. Values include:
///      -  <b>"Manual"</b>
///      -  <b>"Program (Auto)"</b>
///      -  <b>"Aperture priority (Semi-Auto)"</b>
///      -  <b>"Shutter priority (semi-auto)"</b>
///      -  etc
///     @note This is the value of the EXIF ExposureProgram tag (hex code 0x8822).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureExposure `ListItem.PictureExposure`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureExposureBias`</b>,
///                  \anchor ListItem_PictureExposureBias
///                  _string_,
///     @return The exposure bias of the selected picture.
///     Typically this is a number between -99.99 and 99.99.
///     @note This is the value of the EXIF ExposureBiasValue tag (hex code 0x9204).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureExposureBias `ListItem.PictureExposureBias`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureExpTime`</b>,
///                  \anchor ListItem_PictureExpTime
///                  _string_,
///     @return The exposure time of the selected picture\, in seconds.
///     @note This is the value of the EXIF ExposureTime tag (hex code 0x829A).
///     If the ExposureTime tag is not found\, the ShutterSpeedValue tag (hex code 0x9201)
///     might be used.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureFlashUsed`</b>,
///                  \anchor ListItem_PictureFlashUsed
///                  _string_,
///     @return The status of flash when the selected picture was taken. The value
///     will be either "Yes" or "No"\, and might include additional information.
///     @note This is the value of the EXIF Flash tag (hex code 0x9209).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureFlashUsed `ListItem.PictureFlashUsed`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureFocalLen`</b>,
///                  \anchor ListItem_PictureFocalLen
///                  _string_,
///     @return The lens focal length of the selected picture.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureFocusDist`</b>,
///                  \anchor ListItem_PictureFocusDist
///                  _string_,
///     @return The focal length of the lens\, in mm.
///     @note This is the value of the EXIF FocalLength tag (hex code 0x920A).
///   }
///   \table_row3{   <b>`ListItem.PictureGPSLat`</b>,
///                  \anchor ListItem_PictureGPSLat
///                  _string_,
///     @return The latitude where the selected picture was taken (degrees\,
///     minutes\, seconds North or South).
///     @note This is the value of the EXIF GPSInfo.GPSLatitude and GPSInfo.GPSLatitudeRef tags.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureGPSLon`</b>,
///                  \anchor ListItem_PictureGPSLon
///                  _string_,
///     @return The longitude where the selected picture was taken (degrees\,
///     minutes\, seconds East or West).
///     @note This is the value of the EXIF GPSInfo.GPSLongitude and GPSInfo.GPSLongitudeRef tags.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureGPSAlt`</b>,
///                  \anchor ListItem_PictureGPSAlt
///                  _string_,
///     @return The altitude in meters where the selected picture was taken.
///     @note This is the value of the EXIF GPSInfo.GPSAltitude tag.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureHeadline`</b>,
///                  \anchor ListItem_PictureHeadline
///                  _string_,
///     @return A synopsis of the contents of the selected picture.
///     @note This is the value of the IPTC Headline tag (hex code 0x69).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureHeadline `ListItem.PictureHeadline`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureImageType`</b>,
///                  \anchor ListItem_PictureImageType
///                  _string_,
///     @return The color components of the selected picture.
///     @note This is the value of the IPTC ImageType tag (hex code 0x82).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureImageType `ListItem.PictureImageType`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureIPTCDate`</b>,
///                  \anchor ListItem_PictureIPTCDate
///                  _string_,
///     @return The date when the intellectual content of the selected picture was
///     created\, rather than when the picture was created.
///     @note This is the value of the IPTC DateCreated tag (hex code 0x37).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureIPTCDate `ListItem.PictureIPTCDate`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureIPTCTime`</b>,
///                  \anchor ListItem_PictureIPTCTime
///                  _string_,
///     @return The time when the intellectual content of the selected picture was
///     created\, rather than when the picture was created.
///     @note This is the value of the IPTC TimeCreated tag (hex code 0x3C).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureIPTCTime `ListItem.PictureIPTCTime`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureISO`</b>,
///                  \anchor ListItem_PictureISO
///                  _string_,
///     @return The ISO speed of the camera when the selected picture was taken.
///     @note This is the value of the EXIF ISOSpeedRatings tag (hex code 0x8827).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureKeywords`</b>,
///                  \anchor ListItem_PictureKeywords
///                  _string_,
///     @return The keywords assigned to the selected picture.
///     @note This is the value of the IPTC Keywords tag (hex code 0x19).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureLightSource`</b>,
///                  \anchor ListItem_PictureLightSource
///                  _string_,
///     @return The kind of light source when the picture was taken. Possible
///     values include:
///       - <b>"Daylight"</b>
///       - <b>"Fluorescent"</b>
///       - <b>"Incandescent"</b>
///       - etc
///     @note This is the value of the EXIF LightSource tag (hex code 0x9208).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureLightSource `ListItem.PictureLightSource`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureLongDate`</b>,
///                  \anchor ListItem_PictureLongDate
///                  _string_,
///     @return Only the localized date of the selected picture. The long form of
///     the date is used.
///     @note The value of the EXIF DateTimeOriginal tag (hex code
///     0x9003) is preferred. If the DateTimeOriginal tag is not found\, the
///     value of DateTimeDigitized (hex code 0x9004) or of DateTime (hex code
///     0x0132) might be used.
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureLongDate `ListItem.PictureLongDate`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureLongDatetime`</b>,
///                  \anchor ListItem_PictureLongDatetime
///                  _string_,
///     @return The date/timestamp of the selected picture. The localized long
///     form of the date and time is used.
///     @note The value of the EXIF DateTimeOriginal
///     tag (hex code 0x9003) is preferred. if the DateTimeOriginal tag is not
///     found\, the value of DateTimeDigitized (hex code 0x9004) or of DateTime
///     (hex code 0x0132) might be used.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureMeteringMode`</b>,
///                  \anchor ListItem_PictureMeteringMode
///                  _string_,
///     @return The metering mode used when the selected picture was taken. The
///     possible values are:
///      - <b>"Center weight"</b>
///      - <b>"Spot"</b>
///      - <b>"Matrix"</b>
///     @note This is the value of the EXIF MeteringMode tag (hex code 0x9207).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureMeteringMode `ListItem.PictureMeteringMode`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureObjectName`</b>,
///                  \anchor ListItem_PictureObjectName
///                  _string_,
///     @return A shorthand reference for the selected picture.
///     @note This is the value of the IPTC ObjectName tag (hex code 0x05).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureObjectName `ListItem.PictureObjectName`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureOrientation`</b>,
///                  \anchor ListItem_PictureOrientation
///                  _string_,
///     @return The orientation of the selected picture. Possible values are:
///       - <b>"Top Left"</b>
///       - <b>"Top Right"</b>
///       - <b>"Left Top"</b>
///       - <b>"Right Bottom"</b>
///       - etc
///     @note This is the value of the EXIF Orientation tag (hex code 0x0112).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureOrientation `ListItem.PictureOrientation`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PicturePath`</b>,
///                  \anchor ListItem_PicturePath
///                  _string_,
///     @return The filename and path of the selected picture.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureProcess`</b>,
///                  \anchor ListItem_PictureProcess
///                  _string_,
///     @return The process used to compress the selected picture.
///     <p>
///     @deprecated \link ListItem_PictureProcess `ListItem.PictureProcess`\endlink is deprecated and will be removed in future Kodi versions
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureProcess `ListItem.PictureProcess`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureReferenceService`</b>,
///                  \anchor ListItem_PictureReferenceService
///                  _string_,
///     @return The Service Identifier of a prior envelope to which the selected
///     picture refers.
///     @note This is the value of the IPTC ReferenceService tag (hex code 0x2D).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureReferenceService `ListItem.PictureReferenceService`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureResolution`</b>,
///                  \anchor ListItem_PictureResolution
///                  _string_,
///     @return The dimensions of the selected picture.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureSource`</b>,
///                  \anchor ListItem_PictureSource
///                  _string_,
///     @return The original owner of the selected picture.
///     @note This is the value of the IPTC Source tag (hex code 0x73).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureSource `ListItem.PictureSource`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureSpecialInstructions`</b>,
///                  \anchor ListItem_PictureSpecialInstructions
///                  _string_,
///     @return Other editorial instructions concerning the use of the selected
///     picture.
///     @note This is the value of the IPTC SpecialInstructions tag (hex code 0x28).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureSpecialInstructions `ListItem.PictureSpecialInstructions`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureState`</b>,
///                  \anchor ListItem_PictureState
///                  _string_,
///     @return The State/Province where the selected picture was taken.
///     @note This is the value of the IPTC ProvinceState tag (hex code 0x5F).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureState `ListItem.PictureState`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureSublocation`</b>,
///                  \anchor ListItem_PictureSublocation
///                  _string_,
///     @return The location within a city where the selected picture was taken -
///     might indicate the nearest landmark.
///     @note This is the value of the IPTC SubLocation tag (hex code 0x5C).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureSublocation `ListItem.PictureSublocation`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureSupplementalCategories`</b>,
///                  \anchor ListItem_PictureSupplementalCategories
///                  _string_,
///     @return A supplemental category codes to further refine the subject of the
///     selected picture.
///     @note This is the value of the IPTC SuppCategory tag (hex code 0x14).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureSupplementalCategories `ListItem.PictureSupplementalCategories`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureTransmissionReference`</b>,
///                  \anchor ListItem_PictureTransmissionReference
///                  _string_,
///     @return A code representing the location of original transmission of the
///     selected picture.
///     @note This is the value of the IPTC TransmissionReference tag (hex code 0x67).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureTransmissionReference `ListItem.PictureTransmissionReference`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureUrgency`</b>,
///                  \anchor ListItem_PictureUrgency
///                  _string_,
///     @return The urgency of the selected picture. Values are 1-9.
///     @note The "1" is most urgent. Some image management programs use urgency to indicate
///     picture rating\, where urgency "1" is 5 stars and urgency "5" is 1 star.
///     Urgencies 6-9 are not used for rating. This is the value of the IPTC
///     Urgency tag (hex code 0x0A).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureUrgency `ListItem.PictureUrgency`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PictureWhiteBalance`</b>,
///                  \anchor ListItem_PictureWhiteBalance
///                  _string_,
///     @return The white balance mode set when the selected picture was taken.
///     The possible values are:
///       - <b>"Manual"</b>
///       - <b>"Auto"</b>
///     @note This is the value of the EXIF WhiteBalance tag (hex code 0xA403).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_PictureWhiteBalance `ListItem.PictureWhiteBalance`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.FileName`</b>,
///                  \anchor ListItem_FileName
///                  _string_,
///     @return The filename of the currently selected song or movie in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Path`</b>,
///                  \anchor ListItem_Path
///                  _string_,
///     @return The complete path of the currently selected song or movie in a
///     container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.FolderName`</b>,
///                  \anchor ListItem_FolderName
///                  _string_,
///     @return The top most folder of the path of the currently selected song or
///     movie in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.FolderPath`</b>,
///                  \anchor ListItem_FolderPath
///                  _string_,
///     @return The complete path of the currently selected song or movie in a
///     container (without user details).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.FileNameAndPath`</b>,
///                  \anchor ListItem_FileNameAndPath
///                  _string_,
///     @return The full path with filename of the currently selected song or
///     movie in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.FileExtension`</b>,
///                  \anchor ListItem_FileExtension
///                  _string_,
///     @return The file extension (without leading dot) of the currently selected
///     item in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.FileNameNoExtension`</b>,
///                  \anchor ListItem_FileName_No_Extension
///                  _string_,
///     @return The filename without extension of the currently selected
///     item in a container.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_FileName_No_Extension `ListItem.FileNameNoExtension`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Date`</b>,
///                  \anchor ListItem_Date
///                  _string_,
///     @return The file date of the currently selected song or movie in a
///     container / Aired date of an episode / Day\, start time and end time of
///     current selected TV programme (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.DateTime`</b>,
///                  \anchor ListItem_DateTime
///                  _string_,
///     @return The date and time a certain event happened (event log).
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link ListItem_DateTime `ListItem.DateTime`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.DateAdded`</b>,
///                  \anchor ListItem_DateAdded
///                  _string_,
///     @return The date the currently selected item was added to the
///     library / Date and time of an event in the EventLog window.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Size`</b>,
///                  \anchor ListItem_Size
///                  _string_,
///     @return The file size of the currently selected song or movie in a
///     container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Rating([name])`</b>,
///                  \anchor ListItem_Rating
///                  _string_,
///     @return The scraped rating of the currently selected item in a container (1-10).
///     @param name - [opt] you can specify the name of the scraper to retrieve a specific rating\,
///     for use in dialogvideoinfo.xml.
///     <p><hr>
///     @skinning_v18 **[Infolabel Updated]** \link ListItem_Rating `ListItem.Rating([name])`\endlink replaces
///     the old `ListItem.Ratings([name])` infolabel.
///     @skinning_v17 **[New Infolabel]** \link ListItem_Rating `ListItem.Ratings([name])`\endlink
///     @skinning_v17 **[Infolabel Updated]** \link ListItem_Rating `ListItem.Ratings`\endlink
///     for songs it's now the scraped rating.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Set`</b>,
///                  \anchor ListItem_Set
///                  _string_,
///     @return The name of the set the movie is part of.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Set `ListItem.Set`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.SetId`</b>,
///                  \anchor ListItem_SetId
///                  _string_,
///     @return The id of the set the movie is part of.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_SetId `ListItem.SetId`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Status`</b>,
///                  \anchor ListItem_Status
///                  _string_,
///     @return One of the following status:
///       - <b>"returning series"</b>
///       - <b>"in production"</b>
///       - <b>"planned"</b>
///       - <b>"cancelled"</b>
///       - <b>"ended"</b>
///     <p>
///     @note For use with tv shows.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Status `ListItem.Status`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.EndTimeResume`</b>,
///                  \anchor ListItem_EndTimeResume
///                  _string_,
///     @return Returns the time a video will end if you resume it\, instead of playing it from the beginning.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_EndTimeResume `ListItem.EndTimeResume`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.UserRating`</b>,
///                  \anchor ListItem_UserRating
///                  _string_,
///     @return The user rating of the currently selected item in a container (1-10).
///     <p><hr>
///     @skinning_v17 **[Infolabel Updated]** \link ListItem_UserRating `ListItem.UserRating`\endlink
///     now available for albums/songs.
///     @skinning_v16 **[New Infolabel]** \link ListItem_UserRating `ListItem.UserRating`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Votes([name])`</b>,
///                  \anchor ListItem_Votes
///                  _string_,
///     @return The scraped votes of the currently selected movie in a container.
///     @param name - [opt] you can specify the name of the scraper to retrieve specific votes\,
///     for use in `dialogvideoinfo.xml`.
///     <p><hr>
///     @skinning_v17 **[Infolabel Updated]** \link ListItem_Votes `ListItem.Votes([name])`\endlink
///     add optional param <b>name</b> to specify the scrapper.
///     @skinning_v13 **[New Infolabel]** \link ListItem_Votes `ListItem.Votes`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.RatingAndVotes([name])`</b>,
///                  \anchor ListItem_RatingAndVotes
///                  _string_,
///     @return The scraped rating and votes of the currently selected movie in a
///     container (1-10).
///     @param name - [opt] you can specify the name of the scraper to retrieve specific votes\,
///     for use in `dialogvideoinfo.xml`.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_RatingAndVotes `ListItem.RatingAndVotes([name])`\endlink
///     @skinning_v17 **[Infolabel Updated]** \link ListItem_RatingAndVotes `ListItem.RatingAndVotes`\endlink
///     now available for albums/songs.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Mood`</b>,
///                  \anchor ListItem_Mood
///                  _string_,
///     @return The mood of the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Mood `ListItem.Mood`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Mpaa`</b>,
///                  \anchor ListItem_Mpaa
///                  _string_,
///     @return The MPAA rating of the currently selected movie in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.ProgramCount`</b>,
///                  \anchor ListItem_ProgramCount
///                  _string_,
///     @return The number of times an xbe has been run from "my programs".
///     @todo description might be outdated
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Duration`</b>,
///                  \anchor ListItem_Duration
///                  _string_,
///     @return The duration of the currently selected item in a container
///     in the format <b>hh:mm:ss</b>.
///     @note <b>hh:</b> will be omitted if hours value is zero.
///     <p><hr>
///     @skinning_v18 **[Infolabel Updated]** \link ListItem_Duration `ListItem.Duration`\endlink will
///     return <b>hh:mm:ss</b> instead of the duration in minutes.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Duration(format)`</b>,
///                  \anchor ListItem_Duration_format
///                  _string_,
///     @return The duration of the currently selected item in a container in
///     different formats.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.DBTYPE`</b>,
///                  \anchor ListItem_DBTYPE
///                  _string_,
///     @return The database type of the \ref ListItem_DBID "ListItem.DBID" for videos (movie\, set\,
///     genre\, actor\, tvshow\, season\, episode). It does not return any value
///     for the music library.
///     @note Beware with season\, the "*all seasons" entry does
///     give a DBTYPE "season" and a DBID\, but you can't get the details of that
///     entry since it's a virtual entry in the Video Library.
///     <p><hr>
///     @skinning_v17 **[Infolabel Updated]** \link ListItem_DBTYPE `ListItem.DBTYPE`\endlink
///     now available in the music library.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.DBID`</b>,
///                  \anchor ListItem_DBID
///                  _string_,
///     @return The database id of the currently selected listitem in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Appearances`</b>,
///                  \anchor ListItem_Appearances
///                  _string_,
///     @return The number of movies featuring the selected actor / directed by the selected director.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Appearances `ListItem.Appearances`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Cast`</b>,
///                  \anchor ListItem_Cast
///                  _string_,
///     @return A concatenated string of cast members of the currently selected
///     movie\, for use in dialogvideoinfo.xml.
///     <p><hr>
///     @skinning_v15 **[Infolabel Updated]** \link ListItem_Cast `ListItem.Cast`\endlink
///     also supports EPG.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.CastAndRole`</b>,
///                  \anchor ListItem_CastAndRole
///                  _string_,
///     @return A concatenated string of cast members and roles of the currently
///     selected movie\, for use in dialogvideoinfo.xml.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Studio`</b>,
///                  \anchor ListItem_Studio
///                  _string_,
///     @return The studio of current selected Music Video in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Top250`</b>,
///                  \anchor ListItem_Top250
///                  _string_,
///     @return The IMDb top250 position of the currently selected listitem in a
///     container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Trailer`</b>,
///                  \anchor ListItem_Trailer
///                  _string_,
///     @return The full trailer path with filename of the currently selected
///     movie in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Writer`</b>,
///                  \anchor ListItem_Writer
///                  _string_,
///     @return The name of Writer of current Video in a container.
///     <p><hr>
///     @skinning_v15 **[Infolabel Updated]** \link ListItem_Writer `ListItem.Writer`\endlink
///     also supports EPG.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Tag`</b>,
///                  \anchor ListItem_Tag
///                  _string_,
///     @return The summary of current Video in a container.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Tag `ListItem.Tag`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Tagline`</b>,
///                  \anchor ListItem_Tagline
///                  _string_,
///     @return A Small Summary of current Video in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PlotOutline`</b>,
///                  \anchor ListItem_PlotOutline
///                  _string_,
///     @return A small Summary of current Video in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Plot`</b>,
///                  \anchor ListItem_Plot
///                  _string_,
///     @return The complete Text Summary of Video in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IMDBNumber`</b>,
///                  \anchor ListItem_IMDBNumber
///                  _string_,
///     @return The IMDb ID of the selected Video in a container.
///     <p><hr>
///     @skinning_v15 **[New Infolabel]** \link ListItem_IMDBNumber `ListItem.IMDBNumber`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.EpisodeName`</b>,
///                  \anchor ListItem_EpisodeName
///                  _string_,
///     @return The name of the episode if the selected EPG item is a TV Show (PVR).
///     <p><hr>
///     @skinning_v15 **[New Infolabel]** \link ListItem_EpisodeName `ListItem.EpisodeName`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PercentPlayed`</b>,
///                  \anchor ListItem_PercentPlayed
///                  _string_,
///     @return The percentage value [0-100] of how far the selected video has been
///     played.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.LastPlayed`</b>,
///                  \anchor ListItem_LastPlayed
///                  _string_,
///     @return The last play date of Video in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.PlayCount`</b>,
///                  \anchor ListItem_PlayCount
///                  _string_,
///     @return The playcount of Video in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.ChannelName`</b>,
///                  \anchor ListItem_ChannelName
///                  _string_,
///     @return The name of current selected TV channel in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.VideoCodec`</b>,
///                  \anchor ListItem_VideoCodec
///                  _string_,
///     @return The video codec of the currently selected video. Common values:
///      - <b>3iv2</b>
///      - <b>av1</b>
///      - <b>avc1</b>
///      - <b>div2</b>
///      - <b>div3</b>
///      - <b>divx</b>
///      - <b>divx 4</b>
///      - <b>dx50</b>
///      - <b>flv</b>
///      - <b>h264</b>
///      - <b>microsoft</b>
///      - <b>mp42</b>
///      - <b>mp43</b>
///      - <b>mp4v</b>
///      - <b>mpeg1video</b>
///      - <b>mpeg2video</b>
///      - <b>mpg4</b>
///      - <b>rv40</b>
///      - <b>svq1</b>
///      - <b>svq3</b>
///      - <b>theora</b>
///      - <b>vp6f</b>
///      - <b>wmv2</b>
///      - <b>wmv3</b>
///      - <b>wvc1</b>
///      - <b>xvid</b>
///      - etc
///     <p>
///   }
///   \table_row3{   <b>`ListItem.VideoResolution`</b>,
///                  \anchor ListItem_VideoResolution
///                  _string_,
///     @return The resolution of the currently selected video. Possible values:
///       - <b>480</b>
///       - <b>576</b>
///       - <b>540</b>
///       - <b>720</b>
///       - <b>1080</b>
///       - <b>4K</b>
///       - <b>8K</b>
///     @note 540 usually means a widescreen
///     format (around 960x540) while 576 means PAL resolutions (normally
///     720x576)\, therefore 540 is actually better resolution than 576.
///     <p><hr>
///     @skinning_v18 **[Updated Infolabel]** \link ListItem_VideoResolution ListItem.VideoResolution\endlink
///     added <b>8K</b> as a possible value.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.VideoAspect`</b>,
///                  \anchor ListItem_VideoAspect
///                  _string_,
///     @return The aspect ratio of the currently selected video. Possible values:
///      - <b>1.00</b>
///      - <b>1.19</b>
///      - <b>1.33</b>
///      - <b>1.37</b>
///      - <b>1.66</b>
///      - <b>1.78</b>
///      - <b>1.85</b>
///      - <b>2.00</b>
///      - <b>2.20</b>
///      - <b>2.35</b>
///      - <b>2.40</b>
///      - <b>2.55</b>
///      - <b>2.76</b>
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AudioCodec`</b>,
///                  \anchor ListItem_AudioCodec
///                  _string_,
///     @return The audio codec of the currently selected video. Common values:
///       - <b>aac</b>
///       - <b>ac3</b>
///       - <b>cook</b>
///       - <b>dca</b>
///       - <b>dtshd_hra</b>
///       - <b>dtshd_ma</b>
///       - <b>eac3</b>
///       - <b>mp1</b>
///       - <b>mp2</b>
///       - <b>mp3</b>
///       - <b>pcm_s16be</b>
///       - <b>pcm_s16le</b>
///       - <b>pcm_u8</b>
///       - <b>truehd</b>
///       - <b>vorbis</b>
///       - <b>wmapro</b>
///       - <b>wmav2</b>
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AudioChannels`</b>,
///                  \anchor ListItem_AudioChannels
///                  _string_,
///     @return The number of audio channels of the currently selected video. Possible values:
///       - <b>1</b>
///       - <b>2</b>
///       - <b>4</b>
///       - <b>5</b>
///       - <b>6</b>
///       - <b>8</b>
///       - <b>10</b>
///     <p><hr>
///     @skinning_v16 **[Infolabel Updated]** \link ListItem_AudioChannels `ListItem.AudioChannels`\endlink
///     if a video contains no audio\, these infolabels will now return empty.
///     (they used to return 0)
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AudioLanguage`</b>,
///                  \anchor ListItem_AudioLanguage
///                  _string_,
///     @return The audio language of the currently selected video (an
///     ISO 639-2 three character code: e.g. eng\, epo\, deu)
///     <p>
///   }
///   \table_row3{   <b>`ListItem.SubtitleLanguage`</b>,
///                  \anchor ListItem_SubtitleLanguage
///                  _string_,
///     @return The subtitle language of the currently selected video (an
///     ISO 639-2 three character code: e.g. eng\, epo\, deu)
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(AudioCodec.[n])`</b>,
///                  \anchor ListItem_Property_AudioCodec
///                  _string_,
///     @return The audio codec of the currently selected video
///     @param n - the number of the audiostream (values: see \ref ListItem_AudioCodec "ListItem.AudioCodec")
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link ListItem_Property_AudioCodec `ListItem.Property(AudioCodec.[n])`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(AudioChannels.[n])`</b>,
///                  \anchor ListItem_Property_AudioChannels
///                  _string_,
///     @return The number of audio channels of the currently selected video
///     @param n - the number of the audiostream (values: see
///     \ref ListItem_AudioChannels "ListItem.AudioChannels")
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link ListItem_Property_AudioChannels `ListItem.Property(AudioChannels.[n])`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(AudioLanguage.[n])`</b>,
///                  \anchor ListItem_Property_AudioLanguage
///                  _string_,
///     @return The audio language of the currently selected video
///     @param n - the number of the audiostream (values: see \ref ListItem_AudioLanguage "ListItem.AudioLanguage")
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link ListItem_Property_AudioLanguage `ListItem.Property(AudioLanguage.[n])`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(SubtitleLanguage.[n])`</b>,
///                  \anchor ListItem_Property_SubtitleLanguage
///                  _string_,
///     @return The subtitle language of the currently selected video
///     @param n - the number of the subtitle (values: see \ref ListItem_SubtitleLanguage "ListItem.SubtitleLanguage")
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link ListItem_Property_SubtitleLanguage `ListItem.Property(SubtitleLanguage.[n])`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Addon.Disclaimer)`</b>,
///                  \anchor ListItem_Property_AddonDisclaimer
///                  _string_,
///     @return The disclaimer of the currently selected addon.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Addon.Changelog)`</b>,
///                  \anchor ListItem_Property_AddonChangelog
///                  _string_,
///     @return The changelog of the currently selected addon.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Addon.ID)`</b>,
///                  \anchor ListItem_Property_AddonID
///                  _string_,
///     @return The identifier of the currently selected addon.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Addon.Status)`</b>,
///                  \anchor ListItem_Property_AddonStatus
///                  _string_,
///     @return The status of the currently selected addon.
///     @todo missing reference in GuiInfoManager.cpp making it hard to track.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Addon.Orphaned)`</b>,
///                  \anchor ListItem_Property_AddonOrphaned
///                  _boolean_,
///     @return **True** if the Addon is orphanad.
///     @todo missing reference in GuiInfoManager.cpp making it hard to track.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link ListItem_Property_AddonOrphaned `ListItem.Property(Addon.Orphaned)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Addon.Path)`</b>,
///                  \anchor ListItem_Property_AddonPath
///                  _string_,
///     @return The path of the currently selected addon.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.StartTime`</b>,
///                  \anchor ListItem_StartTime
///                  _string_,
///     @return The start time of current selected TV programme in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.EndTime`</b>,
///                  \anchor ListItem_EndTime
///                  _string_,
///     @return The end time of current selected TV programme in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.StartDate`</b>,
///                  \anchor ListItem_StartDate
///                  _string_,
///     @return The start date of current selected TV programme in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.EndDate`</b>,
///                  \anchor ListItem_EndDate
///                  _string_,
///     @return The end date of current selected TV programme in a container.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.NextTitle`</b>,
///                  \anchor ListItem_NextTitle
///                  _string_,
///     @return The title of the next item (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.NextGenre`</b>,
///                  \anchor ListItem_NextGenre
///                  _string_,
///     @return The genre of the next item (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.NextPlot`</b>,
///                  \anchor ListItem_NextPlot
///                  _string_,
///     @return The plot of the next item (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.NextPlotOutline`</b>,
///                  \anchor ListItem_NextPlotOutline
///                  _string_,
///     @return The plot outline of the next item (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.NextStartTime`</b>,
///                  \anchor ListItem_NextStartTime
///                  _string_,
///     @return The start time of the next item (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.NextEndTime`</b>,
///                  \anchor ListItem_NextEndTime
///                  _string_,
///     @return The end of the next item (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.NextStartDate`</b>,
///                  \anchor ListItem_NextStartDate
///                  _string_,
///     @return The start date of the next item (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.NextEndDate`</b>,
///                  \anchor ListItem_NextEndDate
///                  _string_,
///     @return The end date of the next item (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.NextDuration`</b>,
///                  \anchor ListItem_NextDuration
///                  _string_,
///     @return The duration of the next item (PVR) in the format <b>hh:mm:ss</b>.
///     @note <b>hh:</b> will be omitted if hours value is zero.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_NextDuration `ListItem.NextDuration`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.NextDuration(format)`</b>,
///                  \anchor ListItem_NextDuration_format
///                  _string_,
///     @return The duration of the next item (PVR) in different formats.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_NextDuration_format `ListItem.NextDuration(format)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.ChannelGroup`</b>,
///                  \anchor ListItem_ChannelGroup
///                  _string_,
///     @return The channel group of the selected item (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.ChannelNumberLabel`</b>,
///                  \anchor ListItem_ChannelNumberLabel
///                  _string_,
///     @return The channel and subchannel number of the currently selected channel that's
///     currently playing (PVR).
///     <p><hr>
///     @skinning_v14 **[New Infolabel]** \link ListItem_ChannelNumberLabel `ListItem.ChannelNumberLabel`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Progress`</b>,
///                  \anchor ListItem_Progress
///                  _string_,
///     @return The part of the programme that's been played (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.StereoscopicMode`</b>,
///                  \anchor ListItem_StereoscopicMode
///                  _string_,
///     @return The stereomode of the selected video:
///       - <b>mono</b>
///       - <b>split_vertical</b>
///       - <b>split_horizontal</b>
///       - <b>row_interleaved</b>
///       - <b>anaglyph_cyan_red</b>
///       - <b>anaglyph_green_magenta</b>
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link ListItem_StereoscopicMode `ListItem.StereoscopicMode`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.HasTimerSchedule`</b>,
///                  \anchor ListItem_HasTimerSchedule
///                  _boolean_,
///     @return **True** if the item was scheduled by a timer rule (PVR).
///     <p><hr>
///     @skinning_v16 **[New Boolean Condition]** \ref ListItem_HasTimerSchedule "ListItem.HasTimerSchedule"
///     <p>
///   }
///   \table_row3{   <b>`ListItem.HasReminder`</b>,
///                  \anchor ListItem_HasReminder
///                  _boolean_,
///     @return **True** if the item has a reminder set (PVR).
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \ref ListItem_HasReminder "ListItem.HasReminder"
///     <p>
///   }
///   \table_row3{   <b>`ListItem.HasReminderRule`</b>,
///                  \anchor ListItem_ListItem.HasReminderRule
///                  _boolean_,
///     @return **True** if the item was scheduled by a reminder timer rule (PVR).
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \ref ListItem_HasReminderRule "ListItem.HasReminderRule"
///     <p>
///   }
///   \table_row3{   <b>`ListItem.HasRecording`</b>,
///                  \anchor ListItem_HasRecording
///                  _boolean_,
///     @return **True** if a given epg tag item currently gets recorded or has been recorded.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.TimerHasError`</b>,
///                  \anchor ListItem_TimerHasError
///                  _boolean_,
///     @return **True** if the item has a timer and it won't be recorded because of an error (PVR).
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \ref ListItem_TimerHasError "ListItem.TimerHasError"
///     <p>
///   }
///   \table_row3{   <b>`ListItem.TimerHasConflict`</b>,
///                  \anchor ListItem_TimerHasConflict
///                  _boolean_,
///     @return **True** if the item has a timer and it won't be recorded because of a conflict (PVR).
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \ref ListItem_TimerHasConflict "ListItem.TimerHasConflict"
///     <p>
///   }
///   \table_row3{   <b>`ListItem.TimerIsActive`</b>,
///                  \anchor ListItem_TimerIsActive
///                  _boolean_,
///     @return **True** if the item has a timer that will be recorded\, i.e. the timer is enabled (PVR).
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \ref ListItem_TimerIsActive "ListItem.TimerIsActive"
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Comment`</b>,
///                  \anchor ListItem_Comment
///                  _string_,
///     @return The comment assigned to the item (PVR/MUSIC).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.TimerType`</b>,
///                  \anchor ListItem_TimerType
///                  _string_,
///     @return The type of the PVR timer / timer rule item as a human readable string.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.EpgEventTitle`</b>,
///                  \anchor ListItem_EpgEventTitle
///                  _string_,
///     @return The title of the epg event associated with the item\, if any.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.EpgEventIcon`</b>,
///                  \anchor ListItem_EpgEventIcon
///                  _string_,
///     @return The thumbnail for the EPG event associated with the item (if it exists).
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_EpgEventIcon `ListItem.EpgEventIcon`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.InProgress`</b>,
///                  \anchor ListItem_InProgress
///                  _boolean_,
///     @return **True** if the EPG event item is currently active (time-wise).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsParentFolder`</b>,
///                  \anchor ListItem_IsParentFolder
///                  _boolean_,
///     @return **True** if the current list item is the goto parent folder '..'.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link ListItem_IsParentFolder `ListItem.IsParentFolder`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonName`</b>,
///                  \anchor ListItem_AddonName
///                  _string_,
///     @return The name of the currently selected addon.
///     <p><hr>
///     @skinning_v17 **[Infolabel Updated]** \link ListItem_AddonName `ListItem.AddonName`\endlink
///     replaces `ListItem.Property(Addon.Name)`.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonVersion`</b>,
///                  \anchor ListItem_AddonVersion
///                  _string_,
///     @return The version of the currently selected addon.
///     <p><hr>
///     @skinning_v17 **[Infolabel Updated]** \link ListItem_AddonVersion `ListItem.AddonVersion`\endlink
///     replaces `ListItem.Property(Addon.Version)`.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonCreator`</b>,
///                  \anchor ListItem_AddonCreator
///                  _string_,
///     @return The name of the author the currently selected addon.
///     <p><hr>
///     @skinning_v17 **[Infolabel Updated]** \link ListItem_AddonCreator `ListItem.AddonCreator`\endlink
///     replaces `ListItem.Property(Addon.Creator)`.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonSummary`</b>,
///                  \anchor ListItem_AddonSummary
///                  _string_,
///     @return A short description of the currently selected addon.
///     <p><hr>
///     @skinning_v17 **[Infolabel Updated]** \link ListItem_AddonSummary `ListItem.AddonSummary`\endlink
///     replaces `ListItem.Property(Addon.Summary)`.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonDescription`</b>,
///                  \anchor ListItem_AddonDescription
///                  _string_,
///     @return The full description of the currently selected addon.
///     <p><hr>
///     @skinning_v17 **[Infolabel Updated]** \link ListItem_AddonDescription `ListItem.AddonDescription`\endlink
///     replaces `ListItem.Property(Addon.Description)`.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonDisclaimer`</b>,
///                  \anchor ListItem_AddonDisclaimer
///                  _string_,
///     @return The disclaimer of the currently selected addon.
///     <p><hr>
///     @skinning_v17 **[Infolabel Updated]** \link ListItem_AddonDisclaimer `ListItem.AddonDisclaimer`\endlink
///     replaces `ListItem.Property(Addon.Disclaimer)`.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonBroken`</b>,
///                  \anchor ListItem_AddonBroken
///                  _string_,
///     @return A message when the addon is marked as broken in the repo.
///     @deprecated but still available\, use \ref ListItem_AddonLifecycleDesc "ListItem.AddonLifecycleDesc"
///     instead
///     <p><hr>
///     @skinning_v17 **[Infolabel Updated]** \link ListItem_AddonBroken `ListItem.AddonBroken`\endlink
///     replaces `ListItem.Property(Addon.Broken)`.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonLifecycleType`</b>,
///                  \anchor ListItem_AddonLifecycleType
///                  _string_,
///     @return String name when the addon is marked as special condition in the repo.
///       - <b>Label: 24169 (Normal)</b> - Used if an add-on has no special lifecycle state which is the default state
///       - <b>Label: 24170 (Deprecated)</b> - The add-on should be marked as deprecated but is still usable
///       - <b>Label: 24171 (Broken)</b> - The add-on should marked as broken in the repository
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_AddonLifecycleType `ListItem.AddonLifecycleType`\endlink
///     replaces `ListItem.AddonBroken`.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonLifecycleDesc`</b>,
///                  \anchor ListItem_AddonLifecycleDesc
///                  _string_,
///     @return From addon defined message text when it is marked as special condition inside repository.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_AddonLifecycleDesc `ListItem.AddonLifecycleDesc``\endlink
///     replaces `ListItem.AddonBroken`.
///     <p>
///   }

///   \table_row3{   <b>`ListItem.AddonType`</b>,
///                  \anchor ListItem_AddonType
///                  _string_,
///     @return The type (screensaver\, script\, skin\, etc...) of the currently selected addon.
///     <p><hr>
///     @skinning_v17 **[Infolabel Updated]** \link ListItem_AddonType `ListItem.AddonType`\endlink
///     replaces `ListItem.Property(Addon.Type)`.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonInstallDate`</b>,
///                  \anchor ListItem_AddonInstallDate
///                  _string_,
///     @return The date the addon was installed.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_AddonInstallDate `ListItem.AddonInstallDate`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonLastUpdated`</b>,
///                  \anchor ListItem_AddonLastUpdated
///                  _string_,
///     @return The date the addon was last updated.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_AddonLastUpdated `ListItem.AddonLastUpdated`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonLastUsed`</b>,
///                  \anchor ListItem_AddonLastUsed
///                  _string_,
///     @return The date the addon was used last.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_AddonLastUsed `ListItem.AddonLastUsed`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonNews`</b>,
///                  \anchor ListItem_AddonNews
///                  _string_,
///     @return A brief changelog\, taken from the addons' `addon.xml` file.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_AddonNews `ListItem.AddonNews`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonSize`</b>,
///                  \anchor ListItem_AddonSize
///                  _string_,
///     @return The filesize of the addon.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_AddonSize `ListItem.AddonSize`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AddonOrigin`</b>,
///                  \anchor ListItem_AddonOrigin
///                  _string_,
///     @return The name of the repository the add-on originates from.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.ExpirationDate`</b>,
///                  \anchor ListItem_ExpirationDate
///                  _string_,
///     @return The expiration date of the selected item in a container\, empty string if not supported.
///     <p>
///   }
///   \table_row3{   <b>`ListItem.ExpirationTime`</b>,
///                  \anchor ListItem_ExpirationTime
///                  _string_,
///     @return The expiration time of the selected item in a container\, empty string if not supported
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Art(type)`</b>,
///                  \anchor ListItem_Art_Type
///                  _string_,
///     @return A particular art type for an item.
///     @param type - the art type. It can be any value (set by scripts and scrappers). Common values:
///       - <b>clearart</b> - the clearart (if it exists) of the currently selected movie or tv show.
///       - <b>clearlogo</b> - the clearlogo (if it exists) of the currently selected movie or tv show.
///       - <b>landscape</b> - the 16:9 landscape (if it exists) of the currently selected item.
///       - <b>thumb</b> - the thumbnail of the currently selected item.
///       - <b>poster</b> - the poster of the currently selected movie or tv show.
///       - <b>banner</b> - the banner of the currently selected tv show.
///       - <b>fanart</b> - the fanart image of the currently selected item.
///       - <b>set.fanart</b> - the fanart image of the currently selected movieset.
///       - <b>tvshow.poster</b> - the tv show poster of the parent container.
///       - <b>tvshow.banner</b> - the tv show banner of the parent container.
///       - <b>tvshow.clearlogo</b> - the tv show clearlogo (if it exists) of the parent container.
///       - <b>tvshow.landscape</b> - the tv show landscape (if it exists) of the parent container.
///       - <b>tvshow.clearart</b> - the tv show clearart (if it exists) of the parent container.
///       - <b>season.poster</b> - the season poster of the currently selected season. (Only available in DialogVideoInfo.xml).
///       - <b>season.banner</b> - the season banner of the currently selected season. (Only available in DialogVideoInfo.xml).
///       - <b>season.fanart</b> - the fanart image of the currently selected season. (Only available in DialogVideoInfo.xml)
///       - <b>artist.thumb</b> - the artist thumb of an album or song item.
///       - <b>artist.fanart</b> - the artist fanart of an album or song item.
///       - <b>album.thumb</b> - the album thumb (cover) of a song item.
///       - <b>artist[n].*</b> - in case a song has multiple artists\, a digit is added to the art type for the 2nd artist onwards
/// e.g `Listitem.Art(artist1.thumb)` gives the thumb of the 2nd artist of a song.
///       - <b>albumartist[n].*</b> - n case a song has multiple album artists\, a digit is added to the art type for the 2nd artist
/// onwards e.g `Listitem.Art(artist1.thumb)` gives the thumb of the 2nd artist of a song.
///     <p>
///     @todo Find a better way of finding the art types instead of manually defining them here.
///     <p><hr>
///     @skinning_v18 **[Infolabel Updated]** \link ListItem_Art_Type `ListItem.Art(type)`\endlink add <b>artist[n].*</b> and
///     <b>albumartist[n].*</b> as possible targets for <b>type</b>
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Platform`</b>,
///                  \anchor ListItem_Platform
///                  _string_,
///     @return The game platform (e.g. "Atari 2600") (RETROPLAYER).
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_Platform `ListItem.Platform`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Genres`</b>,
///                  \anchor ListItem_Genres
///                  _string_,
///     @return The game genres (e.g. "["Action"\,"Strategy"]") (RETROPLAYER).
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_Genres `ListItem.Genres`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Publisher`</b>,
///                  \anchor ListItem_Publisher
///                  _string_,
///     @return The game publisher (e.g. "Nintendo") (RETROPLAYER).
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_Publisher `ListItem.Publisher`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Developer`</b>,
///                  \anchor ListItem_Developer
///                  _string_,
///     @return The game developer (e.g. "Square") (RETROPLAYER).
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_Developer `ListItem.Developer`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Overview`</b>,
///                  \anchor ListItem_Overview
///                  _string_,
///     @return The game overview/summary (RETROPLAYER).
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_Overview `ListItem.Overview`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.GameClient`</b>,
///                  \anchor ListItem_GameClient
///                  _string_,
///     @return The add-on ID of the game client (a.k.a. emulator) to use for playing the game
///     (e.g. game.libretro.fceumm) (RETROPLAYER).
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_GameClient `ListItem.GameClient`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(propname)`</b>,
///                  \anchor ListItem_Property_Propname
///                  _string_,
///     @return The requested property of a ListItem.
///     @param propname - the property requested
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Role.Composer)`</b>,
///                  \anchor ListItem_Property_Role_Composer
///                  _string_,
///     @return The name of the person who composed the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Property_Role_Composer `ListItem.Property(Role.Composer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Role.Conductor)`</b>,
///                  \anchor ListItem_Property_Role_Conductor
///                  _string_,
///     @return The name of the person who conducted the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Property_Role_Conductor `ListItem.Property(Role.Conductor)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Role.Orchestra)`</b>,
///                  \anchor ListItem_Property_Role_Orchestra
///                  _string_,
///     @return The name of the orchestra performing the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Property_Role_Orchestra `ListItem.Property(Role.Orchestra)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Role.Lyricist)`</b>,
///                  \anchor ListItem_Property_Role_Lyricist
///                  _string_,
///     @return The name of the person who wrote the lyrics of the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Property_Role_Lyricist `ListItem.Property(Role.Lyricist)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Role.Remixer)`</b>,
///                  \anchor ListItem_Property_Role_Remixer
///                  _string_,
///     @return The name of the person who remixed the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Property_Role_Remixer `ListItem.Property(Role.Remixer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Role.Arranger)`</b>,
///                  \anchor ListItem_Property_Role_Arranger
///                  _string_,
///     @return The name of the person who arranged the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Property_Role_Arranger `ListItem.Property(Role.Arranger)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Role.Engineer)`</b>,
///                  \anchor ListItem_Property_Role_Engineer
///                  _string_,
///     @return The name of the person who was the engineer of the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Property_Role_Engineer `ListItem.Property(Role.Engineer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Role.Producer)`</b>,
///                  \anchor ListItem_Property_Role_Producer
///                  _string_,
///     @return The name of the person who produced the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Property_Role_Producer `ListItem.Property(Role.Producer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Role.DJMixer)`</b>,
///                  \anchor ListItem_Property_Role_DJMixer
///                  _string_,
///     @return The name of the dj who remixed the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Property_Role_DJMixer `ListItem.Property(Role.DJMixer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Role.Mixer)`</b>,
///                  \anchor ListItem_Property_Role_Mixer
///                  _string_,
///     @return The name of the person who mixed the selected song.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link ListItem_Property_Role_DJMixer `ListItem.Property(Role.DJMixer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Game.VideoFilter)`</b>,
///                  \anchor ListItem_Property_Game_VideoFilter
///                  _string_,
///     @return The video filter of the list item representing a
///     gamewindow control (RETROPLAYER).
///     See \link RetroPlayer_VideoFilter RetroPlayer.VideoFilter \endlink
///     for the possible values.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_Property_Game_VideoFilter `ListItem.Property(Game.VideoFilter)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Game.StretchMode)`</b>,
///                  \anchor ListItem_Property_Game_StretchMode
///                  _string_,
///     @return The stretch mode of the list item representing a
///     gamewindow control (RETROPLAYER).
///     See \link RetroPlayer_StretchMode RetroPlayer.StretchMode \endlink
///     for the possible values.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_Property_Game_StretchMode `ListItem.Property(Game.StretchMode)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.Property(Game.VideoRotation)`</b>,
///                  \anchor ListItem_Property_Game_VideoRotation
///                  _integer_,
///     @return The video rotation of the list item representing a
///     gamewindow control (RETROPLAYER).
///     See \link RetroPlayer_VideoRotation RetroPlayer.VideoRotation \endlink
///     for the possible values.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link ListItem_Property_Game_VideoRotation `ListItem.Property(Game.VideoRotation)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.ParentalRating`</b>,
///                  \anchor ListItem_ParentalRating
///                  _string_,
///     @return The parental rating of the list item (PVR).
///     <p>
///   }
///   \table_row3{   <b>`ListItem.ParentalRatingCode`</b>,
///                  \anchor ListItem_ParentalRatingCode
///                  _string_,
///     @return The parental rating code (eg: 'PG'\, etc) of the list item (PVR).
///     <p><hr>
///     @skinning_v21 **[New Infolabel]** \link ListItem_ParentalRatingCode `ListItem.ParentalRatingCode`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.CurrentItem`</b>,
///                  \anchor ListItem_CurrentItem
///                  _string_,
///     @return The current index of the item in a container starting at 1.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_CurrentItem `ListItem.CurrentItem`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsNew`</b>,
///                  \anchor ListItem_IsNew
///                  _boolean_,
///     @return **True** if the item is new (for example\, a Live TV show that will be first aired).
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_IsNew `ListItem.IsNew`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsPremiere`</b>,
///                  \anchor ListItem_IsPremiere
///                  _boolean_,
///     @return **True** if the item is a premiere (for example\, a Movie first showing or season first on Live TV).
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_IsPremiere `ListItem.IsPremiere`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsFinale`</b>,
///                  \anchor ListItem_IsFinale
///                  _boolean_,
///     @return **True** if the item is a finale (for example\, a season finale showing on Live TV).
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_IsFinale `ListItem.IsFinale`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsLive`</b>,
///                  \anchor ListItem_IsLive
///                  _boolean_,
///     @return **True** if the item is live (for example\, a Live TV sports event).
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_IsLive `ListItem.IsLive`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.DiscTitle`</b>,
///                  \anchor ListItem_DiscTitle
///                  _string_,
///     @return The disc title of the currently selected album or song.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_DiscTitle `ListItem.DiscTitle`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.IsBoxset`</b>,
///                  \anchor ListItem_IsBoxset
///                  _boolean_,
///     @return **True** if the item is part of a boxset album.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_IsBoxset `ListItem.IsBoxset`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.TotalDiscs`</b>,
///                  \anchor ListItem_TotalDiscs
///                  _boolean_,
///     @return The total number of discs belonging to an album.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_TotalDiscs `ListItem.TotalDiscs`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.ReleaseDate`</b>,
///                  \anchor ListItem_ReleaseDate
///                  _string_,
///     @return The release date of the item.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_ReleaseDate `ListItem.ReleaseDate`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.OriginalDate`</b>,
///                  \anchor ListItem_OriginalDate
///                  _string_,
///     @return The original release date of the item. Can be full or partial date.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_OriginalDate `ListItem.OriginalDate`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.BPM`</b>,
///                  \anchor ListItem_BPM
///                  _string_,
///     @return The BPM of a song.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_BPM `ListItem.BPM`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.UniqueID(name)`</b>,
///                  \anchor ListItem_UniqueID
///                  _string_,
///     @return The scraped metadata id of the currently selected item in a container\,
///     for use in dialogvideoinfo.xml.
///     @param name - the name of the metadata provider.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_UniqueID `ListItem.UniqueID(name)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.BitRate`</b>,
///                  \anchor ListItem_BitRate
///                  _string_,
///     @return The bitrate of a song. Actual rate for CBR\, average rate for VBR.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_BitRate `ListItem.BitRate`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.SampleRate`</b>,
///                  \anchor ListItem_SampleRate
///                  _string_,
///     @return The sample rate of a song / 1000.0 eg 44.1\, 48\, 96 etc.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_SampleRate `ListItem.SampleRate`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.MusicChannels`</b>,
///                  \anchor ListItem_MusicChannels
///                  _string_,
///     @return The number of audio channels of a song.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_No_Of_Channels `ListItem.NoOfChannels`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.TvShowDBID`</b>,
///                  \anchor ListItem_TvShowDBID
///                  _string_,
///     @return The database id of the TvShow for the currently selected Season or Episode.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_TvShowDBID `ListItem.TvShowDBID`\endlink
///     <p>
///   }
///   \table_row3{   <b>`ListItem.AlbumStatus`</b>,
///                  \anchor ListItem_AlbumStatus
///                  _string_,
///     @return The Musicbrainz release status of the album (official, bootleg, promotion etc)
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link ListItem_AlbumStatus `ListItem.AlbumStatus`\endlink
///   }
///   \table_row3{   <b>`ListItem.HdrType`</b>,
///                  \anchor ListItem_HdrType
///                  _string_,
///     @return String containing the name of the detected HDR type or empty if not HDR. See \ref StreamHdrType for the list of possible values.
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link ListItem_HdrType `ListItem.HdrType`\endlink
///   }
///   \table_row3{   <b>`ListItem.SongVideoURL`</b>,
///                  \anchor ListItem_SongVideoURL
///                  _string_,
///     @return Link to a video of a song
///     <p><hr>
///     @skinning_v21 **[New Infolabel]** \link ListItem_SongVideoURL `ListItem.SongVideoURL`\endlink
///   }
///   \table_row3{   <b>`ListItem.VideoWidth`</b>,
///                  \anchor ListItem_VideoWidth
///                  _string_,
///     @return String containing width of video in pixels - empty if unknown.
///     <p><hr>
///     @skinning_v21 **[New Infolabel]** \link ListItem_VideoWidth `ListItem.VideoWidth`\endlink
///   }
///   \table_row3{   <b>`ListItem.VideoHeight`</b>,
///                  \anchor ListItem_VideoHeight
///                  _string_,
///     @return String containing height of video in pixels - empty if unknown.
///     <p><hr>
///     @skinning_v21 **[New Infolabel]** \link ListItem_VideoHeight `ListItem.VideoHeight`\endlink
///   }
///   \table_row3{   <b>`ListItem.HasVideoVersions`</b>,
///                  \anchor ListItem_HasVideoVersions
///                  _boolean_,
///     @return **True** when the selected item has multiple video versions.
///     <p><hr>
///     @skinning_v21 **[New Infolabel]** \link ListItem_HasVideoVersions `ListItem.HasVideoVersions`\endlink
///   }
///   \table_row3{   <b>`ListItem.IsVideoExtra`</b>,
///                  \anchor ListItem_IsVideoExtra
///                  _boolean_,
///     @return **True** when the selected item is a video extra.
///     <p><hr>
///     @skinning_v21 **[New Infolabel]** \link ListItem_IsVideoExtra `ListItem.IsVideoExtra`\endlink
///   }
///   \table_row3{   <b>`ListItem.VideoVersionName`</b>,
///                  \anchor ListItem_VideoVersionName
///                  _string_,
///     @return String containing the name of the version of a video - empty for extras or if no version available
///     <p><hr>
///     @skinning_v21 **[New Infolabel]** \link ListItem_VideoVersionName `ListItem.VideoVersionName`\endlink
///   }
///   \table_row3{   <b>`ListItem.HasVideoExtras`</b>,
///                  \anchor ListItem_HasVideoExtras
///                  _boolean_,
///     @return **True** when the selected item has video extras.
///     <p><hr>
///     @skinning_v21 **[New Infolabel]** \link ListItem_HasVideoExtras `ListItem.HasVideoExtras`\endlink
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
// clang-format off
const infomap listitem_labels[]= {{ "thumb",            LISTITEM_THUMB },
                                  { "icon",             LISTITEM_ICON },
                                  { "actualicon",       LISTITEM_ACTUAL_ICON },
                                  { "overlay",          LISTITEM_OVERLAY },
                                  { "label",            LISTITEM_LABEL },
                                  { "label2",           LISTITEM_LABEL2 },
                                  { "title",            LISTITEM_TITLE },
                                  { "tracknumber",      LISTITEM_TRACKNUMBER },
                                  { "artist",           LISTITEM_ARTIST },
                                  { "album",            LISTITEM_ALBUM },
                                  { "albumartist",      LISTITEM_ALBUM_ARTIST },
                                  { "year",             LISTITEM_YEAR },
                                  { "genre",            LISTITEM_GENRE },
                                  { "contributors",     LISTITEM_CONTRIBUTORS },
                                  { "contributorandrole", LISTITEM_CONTRIBUTOR_AND_ROLE },
                                  { "director",         LISTITEM_DIRECTOR },
                                  { "disctitle",        LISTITEM_DISC_TITLE },
                                  { "filename",         LISTITEM_FILENAME },
                                  { "filenameandpath",  LISTITEM_FILENAME_AND_PATH },
                                  { "fileextension",    LISTITEM_FILE_EXTENSION },
                                  { "filenamenoextension",  LISTITEM_FILENAME_NO_EXTENSION },
                                  { "date",             LISTITEM_DATE },
                                  { "datetime",         LISTITEM_DATETIME },
                                  { "size",             LISTITEM_SIZE },
                                  { "rating",           LISTITEM_RATING },
                                  { "ratingandvotes",   LISTITEM_RATING_AND_VOTES },
                                  { "userrating",       LISTITEM_USER_RATING },
                                  { "votes",            LISTITEM_VOTES },
                                  { "mood",             LISTITEM_MOOD },
                                  { "programcount",     LISTITEM_PROGRAM_COUNT },
                                  { "duration",         LISTITEM_DURATION },
                                  { "isselected",       LISTITEM_ISSELECTED },
                                  { "isplaying",        LISTITEM_ISPLAYING },
                                  { "plot",             LISTITEM_PLOT },
                                  { "plotoutline",      LISTITEM_PLOT_OUTLINE },
                                  { "episode",          LISTITEM_EPISODE },
                                  { "season",           LISTITEM_SEASON },
                                  { "tvshowtitle",      LISTITEM_TVSHOW },
                                  { "premiered",        LISTITEM_PREMIERED },
                                  { "comment",          LISTITEM_COMMENT },
                                  { "path",             LISTITEM_PATH },
                                  { "foldername",       LISTITEM_FOLDERNAME },
                                  { "folderpath",       LISTITEM_FOLDERPATH },
                                  { "picturepath",      LISTITEM_PICTURE_PATH },
                                  { "pictureresolution",LISTITEM_PICTURE_RESOLUTION },
                                  { "picturedatetime",  LISTITEM_PICTURE_DATETIME },
                                  { "picturedate",      LISTITEM_PICTURE_DATE },
                                  { "picturelongdatetime",LISTITEM_PICTURE_LONGDATETIME },
                                  { "picturelongdate",  LISTITEM_PICTURE_LONGDATE },
                                  { "picturecomment",   LISTITEM_PICTURE_COMMENT },
                                  { "picturecaption",   LISTITEM_PICTURE_CAPTION },
                                  { "picturedesc",      LISTITEM_PICTURE_DESC },
                                  { "picturekeywords",  LISTITEM_PICTURE_KEYWORDS },
                                  { "picturecammake",   LISTITEM_PICTURE_CAM_MAKE },
                                  { "picturecammodel",  LISTITEM_PICTURE_CAM_MODEL },
                                  { "pictureaperture",  LISTITEM_PICTURE_APERTURE },
                                  { "picturefocallen",  LISTITEM_PICTURE_FOCAL_LEN },
                                  { "picturefocusdist", LISTITEM_PICTURE_FOCUS_DIST },
                                  { "pictureexpmode",   LISTITEM_PICTURE_EXP_MODE },
                                  { "pictureexptime",   LISTITEM_PICTURE_EXP_TIME },
                                  { "pictureiso",       LISTITEM_PICTURE_ISO },
                                  { "pictureauthor",                 LISTITEM_PICTURE_AUTHOR },
                                  { "picturebyline",                 LISTITEM_PICTURE_BYLINE },
                                  { "picturebylinetitle",            LISTITEM_PICTURE_BYLINE_TITLE },
                                  { "picturecategory",               LISTITEM_PICTURE_CATEGORY },
                                  { "pictureccdwidth",               LISTITEM_PICTURE_CCD_WIDTH },
                                  { "picturecity",                   LISTITEM_PICTURE_CITY },
                                  { "pictureurgency",                LISTITEM_PICTURE_URGENCY },
                                  { "picturecopyrightnotice",        LISTITEM_PICTURE_COPYRIGHT_NOTICE },
                                  { "picturecountry",                LISTITEM_PICTURE_COUNTRY },
                                  { "picturecountrycode",            LISTITEM_PICTURE_COUNTRY_CODE },
                                  { "picturecredit",                 LISTITEM_PICTURE_CREDIT },
                                  { "pictureiptcdate",               LISTITEM_PICTURE_IPTCDATE },
                                  { "picturedigitalzoom",            LISTITEM_PICTURE_DIGITAL_ZOOM },
                                  { "pictureexposure",               LISTITEM_PICTURE_EXPOSURE },
                                  { "pictureexposurebias",           LISTITEM_PICTURE_EXPOSURE_BIAS },
                                  { "pictureflashused",              LISTITEM_PICTURE_FLASH_USED },
                                  { "pictureheadline",               LISTITEM_PICTURE_HEADLINE },
                                  { "picturecolour",                 LISTITEM_PICTURE_COLOUR },
                                  { "picturelightsource",            LISTITEM_PICTURE_LIGHT_SOURCE },
                                  { "picturemeteringmode",           LISTITEM_PICTURE_METERING_MODE },
                                  { "pictureobjectname",             LISTITEM_PICTURE_OBJECT_NAME },
                                  { "pictureorientation",            LISTITEM_PICTURE_ORIENTATION },
                                  { "pictureprocess",                LISTITEM_PICTURE_PROCESS },
                                  { "picturereferenceservice",       LISTITEM_PICTURE_REF_SERVICE },
                                  { "picturesource",                 LISTITEM_PICTURE_SOURCE },
                                  { "picturespecialinstructions",    LISTITEM_PICTURE_SPEC_INSTR },
                                  { "picturestate",                  LISTITEM_PICTURE_STATE },
                                  { "picturesupplementalcategories", LISTITEM_PICTURE_SUP_CATEGORIES },
                                  { "picturetransmissionreference",  LISTITEM_PICTURE_TX_REFERENCE },
                                  { "picturewhitebalance",           LISTITEM_PICTURE_WHITE_BALANCE },
                                  { "pictureimagetype",              LISTITEM_PICTURE_IMAGETYPE },
                                  { "picturesublocation",            LISTITEM_PICTURE_SUBLOCATION },
                                  { "pictureiptctime",               LISTITEM_PICTURE_TIMECREATED },
                                  { "picturegpslat",    LISTITEM_PICTURE_GPS_LAT },
                                  { "picturegpslon",    LISTITEM_PICTURE_GPS_LON },
                                  { "picturegpsalt",    LISTITEM_PICTURE_GPS_ALT },
                                  { "studio",           LISTITEM_STUDIO },
                                  { "country",          LISTITEM_COUNTRY },
                                  { "mpaa",             LISTITEM_MPAA },
                                  { "cast",             LISTITEM_CAST },
                                  { "castandrole",      LISTITEM_CAST_AND_ROLE },
                                  { "writer",           LISTITEM_WRITER },
                                  { "tagline",          LISTITEM_TAGLINE },
                                  { "status",           LISTITEM_STATUS },
                                  { "top250",           LISTITEM_TOP250 },
                                  { "trailer",          LISTITEM_TRAILER },
                                  { "sortletter",       LISTITEM_SORT_LETTER },
                                  { "tag",              LISTITEM_TAG },
                                  { "set",              LISTITEM_SET },
                                  { "setid",            LISTITEM_SETID },
                                  { "videocodec",       LISTITEM_VIDEO_CODEC },
                                  { "videoresolution",  LISTITEM_VIDEO_RESOLUTION },
                                  { "videowidth",       LISTITEM_VIDEO_WIDTH},
                                  { "videoheight",      LISTITEM_VIDEO_HEIGHT},
                                  { "videoaspect",      LISTITEM_VIDEO_ASPECT },
                                  { "audiocodec",       LISTITEM_AUDIO_CODEC },
                                  { "audiochannels",    LISTITEM_AUDIO_CHANNELS },
                                  { "audiolanguage",    LISTITEM_AUDIO_LANGUAGE },
                                  { "subtitlelanguage", LISTITEM_SUBTITLE_LANGUAGE },
                                  { "isresumable",      LISTITEM_IS_RESUMABLE},
                                  { "percentplayed",    LISTITEM_PERCENT_PLAYED},
                                  { "isfolder",         LISTITEM_IS_FOLDER },
                                  { "isparentfolder",   LISTITEM_IS_PARENTFOLDER },
                                  { "iscollection",     LISTITEM_IS_COLLECTION },
                                  { "originaltitle",    LISTITEM_ORIGINALTITLE },
                                  { "lastplayed",       LISTITEM_LASTPLAYED },
                                  { "playcount",        LISTITEM_PLAYCOUNT },
                                  { "discnumber",       LISTITEM_DISC_NUMBER },
                                  { "starttime",        LISTITEM_STARTTIME },
                                  { "endtime",          LISTITEM_ENDTIME },
                                  { "endtimeresume",    LISTITEM_ENDTIME_RESUME },
                                  { "startdate",        LISTITEM_STARTDATE },
                                  { "enddate",          LISTITEM_ENDDATE },
                                  { "nexttitle",        LISTITEM_NEXT_TITLE },
                                  { "nextgenre",        LISTITEM_NEXT_GENRE },
                                  { "nextplot",         LISTITEM_NEXT_PLOT },
                                  { "nextplotoutline",  LISTITEM_NEXT_PLOT_OUTLINE },
                                  { "nextstarttime",    LISTITEM_NEXT_STARTTIME },
                                  { "nextendtime",      LISTITEM_NEXT_ENDTIME },
                                  { "nextstartdate",    LISTITEM_NEXT_STARTDATE },
                                  { "nextenddate",      LISTITEM_NEXT_ENDDATE },
                                  { "nextduration",     LISTITEM_NEXT_DURATION },
                                  { "channelname",      LISTITEM_CHANNEL_NAME },
                                  { "channelnumberlabel", LISTITEM_CHANNEL_NUMBER },
                                  { "channelgroup",     LISTITEM_CHANNEL_GROUP },
                                  { "hasepg",           LISTITEM_HAS_EPG },
                                  { "hastimer",         LISTITEM_HASTIMER },
                                  { "hastimerschedule", LISTITEM_HASTIMERSCHEDULE },
                                  { "hasreminder",      LISTITEM_HASREMINDER },
                                  { "hasreminderrule",  LISTITEM_HASREMINDERRULE },
                                  { "hasrecording",     LISTITEM_HASRECORDING },
                                  { "isrecording",      LISTITEM_ISRECORDING },
                                  { "isplayable",       LISTITEM_ISPLAYABLE },
                                  { "hasarchive",       LISTITEM_HASARCHIVE },
                                  { "inprogress",       LISTITEM_INPROGRESS },
                                  { "isencrypted",      LISTITEM_ISENCRYPTED },
                                  { "progress",         LISTITEM_PROGRESS },
                                  { "dateadded",        LISTITEM_DATE_ADDED },
                                  { "dbtype",           LISTITEM_DBTYPE },
                                  { "dbid",             LISTITEM_DBID },
                                  { "appearances",      LISTITEM_APPEARANCES },
                                  { "stereoscopicmode", LISTITEM_STEREOSCOPIC_MODE },
                                  { "isstereoscopic",   LISTITEM_IS_STEREOSCOPIC },
                                  { "imdbnumber",       LISTITEM_IMDBNUMBER },
                                  { "episodename",      LISTITEM_EPISODENAME },
                                  { "timertype",        LISTITEM_TIMERTYPE },
                                  { "epgeventtitle",    LISTITEM_EPG_EVENT_TITLE },
                                  { "epgeventicon",     LISTITEM_EPG_EVENT_ICON },
                                  { "timerisactive",    LISTITEM_TIMERISACTIVE },
                                  { "timerhaserror",    LISTITEM_TIMERHASERROR },
                                  { "timerhasconflict", LISTITEM_TIMERHASCONFLICT },
                                  { "addonname",        LISTITEM_ADDON_NAME },
                                  { "addonversion",     LISTITEM_ADDON_VERSION },
                                  { "addoncreator",     LISTITEM_ADDON_CREATOR },
                                  { "addonsummary",     LISTITEM_ADDON_SUMMARY },
                                  { "addondescription", LISTITEM_ADDON_DESCRIPTION },
                                  { "addondisclaimer",  LISTITEM_ADDON_DISCLAIMER },
                                  { "addonnews",        LISTITEM_ADDON_NEWS },
                                  { "addonbroken",      LISTITEM_ADDON_BROKEN },
                                  { "addonlifecycletype", LISTITEM_ADDON_LIFECYCLE_TYPE },
                                  { "addonlifecycledesc", LISTITEM_ADDON_LIFECYCLE_DESC },
                                  { "addontype",        LISTITEM_ADDON_TYPE },
                                  { "addoninstalldate", LISTITEM_ADDON_INSTALL_DATE },
                                  { "addonlastupdated", LISTITEM_ADDON_LAST_UPDATED },
                                  { "addonlastused",    LISTITEM_ADDON_LAST_USED },
                                  { "addonorigin",      LISTITEM_ADDON_ORIGIN },
                                  { "addonsize",        LISTITEM_ADDON_SIZE },
                                  { "expirationdate",   LISTITEM_EXPIRATION_DATE },
                                  { "expirationtime",   LISTITEM_EXPIRATION_TIME },
                                  { "art",              LISTITEM_ART },
                                  { "property",         LISTITEM_PROPERTY },
                                  { "parentalrating",   LISTITEM_PARENTAL_RATING },
                                  { "parentalratingcode", LISTITEM_PARENTAL_RATING_CODE },
                                  { "currentitem",      LISTITEM_CURRENTITEM },
                                  { "isnew",            LISTITEM_IS_NEW },
                                  { "isboxset",         LISTITEM_IS_BOXSET },
                                  { "totaldiscs",       LISTITEM_TOTALDISCS },
                                  { "releasedate",      LISTITEM_RELEASEDATE },
                                  { "originaldate",     LISTITEM_ORIGINALDATE },
                                  { "bpm",              LISTITEM_BPM },
                                  { "uniqueid",         LISTITEM_UNIQUEID },
                                  { "bitrate",          LISTITEM_BITRATE },
                                  { "samplerate",       LISTITEM_SAMPLERATE },
                                  { "musicchannels",    LISTITEM_MUSICCHANNELS },
                                  { "ispremiere",       LISTITEM_IS_PREMIERE },
                                  { "isfinale",         LISTITEM_IS_FINALE },
                                  { "islive",           LISTITEM_IS_LIVE },
                                  { "tvshowdbid",       LISTITEM_TVSHOWDBID },
                                  { "albumstatus",      LISTITEM_ALBUMSTATUS },
                                  { "isautoupdateable", LISTITEM_ISAUTOUPDATEABLE },
                                  { "hdrtype",          LISTITEM_VIDEO_HDR_TYPE },
                                  { "songvideourl",     LISTITEM_SONG_VIDEO_URL },
                                  { "hasvideoversions", LISTITEM_HASVIDEOVERSIONS },
                                  { "isvideoextra",     LISTITEM_ISVIDEOEXTRA },
                                  { "videoversionname", LISTITEM_VIDEOVERSION_NAME },
                                  { "hasvideoextras",   LISTITEM_HASVIDEOEXTRAS },
};
// clang-format on

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Visualisation Visualisation
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`Visualisation.Enabled`</b>,
///                  \anchor Visualisation_Enabled
///                  _boolean_,
///     @return **True** if any visualisation has been set in settings (so not None).
///     <p>
///   }
///   \table_row3{   <b>`Visualisation.HasPresets`</b>,
///                  \anchor Visualisation_HasPresets
///                  _boolean_,
///     @return **True** if the visualisation has built in presets.
///     <p><hr>
///     @skinning_v16 **[New Boolean Condition]** \link Visualisation_HasPresets `Visualisation.HasPresets`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Visualisation.Locked`</b>,
///                  \anchor Visualisation_Locked
///                  _boolean_,
///     @return **True** if the current visualisation preset is locked (e.g. in Milkdrop).
///     <p>
///   }
///   \table_row3{   <b>`Visualisation.Preset`</b>,
///                  \anchor Visualisation_Preset
///                  _string_,
///     @return The current preset of the visualisation.
///     <p>
///   }
///   \table_row3{   <b>`Visualisation.Name`</b>,
///                  \anchor Visualisation_Name
///                  _string_,
///     @return the name of the visualisation.
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap visualisation[] =  {{ "locked",           VISUALISATION_LOCKED },
                                  { "preset",           VISUALISATION_PRESET },
                                  { "haspresets",       VISUALISATION_HAS_PRESETS },
                                  { "name",             VISUALISATION_NAME },
                                  { "enabled",          VISUALISATION_ENABLED }};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Fanart Fanart
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`Fanart.Color1`</b>,
///                  \anchor Fanart_Color1
///                  _string_,
///     @return The first of three colors included in the currently selected
///     Fanart theme for the parent TV Show.
///     @note Colors are arranged Lightest to Darkest.
///     <p>
///   }
///   \table_row3{   <b>`Fanart.Color2`</b>,
///                  \anchor Fanart_Color2
///                  _string_,
///     @return The second of three colors included in the currently selected
///     Fanart theme for the parent TV Show.
///     @note Colors are arranged Lightest to Darkest.
///     <p>
///   }
///   \table_row3{   <b>`Fanart.Color3`</b>,
///                  \anchor Fanart_Color3
///                  _string_,
///     @return The third of three colors included in the currently selected
///     Fanart theme for the parent TV Show.
///     @note Colors are arranged Lightest to Darkest.
///     <p>
///   }
///   \table_row3{   <b>`Fanart.Image`</b>,
///                  \anchor Fanart_Image
///                  _string_,
///     @return The fanart image\, if any
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap fanart_labels[] =  {{ "color1",           FANART_COLOR1 },
                                  { "color2",           FANART_COLOR2 },
                                  { "color3",           FANART_COLOR3 },
                                  { "image",            FANART_IMAGE }};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Skin Skin
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`Skin.HasSetting(setting)`</b>,
///                  \anchor Skin_HasSetting
///                  _boolean_,
///     @param setting - the requested skin setting
///     @return **True** if the requested skin setting is true\, false otherwise.
///     @sa \link Skin_SetBool `Skin.SetBool(setting[\,value])`
///     <p>
///   }
///   \table_row3{   <b>`Skin.String(setting)`</b>,
///                  \anchor Skin_StringValue
///                  _string_,
///     @param setting - the requested skin setting
///     @return The value of the requested string setting (as a string)
///     @sa \link Skin_SetString `Skin.SetString(setting[\,value])`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Skin.String(setting[\,value])`</b>,
///                  \anchor Skin_StringCompare
///                  _boolean_,
///     @param setting - the requested skin setting
///     @param value [opt] - the string value to compare the requested setting to
///     @return **True** if the setting value equals the provided value\, false otherwise.
///     @sa \link Skin_SetString `Skin.SetString(setting[\,value])`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Skin.HasTheme(theme)`</b>,
///                  \anchor Skin_HasTheme
///                  _boolean_,
///     @param theme - the requested skin theme
///     @return **True** if the requested theme is enabled\, false otherwise.
///     @sa \link Skin_CycleTheme `Skin.Theme()`\endlink and \link Skin_CurrentTheme `Skin.CurrentTheme`\endlink.
///     <p>
///   }
///   \table_row3{   <b>`Skin.CurrentTheme`</b>,
///                  \anchor Skin_CurrentTheme
///                  _string_,
///     @return The current selected skin theme.
///     <p>
///   }
///   \table_row3{   <b>`Skin.CurrentColourTheme`</b>,
///                  \anchor Skin_CurrentColourTheme
///                  _string_,
///     @return the current selected colour theme of the skin.
///     <p>
///   }
///   \table_row3{   <b>`Skin.AspectRatio`</b>,
///                  \anchor Skin_AspectRatio
///                  _string_,
///     @return The closest aspect ratio match using the resolution info from the skin's `addon.xml` file.
///     <p>
///   }
///   \table_row3{   <b>`Skin.Font`</b>,
///                  \anchor Skin_Font
///                  _string_,
///     @return the current fontset from `Font.xml`.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link Skin_Font `Skin.Font`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Skin.Numeric(settingid)`</b>,
///                  \anchor Skin_Numeric
///                  _integer_,
///     @return return the setting value as an integer/numeric value.
///     @sa \link Skin_SetNumeric `Skin.SetNumeric(settingid)`\endlink
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link Skin_Numeric `Skin.Numeric(settingid)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Skin.TimerElapsedSecs(timer)`</b>,
///                  \anchor Skin_TimerElapsedSecs
///                  _integer_ \, _string_,
///     @return The elapsed time in seconds for the provided `timer`.
///     @param timer - the timer name
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link Skin_TimerElapsedSecs `Skin.TimerElapsedSecs(timer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Skin.TimerIsRunning(timer)`</b>,
///                  \anchor Skin_TimerIsRunning
///                  _boolean_,
///     @return **True** if the given `timer` is active\, false otherwise.
///     @param timer - the timer name
///     <p><hr>
///     @skinning_v20 **[New Infolabel]** \link Skin_TimerIsRunning `Skin.TimerIsRunning(timer)`\endlink
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap skin_labels[] =    {{ "currenttheme",      SKIN_THEME },
                                  { "currentcolourtheme",SKIN_COLOUR_THEME },
                                  { "aspectratio",       SKIN_ASPECT_RATIO},
                                  { "font",              SKIN_FONT}};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Window Window
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`Window.IsMedia`</b>,
///                  \anchor Window_IsMedia
///                  _boolean_,
///     @return **True** if this window is a media window (programs\, music\, video\,
///     scripts\, pictures)
///     <p>
///   }
///   \table_row3{   <b>`Window.Is(window)`</b>,
///                  \anchor Window_Is
///                  _boolean_,
///     @return **True** if the window with the given name is the window which is currently rendered.
///     @param window - the name of the window
///     @note Useful in xml files that are shared between multiple windows or dialogs.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \ref Window_Is "Window.Is(window)"
///     <p>
///   }
///   \table_row3{   <b>`Window.IsActive(window)`</b>,
///                  \anchor Window_IsActive
///                  _boolean_,
///     @return **True** if the window with id or title _window_ is active
///     @param window - the id or name of the window
///     @note Excludes fade out time on dialogs
///     <p>
///   }
///   \table_row3{   <b>`Window.IsVisible(window)`</b>,
///                  \anchor Window_IsVisible
///                  _boolean_,
///     @return **True** if the window is visible
///     @note Includes fade out time on dialogs
///     <p>
///   }
///   \table_row3{   <b>`Window.IsTopmost(window)`</b>,
///                  \anchor Window_IsTopmost
///                  _boolean_,
///     @return **True** if the window with id or title _window_ is on top of the
///     window stack.
///     @param window - the id or name of the window
///     @note Excludes fade out time on dialogs
///     @deprecated use  \ref Window_IsDialogTopmost "Window.IsDialogTopmost(dialog)" instead
///     <p>
///   }
///   \table_row3{   <b>`Window.IsDialogTopmost(dialog)`</b>,
///                  \anchor Window_IsDialogTopmost
///                  _boolean_,
///     @return **True** if the dialog with id or title _dialog_ is on top of the
///     dialog stack.
///     @param window - the id or name of the window
///     @note Excludes fade out time on dialogs
///     <p>
///   }
///   \table_row3{   <b>`Window.IsModalDialogTopmost(dialog)`</b>,
///                  \anchor Window_IsModalDialogTopmost
///                  _boolean_,
///     @return **True** if the dialog with id or title _dialog_ is on top of the
///     modal dialog stack
///     @note Excludes fade out time on dialogs
///     <p>
///   }
///   \table_row3{   <b>`Window.Previous(window)`</b>,
///                  \anchor Window_Previous
///                  _boolean_,
///     @return **True** if the window with id or title _window_ is being moved from.
///     @param window - the window id or title
///     @note Only valid while windows are changing.
///     <p>
///   }
///   \table_row3{   <b>`Window.Next(window)`</b>,
///                  \anchor Window_Next
///                  _boolean_,
///     @return **True** if the window with id or title _window_ is being moved to.
///     @param window - the window id or title
///     @note Only valid while windows are changing.
///     <p>
///   }
///   \table_row3{   <b>`Window.Property(Addon.ID)`</b>,
///                  \anchor Window_Property_AddonId
///                  _string_,
///     @return The id of the selected addon\, in `DialogAddonSettings.xml`.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link Window_Property_AddonId `Window.Property(Addon.ID)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Window.Property(IsRadio)`</b>,
///                  \anchor Window_Property_IsRadio
///                  _string_,
///     @return "true" if the window is a radio window\, empty string otherwise (for use in the PVR windows).
///     <p>
///   }
///   \table_row3{   <b>`Window([window]).Property(key)`</b>,
///                  \anchor Window_Window_Property_key
///                  _string_,
///     @return A window property.
///     @param window - [opt] window id or name.
///     @param key - any value.
///     <p>
///   }
///   \table_row3{   <b>`Window(AddonBrowser).Property(Updated)`</b>,
///                  \anchor Window_Addonbrowser_Property_Updated
///                  _string_,
///     @return The date and time the addon repo was last checked for updates.
///     @todo move to a future window document.
///     <p><hr>
///     @skinning_v15 **[New Infolabel]** \link Window_Addonbrowser_Property_Updated `Window(AddonBrowser).Property(Updated)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Window(Weather).Property(property)`</b>,
///                  \anchor Window_Weather_Property
///                  _string_,
///     @return The property for the weather window.
///     @param property - The requested property. The following are available:
///        - Current.ConditionIcon
///        - Day[0-6].OutlookIcon
///        - Current.FanartCode
///        - Day[0-6].FanartCode
///        - WeatherProviderLogo
///        - Daily.%i.OutlookIcon
///        - 36Hour.%i.OutlookIcon
///        - Weekend.%i.OutlookIcon
///        - Hourly.%i.OutlookIcon
///     @todo move to a future window document.
///     <p><hr>
///     @skinning_v16 **[Updated infolabel]** \link Window_Weather_Property `Window(Weather).Property(property)`\endlink
///     For skins that support extended weather info\, the following infolabels have been changed:
///       - Daily.%i.OutlookIcon
///       - 36Hour.%i.OutlookIcon
///       - Weekend.%i.OutlookIcon
///       - Hourly.%i.OutlookIcon
///
///     previously the openweathermap addon would provide the full\, hardcoded path to the icon
///     ie. `resource://resource.images.weathericons.default/28.png`
///     to make it easier for skins to work with custom icon sets\, it now will return the filename only
///     i.e. 28.png
///     @skinning_v13 **[Infolabel Updated]** \link Window_Weather_Property `Window(Weather).Property(property)`\endlink
///     added `WeatherProviderLogo` property - weather provider logo (for weather addons that support it).
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap window_bools[] =   {{ "ismedia",          WINDOW_IS_MEDIA },
                                  { "is",               WINDOW_IS },
                                  { "isactive",         WINDOW_IS_ACTIVE },
                                  { "isvisible",        WINDOW_IS_VISIBLE },
                                  { "istopmost",        WINDOW_IS_DIALOG_TOPMOST }, //! @deprecated, remove in v19
                                  { "isdialogtopmost",  WINDOW_IS_DIALOG_TOPMOST },
                                  { "ismodaldialogtopmost", WINDOW_IS_MODAL_DIALOG_TOPMOST },
                                  { "previous",         WINDOW_PREVIOUS },
                                  { "next",             WINDOW_NEXT }};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Control Control
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`Control.HasFocus(id)`</b>,
///                  \anchor Control_HasFocus
///                  _boolean_,
///     @return **True** if the currently focused control has id "id".
///     @param id - The id of the control
///     <p>
///   }
///   \table_row3{   <b>`Control.IsVisible(id)`</b>,
///                  \anchor Control_IsVisible
///                  _boolean_,
///     @return **True** if the control with id "id" is visible.
///     @param id - The id of the control
///     <p>
///   }
///   \table_row3{   <b>`Control.IsEnabled(id)`</b>,
///                  \anchor Control_IsEnabled
///                  _boolean_,
///     @return **True** if the control with id "id" is enabled.
///     @param id - The id of the control
///     <p>
///   }
///   \table_row3{   <b>`Control.GetLabel(id)[.index()]`</b>,
///                  \anchor Control_GetLabel
///                  _string_,
///     @return The label value or texture name of the control with the given id.
///     @param id - The id of the control
///     @param index - [opt] Optionally you can specify index(1) to retrieve label2 from an Edit
///     control.
///     <p><hr>
///     @skinning_v15 **[Infolabel Updated]** \link Control_GetLabel `Control.GetLabel(id)`\endlink
///     added index parameter - allows skinner to retrieve label2 of a control. Only edit controls are supported.
///     ** Example** : `Control.GetLabel(999).index(1)` where:
///       - index(0) = label
///       - index(1) = label2
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap control_labels[] = {{ "hasfocus",         CONTROL_HAS_FOCUS },
                                  { "isvisible",        CONTROL_IS_VISIBLE },
                                  { "isenabled",        CONTROL_IS_ENABLED },
                                  { "getlabel",         CONTROL_GET_LABEL }};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Playlist Playlist
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`Playlist.Length(media)`</b>,
///                  \anchor Playlist_Length
///                  _integer_,
///     @return The total size of the current playlist.
///     @param media - [opt] mediatype with is either
///     video or music.
///     <p>
///   }
///   \table_row3{   <b>`Playlist.Position(media)`</b>,
///                  \anchor Playlist_Position
///                  _integer_,
///     @return The position of the current item in the current playlist.
///     @param media - [opt] mediatype with is either
///     video or music.
///     <p>
///   }
///   \table_row3{   <b>`Playlist.Random`</b>,
///                  \anchor Playlist_Random
///                  _integer_,
///     @return String ID for the random mode:
///       - **16041** (On)
///       - **591** (Off)
///     <p><hr>
///     @skinning_v18 **[Infolabel Updated]** \link Playlist_Random `Playlist.Random`\endlink will
///     now return **On/Off**
///     <p>
///   }
///   \table_row3{   <b>`Playlist.Repeat`</b>,
///                  \anchor Playlist_Repeat
///                  _integer_,
///     @return The String Id for the repeat mode. It can be one of the following
///     values:
///       - **592** (Repeat One)
///       - **593** (Repeat All)
///       - **594** (Repeat Off)
///     <p>
///   }
///   \table_row3{   <b>`Playlist.IsRandom`</b>,
///                  \anchor Playlist_IsRandom
///                  _boolean_,
///     @return **True** if the player is in random mode.
///     <p>
///   }
///   \table_row3{   <b>`Playlist.IsRepeat`</b>,
///                  \anchor Playlist_IsRepeat
///                  _boolean_,
///     @return **True** if the player is in repeat all mode.
///     <p>
///   }
///   \table_row3{   <b>`Playlist.IsRepeatOne`</b>,
///                  \anchor Playlist_IsRepeatOne
///                  _boolean_,
///     @return **True** if the player is in repeat one mode.
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap playlist[] =       {{ "length",           PLAYLIST_LENGTH },
                                  { "position",         PLAYLIST_POSITION },
                                  { "random",           PLAYLIST_RANDOM },
                                  { "repeat",           PLAYLIST_REPEAT },
                                  { "israndom",         PLAYLIST_ISRANDOM },
                                  { "isrepeat",         PLAYLIST_ISREPEAT },
                                  { "isrepeatone",      PLAYLIST_ISREPEATONE }};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Pvr Pvr
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`PVR.IsRecording`</b>,
///                  \anchor PVR_IsRecording
///                  _boolean_,
///     @return **True** when the system is recording a tv or radio programme.
///     <p>
///   }
///   \table_row3{   <b>`PVR.HasTimer`</b>,
///                  \anchor PVR_HasTimer
///                  _boolean_,
///     @return **True** when a recording timer is active.
///     <p>
///   }
///   \table_row3{   <b>`PVR.HasTVChannels`</b>,
///                  \anchor PVR_HasTVChannels
///                  _boolean_,
///     @return **True** if there are TV channels available.
///     <p>
///   }
///   \table_row3{   <b>`PVR.HasRadioChannels`</b>,
///                  \anchor PVR_HasRadioChannels
///                  _boolean_,
///     @return **True** if there are radio channels available.
///     <p>
///   }
///   \table_row3{   <b>`PVR.HasNonRecordingTimer`</b>,
///                  \anchor PVR_HasNonRecordingTimer
///                  _boolean_,
///     @return **True** if there are timers present who currently not do recording.
///     <p>
///   }
///   \table_row3{   <b>`PVR.BackendName`</b>,
///                  \anchor PVR_BackendName
///                  _string_,
///     @return The name of the backend being used.
///     <p>
///   }
///   \table_row3{   <b>`PVR.BackendVersion`</b>,
///                  \anchor PVR_BackendVersion
///                  _string_,
///     @return The version of the backend that's being used.
///     <p>
///   }
///   \table_row3{   <b>`PVR.BackendHost`</b>,
///                  \anchor PVR_BackendHost
///                  _string_,
///     @return The backend hostname.
///     <p>
///   }
///   \table_row3{   <b>`PVR.BackendDiskSpace`</b>,
///                  \anchor PVR_BackendDiskSpace
///                  _string_,
///     @return The available diskspace on the backend as string with size.
///     <p>
///   }
///   \table_row3{   <b>`PVR.BackendDiskSpaceProgr`</b>,
///                  \anchor PVR_BackendDiskSpaceProgr
///                  _integer_,
///     @return The available diskspace on the backend as percent value.
///     <p><hr>
///     @skinning_v14 **[New Infolabel]** \link PVR_BackendDiskSpaceProgr `PVR.BackendDiskSpaceProgr`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.BackendChannels`</b>,
///                  \anchor PVR_BackendChannels
///                  _string (integer)_,
///     @return The number of available channels the backend provides.
///     <p>
///   }
///   \table_row3{   <b>`PVR.BackendTimers`</b>,
///                  \anchor PVR_BackendTimers
///                  _string (integer)_,
///     @return The number of timers set for the backend.
///     <p>
///   }
///   \table_row3{   <b>`PVR.BackendRecordings`</b>,
///                  \anchor PVR_BackendRecordings
///                  _string (integer)_,
///     @return The number of recordings available on the backend.
///     <p>
///   }
///   \table_row3{   <b>`PVR.BackendDeletedRecordings`</b>,
///                  \anchor PVR_BackendDeletedRecordings
///                  _string (integer)_,
///     @return The number of deleted recordings present on the backend.
///     <p>
///   }
///   \table_row3{   <b>`PVR.BackendNumber`</b>,
///                  \anchor PVR_BackendNumber
///                  _string_,
///     @return The backend number.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TotalDiscSpace`</b>,
///                  \anchor PVR_TotalDiscSpace
///                  _string_,
///     @return The total diskspace available for recordings.
///     <p>
///   }
///   \table_row3{   <b>`PVR.NextTimer`</b>,
///                  \anchor PVR_NextTimer
///                  _boolean_,
///     @return The next timer date.
///     <p>
///   }
///   \table_row3{   <b>`PVR.IsPlayingTV`</b>,
///                  \anchor PVR_IsPlayingTV
///                  _boolean_,
///     @return **True** when live tv is being watched.
///     <p>
///   }
///   \table_row3{   <b>`PVR.IsPlayingRadio`</b>,
///                  \anchor PVR_IsPlayingRadio
///                  _boolean_,
///     @return **True** when live radio is being listened to.
///     <p>
///   }
///   \table_row3{   <b>`PVR.IsPlayingRecording`</b>,
///                  \anchor PVR_IsPlayingRecording
///                  _boolean_,
///     @return **True** when a recording is being watched.
///     <p>
///   }
///   \table_row3{   <b>`PVR.IsPlayingEpgTag`</b>,
///                  \anchor PVR_IsPlayingEpgTag
///                  _boolean_,
///     @return **True** when an epg tag is being watched.
///     <p>
///   }
///   \table_row3{   <b>`PVR.EpgEventProgress`</b>,
///                  \anchor PVR_EpgEventProgress
///                  _integer_,
///     @return The percentage complete of the currently playing epg event.
///     <p><hr>
///     @skinning_v18 **[Infolabel Updated]** \link PVR_EpgEventProgress `PVR.EpgEventProgress`\endlink replaces
///     the old `PVR.Progress` infolabel.
///     <p>
///   }
///   \table_row3{   <b>`PVR.ActStreamClient`</b>,
///                  \anchor PVR_ActStreamClient
///                  _string_,
///     @return The stream client name.
///     <p>
///   }
///   \table_row3{   <b>`PVR.ActStreamDevice`</b>,
///                  \anchor PVR_ActStreamDevice
///                  _string_,
///     @return The stream device name.
///     <p>
///   }
///   \table_row3{   <b>`PVR.ActStreamStatus`</b>,
///                  \anchor PVR_ActStreamStatus
///                  _string_,
///     @return The status of the stream.
///     <p>
///   }
///   \table_row3{   <b>`PVR.ActStreamSignal`</b>,
///                  \anchor PVR_ActStreamSignal
///                  _string_,
///     @return The signal quality of the stream.
///     <p>
///   }
///   \table_row3{   <b>`PVR.ActStreamSnr`</b>,
///                  \anchor PVR_ActStreamSnr
///                  _string_,
///     @return The signal to noise ratio of the stream.
///     <p>
///   }
///   \table_row3{   <b>`PVR.ActStreamBer`</b>,
///                  \anchor PVR_ActStreamBer
///                  _string_,
///     @return The bit error rate of the stream.
///     <p>
///   }
///   \table_row3{   <b>`PVR.ActStreamUnc`</b>,
///                  \anchor PVR_ActStreamUnc
///                  _string_,
///     @return The UNC value of the stream.
///     <p>
///   }
///   \table_row3{   <b>`PVR.ActStreamProgrSignal`</b>,
///                  \anchor PVR_ActStreamProgrSignal
///                  _integer_,
///     @return The signal quality of the programme.
///     <p>
///   }
///   \table_row3{   <b>`PVR.ActStreamProgrSnr`</b>,
///                  \anchor PVR_ActStreamProgrSnr
///                  _integer_,
///     @return The signal to noise ratio of the programme.
///     <p>
///   }
///   \table_row3{   <b>`PVR.ActStreamIsEncrypted`</b>,
///                  \anchor PVR_ActStreamIsEncrypted
///                  _boolean_,
///     @return **True** when channel is encrypted on source.
///     <p>
///   }
///   \table_row3{   <b>`PVR.ActStreamEncryptionName`</b>,
///                  \anchor PVR_ActStreamEncryptionName
///                  _string_,
///     @return The encryption used on the stream.
///     <p>
///   }
///   \table_row3{   <b>`PVR.ActStreamServiceName`</b>,
///                  \anchor PVR_ActStreamServiceName
///                  _string_,
///     @return The service name of played channel if available.
///     <p>
///   }
///   \table_row3{   <b>`PVR.ActStreamMux`</b>,
///                  \anchor PVR_ActStreamMux
///                  _string_,
///     @return The multiplex type of played channel if available.
///     <p>
///   }
///   \table_row3{   <b>`PVR.ActStreamProviderName`</b>,
///                  \anchor PVR_ActStreamProviderName
///                  _string_,
///     @return The provider name of the played channel if available.
///     <p>
///   }
///   \table_row3{   <b>`PVR.IsTimeShift`</b>,
///                  \anchor PVR_IsTimeShift
///                  _boolean_,
///     @return **True** when for channel is timeshift available.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeShiftProgress`</b>,
///                  \anchor PVR_TimeShiftProgress
///                  _integer_,
///     @return The position of currently timeshifted title on TV as integer.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeShiftSeekbar`</b>,
///                  \anchor PVR_TimeShiftSeekbar
///                  _integer_,
///     @return The percentage we are seeking to in a timeshifted title.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link PVR_TimeShiftSeekbar `PVR.TimeShiftSeekbar`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.NowRecordingTitle`</b>,
///                  \anchor PVR_NowRecordingTitle
///                  _string_,
///     @return The title of the programme being recorded.
///     <p>
///   }
///   \table_row3{   <b>`PVR.NowRecordingDateTime`</b>,
///                  \anchor PVR_NowRecordingDateTime
///                  _Date/Time string_,
///     @return The start date and time of the current recording.
///     <p>
///   }
///   \table_row3{   <b>`PVR.NowRecordingChannel`</b>,
///                  \anchor PVR_NowRecordingChannel
///                  _string_,
///     @return The channel name of the current recording.
///     <p>
///   }
///   \table_row3{   <b>`PVR.NowRecordingChannelIcon`</b>,
///                  \anchor PVR_NowRecordingChannelIcon
///                  _string_,
///     @return The icon of the current recording channel.
///     <p>
///   }
///   \table_row3{   <b>`PVR.NextRecordingTitle`</b>,
///                  \anchor PVR_NextRecordingTitle
///                  _string_,
///     @return The title of the next programme that will be recorded.
///     <p>
///   }
///   \table_row3{   <b>`PVR.NextRecordingDateTime`</b>,
///                  \anchor PVR_NextRecordingDateTime
///                  _Date/Time string_,
///     @return The start date and time of the next recording.
///     <p>
///   }
///   \table_row3{   <b>`PVR.NextRecordingChannel`</b>,
///                  \anchor PVR_NextRecordingChannel
///                  _string_,
///     @return The channel name of the next recording.
///     <p>
///   }
///   \table_row3{   <b>`PVR.NextRecordingChannelIcon`</b>,
///                  \anchor PVR_NextRecordingChannelIcon
///                  _string_,
///     @return The icon of the next recording channel.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TVNowRecordingTitle`</b>,
///                  \anchor PVR_TVNowRecordingTitle
///                  _string_,
///     @return The title of the tv programme being recorded.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_TVNowRecordingTitle `PVR.TVNowRecordingTitle`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TVNowRecordingDateTime`</b>,
///                  \anchor PVR_TVNowRecordingDateTime
///                  _Date/Time string_,
///     @return The start date and time of the current tv recording.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_TVNowRecordingDateTime `PVR.TVNowRecordingDateTime`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TVNowRecordingChannel`</b>,
///                  \anchor PVR_TVNowRecordingChannel
///                  _string_,
///     @return The channel name of the current tv recording.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_TVNowRecordingChannel `PVR.TVNowRecordingChannel`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TVNowRecordingChannelIcon`</b>,
///                  \anchor PVR_TVNowRecordingChannelIcon
///                  _string_,
///     @return The icon of the current recording TV channel.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_TVNowRecordingChannelIcon `PVR.TVNowRecordingChannelIcon`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TVNextRecordingTitle`</b>,
///                  \anchor PVR_TVNextRecordingTitle
///                  _string_,
///     @return The title of the next tv programme that will be recorded.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_TVNextRecordingTitle `PVR.TVNextRecordingTitle`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TVNextRecordingDateTime`</b>,
///                  \anchor PVR_TVNextRecordingDateTime
///                  _Date/Time string_,
///     @return The start date and time of the next tv recording.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_TVNextRecordingDateTime `PVR.TVNextRecordingDateTime`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TVNextRecordingChannel`</b>,
///                  \anchor PVR_TVNextRecordingChannel
///                  _string_,
///     @return The channel name of the next tv recording.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_TVNextRecordingChannel `PVR.TVNextRecordingChannel`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TVNextRecordingChannelIcon`</b>,
///                  \anchor PVR_TVNextRecordingChannelIcon
///                  _string_,
///     @return The icon of the next recording tv channel.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_TVNextRecordingChannelIcon `PVR.TVNextRecordingChannelIcon`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.RadioNowRecordingTitle`</b>,
///                  \anchor PVR_RadioNowRecordingTitle
///                  _string_,
///     @return The title of the radio programme being recorded.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_RadioNowRecordingTitle `PVR.RadioNowRecordingTitle`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.RadioNowRecordingDateTime`</b>,
///                  \anchor PVR_RadioNowRecordingDateTime
///                  _Date/Time string_,
///     @return The start date and time of the current radio recording.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_RadioNowRecordingDateTime `PVR.RadioNowRecordingDateTime`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.RadioNowRecordingChannel`</b>,
///                  \anchor PVR_RadioNowRecordingChannel
///                  _string_,
///     @return The channel name of the current radio recording.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_RadioNowRecordingChannel `PVR.RadioNowRecordingChannel`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.RadioNowRecordingChannelIcon`</b>,
///                  \anchor PVR_RadioNowRecordingChannelIcon
///                  _string_,
///     @return The icon of the current recording radio channel.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_RadioNowRecordingChannelIcon `PVR.RadioNowRecordingChannelIcon`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.RadioNextRecordingTitle`</b>,
///                  \anchor PVR_RadioNextRecordingTitle
///                  _string_,
///     @return The title of the next radio programme that will be recorded.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_RadioNextRecordingTitle `PVR.RadioNextRecordingTitle`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.RadioNextRecordingDateTime`</b>,
///                  \anchor PVR_RadioNextRecordingDateTime
///                  _Date/Time string_,
///     @return The start date and time of the next radio recording.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_RadioNextRecordingDateTime `PVR.RadioNextRecordingDateTime`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.RadioNextRecordingChannel`</b>,
///                  \anchor PVR_RadioNextRecordingChannel
///                  _string_,
///     @return The channel name of the next radio recording.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_RadioNextRecordingChannel `PVR.RadioNextRecordingChannel`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.RadioNextRecordingChannelIcon`</b>,
///                  \anchor PVR_RadioNextRecordingChannelIcon
///                  _string_,
///     @return The icon of the next recording radio channel.
///     <p><hr>
///     @skinning_v17 **[New Infolabel]** \link PVR_RadioNextRecordingChannelIcon `PVR.RadioNextRecordingChannelIcon`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.IsRecordingTV`</b>,
///                  \anchor PVR_IsRecordingTV
///                  _boolean_,
///     @return **True** when the system is recording a tv programme.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link PVR_IsRecordingTV `PVR.IsRecordingTV`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.HasTVTimer`</b>,
///                  \anchor PVR_HasTVTimer
///                  _boolean_,
///     @return **True** if at least one tv timer is active.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link PVR_HasTVTimer `PVR.HasTVTimer`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.HasNonRecordingTVTimer`</b>,
///                  \anchor PVR_HasNonRecordingTVTimer
///                  _boolean_,
///     @return **True** if there are tv timers present who currently not do recording.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link PVR_HasNonRecordingTVTimer `PVR.HasNonRecordingTVTimer`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.IsRecordingRadio`</b>,
///                  \anchor PVR_IsRecordingRadio
///                  _boolean_,
///     @return **True** when the system is recording a radio programme.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link PVR_IsRecordingRadio `PVR.IsRecordingRadio`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.HasRadioTimer`</b>,
///                  \anchor PVR_HasRadioTimer
///                  _boolean_,
///     @return **True** if at least one radio timer is active.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link PVR_HasRadioTimer `PVR.HasRadioTimer`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.HasNonRecordingRadioTimer`</b>,
///                  \anchor PVR_HasNonRecordingRadioTimer
///                  _boolean_,
///     @return **True** if there are radio timers present who currently not do recording.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link PVR_HasNonRecordingRadioTimer `PVR.HasRadioTimer`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.ChannelNumberInput`</b>,
///                  \anchor PVR_ChannelNumberInput
///                  _string_,
///     @return The currently entered channel number while in numeric channel input mode\, an empty string otherwise.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link PVR_ChannelNumberInput `PVR.ChannelNumberInput`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.CanRecordPlayingChannel`</b>,
///                  \anchor PVR_CanRecordPlayingChannel
///                  _boolean_,
///     @return **True** if PVR is currently playing a channel and if this channel can be recorded.
///     <p><hr>
///     @skinning_v18 **[Infolabel Updated]** \link PVR_CanRecordPlayingChannel `PVR.CanRecordPlayingChannel`\endlink replaces
///     the old `Player.CanRecord` infolabel.
///     <p>
///   }
///   \table_row3{   <b>`PVR.IsRecordingPlayingChannel`</b>,
///                  \anchor PVR_IsRecordingPlayingChannel
///                  _boolean_,
///     @return **True** if PVR is currently playing a channel and if this channel is currently recorded.
///     <p><hr>
///     @skinning_v18 **[Infolabel Updated]** \link PVR_IsRecordingPlayingChannel `PVR.IsRecordingPlayingChannel`\endlink replaces
///     the old `Player.Recording` infolabel.
///     <p>
///   }
///   \table_row3{   <b>`PVR.IsPlayingActiveRecording`</b>,
///                  \anchor PVR_IsPlayingActiveRecording
///                  _boolean_,
///     @return **True** if PVR is currently playing an in progress recording.
///     <p><hr>
///     @skinning_v19 **[New Infolabel]** \link PVR_IsPlayingActiveRecording `PVR.IsPlayingActiveRecording`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeshiftProgressPlayPos`</b>,
///                  \anchor PVR_TimeshiftProgressPlayPos
///                  _integer_,
///     @return The percentage of the current play position within the PVR timeshift progress.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link PVR_TimeshiftProgressPlayPos `PVR.TimeshiftProgressPlayPos`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeshiftProgressEpgStart`</b>,
///                  \anchor PVR_TimeshiftProgressEpgStart
///                  _integer_,
///     @return The percentage of the start of the currently playing epg event within the PVR timeshift progress.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link PVR_TimeshiftProgressEpgStart `PVR.TimeshiftProgressEpgStart`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeshiftProgressEpgEnd`</b>,
///                  \anchor PVR_TimeshiftProgressEpgEnd
///                  _integer_,
///     @return The percentage of the end of the currently playing epg event within the PVR timeshift progress.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link PVR_TimeshiftProgressEpgEnd `PVR.TimeshiftProgressEpgEnd`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeshiftProgressBufferStart`</b>,
///                  \anchor PVR_TimeshiftProgressBufferStart
///                  _integer_,
///     @return The percentage of the start of the timeshift buffer within the PVR timeshift progress.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link PVR_TimeshiftProgressBufferStart `PVR.TimeshiftProgressBufferStart`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeshiftProgressBufferEnd`</b>,
///                  \anchor PVR_TimeshiftProgressBufferEnd
///                  _integer_,
///     @return The percentage of the end of the timeshift buffer within the PVR timeshift progress.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link PVR_TimeshiftProgressBufferEnd `PVR.TimeshiftProgressBufferEnd`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.EpgEventIcon`</b>,
///                  \anchor PVR_EpgEventIcon
///                  _string_,
///     @return The icon of the currently playing epg event\, if any.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link PVR_EpgEventIcon `PVR_EpgEventIcon`\endlink
///     <p>
///   }
///
const infomap pvr[] =            {{ "isrecording",              PVR_IS_RECORDING },
                                  { "hastimer",                 PVR_HAS_TIMER },
                                  { "hastvchannels",            PVR_HAS_TV_CHANNELS },
                                  { "hasradiochannels",         PVR_HAS_RADIO_CHANNELS },
                                  { "hasnonrecordingtimer",     PVR_HAS_NONRECORDING_TIMER },
                                  { "backendname",              PVR_BACKEND_NAME },
                                  { "backendversion",           PVR_BACKEND_VERSION },
                                  { "backendhost",              PVR_BACKEND_HOST },
                                  { "backenddiskspace",         PVR_BACKEND_DISKSPACE },
                                  { "backenddiskspaceprogr",    PVR_BACKEND_DISKSPACE_PROGR },
                                  { "backendchannels",          PVR_BACKEND_CHANNELS },
                                  { "backendtimers",            PVR_BACKEND_TIMERS },
                                  { "backendrecordings",        PVR_BACKEND_RECORDINGS },
                                  { "backenddeletedrecordings", PVR_BACKEND_DELETED_RECORDINGS },
                                  { "backendnumber",            PVR_BACKEND_NUMBER },
                                  { "totaldiscspace",           PVR_TOTAL_DISKSPACE },
                                  { "nexttimer",                PVR_NEXT_TIMER },
                                  { "isplayingtv",              PVR_IS_PLAYING_TV },
                                  { "isplayingradio",           PVR_IS_PLAYING_RADIO },
                                  { "isplayingrecording",       PVR_IS_PLAYING_RECORDING },
                                  { "isplayingepgtag",          PVR_IS_PLAYING_EPGTAG },
                                  { "epgeventprogress",         PVR_EPG_EVENT_PROGRESS },
                                  { "actstreamclient",          PVR_ACTUAL_STREAM_CLIENT },
                                  { "actstreamdevice",          PVR_ACTUAL_STREAM_DEVICE },
                                  { "actstreamstatus",          PVR_ACTUAL_STREAM_STATUS },
                                  { "actstreamsignal",          PVR_ACTUAL_STREAM_SIG },
                                  { "actstreamsnr",             PVR_ACTUAL_STREAM_SNR },
                                  { "actstreamber",             PVR_ACTUAL_STREAM_BER },
                                  { "actstreamunc",             PVR_ACTUAL_STREAM_UNC },
                                  { "actstreamprogrsignal",     PVR_ACTUAL_STREAM_SIG_PROGR },
                                  { "actstreamprogrsnr",        PVR_ACTUAL_STREAM_SNR_PROGR },
                                  { "actstreamisencrypted",     PVR_ACTUAL_STREAM_ENCRYPTED },
                                  { "actstreamencryptionname",  PVR_ACTUAL_STREAM_CRYPTION },
                                  { "actstreamservicename",     PVR_ACTUAL_STREAM_SERVICE },
                                  { "actstreammux",             PVR_ACTUAL_STREAM_MUX },
                                  { "actstreamprovidername",    PVR_ACTUAL_STREAM_PROVIDER },
                                  { "istimeshift",              PVR_IS_TIMESHIFTING },
                                  { "timeshiftprogress",        PVR_TIMESHIFT_PROGRESS },
                                  { "timeshiftseekbar",         PVR_TIMESHIFT_SEEKBAR },
                                  { "nowrecordingtitle",        PVR_NOW_RECORDING_TITLE },
                                  { "nowrecordingdatetime",     PVR_NOW_RECORDING_DATETIME },
                                  { "nowrecordingchannel",      PVR_NOW_RECORDING_CHANNEL },
                                  { "nowrecordingchannelicon",  PVR_NOW_RECORDING_CHAN_ICO },
                                  { "nextrecordingtitle",       PVR_NEXT_RECORDING_TITLE },
                                  { "nextrecordingdatetime",    PVR_NEXT_RECORDING_DATETIME },
                                  { "nextrecordingchannel",     PVR_NEXT_RECORDING_CHANNEL },
                                  { "nextrecordingchannelicon", PVR_NEXT_RECORDING_CHAN_ICO },
                                  { "tvnowrecordingtitle",            PVR_TV_NOW_RECORDING_TITLE },
                                  { "tvnowrecordingdatetime",         PVR_TV_NOW_RECORDING_DATETIME },
                                  { "tvnowrecordingchannel",          PVR_TV_NOW_RECORDING_CHANNEL },
                                  { "tvnowrecordingchannelicon",      PVR_TV_NOW_RECORDING_CHAN_ICO },
                                  { "tvnextrecordingtitle",           PVR_TV_NEXT_RECORDING_TITLE },
                                  { "tvnextrecordingdatetime",        PVR_TV_NEXT_RECORDING_DATETIME },
                                  { "tvnextrecordingchannel",         PVR_TV_NEXT_RECORDING_CHANNEL },
                                  { "tvnextrecordingchannelicon",     PVR_TV_NEXT_RECORDING_CHAN_ICO },
                                  { "radionowrecordingtitle",         PVR_RADIO_NOW_RECORDING_TITLE },
                                  { "radionowrecordingdatetime",      PVR_RADIO_NOW_RECORDING_DATETIME },
                                  { "radionowrecordingchannel",       PVR_RADIO_NOW_RECORDING_CHANNEL },
                                  { "radionowrecordingchannelicon",   PVR_RADIO_NOW_RECORDING_CHAN_ICO },
                                  { "radionextrecordingtitle",        PVR_RADIO_NEXT_RECORDING_TITLE },
                                  { "radionextrecordingdatetime",     PVR_RADIO_NEXT_RECORDING_DATETIME },
                                  { "radionextrecordingchannel",      PVR_RADIO_NEXT_RECORDING_CHANNEL },
                                  { "radionextrecordingchannelicon",  PVR_RADIO_NEXT_RECORDING_CHAN_ICO },
                                  { "isrecordingtv",              PVR_IS_RECORDING_TV },
                                  { "hastvtimer",                 PVR_HAS_TV_TIMER },
                                  { "hasnonrecordingtvtimer",     PVR_HAS_NONRECORDING_TV_TIMER },
                                  { "isrecordingradio",           PVR_IS_RECORDING_RADIO },
                                  { "hasradiotimer",              PVR_HAS_RADIO_TIMER },
                                  { "hasnonrecordingradiotimer",  PVR_HAS_NONRECORDING_RADIO_TIMER },
                                  { "channelnumberinput",         PVR_CHANNEL_NUMBER_INPUT },
                                  { "canrecordplayingchannel",    PVR_CAN_RECORD_PLAYING_CHANNEL },
                                  { "isrecordingplayingchannel",  PVR_IS_RECORDING_PLAYING_CHANNEL },
                                  { "isplayingactiverecording",   PVR_IS_PLAYING_ACTIVE_RECORDING },
                                  { "timeshiftprogressplaypos",   PVR_TIMESHIFT_PROGRESS_PLAY_POS },
                                  { "timeshiftprogressepgstart",  PVR_TIMESHIFT_PROGRESS_EPG_START },
                                  { "timeshiftprogressepgend",    PVR_TIMESHIFT_PROGRESS_EPG_END },
                                  { "timeshiftprogressbufferstart", PVR_TIMESHIFT_PROGRESS_BUFFER_START },
                                  { "timeshiftprogressbufferend", PVR_TIMESHIFT_PROGRESS_BUFFER_END },
                                  { "epgeventicon",               PVR_EPG_EVENT_ICON }};

/// \page modules__infolabels_boolean_conditions
///   \table_row3{   <b>`PVR.EpgEventDuration`</b>,
///                  \anchor PVR_EpgEventDuration
///                  _string_,
///     @return The duration of the currently playing epg event in the
///     format <b>hh:mm:ss</b>.
///     @note <b>hh:</b> will be omitted if hours value is zero.
///     <p><hr>
///     @skinning_v18 **[Infolabel Updated]** \link PVR_EpgEventDuration `PVR.EpgEventDuration`\endlink replaces
///     the old `PVR.Duration` infolabel.
///     <p>
///   }
///   \table_row3{   <b>`PVR.EpgEventDuration(format)`</b>,
///                  \anchor PVR_EpgEventDuration_format
///                  _string_,
///     @return The duration of the currently playing EPG event in different formats.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`PVR.EpgEventElapsedTime`</b>,
///                  \anchor PVR_EpgEventElapsedTime
///                  _string_,
///     @return the time of the current position of the currently playing epg event in the
///     format <b>hh:mm:ss</b>.
///     @note <b>hh:</b> will be omitted if hours value is zero.
///     <p><hr>
///     @skinning_v18 **[Infolabel Updated]** \link PVR_EpgEventElapsedTime `PVR.EpgEventElapsedTime`\endlink replaces
///     the old `PVR.Time` infolabel.
///     <p>
///   }
///   \table_row3{   <b>`PVR.EpgEventElapsedTime(format)`</b>,
///                  \anchor PVR_EpgEventElapsedTime_format
///                  _string_,
///     @return The time of the current position of the currently playing epg event in different formats.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`PVR.EpgEventRemainingTime`</b>,
///                  \anchor PVR_EpgEventRemainingTime
///                  _string_,
///     @return The remaining time for currently playing epg event in the
///     format <b>hh:mm:ss</b>.
///     @note <b>hh:</b> will be omitted if hours value is zero.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link PVR_EpgEventRemainingTime `PVR.EpgEventRemainingTime`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.EpgEventRemainingTime(format)`</b>,
///                  \anchor PVR_EpgEventRemainingTime_format
///                  _string_,
///     @return The remaining time for currently playing epg event in different formats.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`PVR.EpgEventSeekTime`</b>,
///                  \anchor PVR_EpgEventSeekTime
///                  _string_,
///     @return The time the user is seeking within the currently playing epg event in the
///     format <b>hh:mm:ss</b>.
///     @note <b>hh:</b> will be omitted if hours value is zero.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link PVR_EpgEventSeekTime `PVR.EpgEventSeekTime`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.EpgEventSeekTime(format)`</b>,
///                  \anchor PVR_EpgEventSeekTime_format
///                  _string_,
///     @return The time the user is seeking within the currently playing epg event in different formats.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`PVR.EpgEventFinishTime`</b>,
///                  \anchor PVR_EpgEventFinishTime
///                  _string_,
///     @return The time the currently playing epg event will end in the
///     format <b>hh:mm:ss</b>.
///     @note <b>hh:</b> will be omitted if hours value is zero.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link PVR_EpgEventFinishTime `PVR.EpgEventFinishTime`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.EpgEventFinishTime(format)`</b>,
///                  \anchor PVR_EpgEventFinishTime_format
///                  _string_,
///     Returns the time the currently playing epg event will end in different formats.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeShiftStart`</b>,
///                  \anchor PVR_TimeShiftStart
///                  _string_,
///     @return The start time of the timeshift buffer in the
///     format <b>hh:mm:ss</b>.
///     @note <b>hh:</b> will be omitted if hours value is zero.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeShiftStart(format)`</b>,
///                  \anchor PVR_TimeShiftStart_format
///                  _string_,
///     Returns the start time of the timeshift buffer in different formats.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeShiftEnd`</b>,
///                  \anchor PVR_TimeShiftEnd
///                  _string_,
///     @return The end time of the timeshift buffer in the
///     format <b>hh:mm:ss</b>.
///     @note <b>hh:</b> will be omitted if hours value is zero.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeShiftEnd(format)`</b>,
///                  \anchor PVR_TimeShiftEnd_format
///                  _string_,
///     @return The end time of the timeshift buffer in different formats.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeShiftCur`</b>,
///                  \anchor PVR_TimeShiftCur
///                  _string_,
///     @return The current playback time within the timeshift buffer in the
///     format <b>hh:mm:ss</b>.
///     @note <b>hh:</b> will be omitted if hours value is zero.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeShiftCur(format)`</b>,
///                  \anchor PVR_TimeShiftCur_format
///                  _string_,
///     Returns the current playback time within the timeshift buffer in different formats.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeShiftOffset`</b>,
///                  \anchor PVR_TimeShiftOffset
///                  _string_,
///     @return The delta of timeshifted time to actual time in the
///     format <b>hh:mm:ss</b>.
///     @note <b>hh:</b> will be omitted if hours value is zero.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeShiftOffset(format)`</b>,
///                  \anchor PVR_TimeShiftOffset_format
///                  _string_,
///     Returns the delta of timeshifted time to actual time in different formats.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeshiftProgressDuration`</b>,
///                  \anchor PVR_TimeshiftProgressDuration
///                  _string_,
///     @return the duration of the PVR timeshift progress in the
///     format <b>hh:mm:ss</b>.
///     @note <b>hh:</b> will be omitted if hours value is zero.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link PVR_TimeshiftProgressDuration `PVR.TimeshiftProgressDuration`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeshiftProgressDuration(format)`</b>,
///                  \anchor PVR_TimeshiftProgressDuration_format
///                  _string_,
///     @return The duration of the PVR timeshift progress in different formats.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeshiftProgressStartTime`</b>,
///                  \anchor PVR_TimeshiftProgressStartTime
///                  _string_,
///     @return The start time of the PVR timeshift progress in the
///     format <b>hh:mm:ss</b>.
///     @note <b>hh:</b> will be omitted if hours value is zero.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link PVR_TimeshiftProgressStartTime `PVR.TimeshiftProgressStartTime`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeshiftProgressStartTime(format)`</b>,
///                  \anchor PVR_TimeshiftProgressStartTime_format
///                  _string_,
///     @return The start time of the PVR timeshift progress in different formats.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeshiftProgressEndTime`</b>,
///                  \anchor PVR_TimeshiftProgressEndTime
///                  _string_,
///     @return The end time of the PVR timeshift progress in the
///     format <b>hh:mm:ss</b>.
///     @note hh: will be omitted if hours value is zero.
///     <p><hr>
///     @skinning_v18 **[New Infolabel]** \link PVR_TimeshiftProgressEndTime `PVR.TimeshiftProgressEndTime`\endlink
///     <p>
///   }
///   \table_row3{   <b>`PVR.TimeshiftProgressEndTime(format)`</b>,
///                  \anchor PVR_TimeshiftProgressEndTime_format
///                  _string_,
///     @return The end time of the PVR timeshift progress in different formats.
///     @param format [opt] The format of the return time value.
///     See \ref TIME_FORMAT for the list of possible values.
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap pvr_times[] =      {{ "epgeventduration",       PVR_EPG_EVENT_DURATION },
                                  { "epgeventelapsedtime",    PVR_EPG_EVENT_ELAPSED_TIME },
                                  { "epgeventremainingtime",  PVR_EPG_EVENT_REMAINING_TIME },
                                  { "epgeventfinishtime",     PVR_EPG_EVENT_FINISH_TIME },
                                  { "epgeventseektime",       PVR_EPG_EVENT_SEEK_TIME },
                                  { "timeshiftstart",         PVR_TIMESHIFT_START_TIME },
                                  { "timeshiftend",           PVR_TIMESHIFT_END_TIME },
                                  { "timeshiftcur",           PVR_TIMESHIFT_PLAY_TIME },
                                  { "timeshiftoffset",        PVR_TIMESHIFT_OFFSET },
                                  { "timeshiftprogressduration",  PVR_TIMESHIFT_PROGRESS_DURATION },
                                  { "timeshiftprogressstarttime", PVR_TIMESHIFT_PROGRESS_START_TIME },
                                  { "timeshiftprogressendtime",   PVR_TIMESHIFT_PROGRESS_END_TIME }};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_RDS RDS
/// @note Only supported if both the PVR backend and the Kodi client support RDS.
///
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`RDS.HasRds`</b>,
///                  \anchor RDS_HasRds
///                  _boolean_,
///     @return **True** if RDS is present.
///     <p><hr>
///     @skinning_v16 **[New Boolean Condition]** \link RDS_HasRds `RDS.HasRds`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.HasRadioText`</b>,
///                  \anchor RDS_HasRadioText
///                  _boolean_,
///     @return **True** if RDS contains also RadioText.
///     <p><hr>
///     @skinning_v16 **[New Boolean Condition]** \link RDS_HasRadioText `RDS.HasRadioText`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.HasRadioTextPlus`</b>,
///                  \anchor RDS_HasRadioTextPlus
///                  _boolean_,
///     @return **True** if RDS with RadioText contains also the plus information.
///     <p><hr>
///     @skinning_v16 **[New Boolean Condition]** \link RDS_HasRadioTextPlus `RDS.HasRadioTextPlus`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.HasHotline`</b>,
///                  \anchor RDS_HasHotline
///                  _boolean_,
///     @return **True** if a hotline phone number is present.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Boolean Condition]** \link RDS_HasHotline `RDS.HasHotline`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.HasStudio`</b>,
///                  \anchor RDS_HasStudio
///                  _boolean_,
///     @return **True** if a studio name is present.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Boolean Condition]** \link RDS_HasStudio `RDS.HasStudio`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.AudioLanguage`</b>,
///                  \anchor RDS_AudioLanguage
///                  _string_,
///     @return The RDS reported audio language of the channel.
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_AudioLanguage `RDS.AudioLanguage`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.ChannelCountry`</b>,
///                  \anchor RDS_ChannelCountry
///                  _string_,
///     @return The country where the radio channel is broadcasted.
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_ChannelCountry `RDS.ChannelCountry`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.GetLine(number)`</b>,
///                  \anchor RDS_GetLine
///                  _string_,
///     @return The last sent RDS text messages on given number.
///     @param number - given number for RDS\, 0 is the
///     last and 4 rows are supported (0-3)
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_GetLine `RDS.GetLine(number)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.Title`</b>,
///                  \anchor RDS_Title
///                  _string_,
///     @return The title of item; e.g. track title of an album.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_Title `RDS.Title`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.Artist`</b>,
///                  \anchor RDS_Artist
///                  _string_,
///     @return A person or band/collective generally considered responsible for the work.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_Artist `RDS.Artist`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.Band`</b>,
///                  \anchor RDS_Band
///                  _string_,
///     @return The band/orchestra/musician.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_Band `RDS.Band`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.Composer`</b>,
///                  \anchor RDS_Composer
///                  _string_,
///     @return The name of the original composer/author.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_Composer `RDS.Composer`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.Conductor`</b>,
///                  \anchor RDS_Conductor
///                  _string_,
///     @return The artist(s) who performed the work. In classical music this would be
///     the conductor.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_Conductor `RDS.Conductor`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.Album`</b>,
///                  \anchor RDS_Album
///                  _string_,
///     @return The album of the song.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_Album `RDS.Album`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.TrackNumber`</b>,
///                  \anchor RDS_TrackNumber
///                  _string_,
///     @return The track number of the item on the album on which it was originally
///     released.
///     @note Only be available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_TrackNumber `RDS.TrackNumber`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.RadioStyle`</b>,
///                  \anchor RDS_RadioStyle
///                  _string_,
///     @return The style of current played radio channel\, it is always
///     updated once the style changes\, e.g "popmusic" to "news" or "weather"...
///     | RDS                     | RBDS                    |
///     |:------------------------|:------------------------|
///     | none                    | none                    |
///     | news                    | news                    |
///     | currentaffairs          | information             |
///     | information             | sport                   |
///     | sport                   | talk                    |
///     | education               | rockmusic               |
///     | drama                   | classicrockmusic        |
///     | cultures                | adulthits               |
///     | science                 | softrock                |
///     | variedspeech            | top40                   |
///     | popmusic                | countrymusic            |
///     | rockmusic               | oldiesmusic             |
///     | easylistening           | softmusic               |
///     | lightclassics           | nostalgia               |
///     | seriousclassics         | jazzmusic               |
///     | othermusic              | classical               |
///     | weather                 | randb                   |
///     | finance                 | softrandb               |
///     | childrensprogs          | language                |
///     | socialaffairs           | religiousmusic          |
///     | religion                | religioustalk           |
///     | phonein                 | personality             |
///     | travelandtouring        | public                  |
///     | leisureandhobby         | college                 |
///     | jazzmusic               | spanishtalk             |
///     | countrymusic            | spanishmusic            |
///     | nationalmusic           | hiphop                  |
///     | oldiesmusic             |                         |
///     | folkmusic               |                         |
///     | documentary             | weather                 |
///     | alarmtest               | alarmtest               |
///     | alarm-alarm             | alarm-alarm             |
///     @note "alarm-alarm" is normally not used from radio stations\, is thought
///     to inform about horrible messages who are needed asap to all people.
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_RadioStyle `RDS.RadioStyle`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.Comment`</b>,
///                  \anchor RDS_Comment
///                  _string_,
///     @return The radio station comment string if available.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_Comment `RDS.Comment`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoNews`</b>,
///                  \anchor RDS_InfoNews
///                  _string_,
///     @return The message / headline (if available).
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoNews `RDS.InfoNews`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoNewsLocal`</b>,
///                  \anchor RDS_InfoNewsLocal
///                  _string_,
///     @return The local information news sended from radio channel (if available).
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoNewsLocal `RDS.InfoNewsLocal`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoStock`</b>,
///                  \anchor RDS_InfoStock
///                  _string_,
///     @return The stock information; either as one part or as several distinct parts:
///     "name 99latest value 99change 99high 99low 99volume" (if available).
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoStock `RDS.InfoStock`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoStockSize`</b>,
///                  \anchor RDS_InfoStockSize
///                  _string_,
///     @return The number of rows present in stock information.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoStockSize `RDS.InfoStockSize`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoSport`</b>,
///                  \anchor RDS_InfoSport
///                  _string_,
///     @return The result of a match; either as one part or as several distinct parts:
///     "match 99result"\, e.g. "Bayern München : Borussia 995:5"  (if available).
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoSport `RDS.InfoSport`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoSportSize`</b>,
///                  \anchor RDS_InfoSportSize
///                  _string_,
///     @return The number of rows present in sport information.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoSportSize `RDS.InfoSportSize`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoLottery`</b>,
///                  \anchor RDS_InfoLottery
///                  _string_,
///     @return The raffle / lottery: "key word 99values" (if available).
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoLottery `RDS.InfoLottery`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoLotterySize`</b>,
///                  \anchor RDS_InfoLotterySize
///                  _string_,
///     @return The number of rows present in lottery information.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoLotterySize `RDS.InfoLotterySize`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoWeather`</b>,
///                  \anchor RDS_InfoWeather
///                  _string_,
///     @return The weather information (if available).
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoWeather `RDS.InfoWeather`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoWeatherSize`</b>,
///                  \anchor RDS_InfoWeatherSize
///                  _string_,
///     @return The number of rows present in weather information.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoWeatherSize `RDS.InfoWeatherSize`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoCinema`</b>,
///                  \anchor RDS_InfoCinema
///                  _string_,
///     @return The information about movies in cinema (if available).
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoCinema `RDS.InfoCinema`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoCinemaSize`</b>,
///                  \anchor RDS_InfoCinemaSize
///                  _string_,
///     @return The number of rows present in cinema information.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoCinemaSize `RDS.InfoCinemaSize`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoHoroscope`</b>,
///                  \anchor RDS_InfoHoroscope
///                  _string_,
///     @return The horoscope; either as one part or as two distinct parts:
///     "key word 99text"\, e.g. "sign of the zodiac 99blablabla" (if available).
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoHoroscope `RDS.InfoHoroscope`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoHoroscopeSize`</b>,
///                  \anchor RDS_InfoHoroscopeSize
///                  _string_,
///     @return The Number of rows present in horoscope information.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoHoroscopeSize `RDS.InfoHoroscopeSize`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoOther`</b>,
///                  \anchor RDS_InfoOther
///                  _string_,
///     @return Other information\, not especially specified: "key word 99info" (if available).
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoOther `RDS.InfoOther`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.InfoOtherSize`</b>,
///                  \anchor RDS_InfoOtherSize
///                  _string_,
///     @return The number of rows present with other information.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_InfoOtherSize `RDS.InfoOtherSize`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.ProgStation`</b>,
///                  \anchor RDS_ProgStation
///                  _string_,
///     @return The name of the radio channel.
///     @note becomes also set from epg if it is not available from RDS
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_ProgStation `RDS.ProgStation`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.ProgNow`</b>,
///                  \anchor RDS_ProgNow
///                  _string_,
///     @return The now playing program name.
///     @note becomes also be set from epg if from RDS not available
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_ProgNow `RDS.ProgNow`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.ProgNext`</b>,
///                  \anchor RDS_ProgNext
///                  _string_,
///     @return The next played program name (if available).
///     @note becomes also be set from epg if from RDS not available
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_ProgNext `RDS.ProgNext`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.ProgHost`</b>,
///                  \anchor RDS_ProgHost
///                  _string_,
///     @return The name of the host of the radio show.
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_ProgHost `RDS.ProgHost`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.ProgEditStaff`</b>,
///                  \anchor RDS_ProgEditStaff
///                  _string_,
///     @return The name of the editorial staff; e.g. name of editorial journalist.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_ProgEditStaff `RDS.ProgEditStaff`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.ProgHomepage`</b>,
///                  \anchor RDS_ProgHomepage
///                  _string_,
///     @return The Link to radio station homepage
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_ProgHomepage `RDS.ProgHomepage`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.ProgStyle`</b>,
///                  \anchor RDS_ProgStyle
///                  _string_,
///     @return A human readable string about radiostyle defined from RDS or RBDS.
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_ProgStyle `RDS.ProgStyle`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.PhoneHotline`</b>,
///                  \anchor RDS_PhoneHotline
///                  _string_,
///     @return The telephone number of the radio station's hotline.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_PhoneHotline `RDS.PhoneHotline`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.PhoneStudio`</b>,
///                  \anchor RDS_PhoneStudio
///                  _string_,
///     @return The telephone number of the radio station's studio.
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_PhoneStudio `RDS.PhoneStudio`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.SmsStudio`</b>,
///                  \anchor RDS_SmsStudio
///                  _string_,
///     @return The sms number of the radio stations studio (to send directly a sms to
///     the studio) (if available).
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_SmsStudio `RDS.SmsStudio`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.EmailHotline`</b>,
///                  \anchor RDS_EmailHotline
///                  _string_,
///     @return The email address of the radio stations hotline (if available).
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_EmailHotline `RDS.EmailHotline`\endlink
///     <p>
///   }
///   \table_row3{   <b>`RDS.EmailStudio`</b>,
///                  \anchor RDS_EmailStudio
///                  _string_,
///     @return The email address of the radio station's studio (if available).
///     @note Only available on RadioText Plus
///     <p><hr>
///     @skinning_v16 **[New Infolabel]** \link RDS_EmailStudio `RDS.EmailStudio`\endlink
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap rds[] =            {{ "hasrds",                   RDS_HAS_RDS },
                                  { "hasradiotext",             RDS_HAS_RADIOTEXT },
                                  { "hasradiotextplus",         RDS_HAS_RADIOTEXT_PLUS },
                                  { "audiolanguage",            RDS_AUDIO_LANG },
                                  { "channelcountry",           RDS_CHANNEL_COUNTRY },
                                  { "title",                    RDS_TITLE },
                                  { "getline",                  RDS_GET_RADIOTEXT_LINE },
                                  { "artist",                   RDS_ARTIST },
                                  { "band",                     RDS_BAND },
                                  { "composer",                 RDS_COMPOSER },
                                  { "conductor",                RDS_CONDUCTOR },
                                  { "album",                    RDS_ALBUM },
                                  { "tracknumber",              RDS_ALBUM_TRACKNUMBER },
                                  { "radiostyle",               RDS_GET_RADIO_STYLE },
                                  { "comment",                  RDS_COMMENT },
                                  { "infonews",                 RDS_INFO_NEWS },
                                  { "infonewslocal",            RDS_INFO_NEWS_LOCAL },
                                  { "infostock",                RDS_INFO_STOCK },
                                  { "infostocksize",            RDS_INFO_STOCK_SIZE },
                                  { "infosport",                RDS_INFO_SPORT },
                                  { "infosportsize",            RDS_INFO_SPORT_SIZE },
                                  { "infolottery",              RDS_INFO_LOTTERY },
                                  { "infolotterysize",          RDS_INFO_LOTTERY_SIZE },
                                  { "infoweather",              RDS_INFO_WEATHER },
                                  { "infoweathersize",          RDS_INFO_WEATHER_SIZE },
                                  { "infocinema",               RDS_INFO_CINEMA },
                                  { "infocinemasize",           RDS_INFO_CINEMA_SIZE },
                                  { "infohoroscope",            RDS_INFO_HOROSCOPE },
                                  { "infohoroscopesize",        RDS_INFO_HOROSCOPE_SIZE },
                                  { "infoother",                RDS_INFO_OTHER },
                                  { "infoothersize",            RDS_INFO_OTHER_SIZE },
                                  { "progstation",              RDS_PROG_STATION },
                                  { "prognow",                  RDS_PROG_NOW },
                                  { "prognext",                 RDS_PROG_NEXT },
                                  { "proghost",                 RDS_PROG_HOST },
                                  { "progeditstaff",            RDS_PROG_EDIT_STAFF },
                                  { "proghomepage",             RDS_PROG_HOMEPAGE },
                                  { "progstyle",                RDS_PROG_STYLE },
                                  { "phonehotline",             RDS_PHONE_HOTLINE },
                                  { "phonestudio",              RDS_PHONE_STUDIO },
                                  { "smsstudio",                RDS_SMS_STUDIO },
                                  { "emailhotline",             RDS_EMAIL_HOTLINE },
                                  { "emailstudio",              RDS_EMAIL_STUDIO },
                                  { "hashotline",               RDS_HAS_HOTLINE_DATA },
                                  { "hasstudio",                RDS_HAS_STUDIO_DATA }};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_slideshow Slideshow
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`Slideshow.IsActive`</b>,
///                  \anchor Slideshow_IsActive
///                  _boolean_,
///     @return **True** if the picture slideshow is running.
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.IsPaused`</b>,
///                  \anchor Slideshow_IsPaused
///                  _boolean_,
///     @return **True** if the picture slideshow is paused.
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.IsRandom`</b>,
///                  \anchor Slideshow_IsRandom
///                  _boolean_,
///     @return **True** if the picture slideshow is in random mode.
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.IsVideo`</b>,
///                  \anchor Slideshow_IsVideo
///                  _boolean_,
///     @return **True** if the picture slideshow is playing a video.
///     <p><hr>
///     @skinning_v13 **[New Boolean Condition]** \link Slideshow_IsVideo `Slideshow.IsVideo`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Altitude`</b>,
///                  \anchor Slideshow_Altitude
///                  _string_,
///     @return The altitude in meters where the current picture was taken.
///     @note This is the value of the EXIF GPSInfo.GPSAltitude tag.
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Aperture`</b>,
///                  \anchor Slideshow_Aperture
///                  _string_,
///     @return The F-stop used to take the current picture.
///     @note This is the value of the EXIF FNumber tag (hex code 0x829D).
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Author`</b>,
///                  \anchor Slideshow_Author
///                  _string_,
///     @return The name of the person involved in writing about the current
///     picture.
///     @note This is the value of the IPTC Writer tag (hex code 0x7A).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_Author `Slideshow.Author`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Byline`</b>,
///                  \anchor Slideshow_Byline
///                  _string_,
///     @return The name of the person who created the current picture.
///     @note This is the value of the IPTC Byline tag (hex code 0x50).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_Byline `Slideshow.Byline`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.BylineTitle`</b>,
///                  \anchor Slideshow_BylineTitle
///                  _string_,
///     @return The title of the person who created the current picture.
///     @note This is the value of the IPTC BylineTitle tag (hex code 0x55).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_BylineTitle `Slideshow.BylineTitle`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.CameraMake`</b>,
///                  \anchor Slideshow_CameraMake
///                  _string_,
///     @return The manufacturer of the camera used to take the current picture.
///     @note This is the value of the EXIF Make tag (hex code 0x010F).
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.CameraModel`</b>,
///                  \anchor Slideshow_CameraModel
///                  _string_,
///     @return The manufacturer's model name or number of the camera used to take
///     the current picture.
///     @note This is the value of the EXIF Model tag (hex code 0x0110).
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Caption`</b>,
///                  \anchor Slideshow_Caption
///                  _string_,
///     @return A description of the current picture.
///     @note This is the value of the IPTC Caption tag (hex code 0x78).
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Category`</b>,
///                  \anchor Slideshow_Category
///                  _string_,
///     @return The subject of the current picture as a category code.
///     @note This is the value of the IPTC Category tag (hex code 0x0F).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_Category `Slideshow.Category`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.CCDWidth`</b>,
///                  \anchor Slideshow_CCDWidth
///                  _string_,
///     @return The width of the CCD in the camera used to take the current
///     picture.
///     @note This is calculated from three EXIF tags (0xA002 * 0xA210 / 0xA20e).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_CCDWidth `Slideshow.CCDWidth`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.City`</b>,
///                  \anchor Slideshow_City
///                  _string_,
///     @return The city where the current picture was taken.
///     @note This is the value of the IPTC City tag (hex code 0x5A).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_City `Slideshow.City`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Colour`</b>,
///                  \anchor Slideshow_Colour
///                  _string_,
///     @return the colour of the picture. It can have one of the following values:
///       - <b>"Colour"</b>
///       - <b>"Black and White"</b>
///     <p>
///     @deprecated Slideshow_Colour `Slideshow.Colour`\endlink is deprecated and will be removed in future Kodi versions
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_Colour `Slideshow.Colour`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.CopyrightNotice`</b>,
///                  \anchor Slideshow_CopyrightNotice
///                  _string_,
///     @return The copyright notice of the current picture.
///     @note This is the value of the IPTC Copyright tag (hex code 0x74).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_CopyrightNotice `Slideshow.CopyrightNotice`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Country`</b>,
///                  \anchor Slideshow_Country
///                  _string_,
///     @return The full name of the country where the current picture was taken.
///     @note This is the value of the IPTC CountryName tag (hex code 0x65).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_Country `Slideshow.Country`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.CountryCode`</b>,
///                  \anchor Slideshow_CountryCode
///                  _string_,
///     @return The country code of the country where the current picture was
///     taken.
///     @note This is the value of the IPTC CountryCode tag (hex code 0x64).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_CountryCode `Slideshow.CountryCode`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Credit`</b>,
///                  \anchor Slideshow_Credit
///                  _string_,
///     @return Who provided the current picture.
///     @note This is the value of the IPTC Credit tag (hex code 0x6E).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_Credit `Slideshow.Credit`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.DigitalZoom`</b>,
///                  \anchor Slideshow_DigitalZoom
///                  _string_,
///     @return The digital zoom ratio when the current picture was taken.
///     @note This is the value of the EXIF .DigitalZoomRatio tag (hex code 0xA404).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_DigitalZoom `Slideshow.DigitalZoom`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.EXIFComment`</b>,
///                  \anchor Slideshow_EXIFComment
///                  _string_,
///     @return A description of the current picture.
///     @note This is the value of the EXIF User Comment tag (hex code 0x9286).
///     This is the same value as \ref Slideshow_SlideComment "Slideshow.SlideComment".
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.EXIFDate`</b>,
///                  \anchor Slideshow_EXIFDate
///                  _string_,
///     @return The localized date of the current picture. The short form of the
///     date is used.
///     @note The value of the EXIF DateTimeOriginal tag (hex code
///     0x9003) is preferred. If the DateTimeOriginal tag is not found\, the
///     value of DateTimeDigitized (hex code 0x9004) or of DateTime (hex code
///     0x0132) might be used.
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_EXIFDate `Slideshow.EXIFDate`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.EXIFDescription`</b>,
///                  \anchor Slideshow_EXIFDescription
///                  _string_,
///     @return A short description of the current picture. The SlideComment\,
///     EXIFComment or Caption values might contain a longer description.
///     @note This is the value of the EXIF ImageDescription tag (hex code 0x010E).
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.EXIFSoftware`</b>,
///                  \anchor Slideshow_EXIFSoftware
///                  _string_,
///     @return The name and version of the firmware used by the camera that took
///     the current picture.
///     @note This is the value of the EXIF Software tag (hex code 0x0131).
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.EXIFTime`</b>,
///                  \anchor Slideshow_EXIFTime
///                  _string_,
///     @return The date/timestamp of the current picture. The localized short
///     form of the date and time is used.
///     @note The value of the EXIF DateTimeOriginal tag (hex code 0x9003) is
///     preferred. If the DateTimeOriginal tag is not found\, the value of
///     DateTimeDigitized (hex code 0x9004) or of DateTime (hex code 0x0132)
///     might be used.
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Exposure`</b>,
///                  \anchor Slideshow_Exposure
///                  _string_,
///     @return The class of the program used by the camera to set exposure when
///     the current picture was taken. Values include:
///      - <b>"Manual"</b>
///      - <b>"Program (Auto)"</b>
///      - <b>"Aperture priority (Semi-Auto)"</b>
///      - <b>"Shutter priority (semi-auto)"</b>
///      - etc...
///     @note This is the value of the EXIF ExposureProgram tag
///     (hex code 0x8822).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_Exposure `Slideshow.Exposure`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.ExposureBias`</b>,
///                  \anchor Slideshow_ExposureBias
///                  _string_,
///     @return The exposure bias of the current picture. Typically this is a
///     number between -99.99 and 99.99.
///     @note This is the value of the EXIF ExposureBiasValue tag (hex code 0x9204).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_ExposureBias `Slideshow.ExposureBias`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.ExposureMode`</b>,
///                  \anchor Slideshow_ExposureMode
///                  _string_,
///     @return The exposure mode of the current picture. The possible values are:
///      - <b>"Automatic"</b>
///      - <b>"Manual"</b>
///      - <b>"Auto bracketing"</b>
///     @note This is the value of the EXIF ExposureMode tag (hex code 0xA402).
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.ExposureTime`</b>,
///                  \anchor Slideshow_ExposureTime
///                  _string_,
///     @return The exposure time of the current picture\, in seconds.
///     @note This is the value of the EXIF ExposureTime tag (hex code 0x829A).
///     If the ExposureTime tag is not found\, the ShutterSpeedValue tag (hex code
///     0x9201) might be used.
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Filedate`</b>,
///                  \anchor Slideshow_Filedate
///                  _string_,
///     @return The file date of the current picture.
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Filename`</b>,
///                  \anchor Slideshow_Filename
///                  _string_,
///     @return The file name of the current picture.
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Filesize`</b>,
///                  \anchor Slideshow_Filesize
///                  _string_,
///     @return The file size of the current picture.
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.FlashUsed`</b>,
///                  \anchor Slideshow_FlashUsed
///                  _string_,
///     @return The status of flash when the current picture was taken. The value
///     will be either <b>"Yes"</b> or <b>"No"</b>\, and might include additional information.
///     @note This is the value of the EXIF Flash tag (hex code 0x9209).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_FlashUsed `Slideshow.FlashUsed`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.FocalLength`</b>,
///                  \anchor Slideshow_FocalLength
///                  _string_,
///     @return The focal length of the lens\, in mm.
///     @note This is the value of the EXIF FocalLength tag (hex code 0x920A).
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.FocusDistance`</b>,
///                  \anchor Slideshow_FocusDistance
///                  _string_,
///     @return The distance to the subject\, in meters.
///     @note This is the value of the EXIF SubjectDistance tag (hex code 0x9206).
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Headline`</b>,
///                  \anchor Slideshow_Headline
///                  _string_,
///     @return A synopsis of the contents of the current picture.
///     @note This is the value of the IPTC Headline tag (hex code 0x69).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_Headline `Slideshow.Headline`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.ImageType`</b>,
///                  \anchor Slideshow_ImageType
///                  _string_,
///     @return The color components of the current picture.
///     @note This is the value of the IPTC ImageType tag (hex code 0x82).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_ImageType `Slideshow.ImageType`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.IPTCDate`</b>,
///                  \anchor Slideshow_IPTCDate
///                  _string_,
///     @return The date when the intellectual content of the current picture was
///     created\, rather than when the picture was created.
///     @note This is the value of the IPTC DateCreated tag (hex code 0x37).
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.ISOEquivalence`</b>,
///                  \anchor Slideshow_ISOEquivalence
///                  _string_,
///     @return The ISO speed of the camera when the current picture was taken.
///     @note This is the value of the EXIF ISOSpeedRatings tag (hex code 0x8827).
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Keywords`</b>,
///                  \anchor Slideshow_Keywords
///                  _string_,
///     @return The keywords assigned to the current picture.
///     @note This is the value of the IPTC Keywords tag (hex code 0x19).
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Latitude`</b>,
///                  \anchor Slideshow_Latitude
///                  _string_,
///     @return The latitude where the current picture was taken (degrees\,
///     minutes\, seconds North or South).
///     @note This is the value of the EXIF GPSInfo.GPSLatitude and
///     GPSInfo.GPSLatitudeRef tags.
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.LightSource`</b>,
///                  \anchor Slideshow_LightSource
///                  _string_,
///     @return The kind of light source when the picture was taken. Possible
///     values include:
///      - <b>"Daylight"</b>
///      - <b>"Fluorescent"</b>
///      - <b>"Incandescent"</b>
///      - etc...
///     @note This is the value of the EXIF LightSource tag (hex code 0x9208).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_LightSource `Slideshow.LightSource`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.LongEXIFDate`</b>,
///                  \anchor Slideshow_LongEXIFDate
///                  _string_,
///     @return Only the localized date of the current picture. The long form of
///     the date is used.
///     @note The value of the EXIF DateTimeOriginal tag (hex code
///     0x9003) is preferred. If the DateTimeOriginal tag is not found\, the
///     value of DateTimeDigitized (hex code 0x9004) or of DateTime (hex code
///     0x0132) might be used.
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_LongEXIFDate `Slideshow.LongEXIFDate`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.LongEXIFTime`</b>,
///                  \anchor Slideshow_LongEXIFTime
///                  _string_,
///     @return The date/timestamp of the current picture. The localized long form
///     of the date and time is used.
///     @note The value of the EXIF DateTimeOriginal tag
///     (hex code 0x9003) is preferred. if the DateTimeOriginal tag is not found\,
///     the value of DateTimeDigitized (hex code 0x9004) or of DateTime (hex
///     code 0x0132) might be used.
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_LongEXIFTime `Slideshow.LongEXIFTime`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Longitude`</b>,
///                  \anchor Slideshow_Longitude
///                  _string_,
///     @return The longitude where the current picture was taken (degrees\,
///     minutes\, seconds East or West).
///     @note This is the value of the EXIF GPSInfo.GPSLongitude and
///     GPSInfo.GPSLongitudeRef tags.
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.MeteringMode`</b>,
///                  \anchor Slideshow_MeteringMode
///                  _string_,
///     @return The metering mode used when the current picture was taken. The
///     possible values are:
///      - <b>"Center weight"</b>
///      - <b>"Spot"</b>
///      - <b>"Matrix"</b>
///     @note This is the value of the EXIF MeteringMode tag (hex code 0x9207).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_MeteringMode `Slideshow.MeteringMode`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.ObjectName`</b>,
///                  \anchor Slideshow_ObjectName
///                  _string_,
///     @return a shorthand reference for the current picture.
///     @note This is the value of the IPTC ObjectName tag (hex code 0x05).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_ObjectName `Slideshow.ObjectName`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Orientation`</b>,
///                  \anchor Slideshow_Orientation
///                  _string_,
///     @return The orientation of the current picture. Possible values are:
///      - <b>"Top Left"</b>
///      - <b>"Top Right"</b>
///      - <b>"Left Top"</b>
///      - <b>"Right Bottom"</b>
///      - etc...
///     @note This is the value of the EXIF Orientation tag (hex code 0x0112).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_Orientation `Slideshow.Orientation`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Path`</b>,
///                  \anchor Slideshow_Path
///                  _string_,
///     @return The file path of the current picture.
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Process`</b>,
///                  \anchor Slideshow_Process
///                  _string_,
///     @return The process used to compress the current picture.
///     <p>
///     @deprecated \link Slideshow_Process `Slideshow.Process`\endlink is deprecated and will be removed in future Kodi versions
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_Process `Slideshow.Process`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.ReferenceService`</b>,
///                  \anchor Slideshow_ReferenceService
///                  _string_,
///     @return The Service Identifier of a prior envelope to which the current
///     picture refers.
///     @note This is the value of the IPTC ReferenceService tag (hex code 0x2D).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_ReferenceService `Slideshow.ReferenceService`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Resolution`</b>,
///                  \anchor Slideshow_Resolution
///                  _string_,
///     @return The dimensions of the current picture (Width x Height)
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.SlideComment`</b>,
///                  \anchor Slideshow_SlideComment
///                  _string_,
///     @return A description of the current picture.
///     @note This is the value of the EXIF User Comment tag (hex code 0x9286).
///     This is the same value as \ref Slideshow_EXIFComment "Slideshow.EXIFComment".
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.SlideIndex`</b>,
///                  \anchor Slideshow_SlideIndex
///                  _string_,
///     @return The slide index of the current picture.
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Source`</b>,
///                  \anchor Slideshow_Source
///                  _string_,
///     @return The original owner of the current picture.
///     @note This is the value of the IPTC Source tag (hex code 0x73).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_Source `Slideshow.Source`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.SpecialInstructions`</b>,
///                  \anchor Slideshow_SpecialInstructions
///                  _string_,
///     @return Other editorial instructions concerning the use of the current
///     picture.
///     @note This is the value of the IPTC SpecialInstructions tag (hex code 0x28).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_SpecialInstructions `Slideshow.SpecialInstructions`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.State`</b>,
///                  \anchor Slideshow_State
///                  _string_,
///     @return The State/Province where the current picture was taken.
///     @note This is the value of the IPTC ProvinceState tag (hex code 0x5F).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_State `Slideshow.State`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Sublocation`</b>,
///                  \anchor Slideshow_Sublocation
///                  _string_,
///     @return The location within a city where the current picture was taken -
///     might indicate the nearest landmark.
///     @note This is the value of the IPTC SubLocation tag (hex code 0x5C).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_Sublocation `Slideshow.Sublocation`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.SupplementalCategories`</b>,
///                  \anchor Slideshow_SupplementalCategories
///                  _string_,
///     @return The supplemental category codes to further refine the subject of the
///     current picture.
///     @note This is the value of the IPTC SuppCategory tag (hex
///     code 0x14).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_SupplementalCategories `Slideshow.SupplementalCategories`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.TimeCreated`</b>,
///                  \anchor Slideshow_TimeCreated
///                  _string_,
///     @return The time when the intellectual content of the current picture was
///     created\, rather than when the picture was created.
///     @note This is the value of the IPTC TimeCreated tag (hex code 0x3C).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_TimeCreated `Slideshow.TimeCreated`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.TransmissionReference`</b>,
///                  \anchor Slideshow_TransmissionReference
///                  _string_,
///     @return A code representing the location of original transmission of the
///     current picture.
///     @note This is the value of the IPTC TransmissionReference tag
///     (hex code 0x67).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_TransmissionReference `Slideshow.TransmissionReference`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.Urgency`</b>,
///                  \anchor Slideshow_Urgency
///                  _string_,
///     @return The urgency of the current picture. Values are 1-9. The 1 is most
///     urgent.
///     @note Some image management programs use urgency to indicate picture
///     rating\, where urgency 1 is 5 stars and urgency 5 is 1 star. Urgencies
///     6-9 are not used for rating. This is the value of the IPTC Urgency tag
///     (hex code 0x0A).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_Urgency `Slideshow.Urgency`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Slideshow.WhiteBalance`</b>,
///                  \anchor Slideshow_WhiteBalance
///                  _string_,
///     @return The white balance mode set when the current picture was taken.
///     The possible values are:
///       - <b>"Manual"</b>
///       - <b>"Auto"</b>
///     <p>
///     @note This is the value of the EXIF WhiteBalance tag (hex code 0xA403).
///     <p><hr>
///     @skinning_v13 **[New Infolabel]** \link Slideshow_WhiteBalance `Slideshow.WhiteBalance`\endlink
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------
const infomap slideshow[] =      {{ "ispaused",               SLIDESHOW_ISPAUSED },
                                  { "isactive",               SLIDESHOW_ISACTIVE },
                                  { "isvideo",                SLIDESHOW_ISVIDEO },
                                  { "israndom",               SLIDESHOW_ISRANDOM },
                                  { "filename",               SLIDESHOW_FILE_NAME },
                                  { "path",                   SLIDESHOW_FILE_PATH },
                                  { "filesize",               SLIDESHOW_FILE_SIZE },
                                  { "filedate",               SLIDESHOW_FILE_DATE },
                                  { "slideindex",             SLIDESHOW_INDEX },
                                  { "resolution",             SLIDESHOW_RESOLUTION },
                                  { "slidecomment",           SLIDESHOW_COMMENT },
                                  { "colour",                 SLIDESHOW_COLOUR },
                                  { "process",                SLIDESHOW_PROCESS },
                                  { "exiftime",               SLIDESHOW_EXIF_DATE_TIME },
                                  { "exifdate",               SLIDESHOW_EXIF_DATE },
                                  { "longexiftime",           SLIDESHOW_EXIF_LONG_DATE_TIME },
                                  { "longexifdate",           SLIDESHOW_EXIF_LONG_DATE },
                                  { "exifdescription",        SLIDESHOW_EXIF_DESCRIPTION },
                                  { "cameramake",             SLIDESHOW_EXIF_CAMERA_MAKE },
                                  { "cameramodel",            SLIDESHOW_EXIF_CAMERA_MODEL },
                                  { "exifcomment",            SLIDESHOW_EXIF_COMMENT },
                                  { "exifsoftware",           SLIDESHOW_EXIF_SOFTWARE },
                                  { "aperture",               SLIDESHOW_EXIF_APERTURE },
                                  { "focallength",            SLIDESHOW_EXIF_FOCAL_LENGTH },
                                  { "focusdistance",          SLIDESHOW_EXIF_FOCUS_DIST },
                                  { "exposure",               SLIDESHOW_EXIF_EXPOSURE },
                                  { "exposuretime",           SLIDESHOW_EXIF_EXPOSURE_TIME },
                                  { "exposurebias",           SLIDESHOW_EXIF_EXPOSURE_BIAS },
                                  { "exposuremode",           SLIDESHOW_EXIF_EXPOSURE_MODE },
                                  { "flashused",              SLIDESHOW_EXIF_FLASH_USED },
                                  { "whitebalance",           SLIDESHOW_EXIF_WHITE_BALANCE },
                                  { "lightsource",            SLIDESHOW_EXIF_LIGHT_SOURCE },
                                  { "meteringmode",           SLIDESHOW_EXIF_METERING_MODE },
                                  { "isoequivalence",         SLIDESHOW_EXIF_ISO_EQUIV },
                                  { "digitalzoom",            SLIDESHOW_EXIF_DIGITAL_ZOOM },
                                  { "ccdwidth",               SLIDESHOW_EXIF_CCD_WIDTH },
                                  { "orientation",            SLIDESHOW_EXIF_ORIENTATION },
                                  { "supplementalcategories", SLIDESHOW_IPTC_SUP_CATEGORIES },
                                  { "keywords",               SLIDESHOW_IPTC_KEYWORDS },
                                  { "caption",                SLIDESHOW_IPTC_CAPTION },
                                  { "author",                 SLIDESHOW_IPTC_AUTHOR },
                                  { "headline",               SLIDESHOW_IPTC_HEADLINE },
                                  { "specialinstructions",    SLIDESHOW_IPTC_SPEC_INSTR },
                                  { "category",               SLIDESHOW_IPTC_CATEGORY },
                                  { "byline",                 SLIDESHOW_IPTC_BYLINE },
                                  { "bylinetitle",            SLIDESHOW_IPTC_BYLINE_TITLE },
                                  { "credit",                 SLIDESHOW_IPTC_CREDIT },
                                  { "source",                 SLIDESHOW_IPTC_SOURCE },
                                  { "copyrightnotice",        SLIDESHOW_IPTC_COPYRIGHT_NOTICE },
                                  { "objectname",             SLIDESHOW_IPTC_OBJECT_NAME },
                                  { "city",                   SLIDESHOW_IPTC_CITY },
                                  { "state",                  SLIDESHOW_IPTC_STATE },
                                  { "country",                SLIDESHOW_IPTC_COUNTRY },
                                  { "transmissionreference",  SLIDESHOW_IPTC_TX_REFERENCE },
                                  { "iptcdate",               SLIDESHOW_IPTC_DATE },
                                  { "urgency",                SLIDESHOW_IPTC_URGENCY },
                                  { "countrycode",            SLIDESHOW_IPTC_COUNTRY_CODE },
                                  { "referenceservice",       SLIDESHOW_IPTC_REF_SERVICE },
                                  { "latitude",               SLIDESHOW_EXIF_GPS_LATITUDE },
                                  { "longitude",              SLIDESHOW_EXIF_GPS_LONGITUDE },
                                  { "altitude",               SLIDESHOW_EXIF_GPS_ALTITUDE },
                                  { "timecreated",            SLIDESHOW_IPTC_TIMECREATED },
                                  { "sublocation",            SLIDESHOW_IPTC_SUBLOCATION },
                                  { "imagetype",              SLIDESHOW_IPTC_IMAGETYPE },
};

/// \page modules__infolabels_boolean_conditions
/// \subsection modules__infolabels_boolean_conditions_Library Library
/// @todo Make this annotate an array of infobools/labels to make it easier to track
/// \table_start
///   \table_h3{ Labels, Type, Description }
///   \table_row3{   <b>`Library.IsScanning`</b>,
///                  \anchor Library_IsScanning
///                  _boolean_,
///     @return **True** if the library is being scanned.
///     <p>
///   }
///   \table_row3{   <b>`Library.IsScanningVideo`</b>,
///                  \anchor Library_IsScanningVideo
///                  _boolean_,
///     @return **True** if the video library is being scanned.
///     <p>
///   }
///   \table_row3{   <b>`Library.IsScanningMusic`</b>,
///                  \anchor Library_IsScanningMusic
///                  _boolean_,
///     @return **True** if the music library is being scanned.
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(music)`</b>,
///                  \anchor Library_HasContent_Music
///                  _boolean_,
///     @return **True** if the library has music content.
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(video)`</b>,
///                  \anchor Library_HasContent_Video
///                  _boolean_,
///     @return **True** if the library has video content.
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(movies)`</b>,
///                  \anchor Library_HasContent_Movies
///                  _boolean_,
///     @return **True** if the library has movies.
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(tvshows)`</b>,
///                  \anchor Library_HasContent_TVShows
///                  _boolean_,
///     @return **True** if the library has tvshows.
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(musicvideos)`</b>,
///                  \anchor Library_HasContent_MusicVideos
///                  _boolean_,
///     @return **True** if the library has music videos.
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(moviesets)`</b>,
///                  \anchor Library_HasContent_MovieSets
///                  _boolean_,
///     @return **True** if the library has movie sets.
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(singles)`</b>,
///                  \anchor Library_HasContent_Singles
///                  _boolean_,
///     @return **True** if the library has singles.
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(compilations)`</b>,
///                  \anchor Library_HasContent_Compilations
///                  _boolean_,
///     @return **True** if the library has compilations.
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(Role.Composer)`</b>,
///                  \anchor Library_HasContent_Role_Composer
///                  _boolean_,
///     @return **True** if there are songs in the library which have composers.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Library_HasContent_Role_Composer `Library.HasContent(Role.Composer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(Role.Conductor)`</b>,
///                  \anchor Library_HasContent_Role_Conductor
///                  _boolean_,
///     @return **True** if there are songs in the library which have a conductor.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Library_HasContent_Role_Conductor `Library.HasContent(Role.Conductor)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(Role.Orchestra)`</b>,
///                  \anchor Library_HasContent_Role_Orchestra
///                  _boolean_,
///     @return **True** if there are songs in the library which have an orchestra.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Library_HasContent_Role_Orchestra `Library.HasContent(Role.Orchestra)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(Role.Lyricist)`</b>,
///                  \anchor Library_HasContent_Role_Lyricist
///                  _boolean_,
///     @return **True** if there are songs in the library which have a lyricist.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Library_HasContent_Role_Lyricist `Library.HasContent(Role.Lyricist)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(Role.Remixer)`</b>,
///                  \anchor Library_HasContent_Role_Remixer
///                  _boolean_,
///     @return **True** if there are songs in the library which have a remixer.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Library_HasContent_Role_Remixer `Library.HasContent(Role.Remixer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(Role.Arranger)`</b>,
///                  \anchor Library_HasContent_Role_Remixer
///                  _boolean_,
///     @return **True** if there are songs in the library which have an arranger.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Library_HasContent_Role_Remixer `Library.HasContent(Role.Arranger)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(Role.Engineer)`</b>,
///                  \anchor Library_HasContent_Role_Engineer
///                  _boolean_,
///     @return **True** if there are songs in the library which have an engineer.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Library_HasContent_Role_Engineer `Library.HasContent(Role.Engineer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(Role.Producer)`</b>,
///                  \anchor Library_HasContent_Role_Producer
///                  _boolean_,
///     @return **True** if there are songs in the library which have an producer.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Library_HasContent_Role_Producer `Library.HasContent(Role.Producer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(Role.DJMixer)`</b>,
///                  \anchor Library_HasContent_Role_DJMixer
///                  _boolean_,
///     @return **True** if there are songs in the library which have a DJMixer.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Library_HasContent_Role_DJMixer `Library.HasContent(Role.DJMixer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(Role.Mixer)`</b>,
///                  \anchor Library_HasContent_Role_Mixer
///                  _boolean_,
///     @return **True** if there are songs in the library which have a mixer.
///     <p><hr>
///     @skinning_v17 **[New Boolean Condition]** \link Library_HasContent_Role_Mixer `Library.HasContent(Role.Mixer)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Library.HasContent(boxsets)`</b>,
///                  \anchor Library_HasContent_Boxsets
///                  _boolean_,
///     @return **True** if there are albums in the library which are boxsets.
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \link Library_HasContent_Boxsets `Library.HasContent(boxsets)`\endlink
///     <p>
///   }
///   \table_row3{   <b>`Library.HasNode(path)`</b>,
///                  \anchor Library_HasNode
///                  _boolean_,
///     @return **True** if there the node is present in the library.
///     <p><hr>
///     @skinning_v19 **[New Boolean Condition]** \link Library_HasNode `Library.HasNode(path)`\endlink
///     <p>
///   }
/// \table_end
///
/// -----------------------------------------------------------------------------

/// \page modules__infolabels_boolean_conditions
/// \section modules_rm_infolabels_booleans Additional revision history for Infolabels and Boolean Conditions
/// <hr>
/// \subsection modules_rm_infolabels_booleans_v21 Kodi v21 (Omega)
/// @skinning_v21 **[Removed Infolabels]** The following infolabels have been removed:
///   - `Network.DHCPAddress` - this info did not return any meaningful value (always an empty string)
///
/// <hr>
/// \subsection modules_rm_infolabels_booleans_v20 Kodi v20 (Nexus)
/// @skinning_v20 **[Removed Boolean conditions]** The following boolean conditions have been removed:
///   - `Player.DisplayAfterSeek` - use \link Player_HasPerformedSeek `Player.HasPerformedSeek(interval)`\endlink instead
///
/// <hr>
/// \subsection modules_rm_infolabels_booleans_v19 Kodi v19 (Matrix)
/// @skinning_v19 **[Removed Infolabels]** The following infolabels have been removed:
///   - `System.Platform.Linux.RaspberryPi` - use \link System_Platform_Linux `System.Platform.Linux`\endlink instead
///
/// <hr>
/// \subsection modules_rm_infolabels_booleans_v18 Kodi v18 (Leia)
///
/// @skinning_v18 **[Removed Infolabels]** The following infolabels have been removed:
///   - `Listitem.Property(artistthumbs)`, `Listitem.Property(artistthumb)` - use
/// \link ListItem_Art_Type `ListItem.Art(type)`\endlink with <b>albumartist[n].*</b> or <b>artist[n].*</b> as <b>type</b>
///   - `ADSP.ActiveStreamType`
///   - `ADSP.DetectedStreamType`
///   - `ADSP.MasterName`
///   - `ADSP.MasterInfo`
///   - `ADSP.MasterOwnIcon`
///   - `ADSP.MasterOverrideIcon`
///   - `ListItem.ChannelNumber`, `ListItem.SubChannelNumber`, `MusicPlayer.ChannelNumber`,
/// `MusicPlayer.SubChannelNumber`, `VideoPlayer.ChannelNumber`,
/// `VideoPlayer.SubChannelNumber`. Please use the following alternatives
/// \link ListItem_ChannelNumberLabel `ListItem.ChannelNumberLabel` \endlink,
/// \link MusicPlayer_ChannelNumberLabel `MusicPlayer.ChannelNumberLabel` \endlink
/// \link VideoPlayer_ChannelNumberLabel `VideoPlayer.ChannelNumberLabel` \endlink from now on.
///
/// @skinning_v18 **[Removed Boolean Conditions]** The following infobools have been removed:
///   - `System.HasModalDialog`  - use \link System_HasActiveModalDialog `System.HasActiveModalDialog` \endlink and
///  \link System_HasVisibleModalDialog `System.HasVisibleModalDialog`\endlink instead
///   - `StringCompare()` - use \link String_IsEqual `String.IsEqual(info,string)`\endlink instead
///   - `SubString()` - use \link String_Contains `String.Contains(info,substring)`\endlink instead
///   - `IntegerGreaterThan()` - use \link Integer_IsGreater `Integer.IsGreater(info,number)`\endlink instead
///   - `IsEmpty()` - use \link String_IsEmpty `String.IsEmpty(info)`\endlink instead
///   - `System.HasADSP`
///   - `ADSP.IsActive`
///   - `ADSP.HasInputResample`
///   - `ADSP.HasPreProcess`
///   - `ADSP.HasMasterProcess`
///   - `ADSP.HasPostProcess`
///   - `ADSP.HasOutputResample`
///   - `ADSP.MasterActive`
/// <hr>
/// \subsection modules_rm_infolabels_booleans_v17 Kodi v17 (Krypton)
/// @skinning_v17 **[Removed Infolabels]** The following infolabels have been removed:
///   - `ListItem.StarRating` - use the other ratings instead.
///
/// @skinning_v17 **[Removed Boolean Conditions]** The following infobools have been removed:
///   - `on`  - use `true` instead
///   - `off`  - use `false` instead
///   - `Player.ShowCodec`
///   - `System.GetBool(pvrmanager.enabled)`
/// <hr>
/// \subsection modules_rm_infolabels_booleans_v16 Kodi v16 (Jarvis)
///  @skinning_v16 **[New Boolean Conditions]** The following infobools were added:
///    - `System.HasADSP`
///    - `ADSP.IsActive`
///    - `ADSP.HasInputResample`
///    - `ADSP.HasPreProcess`
///    - `ADSP.HasMasterProcess`
///    - `ADSP.HasPostProcess`
///    - `ADSP.HasOutputResample`
///    - `ADSP.MasterActive`
///    - `System.HasModalDialog`
///
///  @skinning_v16 **[New Infolabels]** The following infolabels were added:
///    - `ADSP.ActiveStreamType`
///    - `ADSP.DetectedStreamType`
///    - `ADSP.MasterName`
///    - `ADSP.MasterInfo`
///    - `ADSP.MasterOwnIcon`
///    - `ADSP.MasterOverrideIcon`
///
///   @skinning_v16 **[Removed Boolean Conditions]** The following infobols were removed:
///    - `System.Platform.ATV2`

/// <hr>
/// \subsection modules_rm_infolabels_booleans_v15 Kodi v15 (Isengard)
/// <hr>
/// \subsection modules_rm_infolabels_booleans_v14 Kodi v14 (Helix)
///  @skinning_v14 **[New Infolabels]** The following infolabels were added:
///    - `ListItem.SubChannelNumber`
///    - `MusicPlayer.SubChannelNumber`
///    - `VideoPlayer.SubChannelNumber`
///
/// <hr>
/// \subsection modules_rm_infolabels_booleans_v13 XBMC v13 (Gotham)
///   @skinning_v13 **[Removed Infolabels]** The following infolabels were removed:
///    - `Network.SubnetAddress`
///
/// <hr>
// Crazy part, to use tableofcontents must it be on end
/// \page modules__infolabels_boolean_conditions
/// \tableofcontents

CGUIInfoManager::Property::Property(const std::string &property, const std::string &parameters)
: name(property)
{
  CUtil::SplitParams(parameters, params);
}

const std::string &CGUIInfoManager::Property::param(unsigned int n /* = 0 */) const
{
  if (n < params.size())
    return params[n];
  return StringUtils::Empty;
}

unsigned int CGUIInfoManager::Property::num_params() const
{
  return params.size();
}

void CGUIInfoManager::SplitInfoString(const std::string &infoString, std::vector<Property> &info)
{
  // our string is of the form:
  // category[(params)][.info(params).info2(params)] ...
  // so we need to split on . while taking into account of () pairs
  unsigned int parentheses = 0;
  std::string property;
  std::string param;
  for (size_t i = 0; i < infoString.size(); ++i)
  {
    if (infoString[i] == '(')
    {
      if (!parentheses++)
        continue;
    }
    else if (infoString[i] == ')')
    {
      if (!parentheses)
        CLog::Log(LOGERROR, "unmatched parentheses in {}", infoString);
      else if (!--parentheses)
        continue;
    }
    else if (infoString[i] == '.' && !parentheses)
    {
      if (!property.empty()) // add our property and parameters
      {
        StringUtils::ToLower(property);
        info.emplace_back(property, param);
      }
      property.clear();
      param.clear();
      continue;
    }
    if (parentheses)
      param += infoString[i];
    else
      property += infoString[i];
  }

  if (parentheses)
    CLog::Log(LOGERROR, "unmatched parentheses in {}", infoString);

  if (!property.empty())
  {
    StringUtils::ToLower(property);
    info.emplace_back(property, param);
  }
}

/// \brief Translates a string as given by the skin into an int that we use for more
/// efficient retrieval of data.
int CGUIInfoManager::TranslateSingleString(const std::string &strCondition)
{
  bool listItemDependent;
  return TranslateSingleString(strCondition, listItemDependent);
}

int CGUIInfoManager::TranslateSingleString(const std::string &strCondition, bool &listItemDependent)
{
  /* We need to disable caching in INFO::InfoBool::Get if either of the following are true:
   *  1. if condition is between LISTITEM_START and LISTITEM_END
   *  2. if condition is string or integer the corresponding label is between LISTITEM_START and LISTITEM_END
   *  This is achieved by setting the bool pointed at by listItemDependent, either here or in a recursive call
   */
  // trim whitespaces
  std::string strTest = strCondition;
  StringUtils::Trim(strTest);

  std::vector< Property> info;
  SplitInfoString(strTest, info);

  if (info.empty())
    return 0;

  const Property &cat = info[0];
  if (info.size() == 1)
  { // single category
    if (cat.name == "false" || cat.name == "no")
      return SYSTEM_ALWAYS_FALSE;
    else if (cat.name == "true" || cat.name == "yes")
      return SYSTEM_ALWAYS_TRUE;
  }
  else if (info.size() == 2)
  {
    const Property &prop = info[1];
    if (cat.name == "string")
    {
      if (prop.name == "isempty")
      {
        return AddMultiInfo(CGUIInfo(STRING_IS_EMPTY, TranslateSingleString(prop.param(), listItemDependent)));
      }
      else if (prop.num_params() == 2)
      {
        for (const infomap& string_bool : string_bools)
        {
          if (prop.name == string_bool.str)
          {
            int data1 = TranslateSingleString(prop.param(0), listItemDependent);
            // pipe our original string through the localize parsing then make it lowercase (picks up $LBRACKET etc.)
            std::string label = CGUIInfoLabel::GetLabel(prop.param(1), INFO::DEFAULT_CONTEXT);
            StringUtils::ToLower(label);
            // 'true', 'false', 'yes', 'no' are valid strings, do not resolve them to SYSTEM_ALWAYS_TRUE or SYSTEM_ALWAYS_FALSE
            if (label != "true" && label != "false" && label != "yes" && label != "no")
            {
              int data2 = TranslateSingleString(prop.param(1), listItemDependent);
              if (data2 > 0)
                return AddMultiInfo(CGUIInfo(string_bool.val, data1, -data2));
            }
            return AddMultiInfo(CGUIInfo(string_bool.val, data1, label));
          }
        }
      }
    }
    if (cat.name == "integer")
    {
      if (prop.name == "valueof")
      {
        int value = -1;
        std::from_chars(prop.param(0).data(), prop.param(0).data() + prop.param(0).size(), value);
        return AddMultiInfo(CGUIInfo(INTEGER_VALUEOF, value));
      }

      for (const infomap& integer_bool : integer_bools)
      {
        if (prop.name == integer_bool.str)
        {
          std::array<int, 2> data = {-1, -1};
          for (size_t i = 0; i < data.size(); i++)
          {
            std::from_chars_result result = std::from_chars(
                prop.param(i).data(), prop.param(i).data() + prop.param(i).size(), data.at(i));
            if (result.ec == std::errc::invalid_argument)
            {
              // could not translate provided value to int, translate the info string
              data.at(i) = TranslateSingleString(prop.param(i), listItemDependent);
            }
            else
            {
              // conversion succeeded, integer value provided - translate it to an Integer.ValueOf() info.
              data.at(i) = AddMultiInfo(CGUIInfo(INTEGER_VALUEOF, data.at(i)));
            }
          }
          return AddMultiInfo(CGUIInfo(integer_bool.val, data.at(0), data.at(1)));
        }
      }
    }
    else if (cat.name == "player")
    {
      for (const infomap& player_label : player_labels)
      {
        if (prop.name == player_label.str)
          return player_label.val;
      }
      for (const infomap& player_time : player_times)
      {
        if (prop.name == player_time.str)
          return AddMultiInfo(CGUIInfo(player_time.val, TranslateTimeFormat(prop.param())));
      }
      if (prop.name == "process" && prop.num_params())
      {
        for (const infomap& player_proces : player_process)
        {
          if (StringUtils::EqualsNoCase(prop.param(), player_proces.str))
            return player_proces.val;
        }
      }
      if (prop.num_params() == 1)
      {
        for (const infomap& i : player_param)
        {
          if (prop.name == i.str)
            return AddMultiInfo(CGUIInfo(i.val, prop.param()));
        }
      }
    }
    else if (cat.name == "addon")
    {
      for (const infomap& i : addons)
      {
        if (prop.name == i.str && prop.num_params() == 2)
          return AddMultiInfo(CGUIInfo(i.val, prop.param(0), prop.param(1)));
      }
    }
    else if (cat.name == "weather")
    {
      for (const infomap& i : weather)
      {
        if (prop.name == i.str)
          return i.val;
      }
    }
    else if (cat.name == "network")
    {
      for (const infomap& network_label : network_labels)
      {
        if (prop.name == network_label.str)
          return network_label.val;
      }
    }
    else if (cat.name == "musicpartymode")
    {
      for (const infomap& i : musicpartymode)
      {
        if (prop.name == i.str)
          return i.val;
      }
    }
    else if (cat.name == "system")
    {
      for (const infomap& system_label : system_labels)
      {
        if (prop.name == system_label.str)
          return system_label.val;
      }
      if (prop.num_params() == 1)
      {
        const std::string &param = prop.param();
        if (prop.name == "getbool")
        {
          std::string paramCopy = param;
          StringUtils::ToLower(paramCopy);
          return AddMultiInfo(CGUIInfo(SYSTEM_GET_BOOL, paramCopy));
        }
        for (const infomap& i : system_param)
        {
          if (prop.name == i.str)
            return AddMultiInfo(CGUIInfo(i.val, param));
        }
        if (prop.name == "memory")
        {
          if (param == "free")
            return SYSTEM_FREE_MEMORY;
          else if (param == "free.percent")
            return SYSTEM_FREE_MEMORY_PERCENT;
          else if (param == "used")
            return SYSTEM_USED_MEMORY;
          else if (param == "used.percent")
            return SYSTEM_USED_MEMORY_PERCENT;
          else if (param == "total")
            return SYSTEM_TOTAL_MEMORY;
        }
        else if (prop.name == "addontitle")
        {
          // Example: System.AddonTitle(Skin.String(HomeVideosButton1)) => skin string HomeVideosButton1 holds an addon identifier string
          int infoLabel = TranslateSingleString(param, listItemDependent);
          if (infoLabel > 0)
            return AddMultiInfo(CGUIInfo(SYSTEM_ADDON_TITLE, infoLabel, 0));
          std::string label = CGUIInfoLabel::GetLabel(param, INFO::DEFAULT_CONTEXT);
          StringUtils::ToLower(label);
          return AddMultiInfo(CGUIInfo(SYSTEM_ADDON_TITLE, label, 1));
        }
        else if (prop.name == "addonicon")
        {
          int infoLabel = TranslateSingleString(param, listItemDependent);
          if (infoLabel > 0)
            return AddMultiInfo(CGUIInfo(SYSTEM_ADDON_ICON, infoLabel, 0));
          std::string label = CGUIInfoLabel::GetLabel(param, INFO::DEFAULT_CONTEXT);
          StringUtils::ToLower(label);
          return AddMultiInfo(CGUIInfo(SYSTEM_ADDON_ICON, label, 1));
        }
        else if (prop.name == "addonversion")
        {
          int infoLabel = TranslateSingleString(param, listItemDependent);
          if (infoLabel > 0)
            return AddMultiInfo(CGUIInfo(SYSTEM_ADDON_VERSION, infoLabel, 0));
          std::string label = CGUIInfoLabel::GetLabel(param, INFO::DEFAULT_CONTEXT);
          StringUtils::ToLower(label);
          return AddMultiInfo(CGUIInfo(SYSTEM_ADDON_VERSION, label, 1));
        }
        else if (prop.name == "idletime")
          return AddMultiInfo(CGUIInfo(SYSTEM_IDLE_TIME, atoi(param.c_str())));
        else if (prop.name == "locale")
        {
          if (param == "timezonecountry")
          {
            return SYSTEM_LOCALE_TIMEZONECOUNTRY;
          }
          else if (param == "timezone")
          {
            return SYSTEM_LOCALE_TIMEZONE;
          }
          else if (param == "region")
          {
            return SYSTEM_LOCALE_REGION;
          }
          else if (param == "iso")
          {
            return SYSTEM_LOCALE;
          }
        }
      }
      if (prop.name == "alarmlessorequal" && prop.num_params() == 2)
        return AddMultiInfo(CGUIInfo(SYSTEM_ALARM_LESS_OR_EQUAL, prop.param(0), atoi(prop.param(1).c_str())));
      else if (prop.name == "date")
      {
        if (prop.num_params() == 2)
          return AddMultiInfo(CGUIInfo(SYSTEM_DATE, StringUtils::DateStringToYYYYMMDD(prop.param(0)) % 10000, StringUtils::DateStringToYYYYMMDD(prop.param(1)) % 10000));
        else if (prop.num_params() == 1)
        {
          int dateformat = StringUtils::DateStringToYYYYMMDD(prop.param(0));
          if (dateformat <= 0) // not concrete date
            return AddMultiInfo(CGUIInfo(SYSTEM_DATE, prop.param(0), -1));
          else
            return AddMultiInfo(CGUIInfo(SYSTEM_DATE, dateformat % 10000));
        }
        return SYSTEM_DATE;
      }
      else if (prop.name == "time")
      {
        if (prop.num_params() == 0)
          return AddMultiInfo(CGUIInfo(SYSTEM_TIME, TIME_FORMAT_GUESS));
        if (prop.num_params() == 1)
        {
          TIME_FORMAT timeFormat = TranslateTimeFormat(prop.param(0));
          if (timeFormat == TIME_FORMAT_GUESS)
            return AddMultiInfo(CGUIInfo(SYSTEM_TIME, StringUtils::TimeStringToSeconds(prop.param(0))));
          return AddMultiInfo(CGUIInfo(SYSTEM_TIME, timeFormat));
        }
        else
          return AddMultiInfo(CGUIInfo(SYSTEM_TIME, StringUtils::TimeStringToSeconds(prop.param(0)), StringUtils::TimeStringToSeconds(prop.param(1))));
      }
    }
    else if (cat.name == "library")
    {
      if (prop.name == "isscanning")
        return LIBRARY_IS_SCANNING;
      else if (prop.name == "isscanningvideo")
        return LIBRARY_IS_SCANNING_VIDEO; //! @todo change to IsScanning(Video)
      else if (prop.name == "isscanningmusic")
        return LIBRARY_IS_SCANNING_MUSIC;
      else if (prop.name == "hascontent" && prop.num_params())
      {
        std::string cat = prop.param(0);
        StringUtils::ToLower(cat);
        if (cat == "music")
          return LIBRARY_HAS_MUSIC;
        else if (cat == "video")
          return LIBRARY_HAS_VIDEO;
        else if (cat == "movies")
          return LIBRARY_HAS_MOVIES;
        else if (cat == "tvshows")
          return LIBRARY_HAS_TVSHOWS;
        else if (cat == "musicvideos")
          return LIBRARY_HAS_MUSICVIDEOS;
        else if (cat == "moviesets")
          return LIBRARY_HAS_MOVIE_SETS;
        else if (cat == "singles")
          return LIBRARY_HAS_SINGLES;
        else if (cat == "compilations")
          return LIBRARY_HAS_COMPILATIONS;
        else if (cat == "boxsets")
          return LIBRARY_HAS_BOXSETS;
        else if (cat == "role" && prop.num_params() > 1)
          return AddMultiInfo(CGUIInfo(LIBRARY_HAS_ROLE, prop.param(1), 0));
      }
      else if (prop.name == "hasnode" && prop.num_params())
      {
        std::string node = prop.param(0);
        StringUtils::ToLower(node);
        return AddMultiInfo(CGUIInfo(LIBRARY_HAS_NODE, prop.param(), 0));
      }
    }
    else if (cat.name == "musicplayer")
    {
      for (const infomap& player_time : player_times) //! @todo remove these, they're repeats
      {
        if (prop.name == player_time.str)
          return AddMultiInfo(CGUIInfo(player_time.val, TranslateTimeFormat(prop.param())));
      }
      if (prop.name == "content" && prop.num_params())
        return AddMultiInfo(CGUIInfo(MUSICPLAYER_CONTENT, prop.param(), 0));
      else if (prop.name == "property")
      {
        if (StringUtils::EqualsNoCase(prop.param(), "fanart_image"))
          return AddMultiInfo(CGUIInfo(PLAYER_ITEM_ART, "fanart"));

        return AddMultiInfo(CGUIInfo(MUSICPLAYER_PROPERTY, prop.param()));
      }
      return TranslateMusicPlayerString(prop.name);
    }
    else if (cat.name == "videoplayer")
    {
      if (prop.name != "starttime") // player.starttime is semantically different from videoplayer.starttime which has its own implementation!
      {
        for (const infomap& player_time : player_times) //! @todo remove these, they're repeats
        {
          if (prop.name == player_time.str)
            return AddMultiInfo(CGUIInfo(player_time.val, TranslateTimeFormat(prop.param())));
        }
      }
      if (prop.name == "content" && prop.num_params())
      {
        return AddMultiInfo(CGUIInfo(VIDEOPLAYER_CONTENT, prop.param(), 0));
      }
      if (prop.name == "uniqueid" && prop.num_params())
      {
        return AddMultiInfo(CGUIInfo(VIDEOPLAYER_UNIQUEID, prop.param(), 0));
      }
      if (prop.name == "art" && prop.num_params() > 0)
      {
        return AddMultiInfo(CGUIInfo(VIDEOPLAYER_ART, prop.param(), 0));
      }
      return TranslateVideoPlayerString(prop.name);
    }
    else if (cat.name == "retroplayer")
    {
      for (const infomap& i : retroplayer)
      {
        if (prop.name == i.str)
          return i.val;
      }
    }
    else if (cat.name == "slideshow")
    {
      for (const infomap& i : slideshow)
      {
        if (prop.name == i.str)
          return i.val;
      }
    }
    else if (cat.name == "container")
    {
      for (const infomap& i : mediacontainer) // these ones don't have or need an id
      {
        if (prop.name == i.str)
          return i.val;
      }
      int id = atoi(cat.param().c_str());
      for (const infomap& container_bool : container_bools) // these ones can have an id (but don't need to?)
      {
        if (prop.name == container_bool.str)
          return id ? AddMultiInfo(CGUIInfo(container_bool.val, id)) : container_bool.val;
      }
      for (const infomap& container_int : container_ints) // these ones can have an int param on the property
      {
        if (prop.name == container_int.str)
          return AddMultiInfo(CGUIInfo(container_int.val, id, atoi(prop.param().c_str())));
      }
      for (const infomap& i : container_str) // these ones have a string param on the property
      {
        if (prop.name == i.str)
          return AddMultiInfo(CGUIInfo(i.val, id, prop.param()));
      }
      if (prop.name == "sortdirection")
      {
        SortOrder order = SortOrderNone;
        if (StringUtils::EqualsNoCase(prop.param(), "ascending"))
          order = SortOrderAscending;
        else if (StringUtils::EqualsNoCase(prop.param(), "descending"))
          order = SortOrderDescending;
        return AddMultiInfo(CGUIInfo(CONTAINER_SORT_DIRECTION, order));
      }
    }
    else if (cat.name == "listitem" ||
             cat.name == "listitemposition" ||
             cat.name == "listitemnowrap" ||
             cat.name == "listitemabsolute")
    {
      int ret = TranslateListItem(cat, prop, 0, false);
      if (ret)
        listItemDependent = true;
      return ret;
    }
    else if (cat.name == "visualisation")
    {
      for (const infomap& i : visualisation)
      {
        if (prop.name == i.str)
          return i.val;
      }
    }
    else if (cat.name == "fanart")
    {
      for (const infomap& fanart_label : fanart_labels)
      {
        if (prop.name == fanart_label.str)
          return fanart_label.val;
      }
    }
    else if (cat.name == "skin")
    {
      for (const infomap& skin_label : skin_labels)
      {
        if (prop.name == skin_label.str)
          return skin_label.val;
      }
      if (prop.num_params())
      {
        if (prop.name == "string")
        {
          if (prop.num_params() == 2)
            return AddMultiInfo(CGUIInfo(SKIN_STRING_IS_EQUAL, CSkinSettings::GetInstance().TranslateString(prop.param(0)), prop.param(1)));
          else
            return AddMultiInfo(CGUIInfo(SKIN_STRING, CSkinSettings::GetInstance().TranslateString(prop.param(0))));
        }
        else if (prop.name == "numeric")
        {
          return AddMultiInfo(
              CGUIInfo(SKIN_INTEGER, CSkinSettings::GetInstance().TranslateString(prop.param(0))));
        }
        else if (prop.name == "hassetting")
          return AddMultiInfo(CGUIInfo(SKIN_BOOL, CSkinSettings::GetInstance().TranslateBool(prop.param(0))));
        else if (prop.name == "hastheme")
          return AddMultiInfo(CGUIInfo(SKIN_HAS_THEME, prop.param(0)));
        else if (prop.name == "timerisrunning")
          return AddMultiInfo(CGUIInfo(SKIN_TIMER_IS_RUNNING, prop.param(0)));
        else if (prop.name == "timerelapsedsecs")
          return AddMultiInfo(CGUIInfo(SKIN_TIMER_ELAPSEDSECS, prop.param(0)));
      }
    }
    else if (cat.name == "window")
    {
      if (prop.name == "property" && prop.num_params() == 1)
      { //! @todo this doesn't support foo.xml
        int winID = cat.param().empty() ? 0 : CWindowTranslator::TranslateWindow(cat.param());
        if (winID != WINDOW_INVALID)
          return AddMultiInfo(CGUIInfo(WINDOW_PROPERTY, winID, prop.param()));
      }
      for (const infomap& window_bool : window_bools)
      {
        if (prop.name == window_bool.str)
        { //! @todo The parameter for these should really be on the first not the second property
          if (prop.param().find("xml") != std::string::npos)
            return AddMultiInfo(CGUIInfo(window_bool.val, 0, prop.param()));
          int winID = prop.param().empty() ? WINDOW_INVALID : CWindowTranslator::TranslateWindow(prop.param());
          return AddMultiInfo(CGUIInfo(window_bool.val, winID, 0));
        }
      }
    }
    else if (cat.name == "control")
    {
      for (const infomap& control_label : control_labels)
      {
        if (prop.name == control_label.str)
        { //! @todo The parameter for these should really be on the first not the second property
          int controlID = atoi(prop.param().c_str());
          if (controlID)
            return AddMultiInfo(CGUIInfo(control_label.val, controlID, 0));
          return 0;
        }
      }
    }
    else if (cat.name == "controlgroup" && prop.name == "hasfocus")
    {
      int groupID = atoi(cat.param().c_str());
      if (groupID)
        return AddMultiInfo(CGUIInfo(CONTROL_GROUP_HAS_FOCUS, groupID, atoi(prop.param(0).c_str())));
    }
    else if (cat.name == "playlist")
    {
      int ret = -1;
      for (const infomap& i : playlist)
      {
        if (prop.name == i.str)
        {
          ret = i.val;
          break;
        }
      }
      if (ret >= 0)
      {
        if (prop.num_params() <= 0)
          return ret;
        else
        {
          PLAYLIST::Id playlistid = PLAYLIST::TYPE_NONE;
          if (StringUtils::EqualsNoCase(prop.param(), "video"))
            playlistid = PLAYLIST::TYPE_VIDEO;
          else if (StringUtils::EqualsNoCase(prop.param(), "music"))
            playlistid = PLAYLIST::TYPE_MUSIC;

          if (playlistid != PLAYLIST::TYPE_NONE)
            return AddMultiInfo(CGUIInfo(ret, playlistid, 1));
        }
      }
    }
    else if (cat.name == "pvr")
    {
      for (const infomap& i : pvr)
      {
        if (prop.name == i.str)
          return i.val;
      }
      for (const infomap& pvr_time : pvr_times)
      {
        if (prop.name == pvr_time.str)
          return AddMultiInfo(CGUIInfo(pvr_time.val, TranslateTimeFormat(prop.param())));
      }
    }
    else if (cat.name == "rds")
    {
      if (prop.name == "getline")
        return AddMultiInfo(CGUIInfo(RDS_GET_RADIOTEXT_LINE, atoi(prop.param(0).c_str())));

      for (const infomap& rd : rds)
      {
        if (prop.name == rd.str)
          return rd.val;
      }
    }
  }
  else if (info.size() == 3 || info.size() == 4)
  {
    if (info[0].name == "system" && info[1].name == "platform")
    { //! @todo replace with a single system.platform
      std::string platform = info[2].name;
      if (platform == "linux")
        return SYSTEM_PLATFORM_LINUX;
      else if (platform == "windows")
        return SYSTEM_PLATFORM_WINDOWS;
      else if (platform == "uwp")
        return SYSTEM_PLATFORM_UWP;
      else if (platform == "darwin")
        return SYSTEM_PLATFORM_DARWIN;
      else if (platform == "osx")
        return SYSTEM_PLATFORM_DARWIN_OSX;
      else if (platform == "ios")
        return SYSTEM_PLATFORM_DARWIN_IOS;
      else if (platform == "tvos")
        return SYSTEM_PLATFORM_DARWIN_TVOS;
      else if (platform == "android")
        return SYSTEM_PLATFORM_ANDROID;
      else if (platform == "webos")
        return SYSTEM_PLATFORM_WEBOS;
    }
    if (info[0].name == "musicplayer")
    { //! @todo these two don't allow duration(foo) and also don't allow more than this number of levels...
      if (info[1].name == "position")
      {
        int position = atoi(info[1].param().c_str());
        int value = TranslateMusicPlayerString(info[2].name); // musicplayer.position(foo).bar
        return AddMultiInfo(CGUIInfo(value, 2, position)); // 2 => absolute (0 used for not set)
      }
      else if (info[1].name == "offset")
      {
        int position = atoi(info[1].param().c_str());
        int value = TranslateMusicPlayerString(info[2].name); // musicplayer.offset(foo).bar
        return AddMultiInfo(CGUIInfo(value, 1, position)); // 1 => relative
      }
    }
    else if (info[0].name == "videoplayer")
    { //! @todo these two don't allow duration(foo) and also don't allow more than this number of levels...
      if (info[1].name == "position")
      {
        int position = atoi(info[1].param().c_str());
        int value = TranslateVideoPlayerString(info[2].name); // videoplayer.position(foo).bar
        // additional param for the requested infolabel, e.g. VideoPlayer.Position(1).Art(poster): art is the value, poster is the param
        const std::string& param = info[2].param();
        return AddMultiInfo(
            CGUIInfo(value, 2, position, param)); // 2 => absolute (0 used for not set)
      }
      else if (info[1].name == "offset")
      {
        int position = atoi(info[1].param().c_str());
        int value = TranslateVideoPlayerString(info[2].name); // videoplayer.offset(foo).bar
        // additional param for the requested infolabel, e.g. VideoPlayer.Offset(1).Art(poster): art is the value, poster is the param
        const std::string& param = info[2].param();
        return AddMultiInfo(CGUIInfo(value, 1, position, param)); // 1 => relative
      }
    }
    else if (info[0].name == "player")
    { //! @todo these two don't allow duration(foo) and also don't allow more than this number of levels...
      if (info[1].name == "position")
      {
        int position = atoi(info[1].param().c_str());
        int value = TranslatePlayerString(info[2].name); // player.position(foo).bar
        return AddMultiInfo(CGUIInfo(value, 2, position)); // 2 => absolute (0 used for not set)
      }
      else if (info[1].name == "offset")
      {
        int position = atoi(info[1].param().c_str());
        int value = TranslatePlayerString(info[2].name); // player.offset(foo).bar
        return AddMultiInfo(CGUIInfo(value, 1, position)); // 1 => relative
      }
    }
    else if (info[0].name == "container")
    {
      if (info[1].name == "listitem" ||
          info[1].name == "listitemposition" ||
          info[1].name == "listitemabsolute" ||
          info[1].name == "listitemnowrap")
      {
        int id = atoi(info[0].param().c_str());
        int ret = TranslateListItem(info[1], info[2], id, true);
        if (ret)
          listItemDependent = true;
        return ret;
      }
    }
    else if (info[0].name == "control")
    {
      const Property &prop = info[1];
      for (const infomap& control_label : control_labels)
      {
        if (prop.name == control_label.str)
        { //! @todo The parameter for these should really be on the first not the second property
          int controlID = atoi(prop.param().c_str());
          if (controlID)
            return AddMultiInfo(CGUIInfo(control_label.val, controlID, atoi(info[2].param(0).c_str())));
          return 0;
        }
      }
    }
  }

  return 0;
}

int CGUIInfoManager::TranslateListItem(const Property& cat, const Property& prop, int id, bool container)
{
  int ret = 0;
  std::string data3;
  int data4 = 0;
  if (prop.num_params() == 1)
  {
    // special case: map 'property(fanart_image)' to 'art(fanart)'
    if (prop.name == "property" && StringUtils::EqualsNoCase(prop.param(), "fanart_image"))
    {
      ret = LISTITEM_ART;
      data3 = "fanart";
    }
    else if (prop.name == "property" ||
             prop.name == "art" ||
             prop.name == "rating" ||
             prop.name == "votes" ||
             prop.name == "ratingandvotes" ||
             prop.name == "uniqueid")
    {
      data3 = prop.param();
    }
    else if (prop.name == "duration" || prop.name == "nextduration")
    {
      data4 = TranslateTimeFormat(prop.param());
    }
  }

  if (ret == 0)
  {
    for (const infomap& listitem_label : listitem_labels) // these ones don't have or need an id
    {
      if (prop.name == listitem_label.str)
      {
        ret = listitem_label.val;
        break;
      }
    }
  }

  if (ret)
  {
    int offset = std::atoi(cat.param().c_str());

    int flags = 0;
    if (cat.name == "listitem")
      flags = INFOFLAG_LISTITEM_WRAP;
    else if (cat.name == "listitemposition")
      flags = INFOFLAG_LISTITEM_POSITION;
    else if (cat.name == "listitemabsolute")
      flags = INFOFLAG_LISTITEM_ABSOLUTE;
    else if (cat.name == "listitemnowrap")
      flags = INFOFLAG_LISTITEM_NOWRAP;

    if (container)
      flags |= INFOFLAG_LISTITEM_CONTAINER;

    return AddMultiInfo(CGUIInfo(ret, id, offset, flags, data3, data4));
  }

  return 0;
}

int CGUIInfoManager::TranslateMusicPlayerString(const std::string &info) const
{
  for (const infomap& i : musicplayer)
  {
    if (info == i.str)
      return i.val;
  }
  return 0;
}

int CGUIInfoManager::TranslateVideoPlayerString(const std::string& info) const
{
  for (const infomap& i : videoplayer)
  {
    if (info == i.str)
      return i.val;
  }
  return 0;
}

int CGUIInfoManager::TranslatePlayerString(const std::string& info) const
{
  for (const infomap& i : player_labels)
  {
    if (info == i.str)
      return i.val;
  }
  return 0;
}

TIME_FORMAT CGUIInfoManager::TranslateTimeFormat(const std::string &format)
{
  if (format.empty())
    return TIME_FORMAT_GUESS;
  else if (StringUtils::EqualsNoCase(format, "hh"))
    return TIME_FORMAT_HH;
  else if (StringUtils::EqualsNoCase(format, "mm"))
    return TIME_FORMAT_MM;
  else if (StringUtils::EqualsNoCase(format, "ss"))
    return TIME_FORMAT_SS;
  else if (StringUtils::EqualsNoCase(format, "hh:mm"))
    return TIME_FORMAT_HH_MM;
  else if (StringUtils::EqualsNoCase(format, "mm:ss"))
    return TIME_FORMAT_MM_SS;
  else if (StringUtils::EqualsNoCase(format, "hh:mm:ss"))
    return TIME_FORMAT_HH_MM_SS;
  else if (StringUtils::EqualsNoCase(format, "hh:mm:ss xx"))
    return TIME_FORMAT_HH_MM_SS_XX;
  else if (StringUtils::EqualsNoCase(format, "h"))
    return TIME_FORMAT_H;
  else if (StringUtils::EqualsNoCase(format, "m"))
    return TIME_FORMAT_M;
  else if (StringUtils::EqualsNoCase(format, "h:mm:ss"))
    return TIME_FORMAT_H_MM_SS;
  else if (StringUtils::EqualsNoCase(format, "h:mm:ss xx"))
    return TIME_FORMAT_H_MM_SS_XX;
  else if (StringUtils::EqualsNoCase(format, "xx"))
    return TIME_FORMAT_XX;
  else if (StringUtils::EqualsNoCase(format, "secs"))
    return TIME_FORMAT_SECS;
  else if (StringUtils::EqualsNoCase(format, "mins"))
    return TIME_FORMAT_MINS;
  else if (StringUtils::EqualsNoCase(format, "hours"))
    return TIME_FORMAT_HOURS;
  return TIME_FORMAT_GUESS;
}

std::string CGUIInfoManager::GetLabel(int info, int contextWindow, std::string *fallback) const
{
  if (info >= CONDITIONAL_LABEL_START && info <= CONDITIONAL_LABEL_END)
  {
    return GetSkinVariableString(info, contextWindow, false);
  }
  else if (info >= MULTI_INFO_START && info <= MULTI_INFO_END)
  {
    return GetMultiInfoLabel(m_multiInfo[info - MULTI_INFO_START], contextWindow);
  }
  else if (info >= LISTITEM_START && info <= LISTITEM_END)
  {
    const std::shared_ptr<CGUIListItem> item = GUIINFO::GetCurrentListItem(contextWindow);
    if (item && item->IsFileItem())
      return GetItemLabel(static_cast<CFileItem*>(item.get()), contextWindow, info, fallback);
  }

  std::string strLabel;
  m_infoProviders.GetLabel(strLabel, m_currentFile, contextWindow, CGUIInfo(info), fallback);
  return strLabel;
}

bool CGUIInfoManager::GetInt(int &value, int info, int contextWindow, const CGUIListItem *item /* = nullptr */) const
{
  if (info >= MULTI_INFO_START && info <= MULTI_INFO_END)
  {
    return GetMultiInfoInt(value, m_multiInfo[info - MULTI_INFO_START], contextWindow, item);
  }
  else if (info >= LISTITEM_START && info <= LISTITEM_END)
  {
    std::shared_ptr<CGUIListItem> itemPtr;
    if (!item)
    {
      itemPtr = GUIINFO::GetCurrentListItem(contextWindow);
      item = itemPtr.get();
    }
    return GetItemInt(value, item, contextWindow, info);
  }

  value = 0;
  return m_infoProviders.GetInt(value, m_currentFile, contextWindow, CGUIInfo(info));
}

INFO::InfoPtr CGUIInfoManager::Register(const std::string &expression, int context)
{
  std::string condition(CGUIInfoLabel::ReplaceLocalize(expression));
  StringUtils::Trim(condition);

  if (condition.empty())
    return INFO::InfoPtr();

  std::unique_lock<CCriticalSection> lock(m_critInfo);
  std::pair<INFOBOOLTYPE::iterator, bool> res;

  if (condition.find_first_of("|+[]!") != condition.npos)
    res = m_bools.insert(std::make_shared<InfoExpression>(condition, context, m_refreshCounter));
  else
    res = m_bools.insert(std::make_shared<InfoSingle>(condition, context, m_refreshCounter));

  if (res.second)
    res.first->get()->Initialize(this);

  return *(res.first);
}

void CGUIInfoManager::UnRegister(const INFO::InfoPtr& expression)
{
  std::unique_lock<CCriticalSection> lock(m_critInfo);
  m_bools.erase(expression);
}

bool CGUIInfoManager::EvaluateBool(const std::string& expression,
                                   int contextWindow /* = 0 */,
                                   const std::shared_ptr<CGUIListItem>& item /* = nullptr */)
{
  INFO::InfoPtr info = Register(expression, contextWindow);
  if (info)
    return info->Get(contextWindow, item.get());
  return false;
}

bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListItem *item)
{
  bool bReturn = false;
  int condition = std::abs(condition1);

  if (condition >= LISTITEM_START && condition < LISTITEM_END)
  {
    std::shared_ptr<CGUIListItem> itemPtr;
    if (!item)
    {
      itemPtr = GUIINFO::GetCurrentListItem(contextWindow);
      item = itemPtr.get();
    }
    bReturn = GetItemBool(item, contextWindow, condition);
  }
  else if (condition >= MULTI_INFO_START && condition <= MULTI_INFO_END)
  {
    bReturn = GetMultiInfoBool(m_multiInfo[condition - MULTI_INFO_START], contextWindow, item);
  }
  else if (!m_infoProviders.GetBool(bReturn, m_currentFile, contextWindow, CGUIInfo(condition)))
  {
    // default: use integer value different from 0 as true
    int val;
    bReturn = GetInt(val, condition, DEFAULT_CONTEXT) && val != 0;
  }

  return (condition1 < 0) ? !bReturn : bReturn;
}

bool CGUIInfoManager::GetMultiInfoBool(const CGUIInfo &info, int contextWindow, const CGUIListItem *item)
{
  bool bReturn = false;
  int condition = std::abs(info.m_info);

  if (condition >= LISTITEM_START && condition <= LISTITEM_END)
  {
    std::shared_ptr<CGUIListItem> itemPtr;
    if (!item)
    {
      itemPtr = GUIINFO::GetCurrentListItem(contextWindow, info.GetData1(), info.GetData2(), info.GetInfoFlag());
      item = itemPtr.get();
    }
    if (item)
    {
      if (condition == LISTITEM_PROPERTY)
      {
        if (item->HasProperty(info.GetData3()))
          bReturn = item->GetProperty(info.GetData3()).asBoolean();
      }
      else
        bReturn = GetItemBool(item, contextWindow, condition);
    }
    else
    {
      bReturn = false;
    }
  }
  else if (!m_infoProviders.GetBool(bReturn, m_currentFile, contextWindow, info))
  {
    switch (condition)
    {
      case STRING_IS_EMPTY:
        // note: Get*Image() falls back to Get*Label(), so this should cover all of them
        if (item && item->IsFileItem() && IsListItemInfo(info.GetData1()))
          bReturn = GetItemImage(item, contextWindow, info.GetData1()).empty();
        else
          bReturn = GetImage(info.GetData1(), contextWindow).empty();
        break;
      case STRING_STARTS_WITH:
      case STRING_ENDS_WITH:
      case STRING_CONTAINS:
      case STRING_IS_EQUAL:
        {
          std::string compare;
          if (info.GetData2() < 0) // info labels are stored with negative numbers
          {
            int info2 = -info.GetData2();
            std::shared_ptr<CGUIListItem> item2;

            if (IsListItemInfo(info2))
            {
              int iResolvedInfo2 = ResolveMultiInfo(info2);
              if (iResolvedInfo2 != 0)
              {
                const GUIINFO::CGUIInfo& resolvedInfo2 = m_multiInfo[iResolvedInfo2 - MULTI_INFO_START];
                if (resolvedInfo2.GetInfoFlag() & INFOFLAG_LISTITEM_CONTAINER)
                  item2 = GUIINFO::GetCurrentListItem(contextWindow, resolvedInfo2.GetData1()); // data1 contains the container id
              }
            }

            if (item2 && item2->IsFileItem())
              compare = GetItemImage(item2.get(), contextWindow, info2);
            else if (item && item->IsFileItem())
              compare = GetItemImage(item, contextWindow, info2);
            else
              compare = GetImage(info2, contextWindow);
          }
          else if (!info.GetData3().empty())
          { // conditional string
            compare = info.GetData3();
          }
          StringUtils::ToLower(compare);

          std::string label;
          if (item && item->IsFileItem() && IsListItemInfo(info.GetData1()))
            label = GetItemImage(item, contextWindow, info.GetData1());
          else
            label = GetImage(info.GetData1(), contextWindow);
          StringUtils::ToLower(label);

          if (condition == STRING_STARTS_WITH)
            bReturn = StringUtils::StartsWith(label, compare);
          else if (condition == STRING_ENDS_WITH)
            bReturn = StringUtils::EndsWith(label, compare);
          else if (condition == STRING_CONTAINS)
            bReturn = label.find(compare) != std::string::npos;
          else
            bReturn = StringUtils::EqualsNoCase(label, compare);
        }
        break;
      case INTEGER_IS_EQUAL:
      case INTEGER_GREATER_THAN:
      case INTEGER_GREATER_OR_EQUAL:
      case INTEGER_LESS_THAN:
      case INTEGER_LESS_OR_EQUAL:
      case INTEGER_EVEN:
      case INTEGER_ODD:
        {
          auto getIntValue = [this, &item, &contextWindow](int infoNum) {
            int intValue = 0;
            if (!GetInt(intValue, infoNum, contextWindow, item))
            {
              std::string value;
              if (item && item->IsFileItem() && IsListItemInfo(infoNum))
                value = GetItemImage(item, contextWindow, infoNum);
              else
                value = GetImage(infoNum, contextWindow);

              // Handle the case when a value contains time separator (:). This makes Integer.IsGreater
              // useful for Player.Time* members without adding a separate set of members returning time in seconds
              if (value.find_first_of(':') != value.npos)
                intValue = StringUtils::TimeStringToSeconds(value);
              else
                std::from_chars(value.data(), value.data() + value.size(), intValue);
            }
            return intValue;
          };

          int leftIntValue = getIntValue(info.GetData1());
          int rightIntValue = getIntValue(info.GetData2());

          // compare
          if (condition == INTEGER_IS_EQUAL)
            bReturn = leftIntValue == rightIntValue;
          else if (condition == INTEGER_GREATER_THAN)
            bReturn = leftIntValue > rightIntValue;
          else if (condition == INTEGER_GREATER_OR_EQUAL)
            bReturn = leftIntValue >= rightIntValue;
          else if (condition == INTEGER_LESS_THAN)
            bReturn = leftIntValue < rightIntValue;
          else if (condition == INTEGER_LESS_OR_EQUAL)
            bReturn = leftIntValue <= rightIntValue;
          else if (condition == INTEGER_EVEN)
            bReturn = leftIntValue % 2 == 0;
          else if (condition == INTEGER_ODD)
            bReturn = leftIntValue % 2 != 0;
        }
        break;
    }
  }
  return (info.m_info < 0) ? !bReturn : bReturn;
}

bool CGUIInfoManager::GetMultiInfoInt(int &value, const CGUIInfo &info, int contextWindow, const CGUIListItem *item) const
{
  if (info.m_info == INTEGER_VALUEOF)
  {
    value = info.GetData1();
    return true;
  }
  else if (info.m_info >= LISTITEM_START && info.m_info <= LISTITEM_END)
  {
    std::shared_ptr<CGUIListItem> itemPtr;
    if (!item)
    {
      itemPtr = GUIINFO::GetCurrentListItem(contextWindow, info.GetData1(), info.GetData2(), info.GetInfoFlag());
      item = itemPtr.get();
    }
    if (item)
    {
      if (info.m_info == LISTITEM_PROPERTY)
      {
        if (item->HasProperty(info.GetData3()))
        {
          value = item->GetProperty(info.GetData3()).asInteger();
          return true;
        }
        return false;
      }
      else
        return GetItemInt(value, item, contextWindow, info.m_info);
    }
    else
    {
      return false;
    }
  }

  return m_infoProviders.GetInt(value, m_currentFile, contextWindow, info);
}

std::string CGUIInfoManager::GetMultiInfoLabel(const CGUIInfo &constinfo, int contextWindow, std::string *fallback) const
{
  CGUIInfo info(constinfo);

  if (info.m_info >= LISTITEM_START && info.m_info <= LISTITEM_END)
  {
    const std::shared_ptr<CGUIListItem> item = GUIINFO::GetCurrentListItem(
        contextWindow, info.GetData1(), info.GetData2(), info.GetInfoFlag());
    if (item)
    {
      // Image prioritizes images over labels (in the case of music item ratings for instance)
      return GetMultiInfoItemImage(dynamic_cast<CFileItem*>(item.get()), contextWindow, info, fallback);
    }
    else
    {
      return std::string();
    }
  }
  else if (info.m_info == SYSTEM_ADDON_TITLE ||
           info.m_info == SYSTEM_ADDON_ICON ||
           info.m_info == SYSTEM_ADDON_VERSION)
  {
    if (info.GetData2() == 0)
    {
      // resolve the addon id
      const std::string addonId = GetLabel(info.GetData1(), contextWindow);
      info = CGUIInfo(info.m_info, addonId);
    }
  }

  std::string strValue;
  m_infoProviders.GetLabel(strValue, m_currentFile, contextWindow, info, fallback);
  return strValue;
}

/// \brief Obtains the filename of the image to show from whichever subsystem is needed
std::string CGUIInfoManager::GetImage(int info, int contextWindow, std::string *fallback)
{
  if (info >= CONDITIONAL_LABEL_START && info <= CONDITIONAL_LABEL_END)
  {
    return GetSkinVariableString(info, contextWindow, true);
  }
  else if (info >= MULTI_INFO_START && info <= MULTI_INFO_END)
  {
    return GetMultiInfoLabel(m_multiInfo[info - MULTI_INFO_START], contextWindow, fallback);
  }
  else if (info == LISTITEM_THUMB ||
           info == LISTITEM_ICON ||
           info == LISTITEM_ACTUAL_ICON ||
           info == LISTITEM_OVERLAY ||
           info == LISTITEM_ART)
  {
    const std::shared_ptr<CGUIListItem> item = GUIINFO::GetCurrentListItem(contextWindow);
    if (item && item->IsFileItem())
      return GetItemImage(item.get(), contextWindow, info, fallback);
  }

  return GetLabel(info, contextWindow, fallback);
}

void CGUIInfoManager::ResetCurrentItem()
{
  m_currentFile->Reset();
  m_infoProviders.InitCurrentItem(nullptr);
}

void CGUIInfoManager::UpdateCurrentItem(const CFileItem &item)
{
  m_currentFile->UpdateInfo(item);
}

void CGUIInfoManager::SetCurrentItem(const CFileItem &item)
{
  *m_currentFile = item;
  m_currentFile->FillInDefaultIcon();

  m_infoProviders.InitCurrentItem(m_currentFile);

  CServiceBroker::GetAnnouncementManager()->Announce(ANNOUNCEMENT::Info, "OnChanged");
}

void CGUIInfoManager::SetCurrentAlbumThumb(const std::string &thumbFileName)
{
  if (CFileUtils::Exists(thumbFileName))
    m_currentFile->SetArt("thumb", thumbFileName);
  else
  {
    m_currentFile->SetArt("thumb", "");
    m_currentFile->FillInDefaultIcon();
  }
}

void CGUIInfoManager::Clear()
{
  std::unique_lock<CCriticalSection> lock(m_critInfo);
  m_skinVariableStrings.clear();

  /*
    Erase any info bools that are unused. We do this repeatedly as each run
    will remove those bools that are no longer dependencies of other bools
    in the vector.
   */
  INFOBOOLTYPE swapList(&InfoBoolComparator);
  do
  {
    swapList.clear();
    for (auto &item : m_bools)
      if (!item.unique())
        swapList.insert(item);
    m_bools.swap(swapList);
  } while (swapList.size() != m_bools.size());

  // log which ones are used - they should all be gone by now
  for (INFOBOOLTYPE::const_iterator i = m_bools.begin(); i != m_bools.end(); ++i)
    CLog::Log(LOGDEBUG, "Infobool '{}' still used by {} instances", (*i)->GetExpression(),
              (unsigned int)i->use_count());
}

void CGUIInfoManager::UpdateAVInfo()
{
  if (CServiceBroker::GetDataCacheCore().HasAVInfoChanges())
  {
    VideoStreamInfo video;
    AudioStreamInfo audio;
    SubtitleStreamInfo subtitle;

    auto& components = CServiceBroker::GetAppComponents();
    const auto appPlayer = components.GetComponent<CApplicationPlayer>();
    appPlayer->GetVideoStreamInfo(CURRENT_STREAM, video);
    appPlayer->GetAudioStreamInfo(CURRENT_STREAM, audio);
    appPlayer->GetSubtitleStreamInfo(CURRENT_STREAM, subtitle);

    m_infoProviders.UpdateAVInfo(audio, video, subtitle);
  }
}

int CGUIInfoManager::AddMultiInfo(const CGUIInfo &info)
{
  // check to see if we have this info already
  for (unsigned int i = 0; i < m_multiInfo.size(); ++i)
    if (m_multiInfo[i] == info)
      return static_cast<int>(i) + MULTI_INFO_START;
  // return the new offset
  m_multiInfo.emplace_back(info);
  int id = static_cast<int>(m_multiInfo.size()) + MULTI_INFO_START - 1;
  if (id > MULTI_INFO_END)
    CLog::Log(LOGERROR, "{} - too many multiinfo bool/labels in this skin", __FUNCTION__);
  return id;
}

int CGUIInfoManager::ResolveMultiInfo(int info) const
{
  int iLastInfo = 0;

  int iResolvedInfo = info;
  while (iResolvedInfo >= MULTI_INFO_START && iResolvedInfo <= MULTI_INFO_END)
  {
    iLastInfo = iResolvedInfo;
    iResolvedInfo = m_multiInfo[iResolvedInfo - MULTI_INFO_START].m_info;
  }

  return iLastInfo;
}

bool CGUIInfoManager::IsListItemInfo(int info) const
{
  int iResolvedInfo = info;
  while (iResolvedInfo >= MULTI_INFO_START && iResolvedInfo <= MULTI_INFO_END)
    iResolvedInfo = m_multiInfo[iResolvedInfo - MULTI_INFO_START].m_info;

  return (iResolvedInfo >= LISTITEM_START && iResolvedInfo <= LISTITEM_END);
}

bool CGUIInfoManager::GetItemInt(int &value, const CGUIListItem *item, int contextWindow, int info) const
{
  value = 0;

  if (!item)
    return false;

  return m_infoProviders.GetInt(value, item, contextWindow, CGUIInfo(info));
}

std::string CGUIInfoManager::GetItemLabel(const CFileItem *item, int contextWindow, int info, std::string *fallback /* = nullptr */) const
{
  return GetMultiInfoItemLabel(item, contextWindow, CGUIInfo(info), fallback);
}

std::string CGUIInfoManager::GetMultiInfoItemLabel(const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback /* = nullptr */) const
{
  if (!item)
    return std::string();

  std::string value;

  if (info.m_info >= CONDITIONAL_LABEL_START && info.m_info <= CONDITIONAL_LABEL_END)
  {
    return GetSkinVariableString(info.m_info, contextWindow, false, item);
  }
  else if (info.m_info >= MULTI_INFO_START && info.m_info <= MULTI_INFO_END)
  {
    return GetMultiInfoItemLabel(item, contextWindow, m_multiInfo[info.m_info - MULTI_INFO_START], fallback);
  }
  else if (!m_infoProviders.GetLabel(value, item, contextWindow, info, fallback))
  {
    switch (info.m_info)
    {
      case LISTITEM_PROPERTY:
        return item->GetProperty(info.GetData3()).asString();
      case LISTITEM_LABEL:
        return item->GetLabel();
      case LISTITEM_LABEL2:
        return item->GetLabel2();
      case LISTITEM_FILENAME:
      case LISTITEM_FILE_EXTENSION:
      case LISTITEM_FILENAME_NO_EXTENSION:
      {
        std::string strFile = URIUtils::GetFileName(item->GetPath());
        if (info.m_info == LISTITEM_FILE_EXTENSION)
        {
          std::string strExtension = URIUtils::GetExtension(strFile);
          return StringUtils::TrimLeft(strExtension, ".");
        }
        else if (info.m_info == LISTITEM_FILENAME_NO_EXTENSION)
        {
          URIUtils::RemoveExtension(strFile);
        }
        return strFile;
      }
      case LISTITEM_DATE:
        if (item->m_dateTime.IsValid())
          return item->m_dateTime.GetAsLocalizedDate();
        break;
      case LISTITEM_DATETIME:
        if (item->m_dateTime.IsValid())
          return item->m_dateTime.GetAsLocalizedDateTime();
        break;
      case LISTITEM_SIZE:
        if (!item->m_bIsFolder || item->m_dwSize)
          return StringUtils::SizeToString(item->m_dwSize);
        break;
      case LISTITEM_PROGRAM_COUNT:
        return std::to_string(item->m_iprogramCount);
      case LISTITEM_ACTUAL_ICON:
        return item->GetArt("icon");
      case LISTITEM_ICON:
      {
        std::string strThumb = item->GetThumbHideIfUnwatched(item);
        if (strThumb.empty())
          strThumb = item->GetArt("icon");
        if (fallback)
          *fallback = item->GetArt("icon");
        return strThumb;
      }
      case LISTITEM_ART:
        return item->GetArt(info.GetData3());
      case LISTITEM_OVERLAY:
        return item->GetOverlayImage();
      case LISTITEM_THUMB:
        return item->GetThumbHideIfUnwatched(item);
      case LISTITEM_FOLDERPATH:
        return CURL(item->GetPath()).GetWithoutUserDetails();
      case LISTITEM_FOLDERNAME:
      case LISTITEM_PATH:
      {
        std::string path;
        URIUtils::GetParentPath(item->GetPath(), path);
        path = CURL(path).GetWithoutUserDetails();
        if (info.m_info == LISTITEM_FOLDERNAME)
        {
          URIUtils::RemoveSlashAtEnd(path);
          path = URIUtils::GetFileName(path);
        }
        return path;
      }
      case LISTITEM_FILENAME_AND_PATH:
      {
        std::string path = item->GetPath();
        path = CURL(path).GetWithoutUserDetails();
        return path;
      }
      case LISTITEM_SORT_LETTER:
      {
        std::string letter;
        std::wstring character(1, item->GetSortLabel()[0]);
        StringUtils::ToUpper(character);
        g_charsetConverter.wToUTF8(character, letter);
        return letter;
      }
      case LISTITEM_STARTTIME:
      {
        if (item->m_dateTime.IsValid())
          return item->m_dateTime.GetAsLocalizedTime("", false);
        break;
      }
      case LISTITEM_STARTDATE:
      {
        if (item->m_dateTime.IsValid())
          return item->m_dateTime.GetAsLocalizedDate(true);
        break;
      }
      case LISTITEM_CURRENTITEM:
        return std::to_string(item->GetCurrentItem());
    }
  }

  return value;
}

std::string CGUIInfoManager::GetItemImage(const CGUIListItem *item, int contextWindow, int info, std::string *fallback /*= nullptr*/) const
{
  if (!item || !item->IsFileItem())
    return std::string();

  return GetMultiInfoItemImage(static_cast<const CFileItem*>(item), contextWindow, CGUIInfo(info), fallback);
}

std::string CGUIInfoManager::GetMultiInfoItemImage(const CFileItem *item, int contextWindow, const CGUIInfo &info, std::string *fallback /*= nullptr*/) const
{
  if (info.m_info >= CONDITIONAL_LABEL_START && info.m_info <= CONDITIONAL_LABEL_END)
  {
    return GetSkinVariableString(info.m_info, contextWindow, true, item);
  }
  else if (info.m_info >= MULTI_INFO_START && info.m_info <= MULTI_INFO_END)
  {
    return GetMultiInfoItemImage(item, contextWindow, m_multiInfo[info.m_info - MULTI_INFO_START], fallback);
  }

  return GetMultiInfoItemLabel(item, contextWindow, info, fallback);
}

bool CGUIInfoManager::GetItemBool(const CGUIListItem *item, int contextWindow, int condition) const
{
  if (!item)
    return false;

  bool value = false;
  if (!m_infoProviders.GetBool(value, item, contextWindow, CGUIInfo(condition)))
  {
    switch (condition)
    {
      case LISTITEM_ISSELECTED:
        return item->IsSelected();
      case LISTITEM_IS_FOLDER:
        return item->m_bIsFolder;
      case LISTITEM_IS_PARENTFOLDER:
      {
        if (item->IsFileItem())
        {
          const CFileItem *pItem = static_cast<const CFileItem *>(item);
          return pItem->IsParentFolder();
        }
        break;
      }
    }
  }

  return value;
}

void CGUIInfoManager::ResetCache()
{
  // mark our infobools as dirty
  std::unique_lock<CCriticalSection> lock(m_critInfo);
  ++m_refreshCounter;
}

void CGUIInfoManager::SetCurrentVideoTag(const CVideoInfoTag &tag)
{
  m_currentFile->SetFromVideoInfoTag(tag);
  m_currentFile->SetStartOffset(0);
}

void CGUIInfoManager::SetCurrentSongTag(const MUSIC_INFO::CMusicInfoTag &tag)
{
  m_currentFile->SetFromMusicInfoTag(tag);
  m_currentFile->SetStartOffset(0);
}

const MUSIC_INFO::CMusicInfoTag* CGUIInfoManager::GetCurrentSongTag() const
{
  if (m_currentFile->HasMusicInfoTag())
    return m_currentFile->GetMusicInfoTag();

  return nullptr;
}

const CVideoInfoTag* CGUIInfoManager::GetCurrentMovieTag() const
{
  if (m_currentFile->HasVideoInfoTag())
    return m_currentFile->GetVideoInfoTag();

  return nullptr;
}

const KODI::GAME::CGameInfoTag* CGUIInfoManager::GetCurrentGameTag() const
{
  if (m_currentFile->HasGameInfoTag())
    return m_currentFile->GetGameInfoTag();

  return nullptr;
}

int CGUIInfoManager::RegisterSkinVariableString(const CSkinVariableString* info)
{
  if (!info)
    return 0;

  std::unique_lock<CCriticalSection> lock(m_critInfo);
  m_skinVariableStrings.emplace_back(*info);
  delete info;
  return CONDITIONAL_LABEL_START + m_skinVariableStrings.size() - 1;
}

int CGUIInfoManager::TranslateSkinVariableString(const std::string& name, int context)
{
  for (std::vector<CSkinVariableString>::const_iterator it = m_skinVariableStrings.begin();
       it != m_skinVariableStrings.end(); ++it)
  {
    if (StringUtils::EqualsNoCase(it->GetName(), name) && it->GetContext() == context)
      return it - m_skinVariableStrings.begin() + CONDITIONAL_LABEL_START;
  }
  return 0;
}

std::string CGUIInfoManager::GetSkinVariableString(int info,
                                                   int contextWindow,
                                                   bool preferImage /*= false*/,
                                                   const CGUIListItem* item /*= nullptr*/) const
{
  info -= CONDITIONAL_LABEL_START;
  if (info >= 0 && info < static_cast<int>(m_skinVariableStrings.size()))
    return m_skinVariableStrings[info].GetValue(contextWindow, preferImage, item);

  return "";
}

bool CGUIInfoManager::ConditionsChangedValues(const std::map<INFO::InfoPtr, bool>& map)
{
  for (std::map<INFO::InfoPtr, bool>::const_iterator it = map.begin() ; it != map.end() ; ++it)
  {
    if (it->first->Get(INFO::DEFAULT_CONTEXT) != it->second)
      return true;
  }
  return false;
}

int CGUIInfoManager::GetMessageMask()
{
  return TMSG_MASK_GUIINFOMANAGER;
}

void CGUIInfoManager::OnApplicationMessage(KODI::MESSAGING::ThreadMessage* pMsg)
{
  switch (pMsg->dwMessage)
  {
  case TMSG_GUI_INFOLABEL:
  {
    if (pMsg->lpVoid)
    {
      auto infoLabels = static_cast<std::vector<std::string>*>(pMsg->lpVoid);
      for (auto& param : pMsg->params)
        infoLabels->emplace_back(GetLabel(TranslateString(param), DEFAULT_CONTEXT));
    }
  }
  break;

  case TMSG_GUI_INFOBOOL:
  {
    if (pMsg->lpVoid)
    {
      auto infoLabels = static_cast<std::vector<bool>*>(pMsg->lpVoid);
      for (auto& param : pMsg->params)
        infoLabels->push_back(EvaluateBool(param, DEFAULT_CONTEXT));
    }
  }
  break;

  case TMSG_UPDATE_CURRENT_ITEM:
  {
    CFileItem* item = static_cast<CFileItem*>(pMsg->lpVoid);
    if (!item)
      return;

    if (pMsg->param1 == 1 && item->HasMusicInfoTag()) // only grab music tag
      SetCurrentSongTag(*item->GetMusicInfoTag());
    else if (pMsg->param1 == 2 && item->HasVideoInfoTag()) // only grab video tag
      SetCurrentVideoTag(*item->GetVideoInfoTag());
    else
      SetCurrentItem(*item);

    delete item;
  }
  break;

  default:
    break;
  }
}

void CGUIInfoManager::RegisterInfoProvider(IGUIInfoProvider *provider)
{
  if (!CServiceBroker::GetWinSystem())
    return;

  std::unique_lock<CCriticalSection> lock(CServiceBroker::GetWinSystem()->GetGfxContext());

  m_infoProviders.RegisterProvider(provider, false);
}

void CGUIInfoManager::UnregisterInfoProvider(IGUIInfoProvider *provider)
{
  if (!CServiceBroker::GetWinSystem())
    return;

  std::unique_lock<CCriticalSection> lock(CServiceBroker::GetWinSystem()->GetGfxContext());

  m_infoProviders.UnregisterProvider(provider);
}
