# -*- coding: utf-8 -*-
"""fonction client du chat vocal (protocole UDP)"""
import socket
import time
import threading
import os

#modules complémentaires
import pymedia.audio.sound as sound
import pymedia.audio.acodec as acodec
import pyaudio

#modules perso
#from anason import AnaSon
from lecture import Lecture


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(threading.Thread):
    """fil gerant la reception du son"""
    def __init__(self, cnn):
        """création du fil reception"""
        self.connecte = True
        threading.Thread.__init__(self)
        self.cnn = cnn
        self.essais = 0
        self.connectes = {}
        
    def run(self):
        """reception: tourne en boucle tant que la connexion est active"""
        time.sleep(0.1)
        while self.connecte:
            try:
                fr, adresse = self.cnn.recvfrom(taille_paquets)
                #print("recu {}".format(len(fr))) 
                emet = fr[2:4]
                donnee = fr[6:]
                 
                if not emet in self.connectes.keys():
                    #nouveau connecte
                    try:
                       fil = Lecture(emet, cparams, debug)
                       fil.start()
                       self.connectes[emet] = fil
                       print("\n -> Connecte a {}".format(emet))
                    except KeyboardInterrupt:
                       print("{} - Erreur de reception".format(emet))
                else: 
                   if donnee:       
                      self.connectes[emet].lire(donnee)
                
                self.essais = 0
            except IOError, e: 
               if e.errno == 10022:    
                   time.sleep(.003)
                   self.essais += 1
                   if self.essais == 200:
                      print("pas de reception")
                      self.connecte = False

                      
    def stop(self):
        """Fermeture du fil Reception"""
        print("\nChat vocal : Reception interrompue")
        for elt in self.connectes.values():
            elt.stop()
        self.connecte = False
        self.cnn.close()
        
        
#fin du fil reception

class EmissionVoc(threading.Thread):
    """fil gerant l'emission du son"""
    def __init__(self, cnn, idClient, hote):
        """création du fil emission"""
        self.connecte = True
        threading.Thread.__init__(self)
        self.cnn = cnn
        self.idClient = idClient
        self.hote = hote
        
        #flux microphone:
        self.stream = pyaudio.PyAudio().open(format = pyaudio.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 run(self):
       """emission: tourne en boucle tant que la connexion est active"""
       #on affiche les parametres du micro
       #if self.traitement:
          #print(self.ana)
          
       while self.connecte:
              #son = micro.getData()
              try:
                 son = self.stream.read(1024)
              except:
                 son = ""
                 
              if son and len(son) > 0:
                  #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 - 6):
                             #on ajoute le pseudo au debut du paquet
                             envoi = "vd{}ac{}".format(self.idClient, fr)
                             #print("envoi {}".format(len(fr)))
                             self.cnn.sendto(envoi, (self.hote, port))
                         else:
                             print("1 paquet trop volumineux")
              else:
                  #si pas de son, on attend un peu
                  time.sleep(.003)
                  
    def stop(self):
       """Fermeture thread emission"""
       print("\nChat vocal : Emission interrompue")
       self.connecte = False
       self.stream.close()
       self.cnn.close()
        
#fin du fil emission        

#objet client:
class ClientVoc():
    """client pour le chat vocal"""
    def __init__(self):
        """création du client"""
        self.pseudo = ""
        self.hote = ""
        self.port = 6660
        
        ###parametrage du socket udp###
        self.cnn = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.connecte = False
        
    def creer(self, idClient, hote):
        """demarre une instance client pour le chat vocal"""
        self.idClient = idClient
        self.hote = hote
        
        if len(self.idClient) > 0 and len(self.hote) > 0 :
            self.thE = EmissionVoc(self.cnn, self.idClient, self.hote)
            self.thR = ReceptionVoc(self.cnn)
            self.thE.start()
            self.thR.start()
            self.connecte = True
            retour = "*Communication etablie"
        else:
            retour = "pseudo du client et/ou adresse du serveur UDP non definis" 

        return retour
    
    def stop(self):
        """quitte la session de chat"""
        self.connecte = False
        self.thE.stop()
        self.thR.stop()
        self.cnn.close()
        retour = "Fin de la communication"
        print("*Fin de la communication\n")
        return retour
            
### fil principal ###
if __name__ == "__main__":
   # si lancement direct:
   c = ClientVoc()
   test = raw_input("id")
   print(c.creer(test,"localhost"))
   os.system("pause")
   c.stop()



