summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/gui/skin/SkinTimers.dox
blob: 0d6f17140d33bb1b1b985ee7e63bae147d345718 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*!

\page Skin_Timers Skin Timers
\brief **Programatic time-based resources for Skins**

\tableofcontents

--------------------------------------------------------------------------------
\section Skin_Timers_sect1 Description

Skin timers are skin resources that are dependent on time and can be fully controlled from skins either using
\link page_List_of_built_in_functions **Builtin functions**\endlink or
\link modules__infolabels_boolean_conditions **Infolabels and Boolean conditions**\endlink. One can see them
as stopwatches that can be activated and deactivated automatically depending on the value of info expressions or simply activated/deactivated
manually from builtins.
The framework was created to allow skins to control the visibility of windows (and controls) depending on
the elapsed time of timers the skin defines. Skin timers allow multiple use cases in skins, previously only available via the execution
of python scripts:
- Closing a specific window after x seconds have elapsed
- Controlling the visibility of a group (or triggering an animation) depending on the elapsed time of a given timer
- Defining a buffer time window that is kept activated for a short period of time (e.g. keep controls visible for x seconds after a player seek)
- Executing timed actions (on timer stop or timer start)
- etc

Skin timers are defined in the `Timers.xml` file within the xml directory of the skin. The file has the following "schema":

~~~~~~~~~~~~~{.xml}
<timers>
    <timer>...</timer>
    <timer>...</timer>
</timers>
~~~~~~~~~~~~~

see \link Skin_Timers_sect2 the examples section\endlink and \link Skin_Timers_sect3 the list of available tags\endlink for concrete details.

\skinning_v20 Added skin timers

--------------------------------------------------------------------------------
\section Skin_Timers_sect2 Examples

The following example illustrates the simplest possible skin timer. This timer is completely manual (it has to be manually started and stopped):

~~~~~~~~~~~~~{.xml}
<timer>
    <name>mymanualtimer</name>
    <description>100% manual timer</description>
</timer>
~~~~~~~~~~~~~

This timer can be controlled from your skin by executing the \link Builtin_SkinStartTimer `Skin.TimerStart(mymanualtimer)` builtin\endlink or
\link Builtin_SkinStopTimer `Skin.TimerStop(mymanualtimer)` builtin\endlink. You can define the visibility of skin elements based on the internal
properties of the timer, such as the fact that the timer is active/running using \link Skin_TimerIsRunning `Skin.TimerIsRunning(mymanualtimer)` info\endlink
or depending on the elapsed time (e.g. 5 seconds) using the \link Skin_TimerElapsedSecs Integer.IsGreaterOrEqual(Skin.TimerElapsedSecs(mymanualtimer),5) info\endlink.

The following timer is a variation of the previous timer but with the added ability of being automatically stopped by the skinning engine after a maximum of elapsed
5 seconds without having to issue the `Skin.TimerStop(mymanualtimer)` builtin:

~~~~~~~~~~~~~{.xml}
<timer>
    <name>mymanualautocloseabletimer</name>
    <description>100% manual autocloseable timer</description>
    <stop>Integer.IsGreaterOrEqual(Skin.TimerElapsedSecs(mymanualautocloseabletimer),5)</stop>
</timer>
~~~~~~~~~~~~~

This type of timer is particularly useful if you want to automatically close a specific window (or triggering a close animation) after x time has elapsed,
while guaranteeing the timer is also stopped. See the example below:

~~~~~~~~~~~~~{.xml}
<?xml version="1.0" encoding="utf-8"?>
<window type="dialog" id="1109">
	<onload>Skin.TimerStart(mymanualautocloseabletimer)</onload>
    ...
	<controls>
		<control type="group">
			<animation effect="slide" start="0,0" end="0,-80" time="300" condition="Integer.IsGreaterOrEqual(Skin.TimerElapsedSecs(mymanualautocloseabletimer),5)">Conditional</animation>
			...
        </control>
    </controls>
</window>
~~~~~~~~~~~~~

The following timer presents a notification (for 1 sec) whenever the timer is activated or deactivated:

~~~~~~~~~~~~~{.xml}
<timer>
    <name>manualtimerwithactions</name>
    <description>100% manual timer with actions</description>
    <onstart>Notification(skintimer, My timer was started, 1000)</onstart>
    <onstop>Notification(skintimer, My timer was stopped, 1000)</onstop>
</timer>
~~~~~~~~~~~~~

The following timer is an example of a completely automatic timer. The timer is automatically activated or deactivated based on the value
of boolean info expressions. In this particular example, the timer is automatically started whenever the Player is playing a file (if not already running). It is stopped if
there is no file being played (and of course if previously running). Since the timer can be activated/deactivated multiple times, `reset="true"` ensures the timer is
always reset to 0 on each start operation. Whenever the timer is started or stopped, notifications are issued.

~~~~~~~~~~~~~{.xml}
<timer>
    <name>myautomatictimer</name>
    <description>Player state checker</description>
    <start reset="true">Player.Playing</start>
    <stop>!Player.Playing</stop>
    <onstart>Notification(skintimer, Player has started playing a file, 1000)</onstart>
    <onstop>Notification(skintimer, Player is no longer playing a file, 1000)</onstop>
</timer>
~~~~~~~~~~~~~

In certain situations you might want to reset your timer without having to stop and start. For instance, if you want to stop the timer after 5 seconds
but have the timer resetting to 0 seconds if the user provides some input to Kodi. For such cases the `<reset/>` condition can be used:

~~~~~~~~~~~~~{.xml}
<timer>
    <name>windowtimer</name>
    <description>Reset on idle</description>
    <start reset="true">Window.IsActive(mywindow)</start>
    <reset>Window.IsActive(mywindow) + !System.IdleTime(1) + Integer.IsGreaterOrEqual(Skin.TimerElapsedSecs(windowtimer), 1)</reset>
    <stop>!Window.IsActive(mywindow) + Integer.IsGreaterOrEqual(Skin.TimerElapsedSecs(windowtimer), 5)</stop>
    <onstop>Dialog.Close(mywindow)</onstop>
</timer>
~~~~~~~~~~~~~

Finer conditional granularity can also be applied to the `onstop` or `onstart` actions. This allows the skinner to create generic timers which respect a 
limited set of conditions but trigger different actions depending on a condition applied only to the action.
The following timer plays the trailer of a given item when the user is in the videos window, the item has a trailer, the player is not playing and the
global idle time is greater than 3 seconds.
As you can see, the first action (notification) is triggered for any item. The actual playback, on the other hand, will only play if the focused
item has the label "MyAwesomeMovie".

~~~~~~~~~~~~~{.xml}
<timer>
    <name>trailer_autoplay_idle_timer</name>
    <start reset="true">System.IdleTime(3) + Window.IsVisible(videos) + !Player.HasMedia + !String.IsEmpty(ListItem.Trailer)</start>
    <onstart>Notification(skintimer try play, $INFO[ListItem.Trailer], 1000)</onstart>
    <onstart condition="String.IsEqual(ListItem.Label,MyAwesomeMovie)">PlayMedia($INFO[ListItem.Trailer],1,noresume)</onstart>
</timer>
~~~~~~~~~~~~~

--------------------------------------------------------------------------------
\section Skin_Timers_sect3 Available tags

Skin timers have the following available tags:

| Tag           | Description                                                   |
|--------------:|:--------------------------------------------------------------|
| name          | The unique name of the timer. The name is used as the id of the timer, hence needs to be unique. <b>(required)</b>
| description   | The description of the timer, a helper string. <b>(optional)</b>
| start         | An info bool expression that the skinning engine should use to automatically start the timer <b>(optional)</b>
| reset         | An info bool expression that the skinning engine should use to automatically reset the timer <b>(optional)</b>
| stop          | An info bool expression that the skinning engine should use to automatically stop the timer <b>(optional)</b>
| onstart       | A builtin function that the skinning engine should execute when the timer is started <b>(optional)</b><b>(can be repeated)</b>. Supports an additional `"condition"` as element attribute.
| onstop        | A builtin function that the skinning engine should execute when the timer is stopped <b>(optional)</b><b>(can be repeated)</b>. Supports an additional `"condition"` as element attribute.

@note If multiple onstart or onstop actions exist, their execution is triggered sequentially.
@note Both onstart and onstop actions support fine-grained conditional granularity by specifying a "condition" attribute (see the examples above).

--------------------------------------------------------------------------------
\section Skin_Timers_sect4 See also
#### Development:

- [Skinning](http://kodi.wiki/view/Skinning)

*/