From e6c955d51aac73f4eacef16350e10d988b037ed2 Mon Sep 17 00:00:00 2001 From: xdatomic-the-codeur Date: Tue, 25 Feb 2025 16:05:49 +0100 Subject: [PATCH] =?UTF-8?q?S=C3=A9ance=203?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Joueur.java | 9 + src/modele/Boule.java | 25 + src/modele/Jeu.java | 29 + src/modele/JeuClient.java | 33 ++ src/modele/JeuServeur.java | 50 ++ src/modele/Joueur.java | 128 +++++ src/modele/Mur.java | 14 + src/modele/Objet.java | 27 + src/outils/connexion/AsyncResponse.java | 16 + src/outils/connexion/ClientSocket.java | 38 ++ src/outils/connexion/Connection.java | 109 ++++ src/outils/connexion/ServeurSocket.java | 67 +++ src/outils/son/Duree.java | 121 +++++ src/outils/son/Son.java | 55 ++ src/outils/son/Sound.java | 503 ++++++++++++++++++ src/outils/son/ecouteurs/EcouteurSon.java | 21 + .../son/exceptions/SonErreurDiverse.java | 21 + .../son/exceptions/SonErreurLecture.java | 20 + src/outils/son/exceptions/SonException.java | 20 + .../exceptions/SonIntrouvableException.java | 38 ++ .../son/exceptions/SonTypeException.java | 20 + 21 files changed, 1364 insertions(+) create mode 100644 src/modele/Boule.java create mode 100644 src/modele/Jeu.java create mode 100644 src/modele/JeuClient.java create mode 100644 src/modele/JeuServeur.java create mode 100644 src/modele/Joueur.java create mode 100644 src/modele/Mur.java create mode 100644 src/modele/Objet.java create mode 100644 src/outils/connexion/AsyncResponse.java create mode 100644 src/outils/connexion/ClientSocket.java create mode 100644 src/outils/connexion/Connection.java create mode 100644 src/outils/connexion/ServeurSocket.java create mode 100644 src/outils/son/Duree.java create mode 100644 src/outils/son/Son.java create mode 100644 src/outils/son/Sound.java create mode 100644 src/outils/son/ecouteurs/EcouteurSon.java create mode 100644 src/outils/son/exceptions/SonErreurDiverse.java create mode 100644 src/outils/son/exceptions/SonErreurLecture.java create mode 100644 src/outils/son/exceptions/SonException.java create mode 100644 src/outils/son/exceptions/SonIntrouvableException.java create mode 100644 src/outils/son/exceptions/SonTypeException.java diff --git a/src/Joueur.java b/src/Joueur.java index fb3e733..c1ad0b7 100644 --- a/src/Joueur.java +++ b/src/Joueur.java @@ -38,6 +38,10 @@ public class Joueur extends Objet { */ private Boule boule ; + private int vie; + + private int orientation; + /** * Constructeur */ @@ -94,6 +98,11 @@ public class Joueur extends Objet { public void perteVie() { } + + private Boolean toucheMur() { + return null; + } + /** * vrai si la vie est à 0 * @return true si vie = 0 diff --git a/src/modele/Boule.java b/src/modele/Boule.java new file mode 100644 index 0000000..cec3fa5 --- /dev/null +++ b/src/modele/Boule.java @@ -0,0 +1,25 @@ +package modele; +/** + * Gestion de la boule + * + */ +public class Boule extends Objet { + + /** + * instance de JeuServeur pour la communication + */ + private JeuServeur jeuServeur ; + + /** + * Constructeur + */ + public Boule() { + } + + /** + * Tire d'une boule + */ + public void tireBoule() { + } + +} diff --git a/src/modele/Jeu.java b/src/modele/Jeu.java new file mode 100644 index 0000000..f006c1f --- /dev/null +++ b/src/modele/Jeu.java @@ -0,0 +1,29 @@ +package modele; +/** + * Informations et méthodes communes aux jeux client et serveur + * + */ +public abstract class Jeu { + + /** + * Réception d'une connexion (pour communiquer avec un ordinateur distant) + */ + public abstract void connexion() ; + + /** + * Réception d'une information provenant de l'ordinateur distant + */ + public abstract void reception() ; + + /** + * Déconnexion de l'ordinateur distant + */ + public abstract void deconnexion() ; + + /** + * Envoi d'une information vers un ordinateur distant + */ + public void envoi() { + } + +} diff --git a/src/modele/JeuClient.java b/src/modele/JeuClient.java new file mode 100644 index 0000000..ad95b49 --- /dev/null +++ b/src/modele/JeuClient.java @@ -0,0 +1,33 @@ +package modele; +/** + * Gestion du jeu côté client + * + */ +public class JeuClient extends Jeu { + + /** + * Controleur + */ + public JeuClient() { + } + + @Override + public void connexion() { + } + + @Override + public void reception() { + } + + @Override + public void deconnexion() { + } + + /** + * Envoi d'une information vers le serveur + * fais appel une fois à l'envoi dans la classe Jeu + */ + public void envoi() { + } + +} diff --git a/src/modele/JeuServeur.java b/src/modele/JeuServeur.java new file mode 100644 index 0000000..9f1dcaf --- /dev/null +++ b/src/modele/JeuServeur.java @@ -0,0 +1,50 @@ +package modele; +import java.util.ArrayList; + +/** + * Gestion du jeu côté serveur + * + */ +public class JeuServeur extends Jeu { + + /** + * Collection de murs + */ + private ArrayList lesMurs = new ArrayList() ; + /** + * Collection de joueurs + */ + private ArrayList lesJoueurs = new ArrayList() ; + + /** + * Constructeur + */ + public JeuServeur() { + } + + @Override + public void connexion() { + } + + @Override + public void reception() { + } + + @Override + public void deconnexion() { + } + + /** + * Envoi d'une information vers tous les clients + * fais appel plusieurs fois à l'envoi de la classe Jeu + */ + public void envoi() { + } + + /** + * Génération des murs + */ + public void constructionMurs() { + } + +} diff --git a/src/modele/Joueur.java b/src/modele/Joueur.java new file mode 100644 index 0000000..2398473 --- /dev/null +++ b/src/modele/Joueur.java @@ -0,0 +1,128 @@ +package modele; +/** + * Gestion des joueurs + * + */ +public class Joueur extends Objet { + + /** + * vie de départ pour tous les joueurs + */ + private static final int MAXVIE = 10 ; + /** + * gain de points de vie lors d'une attaque + */ + private static final int GAIN = 1 ; + /** + * perte de points de vie lors d'une attaque + */ + private static final int PERTE = 2 ; + + /** + * pseudo saisi + */ + private String pseudo ; + /** + * n° correspondant au personnage (avatar) pour le fichier correspondant + */ + private int numPerso ; + /** + * instance de JeuServeur pour communiquer avec lui + */ + private JeuServeur jeuServeur ; + /** + * numéro d'�tape dans l'animation (de la marche, touché ou mort) + */ + private int etape ; + /** + * la boule du joueur + */ + private Boule boule ; + /** + * vie restante du joueur + */ + private int vie ; + /** + * tourné vers la gauche (0) ou vers la droite (1) + */ + private int orientation ; + + /** + * Constructeur + */ + public Joueur() { + } + + /** + * Initialisation d'un joueur (pseudo et numéro, calcul de la 1ère position, affichage, création de la boule) + */ + public void initPerso() { + } + + /** + * Calcul de la première position aléatoire du joueur (sans chevaucher un autre joueur ou un mur) + */ + private void premierePosition() { + } + + /** + * Affiche le personnage et son message + */ + public void affiche() { + } + + /** + * Gère une action reçue et qu'il faut afficher (déplacement, tire de boule...) + */ + public void action() { + } + + /** + * Gère le déplacement du personnage + */ + private void deplace() { + } + + /** + * Contrôle si le joueur touche un des autres joueurs + * @return true si deux joueurs se touchent + */ + private Boolean toucheJoueur() { + return null; + } + + /** + * Gain de points de vie après avoir touché un joueur + */ + public void gainVie() { + } + + /** + * Perte de points de vie après avoir été touché + */ + public void perteVie() { + } + + /** + * Contrôle si le joueur touche un des murs + * @return true si un joueur touche un mur + */ + private Boolean toucheMur() { + return null; + } + + /** + * vrai si la vie est à 0 + * @return true si vie = 0 + */ + public Boolean estMort() { + return null; + } + + /** + * Le joueur se déconnecte et disparait + */ + public void departJoueur() { + } + +} diff --git a/src/modele/Mur.java b/src/modele/Mur.java new file mode 100644 index 0000000..83e3311 --- /dev/null +++ b/src/modele/Mur.java @@ -0,0 +1,14 @@ +package modele; +/** + * Gestion des murs + * + */ +public class Mur extends Objet { + + /** + * Constructeur + */ + public Mur() { + } + +} diff --git a/src/modele/Objet.java b/src/modele/Objet.java new file mode 100644 index 0000000..9efa6a9 --- /dev/null +++ b/src/modele/Objet.java @@ -0,0 +1,27 @@ +package modele; +/** + * Informations communes � tous les objets (joueurs, murs, boules) + * permet de m�moriser la position de l'objet et de g�rer les collisions + * + */ +public abstract class Objet { + + /** + * position X de l'objet + */ + protected Integer posX ; + /** + * position Y de l'objet + */ + protected Integer posY ; + + /** + * contr�le si l'objet actuel touche l'objet pass� en param�tre + * @param objet contient l'objet � contr�ler + * @return true si les 2 objets se touchent + */ + public Boolean toucheObjet (Objet objet) { + return null; + } + +} diff --git a/src/outils/connexion/AsyncResponse.java b/src/outils/connexion/AsyncResponse.java new file mode 100644 index 0000000..3ff431f --- /dev/null +++ b/src/outils/connexion/AsyncResponse.java @@ -0,0 +1,16 @@ +package outils.connexion; + +/** + * Permet la récupération asynchrone d'une réponse + * @author emds + * + */ +public interface AsyncResponse { + /** + * Méthode à redéfinir pour récupérer la réponse de l'ordinateur distant + * @param connection contient l'objet qui permet de recontacter l'ordinateur distant (pour un envoi) + * @param ordre contient "connexion" si nouvelle connexion, "reception" si nvelle information reçue, "deconnexion" si déconnexion + * @param info contient l'information reçue (si ordre = "réception") + */ + void reception(Connection connection, String ordre, Object info); +} diff --git a/src/outils/connexion/ClientSocket.java b/src/outils/connexion/ClientSocket.java new file mode 100644 index 0000000..2967fbc --- /dev/null +++ b/src/outils/connexion/ClientSocket.java @@ -0,0 +1,38 @@ +package outils.connexion; + +import java.io.IOException; +import java.net.Socket; +import java.net.UnknownHostException; + +import javax.swing.JOptionPane; + +/** + * Gestion d'un client : création d'une connexion cliente + * @author emds + * + */ +public class ClientSocket { + + /** + * Constructeur : crée le socket de type client pour se connecter à un serveur (avec son ip et port d'écoute) + * @param delegate instance de la classe vers laquelle il faut transférer les réponses + * @param ip adresse IP du serveur + * @param port numéro port d'écoute du serveur + */ + public ClientSocket (AsyncResponse delegate, String ip, int port) { + try { + Socket socket = new Socket(ip, port); + System.out.println("connexion serveur réussie"); + // la connexion ne peut se faire que si un objet delegate existe (pour récupérer la réponse) + if(delegate != null) { + // création d'une connexion pour ce client, pour la communication avec le serveur (envoi et réception d'informations) + new Connection(socket, delegate) ; + } + } catch (UnknownHostException e) { + JOptionPane.showMessageDialog(null, "serveur non disponible"); + } catch (IOException e) { + JOptionPane.showMessageDialog(null, "IP incorrecte"); + } + } + +} diff --git a/src/outils/connexion/Connection.java b/src/outils/connexion/Connection.java new file mode 100644 index 0000000..9976c71 --- /dev/null +++ b/src/outils/connexion/Connection.java @@ -0,0 +1,109 @@ +package outils.connexion; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.net.Socket; + +/** + * Gestion de la connexion entre 2 ordinateurs distants + * @author emds + * + */ +public class Connection extends Thread { + + /** + * canal d'entrée + */ + private ObjectInputStream in ; + /** + * canal de sortie + */ + private ObjectOutputStream out ; + /** + * objet de lien avec une autre classe qui implémente AsyncResponse pour transférer les réponses + */ + private AsyncResponse delegate; + + /** + * Constructeur : crée une connexion à partir d'un socket (contenant les spécificités de l'ordinateur distant) + * @param socket objet de connexion de type serveur ou client + * @param delegate instance de la classe vers laquelle il faut transférer les réponses + */ + public Connection(Socket socket, AsyncResponse delegate) { + this.delegate = delegate; + // création du canal de sortie pour envoyer des informations + try { + this.out = new ObjectOutputStream(socket.getOutputStream()) ; + } catch (IOException e) { + System.out.println("erreur création canal out : "+e); + System.exit(0); + } + // création du canal d'entrée pour recevoir des informations + try { + this.in = new ObjectInputStream(socket.getInputStream()) ; + } catch (IOException e) { + System.out.println("erreur création canal in : "+e); + System.exit(0); + } + // démarrage du thread d'écoute (attente d'un message de l'ordi distant) + this.start() ; + // envoi de l'instance de connexion vers la classe qui implémente AsyncResponse pour récupérer la réponse + this.delegate.reception(this, "connexion", null); + } + + /** + * Envoi d'un objet vers l'ordinateur distant, sur le canal de sortie + * @param unObjet contieny l'objet à envoyer + */ + public synchronized void envoi(Object unObjet) { + // l'envoi ne peut se faire que si un objet delegate existe (pour récupérer la réponse) + if(delegate != null) { + try { + this.out.reset(); + out.writeObject(unObjet); + out.flush(); + } catch (IOException e) { + System.out.println("erreur d'envoi sur le canal out : "+e); + } + } + } + + /** + * Méthode thread qui permet d'attendre des messages provenant de l'ordi distant + */ + public void run() { + // permet de savoir s'il faut continuer à écouter + boolean inOk = true ; + // objet qui va récupérer l'information reçue + Object reception ; + // boucle tant qu'il faut écouter + while (inOk) { + try { + // réception d'un objet sur le canal d'entrée + reception = in.readObject(); + // envoi de l'information reçue vers la classe qui implémente AsyncResponse pour récupérer la réponse + delegate.reception(this, "reception", reception); + } catch (ClassNotFoundException e) { + // problème grave qui ne devrait pas se produire : arrêt du programme + System.out.println("erreur de classe sur réception : "+e); + System.exit(0); + } catch (IOException e) { + // envoi de l'information de déconnexion vers la classe qui implémente AsyncResponse pour récupérer la réponse + delegate.reception(this, "deconnexion", null); + // demande d'arrêter de boucler sur l'attente d'une réponse + inOk = false ; + // l'ordinateur distant n'est plus accessible + System.out.println("l'ordinateur distant est déconnecté"); + // fermeture du canal d'entrée + try { + in.close(); + } catch (IOException e1) { + System.out.println("la fermeture du canal d'entrée a échoué : "+e); + } + } + } + + } + +} diff --git a/src/outils/connexion/ServeurSocket.java b/src/outils/connexion/ServeurSocket.java new file mode 100644 index 0000000..5358b93 --- /dev/null +++ b/src/outils/connexion/ServeurSocket.java @@ -0,0 +1,67 @@ +package outils.connexion; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; + +/** + * Gestion d'un serveur : création d'une connexion de type serveur pour attendre les connexions de clients + * @author emds + * + */ +public class ServeurSocket extends Thread { + + /** + * objet pour une connexion de type serveur (pour attendre des connexions de clients) + */ + private ServerSocket serverSocket ; + /** + * objet de lien avec une autre classe qui implémente AsyncResponse pour transférer les réponses + */ + private AsyncResponse delegate=null; + + /** + * Constructeur + * @param delegate instance de la classe vers laquelle il faut transférer les réponses + * @param port numéro port d'écoute du serveur + */ + public ServeurSocket(AsyncResponse delegate, int port) { + // création du socket serveur d'écoute des clients + try { + this.delegate = delegate; + this.serverSocket = new ServerSocket(port); + // le démarrage de l'écoute ne peut se faire que si un objet delegate existe (pour récupérer la réponse) + if(delegate != null) { + this.start(); + } + } catch (IOException e) { + // probl�me grave qui ne devrait pas se produire : arr�t du programme + System.out.println("erreur grave cr�ation socket serveur : "+e); + System.exit(0); + } + } + + /** + * M�thode thread qui va attendre la connexion d'un client + */ + public void run() { + // objet qui va r�cup�rer le socket du client qui s'est connect� + Socket socket ; + // boucle infinie pour attendre un nouveau client + while (true) { + try { + // attente d'une connexion + System.out.println("le serveur attend"); + socket = serverSocket.accept(); + System.out.println("un client s'est connect�"); + // cr�ation d'une connexion vers ce client, pour la communication (envoi et r�ception d'informations) + new Connection(socket, delegate); + } catch (IOException e) { + // probl�me grave qui ne devrait pas se produire : arr�t du programme + System.out.println("erreur sur l'objet serverSocket : "+e); + System.exit(0); + } + } + } + +} diff --git a/src/outils/son/Duree.java b/src/outils/son/Duree.java new file mode 100644 index 0000000..7c02a0b --- /dev/null +++ b/src/outils/son/Duree.java @@ -0,0 +1,121 @@ +package outils.son; + +import java.io.Serializable; + +/** + * Représente une durée + */ + +public class Duree implements Serializable +{ + private long microsecondes; + private int heure, minute, seconde, microseconde; + public Duree() + { + } + public Duree(long microsecondes) + { + this.microsecondes = microsecondes; + long temps = this.microsecondes; + this.microseconde = (int)(temps % 1000000L); + temps = temps / 1000000L; + this.seconde = (int)(temps % 60L); + temps = temps / 60L; + this.minute = (int)(temps % 60L); + temps = temps / 60L; + this.heure = (int)temps; + } + public Duree(int microseconde) + { + if(microseconde < 0) + { + throw new IllegalArgumentException( + "Le nombre de microsecondes ne peut pas être négative"); + } + if(microseconde > 999999) + { + throw new IllegalArgumentException("Le nombre de microsecondes ne peut pas être plus de 999999, sinon on a des secondes"); + } + this.microseconde = microseconde; + this.microsecondes = (long)this.microseconde; + } + public Duree(int seconde, int microseconde) + { + this(microseconde); + if(seconde < 0) + { + throw new IllegalArgumentException( + "Le nombre de secondes ne peut pas être négative"); + } + if(seconde > 59) + { + throw new IllegalArgumentException( + "Le nombre de secondes ne peut pas être plus de 59, sinon on a des minutes"); + } + this.seconde = seconde; + this.microsecondes += 1000000L * (long)this.seconde; + } + public Duree(int minute, int seconde, int microseconde) + { + this(seconde, microseconde); + if(minute < 0) + { + throw new IllegalArgumentException( + "Le nombre de minutes ne peut pas être négative"); + } + if(minute > 59) + { + throw new IllegalArgumentException( + "Le nombre minutes ne peut pas être plus de 59, sinon on a des heures"); + } + this.minute = minute; + this.microsecondes += 60L * 1000000L * (long)this.minute; + } + public Duree(int heure, int minute, int seconde, int microseconde) + { + this(minute, seconde, microseconde); + if(heure < 0) + { + throw new IllegalArgumentException( + "Le nombre d'heure ne peut pas être négative"); + } + this.heure = heure; + this.microsecondes += 60L * 60L * 1000000L * (long)this.heure; + } + public Duree(Duree duree) + { + this.microsecondes = duree.microsecondes; + this.microseconde = duree.microseconde; + this.seconde = duree.seconde; + this.minute = duree.minute; + this.heure = duree.heure; + } + public long enMicrosecondes() + { + return this.microsecondes; + } + public long enMillisecondes() + { + return this.microsecondes / 1000L; + } + public int getMicroseconde() + { + return this.microseconde; + } + public int getMilliseconde() + { + return this.microseconde / 1000; + } + public int getSeconde() + { + return this.seconde; + } + public int getMinute() + { + return this.minute; + } + public int getHeure() + { + return this.heure; + } +} diff --git a/src/outils/son/Son.java b/src/outils/son/Son.java new file mode 100644 index 0000000..0f461e8 --- /dev/null +++ b/src/outils/son/Son.java @@ -0,0 +1,55 @@ +package outils.son; + +import java.io.File; +import outils.son.exceptions.*; +import java.io.Serializable; +import java.net.URL; + +/** + * Gestion des sons + * + * @author non attribuable + * @version 1.0 + */ + +public class Son implements Serializable { + + /** + * son qui peut être joué + */ + private Sound sound ; + + /** + * Création d'un objet de type Sound, à partir d'un fichier de son + * @param nomfic url du fichier + */ + public Son (URL nomfic) { + try { +// this.sound = new Sound(new File(nomfic)); + this.sound = new Sound(nomfic); + } catch (SonException ex) { + } + } + + /** + * Joue le son une fois + */ + public void play() { + this.sound.boucle(1) ; + } + + /** + * ferme le son (libère l'objet de la mémoire) + */ + public void close() { + this.sound.fermer(); + } + + /** + * Joue le son en boucle (musique de fond) + */ + public void playContinue () { + sound.boucle() ; + } + +} diff --git a/src/outils/son/Sound.java b/src/outils/son/Sound.java new file mode 100644 index 0000000..f149d43 --- /dev/null +++ b/src/outils/son/Sound.java @@ -0,0 +1,503 @@ +package outils.son; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Vector; +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.UnsupportedAudioFileException; +import java.io.Serializable; + +import outils.son.ecouteurs.EcouteurSon; +import outils.son.exceptions.SonErreurDiverse; +import outils.son.exceptions.SonErreurLecture; +import outils.son.exceptions.SonException; +import outils.son.exceptions.SonIntrouvableException; +import outils.son.exceptions.SonTypeException; + +/** + * Représente un son.
+ * Les sons les mieux suppoter par Java sont MIDI, AU et certains WAV.
+ * Pour savoir si un son est accèpté, le seul moyen est d'essayer.
+ * Si le son ne sera plus utilisé, il faut le détruire par la méthode fermer,
+ * afin de libérer la mémoire et le flux où se trouve le son.
+ * Attention, une fois détruit, le son n'est plus utilisable.
+ */ + +public class Sound + implements Serializable, Runnable +{ + //Durée du son + private Duree duree; + //Flux de kecture audio + private AudioInputStream lecteurAudio; + //Format du fichier audio + private AudioFileFormat formatFichier; + //Format du son + private AudioFormat format; + //Clip jouant le son + private Clip clip; + //Thread permettant de jouer le son en tâche de fond + private Thread thread; + //Nombre de boucle restante à effectué + private int tour; + //pause : inqique si le son est en pause ou non + //fermerALaFin : indique si le son doit être détruit une fois la derniére boucle de son exécutée + private boolean pause, fermerALaFin; + //Ecouteurs des événement sons + private Vector ecouteurs = new Vector(); + /** + * Construit un son situé à une URL précise + * @param url URL du son + * @throws SonException Si il y a un probléme de construction du son + */ + public Sound(URL url) + throws SonException + { + this.initialise(url); + } + /** + * Construit un son à partir d'un fichier + * @param fichier Fichier contenant le son + * @throws SonException Si il y a un problème de construction du son + */ + public Sound(File fichier) + throws SonException + { + if(!fichier.exists()) + { + throw new SonIntrouvableException(fichier); + } + this.initialise(fichier); + } + //Initialise le son + private void initialise(File fichier) + throws SonException + { + try + { + //Crée le flux + this.lecteurAudio = AudioSystem.getAudioInputStream(fichier); + //Récupére le format du fichier son + this.formatFichier = AudioSystem.getAudioFileFormat(fichier); + //Récupére le format de codage du son + this.format = lecteurAudio.getFormat(); + + //On ne peut pas ouvrir directement des format ALAW/ULA, il faut les convertir en PCM + if((this.format.getEncoding() == AudioFormat.Encoding.ULAW) || + (this.format.getEncoding() == AudioFormat.Encoding.ALAW)) + { + //convertion du format + AudioFormat tmp = new AudioFormat( + AudioFormat.Encoding.PCM_SIGNED, + this.format.getSampleRate(), + this.format.getSampleSizeInBits() * 2, + this.format.getChannels(), + this.format.getFrameSize() * 2, + this.format.getFrameRate(), + true); + //convertion du flux + this.lecteurAudio = AudioSystem.getAudioInputStream(tmp, + this.lecteurAudio); + //On a convertit le format, si bien qu'il change + this.format = tmp; + } + //On crée une information avec le format du flux et en caculant la logueneur totale du son + DataLine.Info info = new DataLine.Info( + Clip.class, + this.lecteurAudio.getFormat(), + ((int)this.lecteurAudio.getFrameLength() * + this.format.getFrameSize())); + //Grac à cette information, on peut creer un clip + this.clip = (Clip)AudioSystem.getLine(info); + //On ouvre le son + reouvrir(); + } + catch(UnsupportedAudioFileException uafe) + { + throw new SonTypeException(); + } + catch(IOException ioe) + { + throw new SonErreurLecture(); + } + catch(Exception e) + { + throw new SonErreurDiverse(e); + } + + //On calcul la durée du son en microseconde + this.duree = new Duree(this.longueurSonMicroseconde()); + } + private void initialise(URL url) + throws SonException + { + try + { + //Crée le flux + this.lecteurAudio = AudioSystem.getAudioInputStream(url); + //Récupére le format du fichier son + this.formatFichier = AudioSystem.getAudioFileFormat(url); + //Récupére le format de codage du son + this.format = lecteurAudio.getFormat(); + + //On ne peut pas ouvrir directement des format ALAW/ULA, il faut les convertir en PCM + if((this.format.getEncoding() == AudioFormat.Encoding.ULAW) || + (this.format.getEncoding() == AudioFormat.Encoding.ALAW)) + { + //convertion du format + AudioFormat tmp = new AudioFormat( + AudioFormat.Encoding.PCM_SIGNED, + this.format.getSampleRate(), + this.format.getSampleSizeInBits() * 2, + this.format.getChannels(), + this.format.getFrameSize() * 2, + this.format.getFrameRate(), + true); + //convertion du flux + this.lecteurAudio = AudioSystem.getAudioInputStream(tmp, + this.lecteurAudio); + //On a convertit le format, si bien qu'il change + this.format = tmp; + } + //On crée une information avec le format du flux et en caculant la logueneur totale du son + DataLine.Info info = new DataLine.Info( + Clip.class, + this.lecteurAudio.getFormat(), + ((int)this.lecteurAudio.getFrameLength() * + this.format.getFrameSize())); + //Grac à cette information, on peut creer un clip + this.clip = (Clip)AudioSystem.getLine(info); + //On ouvre le son + reouvrir(); + } + catch(UnsupportedAudioFileException uafe) + { + throw new SonTypeException(); + } + catch(IOException ioe) + { + throw new SonErreurLecture(); + } + catch(Exception e) + { + throw new SonErreurDiverse(e); + } + + //On calcul la durée du son en microseconde + this.duree = new Duree(this.longueurSonMicroseconde()); + } + /** + * Joue le son une fois + */ + public void jouer() + { + //Si le son n'est pas initialiser, on l'initialise + if(this.thread == null) + { + this.thread = new Thread(this); + this.thread.start(); + } + //On va le jouer une fois + this.tour = 1; + } + /** + * Joue le son plusieurs fois + * @param nbFois Nombre de fois que le son est joué + */ + public void boucle(int nbFois) + { + //Si le son n'est pas initialiser, on l'initialise + if(this.thread == null) + { + this.thread = new Thread(this); + this.thread.start(); + } + //On va le jouer nbFois fois + this.tour = nbFois; + } + /** + * Joue le son un tn trés grand nombre de fois + */ + public void boucle() + { + this.boucle(Integer.MAX_VALUE); + } + /** + * Action du son, ne jamais appelé cette méthode directement, elle est public pour respecter l'implémentation de Runnable + */ + public void run() + { + //Tant que le son est vivant + while(this.thread != null) + { + //Pause de 0.123 seconde + try + { + this.thread.sleep(123); + } + catch(Exception e) + {} + //Si on doit jouer le son au moins une fois + if(this.tour > 0) + { + //On lance le son + this.clip.start(); + //pause de 0.099 seconde (le son est jouer pendant ce temps) + try + { + this.thread.sleep(99); + } + catch(Exception e) + {} + //Tant que le son n'est pas terminer ou que l'on soit en pause et est vivant + while((this.clip.isActive() || this.pause) && (this.thread != null)) + { + //Si on est pas en pause, on avance sur le son + if(!this.pause) + { + this.avancer(); + } + //Pause de 0.099 seconde + try + { + this.thread.sleep(99); + } + catch(Exception e) + { + break; + } + } + //Arréte le son + this.clip.stop(); + //On se place au début du son + this.placeMicroseconde(0); + //On à un tour de moins à jouer + this.tour--; + if(this.tour < 1) + { + //Si on a fini de jouer, on tremine + this.terminer(); + //Si on doit fermer à la fin, on ferme définitivement le son + if(this.fermerALaFin) + { + this.fermer(); + } + } + } + } + } + //Permet de réouvrir le son, ou de l'ouvrir + private void reouvrir() + throws Exception + { + this.clip.open(this.lecteurAudio); + } + /** + * Met le son en pause + */ + public void pause() + { + //Si on est pas déjà en pause, on se met en pause + if(!this.pause) + { + this.clip.stop(); + this.pause = true; + } + } + /** + * Reprend le son ou il était rendu (enlève la pause) + */ + public void reprise() + { + //Si on est en pause, on enléve la pause + if(this.pause) + { + pause = false; + this.clip.start(); + } + } + /** + * Arrête de jouer le son et retour du son au début + */ + public void stop() + { + this.clip.stop(); + this.placeMicroseconde(0); + this.pause = false; + this.tour = 0; + this.thread = null; + } + /** + * Détruit proprement le son + */ + public void fermer() + { + this.stop(); + this.clip.close(); + this.clip = null; + this.duree = null; + this.ecouteurs.clear(); + this.ecouteurs = null; + this.format = null; + this.formatFichier = null; + } + /** + * Indique si le son sera détruit aprés sa derniére fois ou il joue + * @return true si le son est détruit quand c'est finit + */ + public boolean estFermerALaFin() + { + return fermerALaFin; + } + /** + * Change l'état de fermeture à la fin + * @param fermer true pour indiqué que l'on désire que le son soit détruit aprés la derniére fois qu'il joue + */ + public void setFermerALaFin(boolean fermer) + { + this.fermerALaFin = fermer; + } + /** + * Longeur du son en microseconde + * @return Longueur du son + */ + public long longueurSonMicroseconde() + { + return this.clip.getMicrosecondLength(); + } + /** + * Nombre de microsecondes écoulées depuis le début du son + * @return Durée en microseconde de l'écoute + */ + public long getRenduMicroseconde() + { + return this.clip.getMicrosecondPosition(); + } + /** + * Durée de l'écoute + * @return Durée de l'écoute + */ + public Duree getRendu() + { + return new Duree(this.getRenduMicroseconde()); + } + /** + * Place le son à cette durée en milliseconde. + * @param microseconde Place à laquelle on désire commencé le son + */ + public void placeMicroseconde(long microseconde) + { + this.clip.setMicrosecondPosition(microseconde); + } + /** + * Place le son à cette durée + * @param duree Place à laquelle on désire commencé le son + */ + public void placeDuree(Duree duree) + { + this.placeMicroseconde(duree.getMicroseconde()); + } + /** + * Remet le son au départ + */ + public void placeDepart() + { + this.clip.setMicrosecondPosition(0); + } + /** + * Indique si le son est en pause + * @return true si le son est en pause + */ + public boolean estEnPause() + { + return this.pause; + } + /** + * Indique si le son est entrain d'être jouer + * @return true si le son est entrain d'être joué + */ + public boolean estEntrainDeJouer() + { + return!this.pause && (this.tour > 0); + } + /** + * Ajout un écouteur d'événement son + * @param ecouteur Ecouteur ajouté + */ + public void ajouteEcouteurSon(EcouteurSon ecouteur) + { + if(ecouteur != null) + { + this.ecouteurs.addElement(ecouteur); + } + } + /** + * Retire un écouteur d'événement son + * @param ecouteur Ecouteur retiré + */ + public void retireEcouteurSon(EcouteurSon ecouteur) + { + if(ecouteur != null) + { + this.ecouteurs.removeElement(ecouteur); + } + } + //Indique à tout les écouteurs d'événements son, que le son est terminé + private void terminer() + { + Thread t = new Thread() + { + public void run() + { + Sound.this.terminer1(); + } + }; + t.start(); + } + //Indique à tout les écouteurs d'événements son, que le son est terminé + private void terminer1() + { + int nb = this.ecouteurs.size(); + for(int i = 0; i < nb; i++) + { + EcouteurSon ecouteur = (EcouteurSon)this.ecouteurs.elementAt(i); + ecouteur.sonTermine(this); + } + } + //Indique à tout les écouteurs d'événements son, que le son a avancé + private void avancer() + { + Thread t = new Thread() + { + public void run() + { + Sound.this.avancer1(); + } + }; + t.start(); + } + //Indique à tout les écouteurs d'événements son, que le son a avancé + private void avancer1() + { + int nb = this.ecouteurs.size(); + for(int i = 0; i < nb; i++) + { + EcouteurSon ecouteur = (EcouteurSon)this.ecouteurs.elementAt(i); + ecouteur.sonChangePosition(this); + } + } + /** + * Renvoie la durée du son + * @return La durée du son + */ + public Duree getDuree() + { + return this.duree; + } +} diff --git a/src/outils/son/ecouteurs/EcouteurSon.java b/src/outils/son/ecouteurs/EcouteurSon.java new file mode 100644 index 0000000..61582d6 --- /dev/null +++ b/src/outils/son/ecouteurs/EcouteurSon.java @@ -0,0 +1,21 @@ +package outils.son.ecouteurs; + +import outils.son.Sound; + +/** + * Indique que l'objet écoute les événements sons
+ */ + +public interface EcouteurSon +{ + /** + * Indique qu'un son est terminé + * @param son Son qui a finit de joué + */ + public void sonTermine(Sound son); + /** + * Indique qu'un son vient d'avancer sur sa lecture + * @param son Son qui est entrain d'avancer + */ + public void sonChangePosition(Sound son); +} diff --git a/src/outils/son/exceptions/SonErreurDiverse.java b/src/outils/son/exceptions/SonErreurDiverse.java new file mode 100644 index 0000000..f71df55 --- /dev/null +++ b/src/outils/son/exceptions/SonErreurDiverse.java @@ -0,0 +1,21 @@ +package outils.son.exceptions; + +import java.io.Serializable; + +/** + * Exception levée pour signale un manque de droit, un flux coupé en cours de routez, une erreur ...
+ */ + +public class SonErreurDiverse + extends SonException implements Serializable +{ + /** + * Construit l'exception + * @param e Exception générée à la construction du son + */ + public SonErreurDiverse(Exception e) + { + super("Une erreur s'est produite lors de l'analyse du son : " + + e.getMessage()); + } +} diff --git a/src/outils/son/exceptions/SonErreurLecture.java b/src/outils/son/exceptions/SonErreurLecture.java new file mode 100644 index 0000000..b6fb95a --- /dev/null +++ b/src/outils/son/exceptions/SonErreurLecture.java @@ -0,0 +1,20 @@ +package outils.son.exceptions; + +import java.io.Serializable; + +/** + * Exception levée pour signaler une erreur de lecture du son
+ */ + +public class SonErreurLecture + extends SonException implements Serializable +{ + /** + * Construit l'exception + */ + public SonErreurLecture() + { + super("Erreur lors de la lecture du son"); + } + +} diff --git a/src/outils/son/exceptions/SonException.java b/src/outils/son/exceptions/SonException.java new file mode 100644 index 0000000..ab34958 --- /dev/null +++ b/src/outils/son/exceptions/SonException.java @@ -0,0 +1,20 @@ +package outils.son.exceptions; + +import java.io.Serializable; + +/** + * Excpetion générale
+ */ + +public class SonException + extends Exception implements Serializable +{ + /** + * Construit l'exception + * @param message Message de l'exception + */ + public SonException(String message) + { + super(message); + } +} diff --git a/src/outils/son/exceptions/SonIntrouvableException.java b/src/outils/son/exceptions/SonIntrouvableException.java new file mode 100644 index 0000000..9901832 --- /dev/null +++ b/src/outils/son/exceptions/SonIntrouvableException.java @@ -0,0 +1,38 @@ +package outils.son.exceptions; + +import java.io.File; +import java.net.URL; +import java.io.Serializable; + +/** + * Exception levée pour indiquer que le son n'a pas été trouvé
+ */ + +public class SonIntrouvableException + extends SonException implements Serializable +{ + /** + * Constrtuit l'exception pour les fichiers + * @param fichier Fichier non trouvé + */ + public SonIntrouvableException(File fichier) + { + super("Le fichier " + fichier.getAbsolutePath() + " est introuvable"); + } + /** + * Construit l'exception pour les URL + * @param url URL non trouvée + */ + public SonIntrouvableException(URL url) + { + super("L'URL : " + url.getFile() + " est introuvable"); + } + /** + * Construit l'exception pour les sons de la ressource + * @param nom Nom de la ressource non trouvée + */ + public SonIntrouvableException(String nom) + { + super("Le son : " + nom + " est introuvable"); + } +} diff --git a/src/outils/son/exceptions/SonTypeException.java b/src/outils/son/exceptions/SonTypeException.java new file mode 100644 index 0000000..cc2a57e --- /dev/null +++ b/src/outils/son/exceptions/SonTypeException.java @@ -0,0 +1,20 @@ +package outils.son.exceptions; + +import java.io.Serializable; + +/** + * Exception levée si le type de son n'est pas reconnu
+ */ + +public class SonTypeException + extends SonException implements Serializable +{ + /** + * Construit l'exception + */ + public SonTypeException() + { + super("Le type du son n'est pas reconnu"); + } + +}