# jukebox.py
import cfg # simuler var globales, http://effbot.org/pyfaq/how-do-i-share-global-variables-across-modules.htm
# TODO : faire un fichier bash qui crée des situations inattendues
# avant le démarrage de jukebox
# logging : https://docs.python.org/2/library/logging.html
# hotkeys : https://nitratine.net/blog/post/how-to-make-hotkeys-in-python/
# 1. dossier /m vide
# 2. sous-dossiers absents
# 3. espace libre très bas
# TODO : remettre à plat les fichiers de données en lecture seule,
# et les fichiers de configuration système et utilisateur
#
import inc.infos as infos
from inc.inputkiz import input_seq
import inc.mpc as mpc
# import inc.start_stop as start_stop
import mod.aba as aba
import mod.commun as commun
# import mod.juk as juk # accueil placé dans modules
# import mod.rec as rec
import mod.mtn as mtn
import mod.rad as rad
import mod.zik as zik
NOM_APPLI = "Xavbox 2020"
def automate_jk(list_commands):
""" automatiser les commandes """
# ex : lancer RTL au démarrage avec les arguments 1 1 66
# 1 reprend la radio
# 1 lance le groupe 1
# 66 reprend la radio
mnu_commun = cfg.dic_menus["commun"]
for choix in list_commands:
menu_module = cfg.dic_menus[infos.ini_get("py_current_module", "juk")]
infos.m_g("automate : " + choix)
# menu commun
if choix in mnu_commun.keys():
une_commande, description = mnu_commun.get(choix)
commande(choix, une_commande, description)
# menu module
elif choix in menu_module.keys():
une_commande, description = menu_module.get(choix)
commande(choix, une_commande, description)
if infos.ini_get("py_current_module", "juk") == "juk":
nouveauMod = cfg.mnu_juk_activer.get(choix)
infos.ini_set("py_current_module", nouveauMod)
infos.m_g("inp_loop, module " + infos.ini_get("py_current_module", "juk"))
# mauvaise séquence (bipper ?)
else:
arr_msg = ["", "Séquence de touches " + choix + " inconnue pour " + infos.ini_get("py_current_module", "juk")]
infos.pdrNew(arr_msg)
def commande(choix, une_commande, description):
""" Lance la commande pour 'appareil demandé """
mnu_commun = cfg.mnu_commun
menu_module = cfg.dic_menus[infos.ini_get("py_current_module", "juk")]
if choix in mnu_commun.keys():
# lancer commande
mnu_commun.get(choix)[0]()
elif choix in menu_module.keys():
menu_module.get(choix)[0]()
def inp_loop():
""" Choix clavier utilisateur en fonction de l'appareil en cours """
mnu_commun = cfg.dic_menus["commun"]
def la_les_touches(choix1):
lc = len(choix1)
if lc == 1:
return "la touche "
elif lc > 1:
return "les touches "
def a_la_les_touches(choix1):
lc = len(choix1)
c2 = choix1.replace(".", "point ")
c2 = c2.replace("*", "étoile ")
if lc == 1:
return "à la touche " + c2
elif lc > 1:
return "aux touches " + c2
while True:
idx_menu = infos.ini_get("py_current_module", "juk")
menu_module = cfg.dic_menus[idx_menu]
choix = input_seq() # entrer une touche ou combinaison de touches
# fin mode consultation avec "12"
# if choix == "12":
# if infos.ini_get("mode_apprentissage", "off") == "off":
# infos.ini_set("mode_apprentissage", "on")
# msg = "mode apprentissage activé, " + \
# "tapez une touche ou une séquences de touches, " + \
# "pour connaître sa fonction, " + \
# "tapez 12 pour repasser en mode commande"
# else:
# infos.ini_set("mode_apprentissage", "off")
# msg = "les commandes sont de nouveau actives"
# infos.pdrNew(msg)
if choix in ".": # interrompt énoncé vocal en cours, on kille dans tous les cas, pas besoin de vérifier si un message est en cours de lecture
import inc.mpc as mpc
mpc.ferme_ton_clapet()
# elif choix in ".": # interrompt énoncé vocal en cours, on kille dans tous les cas, pas besoin de vérifier si un message est en cours de lecture
# msg = "--> la touche . dans inp_loop a interrompu le message vocal"
# infos.g_m(msg)
# import inc.mpc as mpc
# mpc.killer_pico()
# menu commun
elif choix in mnu_commun.keys():
une_commande, description = mnu_commun.get(choix)
if infos.ini_get("mode_apprentissage", "off") == "on":
msg = la_les_touches(choix) + " " + choix + " " + description
infos.pdrNew(msg)
else:
commande(choix, une_commande, description)
# menu module
elif choix in menu_module.keys():
une_commande, description = menu_module.get(choix)
if infos.ini_get("mode_apprentissage", "off") == "on":
msg = la_les_touches(choix) + " " + choix + " " + description
infos.pdrNew(msg)
else:
commande(choix, une_commande, description)
# 11 : on a quitté un menu spécial avec zéro
if choix == "11": # menu spécial module
# ~ infos.m_g("on a quitté un menu spécial, appelé avec 11, avec zéro,")
# ~ infos.m_g("ou bien on a tapé 11 dans un module")
infos.m_g("choix = 11, on a quitté un menu vocal")
# dans les deux cas, on n'enregistyre pas de
# nouvelle valeur pour py_current_module
elif infos.ini_get("py_current_module", "juk") == "juk":
# c'est ici qu'on décide si on démarre/reprend un module
nouveauMod = cfg.mnu_juk_activer.get(choix)
# bug ici quand on quitte le menu spécial 11 jukebox avec la touche 0
# nouveauMod prend la valeur None
# bug plantant évité grâce à la condition plus haut : if choix == "11":
infos.m_g(" ---> bug$$$, choix = {}".format(choix))
infos.m_g(" ---> bug$$$, nouveauMod = {}".format(nouveauMod))
infos.ini_set("py_current_module", nouveauMod)
infos.m_g("inp_loop, module " + infos.ini_get("py_current_module", "juk"))
# ~ # 11 : on a quitté un menu spécial avec zéro
# ~ elif choix in [ "11", ]:
# ~ infos.m_g("on a quitté un menu spécial avec zéro")
# mauvaise séquence (bipper ?)
else:
msg = "Aucune action associée " + a_la_les_touches(choix)
infos.pdrNew(msg)
def start():
""" accueil tout premier démarrage de jukebox.py """
def willkommen():
""" démarrage de l'application """
# with open(cfg.fichierVersion) as fileVersion:
# version_actu = fileVersion.readlines()[0].strip()
infos.m_g("---------------------------------------------")
infos.m_g(" Bienvenue dans " + NOM_APPLI)
infos.m_g(" version " + mtn.version_current())
infos.m_g(" màj " + mtn.version_update())
infos.m_g("---------------------------------------------")
msg1 = "Bienvenue dans " + NOM_APPLI
if infos.niveau_aide_voc() == 0:
dire_aide_vocale = ""
else:
dire_aide_vocale = ", aide vocale " + str(infos.niveau_aide_voc())
aujourdhui = commun.date_heure_fr()
# mnu_aide_voc = "pressez la séquences de touches " + \
# "33 pour basculer l'aide vocale, " + \
# "11 pour lancer le menu vocal"
mnu_aide_voc = "pressez la séquences de touches " + \
"00 si vous êtes perdu"
msg1 += dire_aide_vocale + ", " + aujourdhui + ", " + mnu_aide_voc
msg2 = msg1
infos.pdrNew([msg1, msg2])
def clean_crash():
""" nettoie les fichiers en attente
qui seraient restés après un crash ou une extinction sauvage
"""
# supprimer éventuel flags arrêt thread
mpc.sub_proc("rm /m/quitter_download")
mpc.sub_proc("rm /m/quitter_dire")
# au démarrage de l'appli :
# supprimer tous les livres en attente de download
mpc.sub_proc("rm /m/aba_dl_bg_*.txt")
mpc.sub_proc("rm -rf /m/temp_dl_media")
mpc.sub_proc("rm -rf /m/tmp_undef")
# mettre à jour toute la base mpd
mpc.update()
def ligne_commande():
""" automatisation des commandes """
# Commandes batch depuis la ligne de commande, cf. doc01
import sys
if len(sys.argv) > 1:
les_argus = sys.argv[1:]
infos.m_g(str(len(les_argus)) + " arguments fournis : ")
n = 0
for i in les_argus:
n += 1
infos.m_g("- argument {} : {}".format(n, i))
automate_jk(les_argus)
# TODO : tester si file system en lecture seule
# symptôme : message prononcé se répète à l'infini
# dans ce cas, rebooter
stats_dev()
mpc.clear()
cmd = "[ -d {0} ] || mkdir {0}".format(cfg.DIRE_FILE_ATTENTE)
make_dir_plz = mpc.sub_proc(cmd)
clean_crash()
infos.ini_set("py_current_module", "juk")
infos.ini_set("mode_apprentissage", "off")
willkommen()
ligne_commande()
inp_loop()
def stats_dev():
""" nb de lignes par module,
nb fonctions par module
"""
def dossier_fichiers(dossier, list_fichiers):
nb_lignes, nb_fonctions = 0, 0
infos.m_g("Dossier {}".format(dossier))
for i in list_fichiers:
nb_lignes_f, nb_fonctions_f = stat_py(dossier, i)
nb_lignes += nb_lignes_f
nb_fonctions += nb_fonctions_f
infos.m_g("Total {:>5d} lignes, {:>4d} fonctions".format(nb_lignes, nb_fonctions))
return int(nb_lignes), int(nb_fonctions)
def stat_py(path, nom):
cmd = "wc -l < {}/{}.py".format(path, nom)
nb_lignes = mpc.sub_proc(cmd)
cmd = "grep '^def ' < {}/{}.py | wc -l".format(path, nom)
nb_fonctions = mpc.sub_proc(cmd)
cmd = "grep '^def ' < {}/{}.py".format(path, nom)
fonctions = mpc.sub_proc(cmd)
infos.m_g("{:>8s}.py, {:>4s} lignes, {:>4s} fonctions".format(nom, nb_lignes, nb_fonctions))
return int(nb_lignes), int(nb_fonctions)
l1, f1 = dossier_fichiers("/opt/jk2019/tou_py", ["cfg", "jukebox"])
infos.m_g("")
l3, f3 = dossier_fichiers("/opt/jk2019/tou_py/inc", ["infos", "inputkiz", "mpc"])
infos.m_g("")
l2, f2 = dossier_fichiers("/opt/jk2019/tou_py/mod", ["aba", "commun", "mtn", "rad", "zik"])
total_L = l1 + l2 + l3
total_F = f1 + f2 + f3
infos.m_g("")
infos.m_g("Total global : {} lignes, {} fonctions".format(total_L, total_F))
def plantage():
""" enreguistrer lke journal de plantage
et l'envoyer par mail ou web
"""
print("except " + "." * 100)
infos.m_g("Le programme a planté")
infos.m_g("Le programme a planté")
# prononcer en natif ici, pas d'arrière-plan
texte = "Le programme a planté."
wav = cfg.WAV_WAV
cmd = 'pico2wave -l "fr-FR" -w ' + wav + ' "' + texte + '"'
mpc.sub_proc(cmd)
# jouer wav
cmd = "aplay -q " + wav
infos.m_g(cmd)
mpc.sub_proc(cmd)
from time import localtime, strftime
date_plantage = strftime("%Y-%m-%d %H:%M:%S", localtime())
date_fichier = strftime("%Y%m%d_%H%M%S", localtime())
fich_log = "/m/plantage_" + str(date_fichier) + ".txt"
fplant = open(fich_log, "a")
fplant.write("Date plantage : " + str(date_plantage + "\n"))
traceback.print_exc(file=fplant)
fplant.write("\n")
fplant.write("Fin plantage : " + str(date_plantage + "\n"))
fplant.close()
infos.m_g("Fichier " + fich_log + " appendé")
cmd = "curl -F \"avatar=@" + fich_log + "\" http://gangand.net/gl/kinote/upload.php"
infos.m_g(cmd)
mpc.sub_proc(cmd)
cmd = "touch /m/quitter_download"
infos.m_g(cmd)
mpc.sub_proc(cmd)
cmd = "touch /m/quitter_dire"
infos.m_g(cmd)
mpc.sub_proc(cmd)
# thread téléchargements
cmd = "rm /m/aba_dl_bg_*.txt"
infos.m_g(cmd)
mpc.sub_proc(cmd)
# utile ?
cmd = "rm -rf /m/temp_dl_media"
infos.m_g(cmd)
mpc.sub_proc(cmd)
# thread pronciation
cmd = "rm -rf {}".format(cfg.DIRE_FILE_ATTENTE)
infos.m_g(cmd)
mpc.sub_proc(cmd)
import traceback
if __name__ == "__main__":
start()
# ~ try:
# ~ start()
# ~ except Exception as inst:
# ~ print("excep " + "." * 100)
# ~ print("Exception dans le module de départ jukebox.py")
# ~ print("tout nettoyer et relancer le programme")
# ~ print(type(inst)) # the exception instance
# ~ print(inst.args) # arguments stored in .args
# ~ print(inst) # __str__ allows args to be printed directly,
# ~ # but may be overridden in exception subclasses
# ~ plantage()
# ~ commun.faire_pause(5)
# ~ import sys
# ~ sys.exit()