# mod/zik.py
# équivalent bash = /run/user/1000/gvfs/sftp:host=192.168.1.12/opt/jk2019/tout/inc/mod/zik.sh
# one-liner pour vérifier favoris :
# x="-----------------------"; echo "$x"; nl /m/playlists/zik_memo; echo "$x"; nl /m/memo/zik/py_memo_zik.txt; echo "$x"
import cfg
import inc.infos as infos
import inc.mpc as mpc
import mod.commun as commun
def add_fav(): # ajouter l'élément courant à la playlist courante
pass
def az_sort(): # ordonné
pass
def az_shuf(): # mélangé
infos.m_g("zik az_shuf")
# infos.pdrNew(["", "Lecture au hasard"])
mpc.stop()
infos.pdrNew(["", "Lecture au hasard"])
mp3_az(cfg.MOUNT_USB, "shuf")
def taches_courantes(): # aide module succincte
pass
def change_fav(): # Change la liste de favoris en cours
pass
def chg_type(): # changer type de musique
infos.m_g("zik chg_type")
def favoris_bannis(file_relative, operation, num_favori):
""" gère les favoris et les bannis
qui sont en fait deux listes de mémoire
file_relative : chemin de fichier .mp3 relatif à /m/music
operation :
"""
SEP = ","
def add_ban_fav(file_relative):
""" ajoute le favori si absent du fichier playlist favoris """
# rappel : /m/playlists/py_zik_fav_1.m3u
playlist_fav = "{}/{}_{}.m3u".format(cfg.PLAYLISTS_PATH, cfg.ZIK_FAV, num_favori)
ligne_presente = False
nb_favoris = 0
len_lignes = 0
if commun.file_exists(playlist_fav):
with open(playlist_fav, "r") as f:
lignes = f.readlines()
len_lignes = len(lignes)
for ligne in lignes:
if ligne.strip() == file_relative:
ligne_presente = True
break
if ligne_presente == False:
with open(playlist_fav, "a") as f:
f.write("\n" + file_relative)
nb_favoris = len_lignes + 1
return nb_favoris, "Ajout favoris {} de {}".format(num_favori, file_relative)
else:
# TODO : remplacer le bip par un énoncé du nombre de favoris présents
# et éventuellement un check de la présence des fichiers pointés
mpc.bip(2)
return len_lignes, "Favori '{}' déjà présent dans '{}'".format(file_relative, playlist_fav)
def del_ban_fav(file_relative):
""" supprime le favori, si présent, du fichier playlist favoris """
playlist_fav = "{}/{}_{}.m3u".format(cfg.PLAYLISTS_PATH, cfg.ZIK_FAV, num_favori)
ligne_presente = False
len_lignes = 0
if commun.file_exists(playlist_fav):
with open(playlist_fav, "r") as f:
lignes = f.readlines()
len_lignes = len(lignes)
reecrire = []
for ligne in lignes:
ligne_stripped = ligne.strip()
if ligne_stripped == file_relative:
ligne_presente = True
else:
reecrire.append(ligne_stripped)
if ligne_presente == True:
with open(playlist_fav, "w") as f:
f.write("\n".join(reecrire))
return len(reecrire), "Suppression des favoris de {}".format(file_relative)
else:
mpc.bip(2)
return len_lignes, "{} déjà absent des favoris".format(file_relative)
################################################
# favoris / bannis #
################################################
if operation == "add_fav":
return add_ban_fav(file_relative)
elif operation == "del_fav":
return del_ban_fav(file_relative)
# gestion des favoris et des bannis
def fav_add():
""" ajoute ce type de ligne au fichier favoris :
type1/S/Joe Satriani/Surfing with the alien/02 - Ice nine.mp3 """
infos.pdrNew([ "", "ajout aux favoris"])
nb_favoris, r = favoris_bannis(mpc.mpc_file(), "add_fav", 1)
zlogger("fav_add, {} favoris, {}".format(nb_favoris, r))
def fav_del():
""" supprime ce type de ligne du fichier favoris :
type1/S/Joe Satriani/Surfing with the alien/02 - Ice nine.mp3 """
infos.pdrNew([ "", "suppression des favoris"])
nb_favoris, r = favoris_bannis(mpc.mpc_file(), "del_fav", 1)
zlogger("fav_del, {} favoris, {}".format(nb_favoris, r))
def fav_menu():
""" lance le menu vocal fav_ban """
explic = "utiliser les touches 1 à {} pour gérer vos favoris, " + \
" zéro pour sortir de ce menu, " + \
"Entrée pour valider la commande entendue"
commun.menu_vocal("zik_fav_ban", "favoris et indésirables", explic)
def fav_play():
""" Jouer les favoris """
mpc.ferme_ton_clapet()
mpd_pl_fav = cfg.ZIK_FAV + "_1"
mpc.clear()
mpc.load(mpd_pl_fav)
mpc.random_off()
mpc.play()
msg = "Lecture des {} favoris".format(mpc.playlist_longueur())
infos.pdrNew(msg)
def fav_play_random():
""" Jouer les favoris dans le désordre """
mpc.ferme_ton_clapet()
mpd_pl_fav = cfg.ZIK_FAV + "_1"
mpc.clear()
mpc.load(mpd_pl_fav)
mpc.random_on()
mpc.play()
msg = "Lecture des {} favoris dans le désordre".format(mpc.playlist_longueur())
infos.pdrNew(msg)
def fwd_30s():
""" avance de 30 secondes """
mpc.fwd_30s()
def infos_fav(): # les favoris n comptent 15 lignes
pass
def keepcd(): # 11 : Jouer seulement les mp3 du dossier en cours
infos.m_g("zik Jouer seulement les chansons du dossier en cours")
cmd = "dirname \"$(mpc -f %file% | head -1)\""
infos.m_g("keepcd, cmd = " + cmd)
dossier_en_cours = mpc.sub_proc(cmd)
infos.m_g("keepcd, dossier_en_cours = " + dossier_en_cours)
mpc.ferme_ton_clapet()
mpc.clear()
mpc.add(dossier_en_cours)
# TODO : reprendre soit au début de l'album, soit la plage en cours
mpc.play()
def keepcdprt(): # 22 : Jouer seulement les mp3 du dossier PARENT en cours
infos.m_g("zik Jouer seulement les chansons du dossier en amont")
cmd = "dirname \"$(dirname \"$(mpc -f %file% | head -1)\")\""
infos.m_g("keepcd, cmd = " + cmd)
dossier_en_cours = mpc.sub_proc(cmd)
infos.m_g("keepcd, dossier_en_cours = " + dossier_en_cours + '/..')
mpc.ferme_ton_clapet()
mpc.clear()
mpc.add(dossier_en_cours)
# TODO : reprendre soit au début de l'album, soit la plage en cours
mpc.play()
def memo_stop_module():
""" TODO quitter module (touche 0) : mémoriser où on est """
zik_memo("save_playlist")
zik_memo("save_position_et_progression")
######################## version bash #############################
# if [ "x$(mpc playlist)" = "x" ]; then # mpc queued ne fonctionne qu'en version 0.29, pas 0.28
# # playlist vide, on ne mémorise rien
# :
# elif [ "x$(mpc -f %position% | head -1 | cut -f1 -d':')" = "xvolume" ]; then
# # playlist fournie mais position indéfinie
# :
# else
# # on mémorise où on est dans le module musique
# mpc rm ${PL_ZIK_MEMO}
# mpc save ${PL_ZIK_MEMO}
# positionPlaylist=$(mpc -f %position% | head -1)
# positionMorceau="$(showProgSec)"
# echo "$(mpc status | grep "# volume:")|${numFav}|${positionPlaylist}|${positionMorceau}" > ${fileZikPosMoment}
# fi
######################## fin bash #############################
infos.m_g("Mémoriser état du module zik avant stop")
def menu_voc11():
""" menu spécial zik """
commun.menu_vocal("zik_special11", "musique")
def play_all():
infos.pdrNew(["", "Lecture globale au hasard"])
mp3_az(cfg.MOUNT_USB, "shuf", "non")
def mp3_az(dossier, ordre, demander = "oui"): # joue dossier selon lettre demandée
# dossier : dossier source (/m ou bien /m_SDcard)
# ordre : sort ou shuf
# ~ typeAction=écoute_mp3_az_$2
chiffres_lettres = {
"1": "A", "2": "B", "3": "C", "4": "D", "5": "E",
"6": "F", "7": "G", "8": "H", "9": "I", "10": "J",
"11": "K", "12": "L", "13": "M", "14": "N", "15": "O",
"16": "P", "17": "Q", "18": "R", "19": "S", "20": "T",
"21": "U", "22": "V", "23": "W", "24": "X", "25": "Y", "26": "Z"
}
lettre = ""
if demander == "oui":
infos.pdrNew(["",
"tapez un nombre de 1 à 26, puis Entrée " + \
"(Entrée seul pour inclure toutes les lettres)"])
lettre = input("")
if lettre in chiffres_lettres.keys():
mp3_lettre(dossier, chiffres_lettres.get(lettre), ordre)
elif lettre == "":
mp3_lettre(dossier, "", ordre)
def mp3_lettre(dossier, lettre, ordre):
""" Joue dossier selon dossier source et lettre """
mpc.ferme_ton_clapet()
mpc.clear()
if ordre == "shuf":
mpc.random_on()
else:
mpc.random_off()
ZIKROOT="type1"
if lettre == "":
# ajouter toutes les lettres
for lettre in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
mpc.add(ZIKROOT+ "/" + lettre)
infos.m_g("mpc -q add " + ZIKROOT+ "/A, " + ZIKROOT+ "/B, ..., " + ZIKROOT + "/Z")
elif lettre in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
mpc.add(ZIKROOT+ "/" + lettre)
# symbole note de musique ici :
# m_g "♫ dernier élément de la playlist : $(mpc playlist | nl | tail -1)" # voir le dernier élément de la playlist
mpc.play()
zik_infos_go()
# intérêt ope_en_cours : si on appuie sur 00, on obtient de l'aide pour la navigation dans la lecture
# infos.ini_file_set(cfg.CONFIG_INI, "ope_en_cours", "lecture")
def prev_trk():
mpc.prev_trk()
zik_infos_go("prev")
def next_trk():
mpc.next_trk()
zik_infos_go("next")
def random_trk():
""" aller à une piste de la playliste au hasard """
infos.m_g("TODO aller à une piste de la playliste au hasard")
def rebours():
infos.m_g("Programmer un arrêt de la musique")
def rem_fav(): # remove from favorites
pass
def rew_10s():
""" recule de 10 secondes """
mpc.rew_10s()
def zik_memo(operation):
""" renvoie variables, fichier de mémorisation,
ou effectue des opérations de mémorisation
"""
if operation == "playlist":
# fichier m3u pour mémoriser la playliste en cours
zlogger("zik memo GET playlist : " + cfg.PL_ZIK_MEMO)
return cfg.PL_ZIK_MEMO
elif operation == "playlist_file":
# fichier m3u pour mémoriser la playliste en cours
f = cfg.PLAYLISTS_PATH + "/" + cfg.PL_ZIK_MEMO + ".m3u"
zlogger("zik memo GET playlist : " + f)
return f
elif operation == "save_playlist":
# sauvegarde mpd de la playlist en cours
zlogger("zik memo --> SAVE playlist : mpc -q save " + cfg.PL_ZIK_MEMO)
mpc.rm(cfg.PL_ZIK_MEMO)
mpc.save(cfg.PL_ZIK_MEMO)
elif operation == "save_position_et_progression":
# sauvegarde dans "/m/memo/zik/py_memo_zik.txt" des :
# options de lecture (volume, ..., random, ...
# X numéro de la liste des favoris (1 pour l'instant)
# X position dans playliste
# X progression dans morceau
options = mpc.options_lecture() # ~ mpc_status = t[0] # volume: 81% repeat: off random: off single: off consume: off
numFav = 1
posPL = mpc.playlist_position()
posTrack = mpc.status_progression()[0]
ligne = "{}|{}|{}|{}".format(options, numFav, posPL, posTrack)
fichier = zik_memo("position")
if fichier == False:
infos.m_g("zik memo --> SAVE position et progression (" + fichier + ") impossible")
else:
infos.m_g("zik memo --> SAVE position et progression (" + fichier + ")")
with open(fichier, "w") as f:
f.write(ligne)
elif operation == "position":
zlogger("zik memo GET position : " + cfg.ZIK_MEMO)
# vérif dossier enregistrements
zm_dir = cfg.ZIK_MEMO_DIR
if not commun.dir_exists(zm_dir):
commun.make_dir(zm_dir)
if not commun.dir_exists(zm_dir):
infos.pdrNew("Problème lors de la création du dossier mémo musique")
commun.faire_pause(3)
return False
return cfg.ZIK_MEMO
def reprendre(): # on reprend la musique quittée
""" reprendre la lecture de la musique quittée
2 fichiers/playlist utilisés :
- /m/playlists/py_zik_memo.m3u
- /m/memo/zik/py_zik_memo.txt """
def init_reprendre():
""" initialisation variables musique """
# TODO : contrôler que tout est bien là :
# - la musique à lire
# - les lieux de mémorisations
infos.ini_set("py_current_module", "zik")
def reprendre_la_musique():
""" rependre où on s'était arrêté """
# 1. récupérer la playliste sauvegardée
if commun.file_exists(zik_memo("playlist_file")):
mpc.ferme_ton_clapet()
mpc.load(zik_memo("playlist"))
else:
infos.m_g("Fichier absent {}".format(zik_memo("playlist_file")))
infos.m_g("Pas de playliste memo zik trouvée")
# zik_memo("save_playlist")
return False
# 2. récupérer les positions et progression sauvegardées
fichier_memo_zik = zik_memo("position")
if commun.file_exists(fichier_memo_zik):
zlogger(fichier_memo_zik + " existe")
# position dans playliste et progression dans morceau
t = commun.file_stripped(fichier_memo_zik)[0].split("|")
mpc_status = t[0] # volume: 81% repeat: off random: off single: off consume: off
numFav = t[1] # 1
positionPlaylist = t[2] # 1:45
positionMorceau = t[3] # 1211
zlogger("rep_l_m : fichier playlist = " + zik_memo("playlist_file"))
zlogger("rep_l_m : playlist = " + zik_memo("playlist"))
zlogger("rep_l_m : numFav = " + numFav)
zlogger("rep_l_m : positionPlaylist = " + positionPlaylist)
zlogger("rep_l_m : positionMorceau = " + positionMorceau)
if mpc_status.find("random: on") > 0:
mode_random = True
else:
mode_random = False
mpc.play(positionPlaylist)
mpc.seek(positionMorceau)
return True
else:
infos.m_g(fichier_memo_zik + " n'existe pas")
numFav = 1
positionPlaylist = 1
positionMorceau = 0
infos.m_g("Pas de positions mémorisées dans playliste trouvée")
mpc.play()
return True
# mpc.play(positionPlaylist)
# mpc.seek(positionMorceau)
# return True
def verif_dir_music():
""" si le dossier /m/music n'existe pas, on quitte
"""
# https://wiki.archlinux.org/index.php/Music_Player_Daemon#Configure_the_location_of_files_and_directories
# ou bien envisager de copier /etc/mpd.conf vers ~/.config/mpf.conf
# et de modifier music_directory en /m au lieu de /m/music
# sudo service mpd stop
# sudo service mpd start
# vérif clé usb montée
if commun.m_is_mounted() == False:
infos.pdrNew("Problème, la clé u s b ne semble pas reconnue, " + \
"veuillez redémarrer ou vérifier votre clé.")
return False
# vérif /m/music existe
dossier = cfg.M_MUSIC + "/type1"
if not commun.dir_exists(dossier):
# proposer déplacer fichiers au bon endroit
msg = "Le dossier musique est absent de la clé u s b"
infos.pdrNew(msg)
msg = "Si vous voulez quand même écouter votre musique, " + \
"vous pouvez autoriser le programme à créer " + \
"les dossiers nécessaires, et y déplacer vos chansons"
infos.pdrNew(msg)
msg = "Appuyer sur 321 puis Entrée pour procéder."
infos.pdrNew(msg)
choix_user = input()
if choix_user == "321":
mpc.ferme_ton_clapet()
cmd = "find /m -iname '*.mp3' | wc -l"
nb_mp3 = int(mpc.sub_proc(cmd))
msg = "{} fichiers m p 3 ont été trouvés sur la clé".format(nb_mp3)
infos.pdrNew(msg)
cmd = "mkdir -p /m/music/type1/A"
mpc.sub_proc(cmd)
cmd = "find /m -iname '*.mp3' | grep -v /m/music | cut -f3 -d'/' | sort | uniq > /tmp/forcer_chansons.txt"
mpc.sub_proc(cmd)
with open("/tmp/forcer_chansons.txt", "r") as f:
lignes = f.readlines()
for ligne in lignes:
cmd = 'cd /m; mv "' + ligne.strip() + '" /m/music/type1/A'
infos.m_g(cmd)
mpc.sub_proc(cmd)
else:
return False
################################################
# reprendre zik #
################################################
mpc.ferme_ton_clapet()
if verif_dir_music() == False:
return 0
init_reprendre()
mpc.clear()
# commenter ci-dessous pour ne pas reprendre_directement la lecture
mpc.update() # important quand on change de clé usb !
infos.m_g("mpc -q update")
msg = "lancement de la musique sur clé u s b"
infos.pdrNew(["", msg, msg, msg])
commun.faire_pause(5, True) # pause de 2s
resultat = reprendre_la_musique()
def trk_first():
infos.m_g("zik trk_first")
mpc.trk_first()
def trk_last():
infos.m_g("zik trk_last")
mpc.trk_last()
def zik_fav3():
pass
def zik_nfo1():
""" appui sur touche / : annoncer titre de auteur """
# ex : "vous écoutez Matrice de Gérard Manset"
msg = "vous écoutez " + mpc.auteur_titre()
infos.pdrNew(msg)
def zik_infos_go(choix = None):
""" copier zik_infos_go () de zik.sh """
if choix is None:
infos.m_g(mpc.auteur_titre())
elif choix in ("prev", "next"):
infos.m_g(choix + " : " + mpc.auteur_titre())
def zik_infos_non_vides(): # renvoie infos mp3 si présentes, sinon nom de fichier si absentes
return ("TODO zik_infos_non_vides")
def zik_nfo(): # "il vous reste 3 minutes 12 pour ce morceau"
pass
def zik_nfo2(): # "élément 8 sur 15"
pass
def zik_nfo3(): # "vous êtes à 3 mn 12 sur 10 mn 30"
pass
def zik_nfo4(): # "la durée totale du livre est de 2 heures 38"
pass
def zlogger(s):
""" fichier log pour débugger """
pass
if __name__ == "__main__":
print("Bienvenue dans le module zik (musique)")