# -*-coding:Latin-1 -*
"""fonction client du chat vocal (protocole UDP)"""
from socket import socket, AF_INET, SOCK_DGRAM
from time import sleep
from threading import Thread
from os import system
import logging

#modules complémentaires
import pymedia.audio.sound as sound
import pymedia.audio.acodec as acodec
from pyaudio import PyAudio, paInt16

#modules perso
from anason import AnaSon
from lecture import Lecture

#gestion des erreurs et log
logging.basicConfig(level=logging.DEBUG)
logCVoc = logging.getLogger(__name__)
handlerCVoc = logging.FileHandler('chatVoc.log')
handlerCVoc.setFormatter(logging.Formatter('[%(asctime)s] %(levelname)s - %(message)s'))  #%(name)s - nom du module
logCVoc.addHandler(handlerCVoc)
logCVoc.debug("    ----------------------    \n")

port = 6660
frequence = 22050
#param d'encodage/decodage
cparams= { 'id': acodec.getCodecID( 'mp3' ),
           'bitrate': 32000,
           'sample_rate': frequence,
           'channels': 1 }
taille_paquets = 1024
debug = False

######### Fils secondaires #########

class ReceptionVoc(Thread):
    """fil gerant la reception du son"""
    def __init__(self, cnn):
        """création du fil reception"""
        self.connecte = True
        Thread.__init__(self)
        self.cnn = cnn
        self.essais = 0
        self.connectes = {}
        
    def run(self):
        """reception: tourne en boucle tant que la connexion est active"""
        while self.connecte:
            try:
                fr, adresse = self.cnn.recvfrom(taille_paquets)
                #print("recu {}".format(len(fr)))

                #les 2 premiers caracteres sont le pseudo de l'expediteur   
                expediteur = fr[:2]
                donnee = fr[2:]
                if not expediteur in self.connectes.keys():
                    #nouveau connecte
                    try:
                       fil = Lecture(expediteur, cparams, debug)
                       fil.start()
                       self.connectes[expediteur] = fil
                       logCVoc.info("\n -> Connecte a {}".format(expediteur))
                    except KeyboardInterrupt:
                       logCVoc.error("{} - Erreur de reception".format(expediteur))
                else: 
                   if donnee:       
                      self.connectes[expediteur].lire(donnee)
                
                self.essais = 0
            except IOError, e: 
               if e.errno == 10022:    
                   sleep(0.001)
                   self.essais += 1
                   if self.essais == 1000:
                      logCVoc.warning("pas de reception")
                      self.essais = 0
                      
    def stop(self):
        """Fermeture du fil Reception"""
        logCVoc.info("\nChat vocal : Reception interrompue")
        for fil in self.connectes.values():
            fil.stop()
        self.connecte = False
        self.cnn.close()
        
        
#fin du fil reception   

#objet client:
class ClientVoc(Thread):
    """client pour le chat vocal"""
    def __init__(self, idClient, ipServeur, port):
        """création du client"""
        Thread.__init__(self)
        self.idClient = idClient
        self.ipServeur = ipServeur
        self.port = 6660
        
        ###parametrage du socket udp###
        self.cnn = socket(AF_INET, SOCK_DGRAM)
        self.connecte = False

        #flux microphone:
        self.stream = PyAudio().open(format = paInt16,    
                                     channels = 1,
                                     rate = frequence,
                                     input = True,
                                     frames_per_buffer = 1024)
        #encodage:
        self.ac = acodec.Encoder( cparams )
        
        #traitement du son?
        self.traitement = False
        if self.traitement:
            #parametres de traitement du son:
            self.ana = AnaSon()
            #on recupere les parametres enregistres si possible
            self.ana = self.ana.recup()
        
    def creer(self):
        """demarre une instance client pour le chat vocal"""
        if len(self.idClient) == 2 and len(self.ipServeur) > 0 :
            self.thR = ReceptionVoc(self.cnn)
            self.thR.start()
            self.connecte = True
            self.start()
            txt = "Chat vocal demarre"
            logCVoc.info(txt)
        else:
            txt = "Chat vocal : erreur dans les parametres d'entree"
            logCVoc.error(txt)  
        return txt 

    def run(self):
       """emission: tourne en boucle tant que la connexion est active"""
       #on affiche les parametres du micro
       if self.traitement:
          logCVoc.info(self.ana)
          
       while self.connecte:
              #son = micro.getData()
              son = self.stream.read(1024)
              if son and len(son):
                  if self.traitement:
                     son = self.ana.traitement(son)
                      
                  if son:
                     son_encode = self.ac.encode(son)
                
                     for fr in son_encode:
                         if len(fr) < (taille_paquets - 2):
                             #on ajoute l'id du client au debut du paquet
                             envoi = self.idClient + fr
                             #print("envoi {}".format(len(fr)))
                             self.cnn.sendto(envoi, (self.ipServeur, port))
                         else:
                             logCVoc.warning("1 paquet trop volumineux")
              else:
                  #si pas de son, on attend un peu
                  sleep(0.003)

    def stop(self):
        """quitte la session de chat"""
        if self.connecte:
            self.thR.stop()
        self.stream.close()
        self.cnn.close()
        txt = "Fermeture du chat vocal"
        logCVoc.info(txt)

        return txt
            
### fil principal ###
if __name__ == "__main__":
   # si lancement direct:
   idClient = raw_input("id client (2car)")
   c = ClientVoc(idClient, "localhost", 6660)
   c.creer()
   system("pause")
   c.stop()



