This page explains and demonstrates how to use Basic Snowmix Scripting and a little advanced Snowmix scripting to create an analogue clock. The clock will display hours, minutes and seconds. We could use text strings, but will in this case we will load some images and manipulate these images to create the illusion of an analogue clock Swiss style.
The image above shows the Swiss style analogue clock.
Initially we need a minimum setup for Snowmix as shown below:
system control port 9999
system geometry 768 576 BGRA
system frame rate 25
system socket /tmp/mixer1
We need no video feeds to run and test the clock. Now we need to load the images to used for creating the clock.
# Load clock image components
image load 10 ../images/SwissClock-trans-259x259.png
image load 11 ../images/SwissClock-trans-hand-9x89.png
image load 12 ../images/SwissClock-trans-second-hand-19x105-center-9-81.png
# Clock case and plate
image place 1 10 129 129 center middle
image scale 1 0.5 0.5
# Second hand shadow
image place 2 12 127 127 center bottom
image scale 2 0.5 0.5
image offset 2 0 22
image alpha 2 0.3
image filter 2 best
# minute hand
image place 3 11 129 129 center bottom
image scale 3 0.55 0.55
image offset 3 -3 19
image filter 3 best
# hour hand
image place 4 11 129 129 center bottom
image scale 4 0.55 0.4
image offset 4 0 22
image filter 4 best
# Second hand
image place 5 12 129 129 center bottom
image scale 5 0.5 0.5
image offset 5 0 22
image filter 5 best
Because the clock's case and plate is optimized for a light background, we will create a shape with grey and fill the mixer bottom background.
shape add 1 coloured background
shape rectangle 1 0 0 1 1
shape fill 1
shape place 1 1 0 0 768 576 0 0.8 0.8 0.8 1
Now we need ensure that the shape and the images a overlayed during each frame mix.
# By default the stack will have the system feed 0 as the bottom background
# stack 0
command create Show
shape overlay 1
image overlay 1..5
loop
command end
overlay finish Show
With the configuration so far, we can now test the visual look of the clock and should see our Swiss analogue clock with hour, minute and seconds hands at 00:00:00. Saving the above command in the file ini/ExampleAnalogueClock.ini, we can now run the following commands:
cd src
./snowmix ../ini/ExampleAnalogueClock.ini
and in another window
cd scripts
./output2screen
However to have the clock running, we need to create a state-machine setting the state of the clock as time progress. To do that, we use the overlay pre command.
command create PreShow
FrameUpdate25
loop
command end
overlay pre PreShow
command create FrameUpdate25
next 24
SecondUpdate
loop
command end
# We move 2*PI/60 = 0.10471975511965977461
command create SecondUpdate
# Move second hands
image place move rotation 2 0.10471975511965977461 1
image place move rotation 5 0.10471975511965977461 1
loop
command end
Here we use the animation command image place move rotation to rotate the second hands 1/60 of 2*PI every second. We could use the same method to rotate the minute hand 1/60 of a full circle every minute and the hour hand 1/(24*60) of a full circle same every same minute. However if we went that way, setting the clock becomes difficult. Further more, the clock will need synchronization because we are using animation based on mixing a frame. We do try to mix frames at frame rate, but that is not a thing that can be guaranteed. To deal with all this, we will synchronize the Clock every minute to the computer clock. Doing so, we might as well set the hour and minute hand to needed rotation.
To get the computer clock, we will need to use the embedded Tcl interpreter. The script that will do this for us is shown below.
tcl eval set last_hour 0
tcl eval set last_minute 0
command create ClockSync.tcl
proc ClockSync { hourhand minutehand secondhand shadowsecondhand } {
global last_hour last_minute
set time [clock format [clock seconds] -format "%l %M %S"]
set minute [lindex $time 1]
set hour [lindex $time 0]
if { $last_minute == $minute && $last_hour == $hour } return
set second [lindex $time 2]
set pi [expr 2*asin(1.0)]
set sec_rot [expr $pi * $second / 30.0 ]
set min_rot [expr $pi * $minute / 30.0 ]
set hour_rot [expr $pi * $hour / 6.0 ]
set last_minute $minute
set last_hour $hour
set command "image place rotation $hourhand $hour_rot\n"
append command "image place rotation $minutehand $min_rot\n"
append command "image place rotation $secondhand $sec_rot\n"
append command "image place rotation $shadowsecondhand $sec_rot\n"
append command "image place move rotation $secondhand 0 0\n"
append command "image place move rotation $shadowsecondhand 0 0\n"
append command "command restart FrameUpdate25\n"
snowmix parse $command
return
}
command end
tcl exec ClockSync.tcl
In the script above, every time it is called, it will get the computer clock. When the minutes change, it will set the seconds, minute and hour hand and reset the FrameUpdate25 command macro.
The last thing needed to get the script running, is to add a call to the Tcl procedure ClockSync every second. This can be done using the following lines:
command pop FrameUpdate25
command push FrameUpdate25 tcl eval ClockSync 4 3 5 2
command push FrameUpdate25 loop
# Last we initialize the clock setting the hour, minute and seconds hands
tcl eval ClockSync 4 3 5 2
The ini file for this example is available as an attachment to this page found at the top of the page. Download the file and use it as ini file for Snowmix to test the example.