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
```
### 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
Overview of used hardware:

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env python2.7
#!/usr/bin/env python3
import time
import RPi.GPIO as GPIO
@@ -16,7 +16,8 @@ class Button:
presstime=0
ignore=0
def __init__(self, gpio):
def __init__(self, gpio,verbose=False):
if verbose:
print("initialize button on gpio %d" %gpio)
self.gpio = gpio
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
0.1.0:
v0.1.0 * added max7219 support, added signal handling
* Added additional logging messages for end of alarm
* implemented SIGINT (Ctrl-C) handling to exit gracefully
0.0.5:
* initial working version
v0.0.5 * initial working version
* show alarmtime in startup
------------------------------------------------------------
@@ -24,5 +24,5 @@ issues
todo
----
add SIGHUP handling for reload config
changes config file format to json
make documentation

313
clocky.py
View File

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