-
Notifications
You must be signed in to change notification settings - Fork 16
Scripting Engine
Skin variables has a powerful skin scripting engine for chaining conditional commands together. Scripting engine files are stored in json format and run via RunScript
RunScript(script.skinvariables,run_executebuiltin=special://skin/shortcuts/builtins/commands.json,use_rules=True)
The above runs the command file shortcuts/builtins/commands.json
Any location and filename can be used.
The use_rules=True
param must be specified to indicate that the script will be running commands from a file.
Below is a basic example script e.g. our commands.json file
{
"infolabels": {
"fanart_path": "ListItem.Art(fanart)",
"landscape_path": "ListItem.Art(landscape)"
},
"regex": {},
"values": {},
"sums": {},
"decode": {},
"encode": {},
"escape": {},
"capitalize": {},
"lower": {},
"upper": {},
"operations": [],
"actions": [
"SetProperty(Fanart_Path,{fanart_path},Home)",
"SetProperty(Landscape_Path,{landscape_path},Home)"
]
}
In effect this example is equivalent to:
SetProperty(Fanart_Path,$INFO[ListItem.Art(fanart)],Home)
SetProperty(Landscape_Path,$INFO[ListItem.Art(landscape)],Home)
NOTE: The lines with empty sections such as "regex" and "values" etc. are optional and can be removed if empty. They are displayed above to demonstrate possible options.
Retrieves $INFO[info]
values and stores as a key
Any infolabel from https://kodi.wiki/view/InfoLabels can be used
"infolabels": {
"key_01": "info_01",
"key_02": "info_02"
}
At times you may want some values to be conditional similar to a $VAR.
Conditional values are specified in the values
section and have a list of rules
to be met for the corresponding value
to be stored into the key
. The conditions are evaluated in order until a match is found (similar to how a $VAR might operate).tion)
Example:
{
"infolabels": {
"landscape_path": "ListItem.Art(landscape)",
"fallback_path": "Skin.String(Landscape.FallBack)"
},
"values": {
"image_path": [
{
"rules": ["{landscape_path}!="],
"value": "{landscape_path}"
},
{
"rules": ["{fallback_path}!="],
"value": "{fallback_path}"
},
"special://skin/extras/backgrounds/default.jpg"
]
},
"actions": [
"SetProperty(Landscape_Path,{image_path},Home)"
]
}
In effect this example is equivalent to:
<variable name="image_path">
<value condition="!String.ISEmpty(ListItem.Art(landscape))">$INFO[ListItem.Art(landscape)]</value>
<value condition="!String.ISEmpty(Skin.String(Landscape.FallBack))">$INFO[Skin.String(Landscape.FallBack)]</value>
<value>special://skin/extras/backgrounds/default.jpg</value>
</variable>
SetProperty(Landscape_Path,$VAR[image_path],Home)
Operator | Description | Example |
---|---|---|
== |
Equal |
["{color}==blue"] "value in color equals blue" |
!= |
Not Equal |
["{color}!=blue"] "value in color does not equal blue" |
<< |
Contains |
["{color}<<blue"] "value in color contains blue" e.g. also matches if value is "deep blue" or "light blue" or "blue green" etc. |
>> |
Contained |
["{color}>>blue"] "value in color contained in blue" i.e. reverse of contains |
!< |
Not Contains |
["{color}!<blue"] "value in color does not contain blue" i.e. inverse of contains |
!> |
Not Contained |
["{color}!>blue"] "value in color is not contained in blue" i.e. inverse of contained |
Rules to compare against an empty value is as simple as leaving the other side of the operator blank
Example ["{color}=="]
is "the value in color is empty"
Example ["{color}!="]
is "the value in color is not empty"
Rules can also use skin engine booleans as conditions.
Any boolean from https://kodi.wiki/view/List_of_boolean_conditions can be used
Example: The value in color contains blue and the videoosd window is visible:
"rules": [
"{color}<<blue",
"Window.IsVisible(videoosd)"
]
Rules can be chained together as a list of AND conditions where all conditions must be met.
AND conditions are a comma separated list of conditions.
Example: Match where value in color contains "blue" but not "deep" so matches "blue" or "light blue" or "blue green" but not "deep blue"
"rules": [
"{color}<<blue",
"{color}!<deep"
]
Rules can also specify an OR
condition with a double pipe ||
symbol
Example: Match where value in color contains either blue or green
["{color}<<blue||{color}<<green"]
Example: Match where value in color contains "blue" or "green" but not "deep"
"rules": [
"{color}<<blue||{color}<<green",
"{color}!<deep"
]
Example: Modify the capitalization of the value stored in key and output to a different key
"capitalize": {"capitalized_key": "{key}"},
"upper": {"upper_key": "{key}"},
"lower": {"lower_key": "{key}"}
Use a regex condition to substitute a value using re.sub()
Example: Substitute all numbers found in key with an "X" and output back to key
"regex": {
"key": {
"regex": "[0-9]",
"value": "X",
"input": "{key}"
}
}
Example: Sum a list of numbers together
"sums": {"total_value": ["{key_01}", "{key_02}", "{key_03}"]}
Apply URL decoding/encoding
Example:
"decode": {"decoded_key": "{key}"},
"encode": {"encoded_key": "{key}"}
Apply XML escaping e.g. convert &
to &
Example:
"escape": {"escaped_key": "{key}"}
By default the order of operations that occur before actions are:
- infolabels
- regex
- values
- sums
- decode
- encode
- escape
- lower
- upper
However, at times you may wish to specify a custom order for operations (e.g. to do regex after values etc.).
A custom list of operations can be specified with the operations
list. The list of operations is conducted after all main operations complete but before actions.
Example:
"operations": [
{"values": {VALUES_SECTION_GOES_HERE}},
{"regex": {REGEX_SECTION_GOES_HERE}}
[etc]
]
At times you may also wish to specify the value of a key at the moment of running the script itself. These key value pairs can be specified when running the script itself. Any key name can be used as long as it doesn't conflict with some other script command used by skin variables.
Example: Set key_01 to value_01 and key_02 to $INFO[System.Time]
RunScript(
script.skinvariables,
run_executebuiltin=special://skin/shortcuts/builtins/commands.json,
use_rules=True,
key_01=value_01,
key_02=$INFO[System.Time]
)
The above example is split onto separate lines for readability. Use as a single line command.
Actions can also be conditional, with multiple actions chained as values.
Example
"actions": [
{
"rules": ["!Container.IsUpdating"],
"value": [
"Notification(Container,Finished updating)",
"SetProperty(ContainerUpdating,False)"
]
},
{
"rules": ["Container.IsUpdating"],
"value": [
"Notification(Container,Still updating)",
"SetProperty(ContainerUpdating,True)"
]
},
]
A sleep command can be used to wait between actions
Example:
"actions": [
"Notification(SV,Sleep for 2.5 seconds)",
"sleep=2.5",
"Notification(SV,Wake Up)"
]
Occasionally you might want to reroute back to a skinvariables script. If you use the normal RunScript approach, the command will be triggered and then the next action will run immediately. However, it might be necessary to wait for the script to complete first. In that case use route=
Example:
"actions": [
"route=run_executebuiltin=special://skin/shortcuts/builtins/other_commands.json&use_rules=True",
"Notification(SV,Other Commands Completed)"
]
More advanced actions that normally wouldn't be permitted by the skinning engine are also possible such as using a variable command from a key
Example: Use command stored in a window property:
"infolabels": {
"string_command": "Window.Property(StringCommand)",
"string_name": "Window.Property(StringName)",
"string_value": "Window.Property(StringValue)"
}
"actions": [
"{string_command}({string_name},{string_value})"
]
If we run SetProperty(StringCommand,Skin.SetString) before running the above then it will run as:
Skin.SetString($INFO[Window.Property(StringName)],$INFO[Window.Property(StringValue)])
If we run SetProperty(StringCommand,SetProperty) however, then the above will run as this instead:
SetProperty($INFO[Window.Property(StringName)],$INFO[Window.Property(StringValue)])