Sign in to follow this  
Followers 0
SadBunny

Nice looking graphical analog/digital clock

4 posts in this topic

#1 ·  Posted (edited)

Sadbunny's analog/digital AutoIt alarm clock!

Simpler but far more effective then my other AutoIt clock... Which also almost no-one cared about. Well heck, as long as I care about my own ability to get out of bed early enough to be only a minute late to work, I guess I can pat myself on the back :D

Born out of the fact that my old alarm clock started boring me. And also because I was trying out a few of these here GuiCtrl[Create/Set]Graphic functions anyway.

Do anything you want with this code except for any commercial stuff. But do credit me. And notify me on the AutoIt forum if you find the time - just for my øwn kicks :P (Not that I believe there's anyone in this world who would find any need to steal some of this code... I just like writing things like that ;))

Use Left Mouse Button to set alarm, and Right Mouse Button to unset alarm or to quit sounding it.

Note: the default alarm sound is @WindowsDir & "\media\ringin.wav". This because it should be present on pretty much any Windows box, and it is a really good alarm clock sound IMHO. I've been waking up to this sound for months now - my AutoItScript is way more useful and dependable than my physical alarm clock.

Known Issues:

Every time a refresh command is sent to one specific Graphic control, all other graphic controls seem to receive a refresh command too. This causes a small (small on my system at least) flicker every time @SEC changes... If anybody has any suggestions, I'd be happy to be informed.

Two advantages:

1 - The alarm keeps sounding FOREVER until you quit it. Hey, I can't bring myself to become conscious in the 30 seconds that most alarm clocks ring. Having to type in my screensaver password before being able to switch off the alarm really, REALLY helps.

2 - The volume is ofcourse adjustable through speaker or windows settings. I'm not a radio or MP3 alarm clock guy, I use a beeping clock for my physical one.

Plans:

1 - introduce a button for a settings window, that will at least include a function to set alarm repetition intended for snoozing, like 'sound for A seconds every B minutes between time C and D, and at time E sound forever until quit by user.

Damn, in the morning I'm so lazy that I don't even want to worry about the need to press the Snooze button -there's gotta be automation for that... :P I make up for that by losing sleep in the evening coding an alarm clock. Damn, sucks to be me! ;)

#include <GUIConstants.au3>

Dim $aDigChar[13]
_initDigChar($aDigChar)

Dim $aXY[2]
Global $sec = @SEC
Global $MinDegree = 0
Global $HourDegree = 0
Global $AlarmDegree = 0
Global $alarmHour = 0
Global $alarmMin = 0
Global $alarmSec = 0
Global $alarmIsSet = False
Global $alarmIsSounding = False
Global $previousMinDegree = 0
Global $previousHourDegree = 0
Global $previousAlarmDegree = 0
Global $pi = 3.14159265358979
Global $degToRad = $pi / 180
Global $RadToDeg = 1 / $degToRad

#include <Sound.au3>
Global $alarmFile = @WindowsDir & "\media\ringin.wav"
Global $soundHandle = _SoundOpen($alarmFile, "alarmfile")

$gui = GUICreate("Test", 702, 702)
GUISetBkColor(0x000000)

GUISetState()

$megavierkant = GUICtrlCreateGraphic(0, 0, 700, 700)
$vierkant = GUICtrlCreateGraphic(150, 150, 400, 400)
$secSquare = GUICtrlCreateGraphic(0, 0, 0, 0)
$timeSquare = GUICtrlCreateGraphic(5, 5, 200, 30)
$alarmSquare = GUICtrlCreateGraphic(560, 5, 200, 30)

_drawInitBorder($megavierkant)

Dim $msg[1]

While 1
    ; main loop, waits until @sec changes and then executes main drawing management function
    While @SEC = $sec
        $msg = GUIGetMsg(1)
        If $msg[0] = -3 Then Exit
        If $msg[0] = $GUI_EVENT_PRIMARYDOWN Then
            $alarmIsSounding = False
            _SoundStop($soundHandle)
            $mX = $msg[3] - 350
            $mY = $msg[4] - 350
            $clickAngle = Int(ATan($mY / $mX) * $RadToDeg) + 90
            If $mX < 0 Then $clickAngle += 180
            $alarmHour = Int($clickAngle / 30)
            $alarmMin = Mod($clickAngle, 30) * 2
            $alarmSec = 0
            $alarmIsSet = True
            _draw()
        EndIf
        If $msg[0] = $GUI_EVENT_SECONDARYDOWN Then
            $alarmIsSounding = False
            _SoundStop($soundHandle)
            GUICtrlDelete($alarmSquare)
            $alarmIsSet = False
            $alarmHour = -1
            _draw(True)
        EndIf
        Sleep(20)
        If $alarmIsSounding Then _soundAlarm()
    WEnd
    _draw()
    Sleep(50)
    $sec = @SEC
    If (@HOUR = $alarmHour Or @HOUR = 12 + $alarmHour) And @MIN = $alarmMin And $alarmIsSet Then
        $alarmIsSounding = True
    EndIf
WEnd
Exit


Func _soundAlarm()
    If _SoundStatus($soundHandle) = "stopped" Then
        _SoundSeek($soundHandle,0,0,0)
        _SoundPlay($soundHandle, 0)
    EndIf
EndFunc   ;==>_soundAlarm


Func _draw($forceDraw = False)
    ; calculates angles for min/sec dials, manages execution of drawing routines
    Local $doDraw = False
    $MinDegree = Int((90 - @MIN * 6) - @SEC * 0.1)
    $HourDegree = Int((90 - @HOUR * 30) - @MIN * .5)
    $AlarmDegree = Int((90 - $alarmHour * 30) - $alarmMin * .5)
    If $MinDegree <> $previousMinDegree Or $AlarmDegree <> $previousAlarmDegree Then
        $doDraw = True
        $previousMinDegree = $MinDegree
        $previousAlarmDegree = $AlarmDegree
    EndIf

    If $doDraw Or $forceDraw Then
        GUICtrlDelete($vierkant)
        $vierkant = GUICtrlCreateGraphic(150, 150, 400, 400)
        _drawHourPie($vierkant)
        _drawMinPie($vierkant)
        If $alarmIsSet Then _drawAlarmPie($vierkant)
        GUICtrlSetGraphic($vierkant, $GUI_GR_REFRESH)
        $doDraw = False
    EndIf
    Sleep(25)
    _drawSec()
    _drawTime()
    If $alarmIsSet Then _drawAlarmTime()
    GUICtrlSetGraphic($secSquare, $GUI_GR_REFRESH)
EndFunc   ;==>_draw

Func _drawTime()
    ; manages execution of write commands for HH MM SS characters
    GUICtrlDelete($timeSquare)
    $timeSquare = GUICtrlCreateGraphic(5, 5, 200, 30)
    _timeWrite(1, Int(@HOUR / 10), "regular", $timeSquare)
    _timeWrite(20, Mod(@HOUR, 10), "regular", $timeSquare)
    _timeWrite(50, Int(@MIN / 10), "regular", $timeSquare)
    _timeWrite(70, Mod(@MIN, 10), "regular", $timeSquare)
    _timeWrite(100, Int(@SEC / 10), "regular", $timeSquare)
    _timeWrite(120, Mod(@SEC, 10), "regular", $timeSquare)
EndFunc   ;==>_drawTime

Func _drawAlarmTime()
    ; manages execution of write commands for HH MM SS characters for the alarm time
    GUICtrlDelete($alarmSquare)
    $alarmSquare = GUICtrlCreateGraphic(480, 5, 220, 30)
    _timeWrite(1, 10, "alarm", $alarmSquare)
    _timeWrite(20, 11, "alarm", $alarmSquare)
    _timeWrite(50, 12, "alarm", $alarmSquare)
    _timeWrite(80, Int($alarmHour / 10), "alarm", $alarmSquare)
    _timeWrite(100, Mod($alarmHour, 10), "alarm", $alarmSquare)
    _timeWrite(130, Int($alarmMin / 10), "alarm", $alarmSquare)
    _timeWrite(150, Mod($alarmMin, 10), "alarm", $alarmSquare)
    _timeWrite(180, Int($alarmSec / 10), "alarm", $alarmSquare)
    _timeWrite(200, Mod($alarmSec, 10), "alarm", $alarmSquare)
EndFunc   ;==>_drawAlarmTime

Func _timeWrite($pos, $num, $type, $graph) ; $type is "regular" or "alarm"
    ; manages coloring and writing of LEDs for time writing
    
    _setColorAndPenForWrite(StringMid($aDigChar[$num], 1, 1), $type);0
    _line($graph, $pos + 5, 2, $pos + 3, 10)
    
    _setColorAndPenForWrite(StringMid($aDigChar[$num], 2, 1), $type);1
    _line($graph, $pos + 2, 14, $pos + 0, 22)
    
    _setColorAndPenForWrite(StringMid($aDigChar[$num], 3, 1), $type);2
    _line($graph, $pos + 5 + 2, 0, $pos + 5 + 8, 0)
    
    _setColorAndPenForWrite(StringMid($aDigChar[$num], 4, 1), $type);3
    _line($graph, $pos + 2 + 2, 12, $pos + 2 + 8, 12)
    
    _setColorAndPenForWrite(StringMid($aDigChar[$num], 5, 1), $type);4
    _line($graph, $pos + 2, 24, $pos + 8, 24)
    
    _setColorAndPenForWrite(StringMid($aDigChar[$num], 6, 1), $type);5
    _line($graph, $pos + 5 + 10, 2, $pos + 3 + 10, 10)
    
    _setColorAndPenForWrite(StringMid($aDigChar[$num], 7, 1), $type);6
    _line($graph, $pos + 2 + 10, 14, $pos + 10, 22)
EndFunc   ;==>_timeWrite

Func _line($graph, $x1, $y1, $x2, $y2)
    ; draws line for time writing
    GUICtrlSetGraphic($graph, $GUI_GR_MOVE, $x1 + 2, $y1 + 2)
    GUICtrlSetGraphic($graph, $GUI_GR_LINE, $x2 + 2, $y2 + 2)
EndFunc   ;==>_line

Func _setColorAndPenForWrite($char, $type)
    ; sets color and pen for next line in time writing, based on '0' or '1' in the DigChar array
    If $char = "1"  Then
        If $type = "alarm"  Then
            GUICtrlSetGraphic($alarmSquare, $GUI_GR_PENSIZE, 2)
            GUICtrlSetGraphic($alarmSquare, $GUI_GR_COLOR, 0xCCCCCC, 0xCCCCCC)
        Else
            GUICtrlSetGraphic($timeSquare, $GUI_GR_PENSIZE, 2)
            GUICtrlSetGraphic($timeSquare, $GUI_GR_COLOR, 0xEE0000, 0xEE0000)
        EndIf
    Else
        If $type = "alarm"  Then
            GUICtrlSetGraphic($alarmSquare, $GUI_GR_PENSIZE, 2)
            GUICtrlSetGraphic($alarmSquare, $GUI_GR_COLOR, 0x444444, 0x444444)
        Else
            GUICtrlSetGraphic($timeSquare, $GUI_GR_PENSIZE, 2)
            GUICtrlSetGraphic($timeSquare, $GUI_GR_COLOR, 0x660000, 0x660000)
        EndIf
    EndIf
EndFunc   ;==>_setColorAndPenForWrite

Func _drawSec()
    ; draws circle seconds indicator
    $aXY = _getXY(@SEC, 240)
    GUICtrlDelete($secSquare)
    $secSquare = GUICtrlCreateGraphic(350 + $aXY[0] - 8, 350 + $aXY[1] - 8, 16, 16)
    GUICtrlSetGraphic($secSquare, $GUI_GR_COLOR, 0x0000FF, 0x0000FF)
    GUICtrlSetGraphic($secSquare, $GUI_GR_ELLIPSE, 0, 0, 16, 16)
EndFunc   ;==>_drawSec

Func _drawAlarmPie($graph)
    ; draws alarm dial
    GUICtrlSetGraphic($graph, $GUI_GR_COLOR, 0xDDDDDD, 0xDDDDDD)
    GUICtrlSetGraphic($graph, $GUI_GR_PIE, 200, 200, 228, $AlarmDegree, 0)
    GUICtrlSetGraphic($graph, $GUI_GR_COLOR, 0xBB9999, 0x000000)
    GUICtrlSetGraphic($graph, $GUI_GR_PIE, 200, 200, 120, $AlarmDegree - 1, 2)
    GUICtrlSetGraphic($graph, $GUI_GR_COLOR, 0x996666, 0x000000)
    GUICtrlSetGraphic($graph, $GUI_GR_PIE, 200, 200, 70, $AlarmDegree - 2, 4)
    GUICtrlSetGraphic($graph, $GUI_GR_COLOR, 0x773333, 0x000000)
    GUICtrlSetGraphic($graph, $GUI_GR_PIE, 200, 200, 20, $AlarmDegree - 4, 8)
    Return True
EndFunc   ;==>_drawAlarmPie

Func _drawMinPie($graph)
    ; draws minute dial
    GUICtrlSetGraphic($graph, $GUI_GR_COLOR, 0xBBBB00, 0xBBBB00)
    GUICtrlSetGraphic($graph, $GUI_GR_PIE, 200, 200, 200, $MinDegree - 2, 4)
    GUICtrlSetGraphic($graph, $GUI_GR_PIE, 200, 200, 220, $MinDegree, 0)
    GUICtrlSetGraphic($graph, $GUI_GR_COLOR, 0x000000, 0x000000)
    GUICtrlSetGraphic($graph, $GUI_GR_PIE, 200, 200, 150, $MinDegree - 1, 2)
    Return True
EndFunc   ;==>_drawMinPie

Func _drawHourPie($graph)
    ; draws hour dial
    GUICtrlSetGraphic($graph, $GUI_GR_COLOR, 0xAA0000, 0xAA0000)
    GUICtrlSetGraphic($graph, $GUI_GR_PIE, 200, 200, 140, $HourDegree - 4, 8)
    GUICtrlSetGraphic($graph, $GUI_GR_PIE, 200, 200, 160, $HourDegree, 0)
    GUICtrlSetGraphic($graph, $GUI_GR_COLOR, 0x000000, 0x000000)
    GUICtrlSetGraphic($graph, $GUI_GR_PIE, 200, 200, 120, $HourDegree - 1, 2)
    Return True
EndFunc   ;==>_drawHourPie

Func _getXY($sec, $hypo)
    ; returns array with X,Y coordinates for the seconds points for $sec seconds, with $hypo(tenuse) distance from center
    Dim $result[2]
    Local $pi = 3.14159265358979
    Local $degToRad = $pi / 180
    Local $degrees = $sec * 6 - 90
    Local $x = Cos($degrees * $degToRad) * $hypo
    Local $y = Sin($degrees * $degToRad) * $hypo
    $result[0] = $x
    $result[1] = $y
    Return $result
EndFunc   ;==>_getXY

Func _drawInitBorder($megavierkant)
    ; draws initial border 'circle'
    For $count = 1 To 60
        If $count / 5 = Int($count / 5) Then
            Dim $a1 = _getXY($count, 260)
            Dim $a2 = _getXY($count, 280)
            GUICtrlSetGraphic($megavierkant, $GUI_GR_PENSIZE, 4)
            GUICtrlSetGraphic($megavierkant, $GUI_GR_COLOR, 0x00CC00, 0x00CC00)
            GUICtrlSetGraphic($megavierkant, $GUI_GR_MOVE, 350 + $a1[0], 350 + $a1[1])
            GUICtrlSetGraphic($megavierkant, $GUI_GR_LINE, 350 + $a2[0], 350 + $a2[1])
        Else
            Dim $a1 = _getXY($count, 270)
            Dim $a2 = _getXY($count, 280)
            GUICtrlSetGraphic($megavierkant, $GUI_GR_PENSIZE, 3)
            GUICtrlSetGraphic($megavierkant, $GUI_GR_COLOR, 0x008800, 0x008800)
            GUICtrlSetGraphic($megavierkant, $GUI_GR_MOVE, 350 + $a1[0], 350 + $a1[1])
            GUICtrlSetGraphic($megavierkant, $GUI_GR_LINE, 350 + $a2[0], 350 + $a2[1])
        EndIf
    Next
EndFunc   ;==>_drawInitBorder

Func _initDigChar(ByRef $aDigChar)
    ; define leds for digital numbers: 1 or 0 for leds on/off in 7-led digital clock characters
    $aDigChar[0] = "1110111"
    $aDigChar[1] = "0000011"
    $aDigChar[2] = "0111110"
    $aDigChar[3] = "0011111"
    $aDigChar[4] = "1001011"
    $aDigChar[5] = "1011101"
    $aDigChar[6] = "1111101"
    $aDigChar[7] = "0010011"
    $aDigChar[8] = "1111111"
    $aDigChar[9] = "1011111"
    $aDigChar[10] = "1111011" ; A
    $aDigChar[11] = "1100100" ; L
    $aDigChar[12] = "0001000" ; -
EndFunc   ;==>_initDigChar
Edited by SadBunny

Roses are FF0000, violets are 0000FF... All my base are belong to you.

Share this post


Link to post
Share on other sites



Very nice. Flicker a lot though.

In your main while loop maybe you could have

While 1
    if GuiGetMsg() = -3 then exit

    If @sec <> $sec then
      _draw()
      $sec = @SEC
   endif

WEnd

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites

Very nice. Flicker a lot though.

In your main while loop maybe you could have

While 1
    if GuiGetMsg() = -3 then exit

    If @sec <> $sec then
      _draw()
      $sec = @SEC
   endif

WEnd
Thanks! Will add the quit thingy :D

I tried to battle the flickering by creating separate Graphic controls and refreshing them separately only when needed, but it turned out that when I sent $GUI_GR_REFRESH to a single Graphic control, all other graphic controls refresh too - making a flicker because everything is redrawn.

I ended up deleting a complete Graphic control and recreating and rebuilding it when it needed a refresh, since that seems to be faster when the Refresh is sent.

If you have any suggestions to refresh or kill/rebuild one Graphic control without affecting the other ones, I would be very happy to receive your enlightenment... It would save me (and my ludicrous amount of dedicated fans) a whole lot of flickering! :P


Roses are FF0000, violets are 0000FF... All my base are belong to you.

Share this post


Link to post
Share on other sites

Added the quit thingy.

More importantly, added an alarm dial that sounds a ringing sound (an age old default Windows sound) at a specified time, not taking AM/PM in consideration, just like an physical old analog alarm clock.

Next, time for the snooze repedition mode definition function. (Damn, in Dutch you could write that all with one word... :D)


Roses are FF0000, violets are 0000FF... All my base are belong to you.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0