Compare commits

13 Commits

Author SHA1 Message Date
Jan
e0db071cc1 wip: update 2019-09-27 17:58:16 +02:00
Jan
f147bc55c6 wip: intergrating clockyconfig in main code 2019-09-27 17:34:25 +02:00
Jan
dd1355509b Merge branch 'clockyconfig' 2019-09-27 11:44:34 +02:00
Jan
124ab39f82 Expanded verbose options 2019-09-26 23:39:32 +02:00
Jan
eaaeadf642 Fixed bug where modulo functions returned float instead of int 2019-09-26 20:44:02 +02:00
Jan
ce9a4837e1 Updated changes.txt and README.md 2019-09-26 17:57:14 +02:00
Jan
c25733b64c Added SIGHUP signal handling, adjusted reloading of file changes, added return value of CheckTrackList() 2019-09-26 17:41:05 +02:00
Jan
88dce016de Added tracklist code to replace readmp3 routine 2019-09-26 16:03:19 +02:00
Jan
20f0eb71b9 Merge branch 'clockytracklist' 2019-09-26 14:01:03 +02:00
Jan
4a5498866c added ChecktTrackList 2019-09-25 17:11:51 +02:00
Jan
1555050909 1st setup for tracklist reading 2019-09-25 16:43:37 +02:00
Jan
3edf9ba34c 1st test of track stuff 2019-09-25 12:32:18 +02:00
Jan
e65eadb2d0 Added clockyconfig.py for better config file handling. (also conftest.py to test this) 2019-09-25 11:28:03 +02:00
8 changed files with 489 additions and 176 deletions

View File

@@ -38,6 +38,16 @@ Say what the step will be
Give the example Give the example
``` ```
### Users Manual
Button 1:
short press: show alarm time
long press: enter edit mode
Button 1 & Button 2 simutaneous:
long press: turn alarm off
### Hardware ### Hardware
Overview of used hardware: Overview of used hardware:

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2.7 #!/usr/bin/env python3
import time import time
import RPi.GPIO as GPIO import RPi.GPIO as GPIO
@@ -16,7 +16,8 @@ class Button:
presstime=0 presstime=0
ignore=0 ignore=0
def __init__(self, gpio): def __init__(self, gpio,verbose=False):
if verbose:
print("initialize button on gpio %d" %gpio) print("initialize button on gpio %d" %gpio)
self.gpio = gpio self.gpio = gpio
GPIO.setup(self.gpio, GPIO.IN, pull_up_down = GPIO.PUD_UP) GPIO.setup(self.gpio, GPIO.IN, pull_up_down = GPIO.PUD_UP)

View File

@@ -1,15 +1,15 @@
v0.2.5 * Changed readmp3s routine to clockytracklist (merge)
v0.2.0 * Adjusted code for python 3
v0.1.0 * added max7219 support, added signal handling
0.1.0:
* Added additional logging messages for end of alarm * Added additional logging messages for end of alarm
* implemented SIGINT (Ctrl-C) handling to exit gracefully * implemented SIGINT (Ctrl-C) handling to exit gracefully
0.0.5: v0.0.5 * initial working version
* initial working version
* show alarmtime in startup * show alarmtime in startup
------------------------------------------------------------ ------------------------------------------------------------
@@ -24,5 +24,5 @@ issues
todo todo
---- ----
add SIGHUP handling for reload config
changes config file format to json changes config file format to json
make documentation

329
clocky.py
View File

@@ -1,79 +1,79 @@
#!/usr/bin/python3 #!/usr/bin/python3
import pickle import pickle
import os.path import os
import time import time
import sys import sys
import tm1637 import tm1637
import max7219 import max7219
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"
import pygame import pygame
from time import sleep,strftime from time import sleep,strftime
import RPi.GPIO as GPIO import RPi.GPIO as GPIO
import button import button
import signal import signal
import clockyconfig
import clockytracklist
VERBOSE=True
settings= {} settings= {}
looptype=0 looptype=0
quit=0 quit=0
print("\n +----------+\n | Clocky |\n | v0.2.0 |\n +----------+\n") print("\n +----------+\n | Clocky |\n | v0.3.0 |\n +----------+\n")
o_configfilename = "clocky.conf" o_configfilename = "clocky.conf"
o_defaultalarmtime = 60*13+24 # hh*60+mm #o_defaultalarmtime = 60*14+10 # hh*60+mm
o_showalarmtime=3 # time that the alarmtime shows after short press #config.settings['showalarmtime']=3 # time that the alarmtime shows after short press
o_showtracktime=2 # note that this is per track, so total time is 10 times longer #config.settings['showtracktime']=2 # note that this is per track, so total time is 10 times longer
o_editdelaytime=3 # time it takes to qualify as longpress #config.settings['editdelaytime']=3 # time it takes to qualify as longpress
o_showtimeout=6 # timeout to exit edit modus #config.settings['edittimeout']=6 # timeout to exit edit modus
o_snoozetime = 9 # time to snooze #config.settings['snoozetime'] = 9 # time to snooze
o_timetomaxvol = 150# seconds it takes to go from 0% to 100% volume #config.settings['timetomaxvolume'] = 150# seconds it takes to go from 0% to 100% volume
o_maxplaytime = 900 # seconds it to play #config.settings['maxalarmtime'] = 900 # seconds it to play
o_soundpreviewtime=5 #config.settings['soundpreviewtime']=5
o_defaultbrightness=0 #config.settings['defaultbrightness']=0
o_loopdelay=0.25 o_loopdelay=0.25
track=0 track=0
stopprogram=0
reload=False
#GPIO.setmode(GPIO.BCM) # set up BCM GPIO numbering #GPIO.setmode(GPIO.BCM) # set up BCM GPIO numbering
#GPIO.setup(16, GPIO.IN, pull_up_down = GPIO.PUD_UP) #GPIO.setup(16, GPIO.IN, pull_up_down = GPIO.PUD_UP)
def signal_handler(signal,frame): #def signal_handler(signal,frame):
global quit # global quit
print("") # print("")
quit=1 # quit=1
def stamp(): def receive_signal(signum, stack):
sys.stdout.write(strftime("[%Y%m%d %H%M%S] ")) global stopprogram
global reload
def writesettings(): if VERBOSE:
"write settings to conf file" print('Received signal: %d' %signum)
with open(o_configfilename, 'wb') as handle:
pickle.dump(settings, handle)
handle.close()
def readmp3list():
c=0
mp3s=[]
dirs=os.listdir('.')
for ent in os.listdir('.'):
if ent.lower().endswith(".mp3") and os.access(ent,os.R_OK):
mp3s.append(ent)
mp3s.sort()
for m in mp3s:
c+=1
if c>99: break
if c:
return(mp3s)
else: else:
return(0) print("")
if signum == signal.SIGHUP:
reload=True
if signum == signal.SIGINT:
stopprogram=1
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
def stamp(str):
sys.stdout.write(strftime("[%Y%m%d %H%M%S] ")+str+"\n")
sys.stdout.flush()
def timetoval(str):
return (str.split(":")[0]*60)+str.split(":")[1]
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
looptype=0 looptype=0
colon=0 colon=0
count=0
digit=1 digit=1
showtime=0 showtime=0
playtime=0 playtime=0
@@ -84,87 +84,111 @@ tvol=0
volume=0.0 volume=0.0
brightness=0 brightness=0
snooze=0 snooze=0
count=0
signal.signal(signal.SIGINT,signal_handler) if VERBOSE:
#display=tm1637.TM1637(CLK=14, DIO=4, brightness=1) print('My PID is %d' %os.getpid())
display=max7219.MAX7219(brightness=1) signal.signal(signal.SIGHUP, receive_signal)
signal.signal(signal.SIGINT, receive_signal)
display.Clear() but1=button.Button(21,verbose=VERBOSE)
display.SetBrightnessRaw(o_defaultbrightness) but2=button.Button(20,verbose=VERBOSE)
but3=button.Button(26,verbose=VERBOSE)
print("") config=clockyconfig.ClockyConfig(verbose=VERBOSE)
print("reading mp3s from directory:") tracks=clockytracklist.ClockyTracklist("mp3",recursive=True,verbose=VERBOSE)
allmp3s=readmp3list()
if allmp3s==0:
print("ERROR: No mp3's found!")
display.showclock(" E rr")
sleep(30)
sys.exit()
c=0 #------------------------------------------------------------------
for m in allmp3s: #------------------------------------------------------------------
print(" %2d : %s"%(c+1,m))
while not stopprogram:
if VERBOSE:
print("Load config...")
reload=False
display=tm1637.TM1637(CLK=14, DIO=4, brightness=1)
# display=max7219.MAX7219(brightness=1)
display.Clear()
display.SetBrightnessRaw(config.settings['defaultbrightness'])
if VERBOSE:
print("Reading mp3s from directory:")
allmp3s=tracks.tracklist
c=0
if True: # VERBOSE:
print("\nTracks:")
for m in allmp3s:
print("%2d : %s"%(c+1,m))
c+=1 c+=1
print("") stamp("Started")
but1=button.Button(21)
but2=button.Button(20)
but3=button.Button(26)
print("")
if not os.path.isfile(o_configfilename): # .................................................................
c=0
config.sequence.clear()
for m in allmp3s:
config.sequence.append(c)
c+=1
if not os.path.isfile(o_configfilename):
print("Createconf: \""+o_configfilename+"\":") print("Createconf: \""+o_configfilename+"\":")
settings = {'track0':1, 'track1':2, 'track2':3, 'track3':4, 'track4':5, 'track5':6, 'track6':7, 'track7':8, 'track8':9, 'track9':10 } settings = {'track0':1, 'track1':2, 'track2':3, 'track3':4, 'track4':5, 'track5':6, 'track6':7, 'track7':8, 'track8':9, 'track9':10 }
settings['alarmtime']=o_defaultalarmtime; config.starttrack=0;
settings['starttrack']=0; config.settings['alarmdisabled']=0;
settings['alarmdisabled']=0;
with open(o_configfilename, 'wb') as handle: with open(o_configfilename, 'wb') as handle:
pickle.dump(settings, handle) pickle.dump(settings, handle)
handle.close() handle.close()
else: else:
if VERBOSE:
print("Configfile: \""+o_configfilename+"\":") print("Configfile: \""+o_configfilename+"\":")
with open(o_configfilename, 'rb') as handle: with open(o_configfilename, 'rb') as handle:
settings = pickle.load(handle) settings = pickle.load(handle)
handle.close() handle.close()
a_mins=settings['alarmtime']%60 a_hour=int(config.settings['alarmtime'].split(":")[0])
a_hour=(settings['alarmtime']-a_mins)/60 a_mins=int(config.settings['alarmtime'].split(":")[1])
print("Alarmtime : %02d:%02d"%(a_hour,a_mins)) if VERBOSE:
print("Alarmdisable: %d"%(settings['alarmdisabled'])) print("Alarmtime : %02d:%02d"%(a_hour,a_mins))
print("Starttrack : %d"%(settings['starttrack'])) print("Alarmdisable: %d"%(config.settings['alarmdisabled']))
print("Starttrack : %d"%(config.starttrack))
for i in range(0,10): for i in range(0,10):
if i==settings['starttrack']: if i==config.starttrack:
if VERBOSE:
print("=>",end='') print("=>",end='')
else: else:
if VERBOSE:
print(" ",end='') print(" ",end='')
if VERBOSE:
print(" [T%01dM%02d] "%(i,settings["track%d"%i]),end='') print(" [T%01dM%02d] "%(i,settings["track%d"%i]),end='')
if settings["track%d"%i] and (settings["track%d"%i]-1 < len(allmp3s)): if settings["track%d"%i] and (settings["track%d"%i]-1 < len(allmp3s)):
if VERBOSE:
print("\""+allmp3s[settings["track%d"%i]-1]+"\"") print("\""+allmp3s[settings["track%d"%i]-1]+"\"")
else: else:
if VERBOSE:
print("") print("")
settings["track%d"%i]=0 settings["track%d"%i]=0
writesettings()
print("") # .................................................................
stamp() # Main loop without reload and stuff
print("Started") #
sys.stdout.flush() while not reload and not stopprogram:
#------------------------------------------------------------------
#------------------------------------------------------------------
while quit!=True:
count+=1; count+=1;
sleep(o_loopdelay) sleep(o_loopdelay)
mytime=time.localtime(time.time()) mytime=time.localtime(time.time())
currenttime=mytime[3]*60 + mytime[4]; currenttime=mytime[3]*60 + mytime[4];
if not settings["alarmdisabled"]: if not config.settings["alarmdisabled"]:
if currenttime == settings['alarmtime']: if currenttime == timetoval(config.settings['alarmtime']):
if looptype==0 and not silencedalarm: if looptype==0 and not silencedalarm:
looptype=5 looptype=5
else: else:
@@ -179,16 +203,12 @@ while quit!=True:
if but1.WasLong(): if but1.WasLong():
if but2.WasPressed(): if but2.WasPressed():
if but2.WasLong(): if but2.WasLong():
if settings["alarmdisabled"]==0: if config.settings["alarmdisabled"]==0:
settings["alarmdisabled"]=1 config.settings["alarmdisabled"]=1
stamp() stamp("Alarm disabled")
print("Alarm disabled")
writesettings()
else: else:
settings["alarmdisabled"]=0 config.settings["alarmdisabled"]=0
stamp() stamp("Alarm enabled")
print("Alarm enabled")
writesettings()
looptype=1 looptype=1
else: else:
looptype=2 looptype=2
@@ -201,16 +221,12 @@ while quit!=True:
if but3.WasPressed(): if but3.WasPressed():
if but3.WasLong(): if but3.WasLong():
if settings["alarmdisabled"]==0: if config.settings["alarmdisabled"]==0:
settings["alarmdisabled"]=1 config.settings["alarmdisabled"]=1
stamp() stamp("Alarm disabled")
print("Alarm disabled")
writesettings()
else: else:
settings["alarmdisabled"]=0 config.settings["alarmdisabled"]=0
stamp() stamp("Alarm enabled")
print("Alarm enabled")
writesettings()
looptype=1 looptype=1
@@ -225,9 +241,9 @@ while quit!=True:
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if looptype==1: # show alarmtime if looptype==1: # show alarmtime
if not settings["alarmdisabled"]==1: if not config.settings["alarmdisabled"]==1:
a_mins=settings['alarmtime']%60 a_hour=int(config.settings['alarmtime'].split(":")[1])
a_hour=(settings['alarmtime']-a_mins)/60 a_mins=int(config.settings['alarmtime'].split(":")[1])
if colon: if colon:
tim="%02d:%02d" % (a_hour, a_mins) tim="%02d:%02d" % (a_hour, a_mins)
@@ -238,7 +254,7 @@ while quit!=True:
else: else:
display.showclock(" O FF") display.showclock(" O FF")
if showtime > o_showalarmtime: if showtime > config.settings['showalarmtime']:
if but1.WasPressed(): # drop intermediate presses if but1.WasPressed(): # drop intermediate presses
{} {}
if but2.WasPressed(): if but2.WasPressed():
@@ -254,11 +270,12 @@ while quit!=True:
if looptype==2: # edit alarmtime if looptype==2: # edit alarmtime
delta=0 delta=0
sm=settings['alarmtime']%10 dh=int(config.settings['alarmtime'][0])
dm=((settings['alarmtime']-sm)/10)%6 sh=int(config.settings['alarmtime'][1])
sh=(settings['alarmtime']-dm)/60%10 dm=int(config.settings['alarmtime'][3])
dh=(settings['alarmtime']-sh)/600 sm=int(config.settings['alarmtime'][4])
if colon: if colon:
tim="%0d%0d:%0d%0d" % (dh,sh,dm,sm) tim="%0d%0d:%0d%0d" % (dh,sh,dm,sm)
@@ -310,27 +327,24 @@ while quit!=True:
colon=1-colon colon=1-colon
if showtime > o_showtimeout: if showtime > config.settings['edittimeout']:
showtime=0 showtime=0
if dh==2 and sh>3: if dh==2 and sh>3:
sh=3 sh=3
looptype=1 looptype=1
else: else:
looptype=0 looptype=0
if settings["alarmdisabled"]==1: if config.settings["alarmdisabled"]==1:
settings["alarmdisabled"]=0 config.settings["alarmdisabled"]=0
stamp() stamp("Alarm enabled")
print("Alarm enabled") config.settings['alarmtime']=("%d%d:%d%d" %(dh,sh,dm,sm))
settings['alarmtime']=dh*600+sh*60+dm*10+sm stamp("Set alarmtime = %d%d:%d%d"%(dh,sh,dm,sm))
writesettings()
stamp()
print("Set alarmtime = %d%d:%d%d"%(dh,sh,dm,sm))
sys.stdout.flush() sys.stdout.flush()
digit=1 digit=1
else: else:
showtime+=o_loopdelay showtime+=o_loopdelay
settings['alarmtime']=dh*600+sh*60+dm*10+sm config.settings['alarmtime']=("%d%d:%d%d" %(dh,sh,dm,sm))
if but1.WasPressed(): if but1.WasPressed():
showtime=0 showtime=0
@@ -366,8 +380,8 @@ while quit!=True:
soundpreview=1 soundpreview=1
tr=track tr=track
tl=settings["track%d"%tr]%10 tl=int(settings["track%d"%tr]%10)
th=(settings["track%d"%tr]-tl)/10 th=int((settings["track%d"%tr]-tl)/10)
if colon: if colon:
tim="%d=:%d%d" % (tr,th,tl) tim="%d=:%d%d" % (tr,th,tl)
@@ -381,7 +395,7 @@ while quit!=True:
colon=1-colon colon=1-colon
if soundpreview: if soundpreview:
if pygame.mixer.music.get_pos() >o_soundpreviewtime*1000: if pygame.mixer.music.get_pos() >config.settings['soundpreviewtime']*1000:
if pygame.mixer.get_init(): if pygame.mixer.get_init():
pygame.mixer.music.set_volume(0) pygame.mixer.music.set_volume(0)
pygame.mixer.music.stop() pygame.mixer.music.stop()
@@ -393,7 +407,7 @@ while quit!=True:
looptype=0 looptype=0
else: else:
if showtime > o_showtracktime: if showtime > config.settings['showtracktime']:
showtime=0 showtime=0
track+=1; track+=1;
if track>9: if track>9:
@@ -408,8 +422,8 @@ while quit!=True:
delta=0 delta=0
tr=track tr=track
tl=settings["track%d"%tr]%10 tl=int(settings["track%d"%tr]%10)
th=(settings["track%d"%tr]-tl)/10 th=int((settings["track%d"%tr]-tl)/10)
if colon: if colon:
tim="%d=:%d%d" % (tr,th,tl) tim="%d=:%d%d" % (tr,th,tl)
@@ -452,10 +466,9 @@ while quit!=True:
settings["track%d"%tr]=th*10+tl settings["track%d"%tr]=th*10+tl
track=tr track=tr
if showtime > o_showtimeout: if showtime > config.settings['edittimeout']:
showtime=0 showtime=0
looptype=0 looptype=0
writesettings()
else: else:
showtime+=o_loopdelay showtime+=o_loopdelay
@@ -469,8 +482,8 @@ while quit!=True:
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if looptype==5: # Alarm! if looptype==5: # Alarm loop!
#o_timetomaxvol = 60 # seconds it takes to go from 0% to 100% volume #config.settings['timetomaxvolume'] = 60 # seconds it takes to go from 0% to 100% volume
if colon: if colon:
display.SetBrightnessRaw(0) display.SetBrightnessRaw(0)
@@ -483,9 +496,8 @@ while quit!=True:
colon=1-colon colon=1-colon
if not alarmstarted: if not alarmstarted:
track=settings['starttrack']; track=config.starttrack;
stamp() stamp("[T%02dM%02d] \"%s\""%(track,settings["track%d"%track],(allmp3s[settings["track%d"%track]-1])))
print("[T%02dM%02d] \"%s\""%(track,settings["track%d"%track],(allmp3s[settings["track%d"%track]-1])))
sys.stdout.flush() sys.stdout.flush()
if not pygame.mixer.get_init(): if not pygame.mixer.get_init():
pygame.mixer.init() pygame.mixer.init()
@@ -498,15 +510,14 @@ while quit!=True:
track=0 track=0
if settings["track%d"%track]==0: if settings["track%d"%track]==0:
track=0 track=0
settings['starttrack']=track; config.starttrack=track;
writesettings()
playtime=0 playtime=0
alarmstarted=1 alarmstarted=1
else: # alarmstarted else: # alarmstarted
if playtime < o_timetomaxvol: if playtime < config.settings['timetomaxvolume']:
brightness=int((playtime / o_timetomaxvol)*255) brightness=int((playtime / config.settings['timetomaxvolume'])*255)
volume = float(int((playtime*100) / o_timetomaxvol))/100 volume = float(int((playtime*100) / config.settings['timetomaxvolume']))/100
# print("------> %d / %d => %f - %f [%d]"%(playtime,o_timetomaxvol,tvol,volume,brightness)) # print("------> %d / %d => %f - %f [%d]"%(playtime,config.settings['timetomaxvolume'],tvol,volume,brightness))
else: else:
volume=1 volume=1
@@ -517,9 +528,8 @@ while quit!=True:
if pygame.mixer.get_init(): if pygame.mixer.get_init():
if not pygame.mixer.music.get_busy(): if not pygame.mixer.music.get_busy():
track=settings['starttrack'] track=config.starttrack
stamp() stamp("[T%02dM%02d] \"%s\""%(track,settings["track%d"%track],(allmp3s[settings["track%d"%track]-1])))
print("[T%02dM%02d] \"%s\""%(track,settings["track%d"%track],(allmp3s[settings["track%d"%track]-1])))
sys.stdout.flush() sys.stdout.flush()
pygame.mixer.music.load(allmp3s[settings["track%d"%track]-1]) pygame.mixer.music.load(allmp3s[settings["track%d"%track]-1])
pygame.mixer.music.play() pygame.mixer.music.play()
@@ -528,20 +538,18 @@ while quit!=True:
track=0 track=0
if settings["track%d"%track]==0: if settings["track%d"%track]==0:
track=0 track=0
settings['starttrack']=track; config.starttrack=track;
writesettings()
if playtime > o_maxplaytime: if playtime > config.settings['maxalarmtime']:
looptype=0 looptype=0
playtime=0 playtime=0
if pygame.mixer.get_init(): if pygame.mixer.get_init():
pygame.mixer.music.set_volume(0) pygame.mixer.music.set_volume(0)
pygame.mixer.music.stop() pygame.mixer.music.stop()
pygame.mixer.quit() pygame.mixer.quit()
display.SetBrightnessRaw(o_defaultbrightness) display.SetBrightnessRaw(config.settings['defaultbrightness'])
alarmstarted=0 alarmstarted=0
stamp() stamp("Alarmtime expired")
print("Alarmtime expired")
if but1.WasPressed(): if but1.WasPressed():
if but1.WasLong(): # Finished if but1.WasLong(): # Finished
@@ -549,7 +557,7 @@ while quit!=True:
pygame.mixer.music.set_volume(0) pygame.mixer.music.set_volume(0)
pygame.mixer.music.stop() pygame.mixer.music.stop()
pygame.mixer.quit() pygame.mixer.quit()
display.SetBrightnessRaw(o_defaultbrightness) display.SetBrightnessRaw(config.settings['defaultbrightness'])
playtime=0 playtime=0
if but1.WasPressed(): # flush intermediate presses if but1.WasPressed(): # flush intermediate presses
{} {}
@@ -560,8 +568,7 @@ while quit!=True:
looptype=0 looptype=0
alarmstarted=0 alarmstarted=0
silencedalarm=1 silencedalarm=1
stamp() stamp("Silenced alarm")
print("Silenced alarm")
if but2.WasPressed(): if but2.WasPressed():
@@ -570,9 +577,8 @@ while quit!=True:
if pygame.mixer.music.get_busy(): if pygame.mixer.music.get_busy():
pygame.mixer.music.stop() pygame.mixer.music.stop()
track=settings['starttrack'] track=config.starttrack
stamp() stamp("[T%02dM%02d] \"%s\""%(track,settings["track%d"%track],(allmp3s[settings["track%d"%track]-1])))
print("[T%02dM%02d] \"%s\""%(track,settings["track%d"%track],(allmp3s[settings["track%d"%track]-1])))
sys.stdout.flush() sys.stdout.flush()
if pygame.mixer.get_init(): if pygame.mixer.get_init():
pygame.mixer.music.load(allmp3s[settings["track%d"%track]-1]) pygame.mixer.music.load(allmp3s[settings["track%d"%track]-1])
@@ -582,9 +588,13 @@ while quit!=True:
track=0 track=0
if settings["track%d"%track]==0: if settings["track%d"%track]==0:
track=0 track=0
settings['starttrack']=track; config.starttrack=track;
writesettings()
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if count % 40 == 0: # every 10 seconds
if tracks.CheckTrackList() or config.CheckConfig():
reload = True;
#------------------------------------------------------------------ #------------------------------------------------------------------
if pygame.mixer.get_init(): if pygame.mixer.get_init():
@@ -593,5 +603,4 @@ if pygame.mixer.get_init():
pygame.mixer.quit() pygame.mixer.quit()
display.cleanup() display.cleanup()
sys.stdout.flush() sys.stdout.flush()
stamp() stamp("Shutdown!")
print("Shutdown!")

138
clockyconfig.py Normal file
View File

@@ -0,0 +1,138 @@
#!/usr/bin/python3
import json
import os
import time
import copy
CONFIGFILEVERSION="1.1"
class ClockyConfig:
"""Read/write clocky config files."""
def __init__(self,filename="clocky.json",verbose=0):
"""Open existing Clocky config file and read config data. If no file can be found create a new one with default values."""
self.filename=filename
self.__verbose=verbose
if os.access(self.filename,os.R_OK):
self.__Read()
else:
self.__data={}
self.__data["clocky"]={}
self.__data["clocky"]["version"]=CONFIGFILEVERSION
self.__data["clocky"]["settings"]={}
self.__data["clocky"]["settings"]["alarmtime"]="09:00"
self.__data["clocky"]["settings"]["alarmdisabled"]=0
self.__data["clocky"]["settings"]["maxalarmtime"]=30
self.__data["clocky"]["settings"]["snoozetime"]=9
self.__data["clocky"]["settings"]["showalarmtime"]=3
self.__data["clocky"]["settings"]["showtracktime"]=2
self.__data["clocky"]["settings"]["editdelaytime"]=3
self.__data["clocky"]["settings"]["edittimeout"]=5
self.__data["clocky"]["settings"]["timetomaxvolume"]=150
self.__data["clocky"]["settings"]["soundpreviewtime"]=5
self.__data["clocky"]["settings"]["defaultbrightness"]=0
self.__data["clocky"]["settings"]["playmode"]="random"
self.__data["clocky"]["tracks"]={}
self.__data["clocky"]["starttrack"]=0
self.__data["clocky"]["tracklist"]=[]
self.__data["clocky"]["tracksequence"]=[]
self.__Write()
if(self.__verbose):
print("Created new config file called \"%s\"" %self.filename)
def __Read(self):
"""Internal function to do the actual reading of file in to config"""
with open(self.filename) as json_data_file:
self.__data = json.load(json_data_file)
if(self.__data["clocky"]["version"] != CONFIGFILEVERSION):
print ("ERROR: configfile \""+self.filename+"\" version ("+self.__data["clocky"]["version"]+") does not match program version ("+CONFIGFILEVERSION+")!")
exit();
if(self.__data["clocky"]["settings"]["alarmtime"][1]==':'): # make sure time data is like "09:00", not "9:00"
self.__data["clocky"]["settings"]["alarmtime"]="0"+self.__data["clocky"]["settings"]["alarmtime"]
self.__readdata=copy.deepcopy(self.__data)
self.__timestamp=os.stat(self.filename).st_mtime
self.settings=self.__data["clocky"]["settings"]
self.starttrack=self.__data["clocky"]["starttrack"]
self.tracklist=self.__data["clocky"]["tracklist"]
self.sequence=self.__data["clocky"]["tracksequence"]
def __Write(self):
"""Internal function to do the actual writing of data into file"""
if(self.__data["clocky"]["settings"]["alarmtime"][1]==':'): # make sure time data is like "09:00", not "9:00"
self.__data["clocky"]["settings"]["alarmtime"]="0"+self.__data["clocky"]["settings"]["alarmtime"]
with open(self.filename,"w") as json_data_file:
json.dump(self.__data,json_data_file)
self.__readdata=copy.deepcopy(self.__data)
self.__timestamp=os.stat(self.filename).st_mtime
self.settings=self.__data["clocky"]["settings"]
self.starttrack=self.__data["clocky"]["starttrack"]
self.tracklist=self.__data["clocky"]["tracklist"]
self.sequence=self.__data["clocky"]["tracksequence"]
def Print(self):
"""Print current config data in human readable format"""
print("--ClockyConfig-------------")
print("filename =",self.filename)
print("version =",self.__data["clocky"]["version"])
for x in self.__data["clocky"]["settings"].keys():
print("%-14s= %s" %(x,self.__data["clocky"]["settings"][x]))
print("...........................")
print("starttrack =",self.__data["clocky"]["starttrack"])
nrtracks=len(self.__data["clocky"]["tracklist"])
print ("%d Tracks:" %nrtracks)
for str in self.__data["clocky"]["tracklist"]:
print(" "+str)
print("%d sequence items:" %(len(self.__data["clocky"]["tracksequence"])) )
for num in self.__data["clocky"]["tracksequence"]:
if num<nrtracks:
print(" %d -> %s" %(num,self.__data["clocky"]["tracklist"][num]) )
else:
print(" %d UNKNOWN TRACK" %num)
print("---------------------------")
def Dump(self):
"""Dump current config data in json format"""
print(self.__data)
def CheckConfig(self):
"""Check if config file has changed or removed since reading, or if the settings have changed.
Re-write or Re-read when necessary"""
if not os.access(self.filename,os.R_OK):
self.__Write()
if(self.__verbose):
print("Re-write settings because of config file removal!")
self.Print()
return True
elif(os.stat(self.filename).st_mtime != self.__timestamp):
self.__Read()
if(self.__verbose):
print("Re-read settings because of config file change!")
self.Print()
return True
if(self.__data != self.__readdata):
self.__Write()
if(self.__verbose):
print("Re-write settings because of settings change!")
self.Print()
return True
return False

92
clockytracklist.py Normal file
View File

@@ -0,0 +1,92 @@
#!/usr/bin/python3
from pathlib import Path
EXTENSIONS=(".mp3",".ogg",".wav",".mpa",".m4a",".flac")
class ClockyTracklist:
"""read and monitor directory with audio files"""
def __init__(self,path=".",recursive=False,sort=True,verbose=False):
"""Read (current or supplied) path for all audio files. Add recursive=True to check all subdirectories too"""
self.recursive=recursive
self.path=path
self.__verbose=verbose
self.__sort=sort
self.__reloaded=False
self.supportedformats=EXTENSIONS
p=Path(self.path)
if not p.exists():
print("ERROR: directory \""+path+"\" does not exist")
exit();
if not p.is_dir():
print("ERROR: \""+path+"\" is not an directory")
exit();
self.__ReadTrackList()
if self.count==0:
print("ERROR: no (supported) files found in directory \""+path+"\"")
exit();
if(self.__verbose):
self.ShowTrackList()
def __ReadTrackList(self):
"""do the actual reading"""
self.tracklist=[]
self.count=0
path=Path(self.path)
if(self.recursive):
selection='**/*'
else:
selection='*'
for entry in path.glob(selection):
if entry.suffix in EXTENSIONS:
self.tracklist.append(entry.as_posix())
self.count+=1
if self.__sort:
self.tracklist.sort()
def ShowTrackList(self):
"""Print the list"""
print("Tracklist:")
print(" path = %s" %self.path)
print(" recursive = %s" %self.recursive)
print(" count = %d" %self.count)
print(" tracks:")
for track in self.tracklist:
print(" "+track)
f=open(track,"r")
if(f):
f.close()
def CheckTrackList(self):
"""Check path for filechanges"""
newtracklist=[]
newcount=0
if self.__reloaded:
self.__reloaded=False
newpath=Path(self.path)
if(self.recursive):
selection='**/*'
else:
selection='*'
for newentry in newpath.glob(selection):
if newentry.suffix in EXTENSIONS:
newtracklist.append(newentry.as_posix())
newcount+=1
if self.__sort:
newtracklist.sort()
if(newcount != self.count) or (newtracklist != self.tracklist):
if(self.__verbose):
print("Changes in filenames or number of files detected! Re-read tracklist.")
self.__ReadTrackList()
self.__reloaded=True
return self.__reloaded

67
conftest.py Executable file
View File

@@ -0,0 +1,67 @@
#!/usr/bin/python3
import json
import os
import time
import copy
import clockyconfig
class Tracklist:
def __init__(self,path="."):
self.path=path
self.tracklist=[]
self.count=0
olddir=os.getcwd()
if(self.path != '.'):
if(not os.path.isdir(self.path)):
print("ERROR: \""+self.path+"\" is not an existing directory")
exit();
os.chdir(self.path)
for ent in os.listdir("."):
if ent.lower().endswith(".mp3") and os.access(ent,os.R_OK):
self.tracklist.append(ent)
self.count+=1
self.tracklist.sort()
os.chdir(olddir)
def Show(self):
print("Tracklist.path = %s" %self.path)
print("Tracklist.count= %d" %self.count)
print("Tracks:")
for track in self.tracklist:
print (" "+track)
config=clockyconfig.ClockyConfig()
config.Print()
tl=Tracklist("mp3")
tl.Show()
if (tl.tracklist == config.tracklist):
print("Same!")
else:
print("diff")
a=0
t=0
while True:
t+=1
config.CheckConfig()
time.sleep(1)
a+=1
if(a>5):
config.settings["alarmdisabled"]=1-config.settings["alarmdisabled"]
print(config.settings["alarmdisabled"])
a=0
if(t>30):
break
tracklist=Tracklist()
#tracklist.Read("old")
#tracklist.Show()

View File

@@ -1,8 +1,4 @@
#!/usr/bin/env python #!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2017-18 Richard Hull and contributors
# See LICENSE.rst for details.
import re import re
import time import time