732 lines
18 KiB
Python
Executable File
732 lines
18 KiB
Python
Executable File
#! /usr/local/bin/python
|
|
|
|
# "M Clock"
|
|
#
|
|
# An implementation in software of an original design by Rob Juda.
|
|
# Clock implementation: Guido van Rossum.
|
|
# Alarm and Gong features: Sape Mullender.
|
|
#
|
|
# XXX TO DO:
|
|
# add arguments to specify initial window position and size
|
|
# find out local time zone difference automatically
|
|
# add a date indicator
|
|
# allow multiple alarms
|
|
# allow the menu to change more parameters
|
|
|
|
import sys
|
|
|
|
from gl import *
|
|
from GL import *
|
|
from DEVICE import *
|
|
import time
|
|
import getopt
|
|
import string
|
|
import os
|
|
from math import pi
|
|
import math
|
|
|
|
FULLC = 3600 # Full circle in 1/10-ths of a degree
|
|
MIDN = 900 # Angle of the 12 o'clock position
|
|
R, G, B = 0, 1, 2 # Indices of colors in RGB list
|
|
|
|
HOUR = 3600 # Number of seconds per hour
|
|
MINUTE = 60 # Number of seconds per minute
|
|
|
|
class struct: pass # Class to define featureless structures
|
|
Gl = struct() # Object to hold writable global variables
|
|
|
|
# Default constants (used in multiple places)
|
|
|
|
SCREENBG = 127, 156, 191
|
|
NPARTS = 9
|
|
TITLE = 'M Clock'
|
|
|
|
import tzparse
|
|
TZDIFF = tzparse.timezone
|
|
if tzparse.isdst(time.time()):
|
|
TZDIFF = tzparse.altzone
|
|
|
|
# Default parameters
|
|
|
|
Gl.foreground = 0 # If set, run in the foreground
|
|
Gl.fullscreen = 0 # If set, run on full screen
|
|
Gl.tzdiff = TZDIFF # Seconds west of Greenwich (winter time)
|
|
Gl.nparts = NPARTS # Number of parts each circle is divided in (>= 2)
|
|
Gl.debug = 0 # If set, print debug output
|
|
Gl.doublebuffer = 1 # If set, use double buffering
|
|
Gl.update = 0 # Update interval; seconds hand is suppressed if > 1
|
|
Gl.colorsubset = 0 # If set, display only a subset of the colors
|
|
Gl.cyan = 0 # If set, display cyan overlay (big hand)
|
|
Gl.magenta = 0 # If set, display magenta overlay (little hand)
|
|
Gl.yellow = 0 # If set, display yellow overlay (fixed background)
|
|
Gl.black = 0 # If set, display black overlay (hands)
|
|
Gl.colormap = 0 # If set, use colormap mode instead of RGB mode
|
|
Gl.warnings = 0 # If set, print warnings
|
|
Gl.title = '' # Window title (default set later)
|
|
Gl.name = 'mclock' # Window title for resources
|
|
Gl.border = 1 # If set, use a window border (and title)
|
|
Gl.bg = 0, 0, 0 # Background color R, G, B value
|
|
Gl.iconic = 0 # Set in iconic state
|
|
Gl.fg = 255, 0, 0 # Alarm background RGB (either normal or alarm)
|
|
Gl.ox,Gl.oy = 0,0 # Window origin
|
|
Gl.cx,Gl.cy = 0,0 # Window size
|
|
Gl.alarm_set = 0 # Alarm on or off
|
|
Gl.alarm_on = 0 # Alarm is ringing
|
|
Gl.alarm_time = 0 # Alarm time in seconds after midnight
|
|
Gl.alarm_hours = 0 # Alarm hour setting, 24 hour clock
|
|
Gl.alarm_minutes = 0 # Alarm minutes setting
|
|
Gl.alarm_rgb = 0,0,0 # Alarm display RGB colors
|
|
Gl.alarm_cmd = '' # Command to execute when alarm goes off
|
|
Gl.mouse2down = 0 # Mouse button state
|
|
Gl.mouse3down = 0 # Mouse button state
|
|
Gl.gong_cmd = '' # Command to execute when chimes go off
|
|
Gl.gong_int = 3600 # Gong interval
|
|
Gl.indices = R, G, B # Colors (permuted when alarm is on)
|
|
|
|
def main():
|
|
#
|
|
sys.stdout = sys.stderr # All output is errors/warnings etc.
|
|
#
|
|
try:
|
|
args = getoptions()
|
|
except string.atoi_error, value:
|
|
usage(string.atoi_error, value)
|
|
except getopt.error, msg:
|
|
usage(getopt.error, msg)
|
|
#
|
|
if args:
|
|
realtime = 0
|
|
hours = string.atoi(args[0])
|
|
minutes = seconds = 0
|
|
if args[1:]: minutes = string.atoi(args[1])
|
|
if args[2:]: seconds = string.atoi(args[2])
|
|
localtime = ((hours*60)+minutes)*60+seconds
|
|
else:
|
|
realtime = 1
|
|
#
|
|
if Gl.title == '':
|
|
if realtime:
|
|
Gl.title = TITLE
|
|
else:
|
|
title = ''
|
|
for arg in args: title = title + ' ' + arg
|
|
Gl.title = title[1:]
|
|
del title
|
|
#
|
|
wid = makewindow()
|
|
Gl.ox,Gl.oy = getorigin()
|
|
Gl.cx,Gl.cy = getsize()
|
|
initmenu()
|
|
clearall()
|
|
#
|
|
if not Gl.update:
|
|
Gl.update = 60
|
|
#
|
|
if Gl.update <= 1:
|
|
Gl.timernoise = 6
|
|
else:
|
|
Gl.timernoise = 60
|
|
noise(TIMER0, Gl.timernoise)
|
|
#
|
|
qdevice(WINSHUT)
|
|
qdevice(WINQUIT)
|
|
qdevice(ESCKEY)
|
|
if realtime:
|
|
qdevice(TIMER0)
|
|
qdevice(REDRAW)
|
|
qdevice(WINFREEZE)
|
|
qdevice(WINTHAW)
|
|
qdevice(MENUBUTTON) # MOUSE1
|
|
qdevice(MOUSE3) # Left button
|
|
qdevice(MOUSE2) # Middle button
|
|
unqdevice(INPUTCHANGE)
|
|
#
|
|
lasttime = 0
|
|
Gl.change = 1
|
|
while 1:
|
|
if realtime:
|
|
localtime = time.time() - Gl.tzdiff
|
|
if Gl.alarm_set:
|
|
if localtime%(24*HOUR) == Gl.alarm_time:
|
|
# Ring the alarm!
|
|
if Gl.debug:
|
|
print 'Rrrringg!'
|
|
Gl.alarm_on = 1
|
|
if Gl.alarm_cmd <> '':
|
|
d = os.system(Gl.alarm_cmd+' '+`Gl.alarm_time/3600`+' '+`(Gl.alarm_time/60)%60` + ' &')
|
|
Gl.change = 1
|
|
clearall()
|
|
if Gl.alarm_on:
|
|
if (localtime - Gl.alarm_time) % (24*HOUR) > 300:
|
|
# More than 5 minutes away from alarm
|
|
Gl.alarm_on = 0
|
|
if Gl.debug:
|
|
print 'Alarm turned off'
|
|
Gl.change = 1
|
|
clearall()
|
|
Gl.indices = R, G, B
|
|
else:
|
|
if localtime % 2 == 0:
|
|
# Permute color indices
|
|
Gl.indices = Gl.indices[2:] + Gl.indices[:2]
|
|
Gl.change = 1
|
|
if Gl.gong_cmd <> '' and localtime%Gl.gong_int == 0:
|
|
d = os.system(Gl.gong_cmd+' '+`(localtime/3600)%24`+' '+`(localtime/60)%60` + ' &')
|
|
if localtime/Gl.update <> lasttime/Gl.update:
|
|
if Gl.debug: print 'new time'
|
|
Gl.change = 1
|
|
if Gl.change:
|
|
if Gl.debug: print 'drawing'
|
|
doit(localtime)
|
|
lasttime = localtime
|
|
Gl.change = 0
|
|
dev, data = qread()
|
|
if Gl.debug and dev <> TIMER0:
|
|
print dev, data
|
|
if dev == TIMER0:
|
|
if Gl.debug > 1:
|
|
print dev, data
|
|
elif dev == MOUSE3:
|
|
mousex = getvaluator(MOUSEX)
|
|
mousey = getvaluator(MOUSEY)
|
|
if mouseclick(3, data, mousex, mousey):
|
|
Gl.change = 1
|
|
elif dev == MOUSE2:
|
|
mousex = getvaluator(MOUSEX)
|
|
mousey = getvaluator(MOUSEY)
|
|
if mouseclick(2, data, mousex, mousey):
|
|
Gl.change = 1
|
|
elif dev == MOUSEX:
|
|
mousex = data
|
|
if Gl.mouse2down:
|
|
mouse2track(mousex, mousey)
|
|
if Gl.mouse3down:
|
|
mouse3track(mousex, mousey)
|
|
elif dev == MOUSEY:
|
|
mousey = data
|
|
if Gl.mouse2down:
|
|
mouse2track(mousex, mousey)
|
|
if Gl.mouse3down:
|
|
mouse3track(mousex, mousey)
|
|
elif dev == REDRAW or dev == REDRAWICONIC:
|
|
if Gl.debug:
|
|
if dev == REDRAW: print 'REDRAW'
|
|
else: print 'REDRAWICONIC'
|
|
reshapeviewport()
|
|
Gl.ox,Gl.oy = getorigin()
|
|
Gl.cx,Gl.cy = getsize()
|
|
Gl.change = 1
|
|
clearall()
|
|
elif dev == MENUBUTTON:
|
|
if Gl.debug: print 'MENUBUTTON'
|
|
handlemenu()
|
|
elif dev == WINFREEZE:
|
|
if Gl.debug: print 'WINFREEZE'
|
|
Gl.iconic = 1
|
|
noise(TIMER0, 60*60) # Redraw every 60 seconds only
|
|
elif dev == WINTHAW:
|
|
if Gl.debug: print 'WINTHAW'
|
|
Gl.iconic = 0
|
|
noise(TIMER0, Gl.timernoise)
|
|
Gl.change = 1
|
|
elif dev == ESCKEY or dev == WINSHUT or dev == WINQUIT:
|
|
if Gl.debug: print 'Exit'
|
|
sys.exit(0)
|
|
|
|
def getoptions():
|
|
optlist, args = getopt.getopt(sys.argv[1:], 'A:a:B:bc:dFfG:g:n:sT:t:u:wCMYK')
|
|
for optname, optarg in optlist:
|
|
if optname == '-A':
|
|
Gl.fg = eval(optarg) # Should be (r,g,b)
|
|
elif optname == '-a':
|
|
Gl.alarm_cmd = optarg
|
|
elif optname == '-B':
|
|
Gl.bg = eval(optarg) # Should be (r,g,b)
|
|
elif optname == '-b':
|
|
Gl.border = 0
|
|
elif optname == '-c':
|
|
Gl.colormap = string.atoi(optarg)
|
|
elif optname == '-d':
|
|
Gl.debug = Gl.debug + 1
|
|
Gl.warnings = 1
|
|
elif optname == '-F':
|
|
Gl.foreground = 1
|
|
elif optname == '-f':
|
|
Gl.fullscreen = 1
|
|
elif optname == '-G':
|
|
Gl.gong_int = 60*string.atoi(optarg)
|
|
elif optname == '-g':
|
|
Gl.gong_cmd = optarg
|
|
elif optname == '-n':
|
|
Gl.nparts = string.atoi(optarg)
|
|
elif optname == '-s':
|
|
Gl.doublebuffer = 0
|
|
elif optname == '-T':
|
|
Gl.title = Gl.name = optarg
|
|
elif optname == '-t':
|
|
Gl.tzdiff = string.atoi(optarg)
|
|
elif optname == '-u':
|
|
Gl.update = string.atoi(optarg)
|
|
elif optname == '-w':
|
|
Gl.warnings = 1
|
|
elif optname == '-C':
|
|
Gl.cyan = Gl.colorsubset = 1
|
|
elif optname == '-M':
|
|
Gl.magenta = Gl.colorsubset = 1
|
|
elif optname == '-Y':
|
|
Gl.yellow = Gl.colorsubset = 1
|
|
elif optname == '-K':
|
|
Gl.black = Gl.colorsubset = 1
|
|
else:
|
|
print 'Unsupported option', optname
|
|
return args
|
|
|
|
def usage(exc, msg):
|
|
if sys.argv:
|
|
progname = os.path.basename(sys.argv[0])
|
|
else:
|
|
progname = 'mclock'
|
|
#
|
|
print progname + ':',
|
|
if exc == string.atoi_error:
|
|
print 'non-numeric argument:',
|
|
print msg
|
|
#
|
|
print 'usage:', progname, '[options] [hh [mm [ss]]]'
|
|
#
|
|
print '-A r,g,b : alarm background red,green,blue [255,0,0]'
|
|
print '-a cmd : shell command executed when alarm goes off'
|
|
print '-B r,g,b : background red,green,blue [0,0,0]'
|
|
print ' (-B SCREENBG uses the default screen background)'
|
|
print '-b : suppress window border and title'
|
|
print '-c cmapid : select explicit colormap'
|
|
print '-d : more debug output (implies -F, -w)'
|
|
print '-F : run in foreground'
|
|
print '-f : use full screen'
|
|
print '-G intrvl : interval between chimes in minutes [60]'
|
|
print '-g cmd : shell command executed when chimes go off'
|
|
print '-s : single buffer mode'
|
|
print '-w : print various warnings'
|
|
print '-n nparts : number of parts [' + `NPARTS` + ']'
|
|
print '-T title : alternate window title [\'' + TITLE + '\']'
|
|
print '-t tzdiff : time zone difference [' + `TZDIFF` + ']'
|
|
print '-u update : update interval [60]'
|
|
print '-CMYK : Cyan, Magenta, Yellow or blacK overlay only'
|
|
print 'if hh [mm [ss]] is specified, display that time statically'
|
|
print 'on machines with < 12 bitplanes, -c and -s are forced on'
|
|
#
|
|
sys.exit(2)
|
|
|
|
def doit(localtime):
|
|
hands = makehands(localtime)
|
|
list = makelist(hands)
|
|
render(list, hands)
|
|
|
|
def makehands(localtime):
|
|
localtime = localtime % (12*HOUR)
|
|
seconds_hand = MIDN + FULLC - (localtime*60) % FULLC
|
|
big_hand = (MIDN + FULLC - (localtime%HOUR)) % FULLC
|
|
little_hand = (MIDN + FULLC - ((localtime/12) % HOUR)) % FULLC
|
|
return little_hand, big_hand, seconds_hand
|
|
|
|
def makelist(little_hand, big_hand, seconds_hand):
|
|
total = []
|
|
if Gl.cyan or not Gl.colorsubset:
|
|
total = total + makesublist(big_hand, Gl.indices[0])
|
|
if Gl.magenta or not Gl.colorsubset:
|
|
total = total + makesublist(little_hand, Gl.indices[1])
|
|
if Gl.yellow or not Gl.colorsubset:
|
|
total = total + makesublist(MIDN, Gl.indices[2])
|
|
total.sort()
|
|
return total
|
|
|
|
def makesublist(first, icolor):
|
|
list = []
|
|
alpha = FULLC/Gl.nparts
|
|
a = first - alpha/2
|
|
for i in range(Gl.nparts):
|
|
angle = (a + i*alpha + FULLC) % FULLC
|
|
value = 255*(Gl.nparts-1-i)/(Gl.nparts-1)
|
|
list.append(angle, icolor, value)
|
|
list.sort()
|
|
a, icolor, value = list[0]
|
|
if a <> 0:
|
|
a, icolor, value = list[len(list)-1]
|
|
t = 0, icolor, value
|
|
list.insert(0, t)
|
|
return list
|
|
|
|
def rgb_fg():
|
|
return Gl.fg
|
|
# Obsolete code:
|
|
if Gl.alarm_on:
|
|
return Gl.bg
|
|
else:
|
|
return Gl.fg
|
|
|
|
def rgb_bg():
|
|
return Gl.bg
|
|
# Obsolete code:
|
|
if Gl.alarm_on:
|
|
return Gl.fg
|
|
else:
|
|
return Gl.bg
|
|
|
|
def clearall():
|
|
Gl.c3i(rgb_bg())
|
|
clear()
|
|
if Gl.doublebuffer:
|
|
swapbuffers()
|
|
clear()
|
|
|
|
def draw_alarm(color):
|
|
frontbuffer(TRUE)
|
|
Gl.c3i(color)
|
|
pushmatrix()
|
|
rotate(-((Gl.alarm_time/12)%3600), 'z')
|
|
bgnpolygon()
|
|
v2f( 0.00,1.00)
|
|
v2f( 0.04,1.05)
|
|
v2f(-0.04,1.05)
|
|
endpolygon()
|
|
popmatrix()
|
|
#
|
|
pushmatrix()
|
|
rotate(-((Gl.alarm_time)%3600), 'z')
|
|
bgnpolygon()
|
|
v2f( 0.00,1.05)
|
|
v2f( 0.07,1.10)
|
|
v2f(-0.07,1.10)
|
|
endpolygon()
|
|
popmatrix()
|
|
#
|
|
cmov2(-1.06, -1.06)
|
|
charstr(string.rjust(`Gl.alarm_time/3600`,2))
|
|
charstr(':')
|
|
charstr(string.zfill((Gl.alarm_time/60)%60,2))
|
|
frontbuffer(FALSE)
|
|
|
|
def render(list, (little_hand, big_hand, seconds_hand)):
|
|
#
|
|
if Gl.colormap:
|
|
resetindex()
|
|
#
|
|
if not list:
|
|
Gl.c3i((255, 255, 255)) # White
|
|
circf(0.0, 0.0, 1.0)
|
|
else:
|
|
list.append(3600, 0, 255) # Sentinel
|
|
#
|
|
rgb = [255, 255, 255]
|
|
a_prev = 0
|
|
for a, icolor, value in list:
|
|
if a <> a_prev:
|
|
[r, g, b] = rgb
|
|
if Gl.debug > 1:
|
|
print rgb, a_prev, a
|
|
Gl.c3i((r, g, b))
|
|
arcf(0.0, 0.0, 1.0, a_prev, a)
|
|
rgb[icolor] = value
|
|
a_prev = a
|
|
#
|
|
if Gl.black or not Gl.colorsubset:
|
|
#
|
|
# Draw the hands -- in black
|
|
#
|
|
Gl.c3i((0, 0, 0))
|
|
#
|
|
if Gl.update == 1 and not Gl.iconic:
|
|
# Seconds hand is only drawn if we update every second
|
|
pushmatrix()
|
|
rotate(seconds_hand, 'z')
|
|
bgnline()
|
|
v2f(0.0, 0.0)
|
|
v2f(1.0, 0.0)
|
|
endline()
|
|
popmatrix()
|
|
#
|
|
pushmatrix()
|
|
rotate(big_hand, 'z')
|
|
rectf(0.0, -0.01, 0.97, 0.01)
|
|
circf(0.0, 0.0, 0.01)
|
|
circf(0.97, 0.0, 0.01)
|
|
popmatrix()
|
|
#
|
|
pushmatrix()
|
|
rotate(little_hand, 'z')
|
|
rectf(0.04, -0.02, 0.63, 0.02)
|
|
circf(0.04, 0.0, 0.02)
|
|
circf(0.63, 0.0, 0.02)
|
|
popmatrix()
|
|
#
|
|
# Draw the alarm time, if set or being set
|
|
#
|
|
if Gl.alarm_set:
|
|
draw_alarm(rgb_fg())
|
|
#
|
|
if Gl.doublebuffer: swapbuffers()
|
|
|
|
def makewindow():
|
|
#
|
|
if Gl.debug or Gl.foreground:
|
|
foreground()
|
|
#
|
|
if Gl.fullscreen:
|
|
scrwidth, scrheight = getgdesc(GD_XPMAX), getgdesc(GD_YPMAX)
|
|
prefposition(0, scrwidth-1, 0, scrheight-1)
|
|
else:
|
|
keepaspect(1, 1)
|
|
prefsize(100, 100)
|
|
#
|
|
if not Gl.border:
|
|
noborder()
|
|
wid = winopen(Gl.name)
|
|
wintitle(Gl.title)
|
|
#
|
|
if not Gl.fullscreen:
|
|
keepaspect(1, 1)
|
|
minsize(10, 10)
|
|
maxsize(2000, 2000)
|
|
iconsize(66, 66)
|
|
winconstraints()
|
|
#
|
|
nplanes = getplanes()
|
|
nmaps = getgdesc(GD_NMMAPS)
|
|
if Gl.warnings:
|
|
print nplanes, 'color planes,', nmaps, 'color maps'
|
|
#
|
|
if nplanes < 12 or Gl.colormap:
|
|
if not Gl.colormap:
|
|
Gl.colormap = nmaps - 1
|
|
if Gl.warnings:
|
|
print 'not enough color planes available',
|
|
print 'for RGB mode; forcing colormap mode'
|
|
print 'using color map number', Gl.colormap
|
|
if not Gl.colorsubset:
|
|
needed = 3
|
|
else:
|
|
needed = Gl.cyan + Gl.magenta + Gl.yellow
|
|
needed = needed*Gl.nparts
|
|
if Gl.bg <> (0, 0, 0):
|
|
needed = needed+1
|
|
if Gl.fg <> (0, 0, 0):
|
|
needed = needed+1
|
|
if Gl.doublebuffer:
|
|
if needed > available(nplanes/2):
|
|
Gl.doublebuffer = 0
|
|
if Gl.warnings:
|
|
print 'not enough colors available',
|
|
print 'for double buffer mode;',
|
|
print 'forcing single buffer mode'
|
|
else:
|
|
nplanes = nplanes/2
|
|
if needed > available(nplanes):
|
|
# Do this warning always
|
|
print 'still not enough colors available;',
|
|
print 'parts will be left white'
|
|
print '(needed', needed, 'but have only',
|
|
print available(nplanes), 'colors available)'
|
|
#
|
|
if Gl.doublebuffer:
|
|
doublebuffer()
|
|
gconfig()
|
|
#
|
|
if Gl.colormap:
|
|
Gl.c3i = pseudo_c3i
|
|
fixcolormap()
|
|
else:
|
|
Gl.c3i = c3i
|
|
RGBmode()
|
|
gconfig()
|
|
#
|
|
if Gl.fullscreen:
|
|
# XXX Should find out true screen size using getgdesc()
|
|
ortho2(-1.1*1.280, 1.1*1.280, -1.1*1.024, 1.1*1.024)
|
|
else:
|
|
ortho2(-1.1, 1.1, -1.1, 1.1)
|
|
#
|
|
return wid
|
|
|
|
def available(nplanes):
|
|
return pow(2, nplanes) - 1 # Reserve one pixel for black
|
|
|
|
def fixcolormap():
|
|
multimap()
|
|
gconfig()
|
|
nplanes = getplanes()
|
|
if Gl.warnings:
|
|
print 'multimap mode has', nplanes, 'color planes'
|
|
imap = Gl.colormap
|
|
Gl.startindex = pow(2, nplanes) - 1
|
|
Gl.stopindex = 1
|
|
setmap(imap)
|
|
mapcolor(0, 0, 0, 0) # Fixed entry for black
|
|
if Gl.bg <> (0, 0, 0):
|
|
r, g, b = Gl.bg
|
|
mapcolor(1, r, g, b) # Fixed entry for Gl.bg
|
|
Gl.stopindex = 2
|
|
if Gl.fg <> (0, 0, 0):
|
|
r, g, b = Gl.fg
|
|
mapcolor(2, r, g, b) # Fixed entry for Gl.fg
|
|
Gl.stopindex = 3
|
|
Gl.overflow_seen = 0
|
|
resetindex()
|
|
|
|
def resetindex():
|
|
Gl.index = Gl.startindex
|
|
|
|
r0g0b0 = (0, 0, 0)
|
|
|
|
def pseudo_c3i(rgb):
|
|
if rgb == r0g0b0:
|
|
index = 0
|
|
elif rgb == Gl.bg:
|
|
index = 1
|
|
elif rgb == Gl.fg:
|
|
index = 2
|
|
else:
|
|
index = definecolor(rgb)
|
|
color(index)
|
|
|
|
def definecolor(rgb):
|
|
index = Gl.index
|
|
if index < Gl.stopindex:
|
|
if Gl.debug: print 'definecolor hard case', rgb
|
|
# First see if we already have this one...
|
|
for index in range(Gl.stopindex, Gl.startindex+1):
|
|
if rgb == getmcolor(index):
|
|
if Gl.debug: print 'return', index
|
|
return index
|
|
# Don't clobber reserverd colormap entries
|
|
if not Gl.overflow_seen:
|
|
# Shouldn't happen any more, hence no Gl.warnings test
|
|
print 'mclock: out of colormap entries'
|
|
Gl.overflow_seen = 1
|
|
return Gl.stopindex
|
|
r, g, b = rgb
|
|
if Gl.debug > 1: print 'mapcolor', (index, r, g, b)
|
|
mapcolor(index, r, g, b)
|
|
Gl.index = index - 1
|
|
return index
|
|
|
|
# Compute n**i
|
|
def pow(n, i):
|
|
x = 1
|
|
for j in range(i): x = x*n
|
|
return x
|
|
|
|
def mouseclick(mouse, updown, x, y):
|
|
if updown == 1:
|
|
# mouse button came down, start tracking
|
|
if Gl.debug:
|
|
print 'mouse', mouse, 'down at', x, y
|
|
if mouse == 2:
|
|
Gl.mouse2down = 1
|
|
mouse2track(x, y)
|
|
elif mouse == 3:
|
|
Gl.mouse3down = 1
|
|
mouse3track(x, y)
|
|
else:
|
|
print 'fatal error'
|
|
qdevice(MOUSEX)
|
|
qdevice(MOUSEY)
|
|
return 0
|
|
else:
|
|
# mouse button came up, stop tracking
|
|
if Gl.debug:
|
|
print 'mouse', mouse, 'up at', x, y
|
|
unqdevice(MOUSEX)
|
|
unqdevice(MOUSEY)
|
|
if mouse == 2:
|
|
mouse2track(x, y)
|
|
Gl.mouse2down = 0
|
|
elif mouse == 3:
|
|
mouse3track(x, y)
|
|
Gl.mouse3down = 0
|
|
else:
|
|
print 'fatal error'
|
|
Gl.alarm_set = 1
|
|
return 1
|
|
|
|
def mouse3track(x, y):
|
|
# first compute polar coordinates from x and y
|
|
cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2
|
|
x, y = x - cx, y - cy
|
|
if (x, y) == (0, 0): return # would cause an exception
|
|
minutes = int(30.5 + 30.0*math.atan2(float(-x), float(-y))/pi)
|
|
if minutes == 60: minutes = 0
|
|
a,b = Gl.alarm_minutes/15, minutes/15
|
|
if (a,b) == (0,3):
|
|
# Moved backward through 12 o'clock:
|
|
Gl.alarm_hours = Gl.alarm_hours - 1
|
|
if Gl.alarm_hours < 0: Gl.alarm_hours = Gl.alarm_hours + 24
|
|
if (a,b) == (3,0):
|
|
# Moved forward through 12 o'clock:
|
|
Gl.alarm_hours = Gl.alarm_hours + 1
|
|
if Gl.alarm_hours >= 24: Gl.alarm_hours = Gl.alarm_hours - 24
|
|
Gl.alarm_minutes = minutes
|
|
seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE
|
|
if seconds <> Gl.alarm_time:
|
|
draw_alarm(rgb_bg())
|
|
Gl.alarm_time = seconds
|
|
draw_alarm(rgb_fg())
|
|
|
|
def mouse2track(x, y):
|
|
# first compute polar coordinates from x and y
|
|
cx, cy = Gl.ox + Gl.cx/2, Gl.oy + Gl.cy/2
|
|
x, y = x - cx, y - cy
|
|
if (x, y) == (0, 0): return # would cause an exception
|
|
hours = int(6.5 - float(Gl.alarm_minutes)/60.0 + 6.0*math.atan2(float(-x), float(-y))/pi)
|
|
if hours == 12: hours = 0
|
|
if (Gl.alarm_hours,hours) == (0,11):
|
|
# Moved backward through midnight:
|
|
Gl.alarm_hours = 23
|
|
elif (Gl.alarm_hours,hours) == (12,11):
|
|
# Moved backward through noon:
|
|
Gl.alarm_hours = 11
|
|
elif (Gl.alarm_hours,hours) == (11,0):
|
|
# Moved forward through noon:
|
|
Gl.alarm_hours = 12
|
|
elif (Gl.alarm_hours,hours) == (23,0):
|
|
# Moved forward through midnight:
|
|
Gl.alarm_hours = 0
|
|
elif Gl.alarm_hours < 12:
|
|
Gl.alarm_hours = hours
|
|
else:
|
|
Gl.alarm_hours = hours + 12
|
|
seconds = Gl.alarm_hours * HOUR + Gl.alarm_minutes * MINUTE
|
|
if seconds <> Gl.alarm_time:
|
|
draw_alarm(rgb_bg())
|
|
Gl.alarm_time = seconds
|
|
draw_alarm(rgb_fg())
|
|
|
|
def initmenu():
|
|
Gl.pup = pup = newpup()
|
|
addtopup(pup, 'M Clock%t|Alarm On/Off|Seconds Hand On/Off|Quit', 0)
|
|
|
|
def handlemenu():
|
|
item = dopup(Gl.pup)
|
|
if item == 1:
|
|
# Toggle alarm
|
|
if Gl.alarm_set:
|
|
Gl.alarm_set = 0
|
|
Gl.alarm_on = 0
|
|
else:
|
|
Gl.alarm_set = 1
|
|
Gl.change = 1
|
|
clearall()
|
|
elif item == 2:
|
|
# Toggle Seconds Hand
|
|
if Gl.update == 1:
|
|
Gl.update = 60
|
|
Gl.timernoise = 60
|
|
else:
|
|
Gl.update = 1
|
|
Gl.timernoise = 6
|
|
Gl.change = 1
|
|
elif item == 3:
|
|
if Gl.debug: print 'Exit'
|
|
sys.exit(0)
|
|
|
|
main()
|