/*********************************
 * TvOnResel 0.1a
 * La classe principale TvOnResel
 * repr�sente la fen�tre principale
 *********************************/

import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.util.regex.*;
import java.net.*;

public class TvOnResel extends JFrame
{   
                
        /*Composants de l'interface*/
        
        //repr�sente l'objet TvOnResel ( = this )
        JFrame frameComplete;
        
        //onglets
        JTabbedPane onglets;
        
        //Onglet principal
        JButton regarder;
        JButton enregistrer;
        JButton programmer;
        JLabel labelEnCours;
        JList listeAff;
        
        //onglet enregistrements
        JButton arrEnr;
        JButton lireEnr;
        JButton progFinEnr;
        JList listeAffEnr;
        
        //onglet programmations
        JButton nouvProg;
        JButton arretEnrProg;
        JButton supprProg;
        JList listeAffProg;
        
        //onglet fichiers
        JButton lireFic;
        JButton supprFic;
        JButton majListeFic;
        JList listeAffFic;
        
        //onglet options
        JButton enrOptions;
        JButton majListeChaines;
        JTextField champChmVlc;
        JTextField champChmEnregistrements;
                
        /* Configuration en "dur" */
        public final static String versionLog = "0.1a";
        public final static String nomLog = "TvOnResel";
        public final static String nomFicOptions = "config.txt";
        final String sepDoss = System.getProperty( "file.separator" );
        final Dimension tailleFen = new Dimension( 600, 350 );
        
        /* variables de fonctionnement */
        
        //les listes � l'affichage sont-elles initialis�es ?
        boolean listeAffEnrOk = false;
        boolean listeAffFicOk = false;
        boolean listeAffProgOk = false;
        
        //repr�sente la liste des chaines
        Vector listeChaines = new Vector();
        
        //repr�sente la lecture en cours (thread)
        LectureEnCours lectureEnCours = new LectureEnCours();
        
        //repr�sente les enregistrements en cours (vecteur de threads)
        Vector enrEnCours = new Vector();
        
        //repr�sente les programmations en cours (vecteur de threads)*/
        Vector listeProgrammes = new Vector();
        
        //repr�sente la liste des fichiers
        Vector listeFic = new Vector();
        
        /* Confguration du fichier de config */
        
        //fichier liste des chaines
        String nomFicChaines;
        
        //fichier liste des programmations
        String nomFicProgrammations = "programmations.xml";
        
        //chemin vers VLC
        String chmVlc;
        
        //chemin ou enregistrer les enregistrements
        String chmEnregistrements;
        
        //url de la liste des chaines distante
        String urlListeChaines;
        
        //extention des enregistrements
        String extVideo = ".mpg";
        
        //premier d�marrage ?
        boolean premierDemarrage;
        
/*********************************************
 *Cr�ation de l'interface
 *et initialiation
 *********************************************/

/* initialisation */
        
        //proc�dure d'initialisation
        public static void main(String[] args)
        {                
                                
                //Affichage du d�marrage
                System.out.println( nomLog + " " + versionLog );
                
                //Cr�ation de l'objet fen�tre principale
                new TvOnResel();
        }
        
        //Constructeur de la fen�tre principale
        TvOnResel()
        {
                
                //Cr�ation de la fen�tre
                super( nomLog + " " + versionLog );
                
                frameComplete = this;
                
                //R�cup�ration des options
                lireOptions();
                
                //Evenement de fermeture
                WindowListener fermeture = new WindowAdapter()
                {
                        public void windowClosing(WindowEvent e)
                        {
                                sortir();
                        }
                };
                addWindowListener( fermeture );
                                
                //Lecture de la liste de lecture
                lireListeChaines();
                            
                //Cr�ation de l'onglet principal
                JPanel panelPrincipal = fairePanelPrincipal();
                
                //Cr�ation de l'onglet options
                JPanel panelOptions = fairePanelOptions();
                
                //Cr�ation de l'onglet enregistrements
                JPanel panelEnregistrements = fairePanelEnregistrements();
                
                //Cr�ation de l'onglet fichiers
                JPanel panelFichiers = fairePanelFichiers();
                
                //Cr�ation de l'onglet programmations
                JPanel panelProgrammes = fairePanelProgrammes();
                
                //S�paration en onglets
                onglets = new JTabbedPane( SwingConstants.TOP );
                onglets.addTab( "Principal", panelPrincipal );
                onglets.addTab( "Enregistrements", panelEnregistrements );
                onglets.addTab( "Programmations", panelProgrammes );
                onglets.addTab( "Fichiers", panelFichiers );
                onglets.addTab( "Configuration", panelOptions );
                
                //Panel contenant tout le reste
                JPanel panelGlobal = new JPanel();
                panelGlobal.setLayout( new BorderLayout() );
                panelGlobal.add( onglets, BorderLayout.CENTER );
                
                //Affichage de la fen�tre
                setContentPane( panelGlobal );
                setSize( tailleFen );
                setVisible(true);
                
                //Gestion du premier demarrage
                if( premierDemarrage )
                {
                        //affichage console
                        System.out.println( "Ceci est le premier demarrage de l'application, pensez a remplir la configuration !" );
                        //affichage fen�tre
                        JOptionPane.showMessageDialog( frameComplete, "C'est la premiere fois que vous demarrez "+nomLog+".\nCommencez par remplir la configuration !", "Bienvenue", JOptionPane.INFORMATION_MESSAGE);
                        //s�lection onglet options
                        onglets.setSelectedIndex( 4 );
                        
                        //config par d�faut selon syst�me d'exploitation
                        String systeme = System.getProperty( "os.name" );
                        Pattern masqueWin = Pattern.compile( "windows" );
                        Matcher trouveurWin = masqueWin.matcher( systeme.toLowerCase() );
                        try
                        {
                                if( trouveurWin.find() )
                                {
                                    chmVlc = ( new File( "C:\\Program Files\\VideoLAN\\VLC\\vlc.exe" ) ).getCanonicalPath();
                                    chmEnregistrements = ( new File( "enregistrements" ) ).getCanonicalPath();
                                }
                                else
                                {
                                    chmVlc = ( new File( "/usr/bin/vlc" ) ).getCanonicalPath();
                                    chmEnregistrements = ( new File(  "enregistrements" ) ).getCanonicalPath();
                                }
                                champChmVlc.setText( chmVlc );
                                champChmEnregistrements.setText( chmEnregistrements );
                                enregistrerOptions(); 
                        }
                        catch( Exception e )
                        {
                                
                        }
                }
                
                //import des programmations enregistr�es
                importerProg();
                //M�j liste fichiers DOIT etre fait apres affichage
                majListeFic();
        }
        
/* cr�ation de tous les panels */
        
        //Panel de commande de l'onglet 
        JPanel fairePanelDroite()
        {
                //Boutons de commande
                regarder = new JButton( "Regarder la chaine" );
                regarder.addActionListener( new ActionLireChaine() );
                
                enregistrer = new JButton( "Enregistrer la chaine" );
                enregistrer.addActionListener( new ActionEnrChaine() );
                
                programmer = new JButton( "Programmer un enregistrement");
                programmer.addActionListener( new ActionProgChaine() );
                
                //Mise en place du panel droite (boutons de commande)
                JPanel panelDroite = new JPanel();    
                panelDroite.setLayout( new GridLayout( 3, 1 ) );
                panelDroite.add( regarder );                          
                panelDroite.add( enregistrer );                 
                panelDroite.add( programmer );
                return panelDroite;
        }
        
        //Panel de la liste des chaines
        JPanel fairePanelGauche()
        {
                //Mise en place du panel gauche (liste des chaines)
                JPanel panelGauche = new JPanel();
                panelGauche.setLayout( new BorderLayout( 0, 0 ) );
                                
                listeAff = new javax.swing.JList();
                listeAff.setCellRenderer( new RenduListeChaines() );
                listeAff.setListData( listeChaines );
                listeAff.setSelectedIndex(0);
                listeAff.addMouseListener( new ActionDblClicChaine() );
                JScrollPane listeAvecAscenseur = new JScrollPane( listeAff );
                
                panelGauche.add( listeAvecAscenseur, BorderLayout.CENTER );
                return panelGauche;
        }
        
        //panel principal
        JPanel fairePanelPrincipal()
        {
                //Cr�ation panel gauche
                JPanel panelGauche = fairePanelGauche();
                
                //Cr�ation panel droite
                JPanel panelDroite = fairePanelDroite();
                
                //Panel principal : liste + boutons + en cours
                JPanel panelPrincipal = new JPanel();
                panelPrincipal.setLayout(new BorderLayout( 10, 10 ) );
                panelPrincipal.add(panelGauche, BorderLayout.CENTER);
                panelPrincipal.add(panelDroite, BorderLayout.EAST);
                labelEnCours = new JLabel( "En cours : " );
                panelPrincipal.add( labelEnCours, BorderLayout.SOUTH );
                return panelPrincipal;
        }
        
        //panel des enregsitrements
        JPanel fairePanelEnregistrements()
        {                
                //Panel d'enregistrements
                JPanel panelEnregistrements = new JPanel();
                panelEnregistrements.setLayout(new BorderLayout( 5, 5 ) );
                
                panelEnregistrements.add( new JLabel( "Enregistrements en cours :" ), BorderLayout.NORTH );
                                               
                listeAffEnr = new javax.swing.JList();                
                listeAffEnr.addListSelectionListener( new ActionSelListeEnr() );
                
                JScrollPane listeEnrAvecAscenseur = new JScrollPane( listeAffEnr );
                
                JPanel panelControle = new JPanel();
                
                arrEnr = new JButton( "Arreter" );
                arrEnr.addActionListener( new ActionArrEnr() );
                
                lireEnr = new JButton( "Lire" );
                lireEnr.addActionListener( new ActionLireEnr() );
                
                progFinEnr = new JButton( "Programmer la fin" );
                progFinEnr.addActionListener( new ActionProgFinEnr() );
                
                arrEnr.setEnabled( false );
                progFinEnr.setEnabled( false );
                lireEnr.setEnabled( false );
                
                panelControle.setLayout(new GridLayout( 1, 3, 3, 3 ) );
                panelControle.add( arrEnr );
                panelControle.add( lireEnr );
                panelControle.add( progFinEnr );
                
                panelEnregistrements.add( listeEnrAvecAscenseur, BorderLayout.CENTER );
                panelEnregistrements.add( panelControle, BorderLayout.SOUTH ); 
                return panelEnregistrements;
        }
        
        //panel des programmations
        JPanel fairePanelProgrammes()
        {                
                //Panel des programmations
                JPanel panelProgrammes = new JPanel();
                panelProgrammes.setLayout(new BorderLayout( 5, 5 ) );
                
                panelProgrammes.add( new JLabel( "Enregistrements programmes :" ), BorderLayout.NORTH );
                                               
                listeAffProg = new javax.swing.JList();
                listeAffProg.addListSelectionListener( new ActionSelListeProgrammes() );
                
                JScrollPane listeProgAvecAscenseur = new JScrollPane( listeAffProg );
                
                JPanel panelControle = new JPanel();
                
                nouvProg = new JButton( "Programmer un enregistrement" );
                nouvProg.addActionListener( new ActionNouvProg() );
                
                arretEnrProg = new JButton( "Arreter l'enregistrement" );
                arretEnrProg.addActionListener( new ActionArretEnrProg() );
                arretEnrProg.setEnabled( false );
                
                supprProg = new JButton( "Supprimer la programmation" );
                supprProg.addActionListener( new ActionSupprProg() );
                supprProg.setEnabled( false );
                                
                panelControle.setLayout(new GridLayout( 2, 1 , 3, 3 ) );
                JPanel panelLigne = new JPanel();
                panelLigne.setLayout(new GridLayout( 1, 2, 3, 3 ) );
                panelLigne.add( arretEnrProg );
                panelLigne.add( supprProg );
                panelControle.add( panelLigne );
                panelControle.add( nouvProg );
                
                panelProgrammes.add( listeProgAvecAscenseur, BorderLayout.CENTER );
                panelProgrammes.add( panelControle, BorderLayout.SOUTH ); 
                return panelProgrammes;
        }
        
        //panel des fichiers
        JPanel fairePanelFichiers()
        {                
                //Panel de gestion des fichiers
                JPanel panelFichiers = new JPanel();
                panelFichiers.setLayout(new BorderLayout( 5, 5 ) );
                
                panelFichiers.add( new JLabel( "Fichiers disponibles :" ), BorderLayout.NORTH );
                
                String[] labelsFicAff = new String[0];                                
                listeAffFic = new javax.swing.JList( labelsFicAff );
                
                
                JScrollPane listeFicAvecAscenseur = new JScrollPane( listeAffFic );
                
                JPanel panelControle = new JPanel();
                
                supprFic = new JButton( "Supprimer" );
                supprFic.addActionListener( new ActionSupprFic() );
                
                majListeFic = new JButton( "Actualiser" );
                majListeFic.addActionListener( new ActionMajListeFic() );
                
                lireFic = new JButton( "Lire" );
                lireFic.addActionListener( new ActionLireFic() );
                
                supprFic.setEnabled( false );
                lireFic.setEnabled( false );
                
                panelControle.setLayout(new GridLayout( 1, 3, 3, 3 ) );
                panelControle.add( lireFic );
                panelControle.add( supprFic );
                panelControle.add( majListeFic );
                
                panelFichiers.add( listeFicAvecAscenseur, BorderLayout.CENTER );
                panelFichiers.add( panelControle, BorderLayout.SOUTH ); 
                return panelFichiers;
        }
        
        //panel des options
        JPanel fairePanelOptions()
        {                
                //Panel d'options
                JPanel panelOptions = new JPanel();
                panelOptions.setLayout( new GridLayout( 6, 1, 3, 3 ) );
                champChmVlc = new JTextField( chmVlc, 30 );
                champChmEnregistrements = new JTextField( chmEnregistrements, 30 );
                
                enrOptions = new JButton( "Enregistrer" );
                enrOptions.addActionListener( new ActionEnrOptions() );
                
                majListeChaines = new JButton( "Actualiser la liste des chaines" );
                majListeChaines.addActionListener( new ActionImporterListeChaines() );
                                
                panelOptions.add( new JLabel( "Chemin complet vers VLC :" ) );
                panelOptions.add( champChmVlc );
                panelOptions.add( new JLabel( "Dossier pour stocker les enregistrements :" ) );
                panelOptions.add( champChmEnregistrements );
                panelOptions.add( enrOptions );
                panelOptions.add( majListeChaines );
                return panelOptions;
        }
        
/* Diff�rents rendus des listes */
        
        //rendu liste chaines
        class RenduListeChaines extends JLabel implements ListCellRenderer
        {            
                RenduListeChaines( )
                {
                        super();
                         setBorder( BorderFactory.createCompoundBorder(
                             BorderFactory.createMatteBorder( 0, 0, 1, 0, Color.lightGray ),
                             BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) ) );
                         setOpaque( true );
                }
                //construit un �l�ment
                public Component getListCellRendererComponent(
                    JList liste,
                    Object valeur,
                    int index,
                    boolean isSelected,
                    boolean aFocus)
                {
                        
                        Chaine infos = (Chaine) valeur;
                        String nomChaine = infos.nom;
                        setText( nomChaine );
                        if( isSelected || aFocus )
                        {
                                setBackground( liste.getSelectionBackground() );
                                setForeground( liste.getSelectionForeground() );
                        }
                        else
                        {
                                setBackground( Color.white );
                                setForeground( Color.black );
                        }
                        return this;
                }
        }
        
        //rendu liste enregistrements
        class RenduListeEnr extends JTextArea implements ListCellRenderer
        {            
                RenduListeEnr( )
                {
                        super();
                         setBorder( BorderFactory.createCompoundBorder(
                             BorderFactory.createMatteBorder( 0, 0, 1, 0, Color.lightGray ),
                             BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) ) );
                        setColumns( (tailleFen.width - 30 ) / getColumnWidth() );
                }
                //construit un �l�ment
                public Component getListCellRendererComponent(
                    JList liste,
                    Object valeur,
                    int index,
                    boolean isSelected,
                    boolean aFocus)
                {
                        EnrEnCours infos = (EnrEnCours) valeur;
                        int idChaine = infos.indChaine;
                        
                        Date debut = infos.momentDep;
                        Calendar cal = Calendar.getInstance();
                        cal.setTime( debut );
                        
                        String nomChaine = ((Chaine) listeChaines.elementAt( idChaine )).nom;
                        String nomDebut = nbrDbl( cal.get( Calendar.DAY_OF_MONTH ) )+"/"+nbrDbl( cal.get( Calendar.MONTH ) )+"/"+ cal.get( Calendar.YEAR ) +" "+nbrDbl( cal.get( Calendar.HOUR_OF_DAY ) )+"h"+nbrDbl( cal.get( Calendar.MINUTE ) );
                                                
                        String programme = "";
                        if( infos.enrProgramme )
                                programme = "Programme par " + infos.getProgParent().nom + "\n";
                        
                        majBtnProg();
                        setText( "Chaine : " + nomChaine + "\nDebut : " + nomDebut + "\nFichier : " + infos.nomFichier + "\n" + programme );
                        if( isSelected )
                        {
                                setBackground( liste.getSelectionBackground() );
                                setForeground( liste.getSelectionForeground() );
                        }
                        else
                        {
                                setBackground( Color.white );
                                setForeground( Color.black );
                        }
                        return this;
                }
        }
        
        
        //rendu liste fichiers
        class RenduListeFic extends JTextArea implements ListCellRenderer
        {            
                RenduListeFic( )
                {
                        super();
                         setBorder( BorderFactory.createCompoundBorder(
                             BorderFactory.createMatteBorder( 0, 0, 1, 0, Color.lightGray ),
                             BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) ) );
                        setColumns( (tailleFen.width - 30 ) / getColumnWidth() );
                }
                //construit un �l�ment
                public Component getListCellRendererComponent(
                    JList liste,
                    Object valeur,
                    int index,
                    boolean isSelected,
                    boolean aFocus)
                {
                        
                        Fichier infos = (Fichier) valeur;
                        String nomFic = infos.nom;
                        int tailleFic = infos.taille;
                        setText( "Fichier : " + nomFic + "\nTaille : " + tailleFic + " Mo\n" );
                        if( isSelected )
                        {
                                setBackground( liste.getSelectionBackground() );
                                setForeground( liste.getSelectionForeground() );
                        }
                        else
                        {
                                setBackground( Color.white );
                                setForeground( Color.black );
                        }
                        return this;
                }
        }
        
        
        //rendu liste programmations
        class RenduListeProg extends JTextArea implements ListCellRenderer
        {            
                RenduListeProg( )
                {
                        super();
                        setColumns( (tailleFen.width - 30 ) / getColumnWidth() );
                         setBorder( BorderFactory.createCompoundBorder(
                             BorderFactory.createMatteBorder( 0, 0, 1, 0, Color.lightGray ),
                             BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) ) );
                }
                //construit un �l�ment
                public Component getListCellRendererComponent(
                    JList liste,
                    Object valeur,
                    int index,
                    boolean isSelected,
                    boolean aFocus)
                {
                        
                        Programmation infos = (Programmation) valeur;
                        String nomProg = infos.nom;
                        String enCours;
                        if( infos.enCours )
                                enCours = "En cours d'enregistrement";
                        else
                                enCours = "En attente";
                        String date;
                        if( infos.estPonctuel )
                        {
                                date = "Le " + nbrDbl( infos.jour ) + "/" + nbrDbl( infos.mois ) + "/" + infos.annee;
                        }
                        else
                        {
                                date = "Tous les";
                                for( int k=0; k < infos.jours.size(); k++ )
                                {
                                        if( k == 0 )
                                                date+= " ";
                                        else
                                                date+= ", ";
                                        int jour = ((Integer) infos.jours.elementAt( k )).intValue();
                                        switch( jour )
                                        {
                                                case Calendar.MONDAY:
                                                        date+= "lundi";
                                                        break;
                                                case Calendar.TUESDAY:
                                                        date+= "mardi";
                                                        break;
                                                case Calendar.WEDNESDAY:
                                                        date+= "mercredi";
                                                        break;
                                                case Calendar.THURSDAY:
                                                        date+= "jeudi";
                                                        break;
                                                case Calendar.FRIDAY:
                                                        date+= "vendredi";
                                                        break;
                                                case Calendar.SATURDAY:
                                                        date+= "samedi";
                                                        break;
                                                case Calendar.SUNDAY:
                                                        date+= "dimanche";
                                                        break;
                                        }
                                }
                        }
                        setText( "Programmation : " + nomProg + "\n"
                            + date + "\n"
                            + "De " + nbrDbl( infos.heureDep ) + ":" + nbrDbl( infos.minuteDep ) + " a " + nbrDbl( infos.heureFin ) + ":" + nbrDbl( infos.minuteFin ) + "\n"
                            + enCours + "\n" );
                        if( isSelected )
                        {
                                setBackground( liste.getSelectionBackground() );
                                setForeground( liste.getSelectionForeground() );
                        }
                        else
                        {
                                setBackground( Color.white );
                                setForeground( Color.black );
                        }
                        return this;
                }
        }
        
/**************************************
 *Classes repr�sentant les actions
 *possibles depuis l'interface
 **************************************/

/* Actions de l'onglet principal */
        
        //action lecture/arret chaine s�lectionn�e
        class ActionLireChaine implements ActionListener
        {
                public void actionPerformed(ActionEvent event)
                {
                        if(! lectureEnCours.enCours )
                        {
                                //Lance la lecture d'une chaine
                                lectureEnCours.lancerChaine();
                        }
                        else
                        {
                                lectureEnCours.arreter();
                        }
                }
        }
        
        //action double clic sur la liste de chaines => lecture chaine s�lectionn�e
        class ActionDblClicChaine extends java.applet.Applet implements MouseListener
        {
                public void mouseClicked( MouseEvent event)
                {
                        if( event.getClickCount() == 2 )
                        {
                                //Lance la lecture d'une chaine
                                lectureEnCours.lancerChaine();
                        }
                }
                
                public void mouseEntered( MouseEvent e ){}
                public void mouseExited( MouseEvent e ){}                
                public void mousePressed( MouseEvent e ){}
                public void mouseReleased( MouseEvent e ){}
        }
        
        //action enregistrement immediat chaine s�lectionn�e
        class ActionEnrChaine implements ActionListener
        {
                public void actionPerformed(ActionEvent event)
                {
                        int indChaine;
                        indChaine = listeAff.getSelectedIndex();
                        String nomChaine = ((Chaine) listeChaines.elementAt( indChaine ) ).nom;
                        Calendar maintenant = Calendar.getInstance();
                        String nomFichier = simpChaine( nomChaine ) + "-" + maintenant.get( Calendar.DAY_OF_MONTH ) + "-" + maintenant.get( Calendar.MONTH ) + "-" + maintenant.get( Calendar.YEAR ) + "-" + maintenant.get( Calendar.HOUR_OF_DAY ) + "h" + maintenant.get( Calendar.MINUTE ) + extVideo;
                        enrEnCours.add( new EnrEnCours( indChaine, nomFichier ) );
                        //modif interface
                        majListeEnrEnCours();
                }
        }
        
        //action cr�ation nouveau programme pour la chaine s�lectionn�e
        class ActionProgChaine implements ActionListener
        {
                public void actionPerformed(ActionEvent event)
                {
                        FenetreProgrammation fenetre = new FenetreProgrammation();
                        fenetre.setChaineDep( listeAff.getSelectedIndex() );
                }
        }
        
/* Actions de l'onglet enregistrements */
        
        //action arret de l'enregistrement s�lectionn�
        class ActionArrEnr implements ActionListener
        {
                public void actionPerformed(ActionEvent event)
                {
                        int indEnr;
                        indEnr = listeAffEnr.getSelectedIndex();
                        //Suppression
                        ((EnrEnCours) enrEnCours.elementAt( indEnr )).arreter();
                }
        }
        
        //action lecture de l'enregistrement en cours s�lectionn�
        class ActionLireEnr implements ActionListener
        {
                public void actionPerformed(ActionEvent event)
                {
                        int indEnr;
                        indEnr = listeAffEnr.getSelectedIndex();
                        String nomFichier = ((EnrEnCours) enrEnCours.elementAt( indEnr )).nomFichier;

                        //Lance la lecture du fichier
                        lectureEnCours.lancerFichier( nomFichier );
                }
        }
        
        //action programmation de la fin d'un enregistrement
        class ActionProgFinEnr implements ActionListener
        {
                public void actionPerformed(ActionEvent event)
                {
                        int indEnr = listeAffEnr.getSelectedIndex();
                        FenetreProgrammation fenetre = new FenetreProgrammation();
                        fenetre.setEnr( (EnrEnCours) enrEnCours.elementAt( indEnr ) );
                }
        }
        
        //action changement s�lection liste enregistrements en cours (m�j validit� boutons)
        class ActionSelListeEnr implements ListSelectionListener
        {
                public void valueChanged(ListSelectionEvent event)
                {
                        //m�j des boutons valides
                        majBtnEnr();
                }
        }
        
/* Actions de l'onglet programmations */
        
        //action cr�ation nouveau programme
        class ActionNouvProg implements ActionListener
        {
                public void actionPerformed(ActionEvent event)
                {
                        new FenetreProgrammation();
                }
        }
        
        //action arret d'un enregistrement d'une programmation
        class ActionArretEnrProg implements ActionListener
        {
                public void actionPerformed(ActionEvent event)
                {
                        int indProg;
                        indProg = listeAffProg.getSelectedIndex();
                        //Suppression
                        ((Programmation) listeProgrammes.elementAt( indProg )).arreterEnrEnCours();
                }
        }
        
        //action suppression d'une programmation
        class ActionSupprProg implements ActionListener
        {
                public void actionPerformed(ActionEvent event)
                {
                        int indProg;
                        indProg = listeAffProg.getSelectedIndex();                        
                        Programmation prog = (Programmation) listeProgrammes.elementAt( indProg );
                        if(! prog.fini )
                        {
                                prog.supprimer();
                                listeProgrammes.removeElementAt( indProg );
                        }
                        majListeProg();
                }
        }
        
        //action changement s�lection liste programmes (m�j validit� boutons)
        class ActionSelListeProgrammes implements ListSelectionListener
        {
                public void valueChanged(ListSelectionEvent event)
                {
                        //m�j des boutons valides
                        majBtnProg();
                }
        }
        
/* Actions de l'onglet fichiers */
        
        //action lecture d'un fichier
        class ActionLireFic implements ActionListener
        {
                public void actionPerformed(ActionEvent event)
                {
                        int indFic;
                        indFic = listeAffFic.getSelectedIndex();
                        String nomFichier = ((Fichier) listeFic.elementAt( indFic )).nom;

                        //Lance la lecture du fichier
                        lectureEnCours.lancerFichier( nomFichier );
                }
        }
        
        //action suppression d'un fichier
        class ActionSupprFic implements ActionListener
        {
                public void actionPerformed(ActionEvent event)
                {
                        int indFic;
                        indFic = listeAffFic.getSelectedIndex();
                        String nomFichier = ((Fichier) listeFic.elementAt( indFic )).nom;
                        int rep = JOptionPane.showConfirmDialog( frameComplete, "Supprimer le fichier "+nomFichier+" ?", "Suppression", JOptionPane.YES_NO_OPTION);
                        if( rep == JOptionPane.YES_OPTION )
                        {
                                try
                                {
                                        File fic = new File( chmEnregistrements + sepDoss + nomFichier );
                                        fic.delete();
                                        majListeFic();
                                }
                                catch( Exception e )
                                {
                                        System.out.println( "Impossible de supprimer le fichier : " + e.toString() );
                                        JOptionPane.showMessageDialog( frameComplete, "Impossible de supprimer le fichier.", "Erreur", JOptionPane.ERROR_MESSAGE);
                                }
                        }
                }
        }
        
        //action maj liste fichiers
        class ActionMajListeFic implements ActionListener
        {
                public void actionPerformed(ActionEvent event)
                {
                        majListeFic();
                }
        }
        
/* Actions de l'onglet options */
             
        //action enregistrement options
        class ActionEnrOptions implements ActionListener
        {
 
                public void actionPerformed(ActionEvent event)
                {
                        //Enregistre les options de l'onglet options
                        try
                        {
                                chmVlc = ( new File( champChmVlc.getText() ) ).getCanonicalPath();
                                File dossEnr = new File( champChmEnregistrements.getText() );
                                chmEnregistrements = dossEnr.getCanonicalPath();
                                if(! dossEnr.isDirectory() )
                                        dossEnr.mkdirs();
                                //Gestion du premier demarrage
                                if( premierDemarrage )
                                {
                                        premierDemarrage = false;
                                }
                                
                                //Enregistrement
                                enregistrerOptions();
                                majListeFic();
                                
                                JOptionPane.showMessageDialog( frameComplete, "Configuration enregistree", "Confirmation", JOptionPane.PLAIN_MESSAGE);
                                
                                onglets.setSelectedIndex( 0 );
                                
                        }
                        catch( Exception e )
                        {
                                System.out.println( "Erreur de prise en compte de la configuration : " + e );
                                JOptionPane.showMessageDialog( frameComplete, "La configuration n'a pas ete enregistree.", "Erreur", JOptionPane.ERROR_MESSAGE);
                        }
                }
        }
        
        //action importation liste des chaines
        class ActionImporterListeChaines implements ActionListener
        {
                public void actionPerformed(ActionEvent event)
                {
                        //m�j des boutons valides
                        importerListeChaines();
                }
        }
        
        
/*****************************************
 * Classe repr�sentant la fen�tre
 * de choix pour les programmations
 ****************************************/
        
        //classe pour les choix pour les programmations
        class FenetreProgrammation extends JFrame
        {
                //champs � remplir
                JTextField nom;
                JComboBox chaine;
                JTextField heureDep;
                JTextField heureFin;
                JTextField minuteDep;
                JTextField minuteFin;
                JTextField jour;
                JTextField mois;
                JTextField annee;
                JRadioButton btnDate;
                JRadioButton btnRep;
                JCheckBox lundi;
                JCheckBox mardi;
                JCheckBox mercredi;
                JCheckBox jeudi;
                JCheckBox vendredi;
                JCheckBox samedi;
                JCheckBox dimanche;
                
                //enregistrement � inclure dans une programmation si n�cessaire
                EnrEnCours enrAProg = null;
                
                //construit la fen�tre
                public FenetreProgrammation()
                {
                        //Cr�ation de la fen�tre
                        super( nomLog + " - Programmer un enregistrement" );
                        
                        setLocationRelativeTo(null);
                        
                        //Evenement de fermeture
                        WindowListener fermeture = new WindowAdapter()
                        {
                                public void windowClosing(WindowEvent e)
                                {
                                        sortir();
                                }
                        };
                        addWindowListener( fermeture );
                        
                        //Ajout des composantes initialis�es
                        
                        Calendar aujourdhui = Calendar.getInstance();
                        
                        setLayout( new BorderLayout( 3, 3 ) );
                        JPanel panelIntitules = new JPanel();
                        JPanel panelValeurs = new JPanel();
                        JPanel panelControle = new JPanel();
                        add( new JLabel("Configurez votre programmation : " ), BorderLayout.NORTH );
                        add( panelIntitules, BorderLayout.WEST );
                        add( panelValeurs, BorderLayout.CENTER );
                        add( panelControle, BorderLayout.SOUTH );
                        
                        panelIntitules.setLayout( new GridLayout( 9, 1, 1, 1 ) );
                        panelValeurs.setLayout( new GridLayout( 9, 1, 1, 1 ) );
                        
                        panelIntitules.add( new JLabel( "Nom de la programmation : " ) );
                        nom = new JTextField( "prog" );
                        panelValeurs.add( nom );
                                               
                        panelIntitules.add( new JLabel( "Chaine a enregistrer : " ) );
                        String[] chaines = new String[listeChaines.size()];
                        for( int k=0 ; k < listeChaines.size() ; k++ )
                        {
                                chaines[k] = ( (Chaine) listeChaines.elementAt( k ) ).nom;
                        }
                        chaine = new JComboBox( chaines );
                        panelValeurs.add( chaine );
                        
                        panelIntitules.add( new JLabel( "Heure de debut : ") );
                        JPanel panelHeureDep = new JPanel();
                        heureDep = new JTextField( "" + aujourdhui.get( Calendar.HOUR_OF_DAY), 5 );
                        panelHeureDep.add( heureDep );
                        panelHeureDep.add( new JLabel( " : " ) );
                        minuteDep = new JTextField( "" + aujourdhui.get( Calendar.MINUTE ), 5 );
                        panelHeureDep.add( minuteDep );
                        panelValeurs.add( panelHeureDep );
                        
                        panelIntitules.add( new JLabel( "Heure de fin : ") );
                        JPanel panelHeureFin = new JPanel();
                        heureFin = new JTextField( "" + aujourdhui.get( Calendar.HOUR_OF_DAY), 5 );
                        panelHeureFin.add( heureFin );
                        panelHeureFin.add( new JLabel( " : " ) );
                        minuteFin = new JTextField( "" + aujourdhui.get( Calendar.MINUTE ), 5 );
                        panelHeureFin.add( minuteFin );
                        panelValeurs.add( panelHeureFin );
                        
                        panelIntitules.add( new JLabel( "Type de programmation : " ) );
                        ButtonGroup choixRep = new ButtonGroup();
                        btnDate = new JRadioButton( "Programmation ponctuelle le : ", true );
                        btnRep = new JRadioButton( "Repeter la programmation tous les : ", false );
                        choixRep.add( btnDate );
                        choixRep.add( btnRep );
                        
                        panelValeurs.add( btnDate );
                        
                        JPanel panelDate = new JPanel();
                        jour = new JTextField( "" + aujourdhui.get( Calendar.DAY_OF_MONTH ), 4 );
                        mois = new JTextField( "" + ( aujourdhui.get( Calendar.MONTH ) + 1 ), 4 );
                        annee = new JTextField( "" + aujourdhui.get( Calendar.YEAR ), 4 );
                        panelDate.add( jour );
                        panelDate.add( new JLabel( "/" ) );
                        panelDate.add( mois );
                        panelDate.add( new JLabel( "/" ) );
                        panelDate.add( annee );
                        panelValeurs.add( panelDate );
                        
                        panelValeurs.add( btnRep );
                        
                        JPanel ligne1 = new JPanel();
                        JPanel ligne2 = new JPanel();
                        
                        lundi = new JCheckBox( "lundi", aujourdhui.get( Calendar.DAY_OF_WEEK ) == Calendar.MONDAY );
                        mardi = new JCheckBox( "mardi", aujourdhui.get( Calendar.DAY_OF_WEEK ) == Calendar.TUESDAY );
                        mercredi = new JCheckBox( "mercredi", aujourdhui.get( Calendar.DAY_OF_WEEK ) == Calendar.WEDNESDAY );
                        jeudi = new JCheckBox( "jeudi", aujourdhui.get( Calendar.DAY_OF_WEEK ) == Calendar.THURSDAY );
                        vendredi = new JCheckBox( "vendredi", aujourdhui.get( Calendar.DAY_OF_WEEK ) == Calendar.FRIDAY );
                        samedi = new JCheckBox( "samedi", aujourdhui.get( Calendar.DAY_OF_WEEK ) == Calendar.SATURDAY );
                        dimanche = new JCheckBox( "dimanche", aujourdhui.get( Calendar.DAY_OF_WEEK ) == Calendar.SUNDAY );
                        
                        ligne1.add( lundi );
                        ligne1.add( mardi );
                        ligne1.add( mercredi );
                        ligne1.add( jeudi );
                        ligne2.add( vendredi );
                        ligne2.add( samedi );
                        ligne2.add( dimanche );
                        
                        panelValeurs.add( ligne1 );
                        panelValeurs.add( ligne2 );
                        
                        JButton valider = new JButton( "Valider" );
                        JButton annuler = new JButton( "Annuler" );
                        valider.addActionListener( new ActionValider() );
                        annuler.addActionListener( new ActionSortir() );
                        panelControle.setLayout( new GridLayout( 1, 2, 3, 3 ) );
                        panelControle.add( valider );
                        panelControle.add( annuler );
                        
                        //Affichage
                        pack();
                        setVisible( true );
                }
                
                //Choisir la chaine par d�faut (la chaine a donc �t� choisie d'abord par l'utilisateur)
                public void setChaineDep( int indChaine )
                {
                        chaine.setSelectedIndex( indChaine );
                }
                
                //Choisir un enregistrement � encadrer (l'utilisateur a cliqu� sur Programmer la fin de l'enregistrement)
                public void setEnr( EnrEnCours enr )
                {
                        enrAProg = enr;
                        Calendar momDep = Calendar.getInstance();
                        momDep.setTime( enr.momentDep );
                        heureDep.setText( "" + momDep.get( Calendar.HOUR_OF_DAY ));
                        heureDep.setEnabled( false );
                        minuteDep.setText( "" + momDep.get( Calendar.MINUTE ));
                        minuteDep.setEnabled( false );
                        chaine.setSelectedIndex( enr.indChaine );
                        chaine.setEnabled( false );
                        btnRep.setEnabled( false );
                        jour.setText( "" + momDep.get( Calendar.DAY_OF_MONTH ));
                        mois.setText( "" + ( momDep.get( Calendar.MONTH ) + 1 ) );
                        annee.setText( "" + momDep.get( Calendar.YEAR ) );
                        jour.setEnabled( false );
                        mois.setEnabled( false );
                        annee.setEnabled( false );
                        lundi.setEnabled( false );
                        mardi.setEnabled( false );
                        mercredi.setEnabled( false );
                        jeudi.setEnabled( false );
                        vendredi.setEnabled( false );
                        samedi.setEnabled( false );
                        dimanche.setEnabled( false );
                }
                
                //fermer la fen�tre
                void sortir()
                {
                        setVisible( false );
                }
                
                //message d'erreur
                void erreurFormat()
                {
                        JOptionPane.showMessageDialog( frameComplete, "Il y a une erreur dans votre programmation.", "Format incorrect", JOptionPane.ERROR_MESSAGE);
                }
        
                //action annulation
                class ActionSortir implements ActionListener
                {
                        public void actionPerformed(ActionEvent event)
                        {
                                sortir();
                        }
                }
        
                //action validation
                class ActionValider implements ActionListener
                {
                        public void actionPerformed(ActionEvent event)
                        {
                                try
                                {
                                        //V�rification du format des donn�es
                                        String nomC = simpChaine( nom.getText() );
                                        int heureDepC = Integer.parseInt( heureDep.getText() );
                                        int minuteDepC = Integer.parseInt( minuteDep.getText() );
                                        int heureFinC = Integer.parseInt( heureFin.getText() );
                                        int minuteFinC = Integer.parseInt( minuteFin.getText() );
                                        int chaineC = chaine.getSelectedIndex();
                                        
                                        //format des heures et minutes
                                        if( heureDepC > 23 || heureFinC > 23 || minuteDepC > 59 || minuteFinC > 59 || heureDepC < 0 || heureFinC < 0 || minuteDepC < 0 || minuteFinC < 0 )
                                        {
                                                erreurFormat();
                                        }
                                        else
                                        {
                                                boolean estPonctuel = btnDate.isSelected();
                                                if( estPonctuel )
                                                {
                                                        //enregistrement ponctuel
                                                        int jourC = Integer.parseInt( jour.getText() );
                                                        int moisC = Integer.parseInt( mois.getText() );
                                                        int anneeC = Integer.parseInt( annee.getText() );
                                                        
                                                        //le mois
                                                        if( moisC > 12 || moisC < 1 )
                                                        {
                                                                erreurFormat();
                                                        }
                                                        else
                                                        {
                                                                Calendar dateDem = Calendar.getInstance();
                                                                dateDem.set( Calendar.YEAR, anneeC );
                                                                dateDem.set( Calendar.MONTH, moisC );
                                                                //le jour
                                                                if( jourC > dateDem.getActualMaximum( Calendar.DATE ) || jourC < 0 )
                                                                {
                                                                        erreurFormat();
                                                                }
                                                                else
                                                                {
                                                                        if( enrAProg == null )
                                                                        {
                                                                                //on cr�e une programmation de toutes pi�ces
                                                                                listeProgrammes.add( new Programmation( nomC, chaineC, jourC, moisC - 1, anneeC, heureDepC, minuteDepC, heureFinC, minuteFinC ) );
                                                                                majListeProg();    
                                                                                sortir();
                                                                        }
                                                                        else
                                                                        {
                                                                                //on inclut un enregistrement dans une programmation
                                                                                listeProgrammes.add( new Programmation( nomC, enrAProg, heureFinC, minuteFinC ) );
                                                                                majListeProg();
                                                                                sortir();
                                                                        }
                                                                }
                                                        }
                                                }
                                                else
                                                {
                                                        //Programmation chaque semaine
                                                        Vector jours = new Vector();
                                                        if( lundi.isSelected() ) jours.add( new Integer( Calendar.MONDAY ) );
                                                        if( mardi.isSelected() ) jours.add( new Integer( Calendar.TUESDAY ) );
                                                        if( mercredi.isSelected() ) jours.add( new Integer( Calendar.WEDNESDAY ) );
                                                        if( jeudi.isSelected() ) jours.add( new Integer( Calendar.THURSDAY ) );
                                                        if( vendredi.isSelected() ) jours.add( new Integer( Calendar.FRIDAY ) );
                                                        if( samedi.isSelected() ) jours.add( new Integer( Calendar.SATURDAY ) );
                                                        if( dimanche.isSelected() ) jours.add( new Integer( Calendar.SUNDAY ) );
                                                        listeProgrammes.add( new Programmation( nomC, chaineC, jours, heureDepC, minuteDepC, heureFinC, minuteFinC ) );
                                                        majListeProg();
                                                        sortir();
                                                }
                                        }
                                }
                                catch( Exception e )
                                {
                                       System.out.println( e.toString() );
                                        erreurFormat();
                                }
                        }
                }
        }
 
/*********************************
 * Fonctions diverses
 *********************************/
        
/* Fonctions souvent utiles */
        
        //Sortie du programme : ferme tout        
        public boolean sortir()
        {
                int rep = JOptionPane.YES_OPTION;
                /*
                if( lectureEnCours.enCours || enrEnCours.size() > 0 )
                {
                        rep = JOptionPane.showConfirmDialog( frameComplete, "Fermer " + nomLog + " ?\nLes enregistrements et lectures en cours seront arr?t?s.", "Au revoir", JOptionPane.YES_NO_OPTION);
                }
                 */
                if( rep == JOptionPane.YES_OPTION )
                {
                    lectureEnCours.arreter();

                    //Enregistrement des programmes
                    enregistrerProg();

                    //Arret des programmes !
                    //� faire avant l'arret des enregistrements !
                    for( int k=0; k < listeProgrammes.size(); k++ )
                    {
                            Programmation prog = (Programmation) listeProgrammes.elementAt(k);
                            if( prog.enCours )
                            {
                                    prog.arreterEnrEnCours();
                                    k--; //maj integree enleve l'element de la liste
                            }
                    }

                    //arret des enregistrements
                    for( int k=0; k < enrEnCours.size(); k++ )
                    {
                            EnrEnCours enr = (EnrEnCours) enrEnCours.elementAt(k);
                            enr.arreter();
                            k--; //maj integree enleve l'element de la liste
                    }

                    //fin
                    System.exit(0);
                    return true;
                }
                else
                {
                    return false;
                }
        }
        
        //simplification d'une chaine pour en faire un nom de fichier
        String simpChaine( String chaine )
        {
                char car;
                String resultat = "";
                for (int i = 0 ; i < chaine.length() ;i++)
                {
                        car = chaine.charAt( i );
                        if( ( car >= 'a' && car <= 'z' ) || ( car >= 'A' && car <= 'Z' ) || ( car >= '0' && car <= '9' ) )
                                resultat+=car;
                }
                return resultat;
        }
        
        //Rajoute un 0 � gauche des nombres si n�cessaire pour obtenir deux chiffres : 1 -> 01
        String nbrDbl( int nbr )
        {
                if( nbr < 10 )
                        return "0" + nbr;
                else
                        return "" + nbr;
        }
        
/* Fonctions agissant sur la liste des chaines */
       
        //lecture du fichier local de liste des chaines, enregistrement du vecteur qui les repr�sente
        void lireListeChaines()
        {
                //Lecture du fichier liste des chaines
                int lu;
                char carLu;
                String ligne;
                String nomChaine = "";
                String adresseChaine = "";
                listeChaines.clear();
                try
                {
                        FileReader liste = new FileReader( nomFicChaines );
                        //lecture par caract�re
                        lu = liste.read();
                        while( lu != -1 )
                        {
                                carLu = (char) lu;
                                ligne = "";
                                while( carLu != '\n' && lu != -1 )
                                {
                                        ligne+= carLu;
                                        lu = liste.read();
                                        if( lu != -1 )
                                                carLu = (char) lu;
                                }
                                //on a toute une ligne
                                if( nomChaine == "" )
                                {
                                        Pattern masque = Pattern.compile( "^\\s*#EXTINF\\s*:\\s*0\\s*,\\s*(.+?)\\s*$" );
                                        Matcher trouveur = masque.matcher( ligne );
                                        
                                        if( trouveur.find() )
                                        {
                                                //on trouve un nom de chaine
                                                nomChaine = trouveur.group( 1 );
                                        }
                                }
                                else
                                {
                                        //on a toutes les infos sur la chaine : on ajoute
                                        Pattern masque2 = Pattern.compile( "^\\s*(.*?)\\s*$" );
                                        Matcher trouveur2 = masque2.matcher( ligne );
                                        trouveur2.find();
                                        
                                        adresseChaine = trouveur2.group( 1 );
                                        listeChaines.addElement( new Chaine( adresseChaine, nomChaine ) );
                                        nomChaine = "";
                                }
                                lu = liste.read();
                        }
                }
                catch( Exception e )
                {
                        System.out.println( "Erreur de lecture de la liste de chaines : " + e );
                }
        }
        
        //R�cup�re la liste de chaines dans un fichier distant
        //url dans la config
        //copie cette liste dans le fichier local et m�j
        void importerListeChaines()
        {
                //r�cup�ration du fichier complet
                String contenu = "";
                try
                {
                        //lecture � l'url
                        URL ficDist = new URL( urlListeChaines );
                        InputStream flux =  ficDist.openStream();
                        for( int carLu = flux.read(); carLu != -1; carLu = flux.read() )
                        {
                                contenu += (char) carLu;
                        }
                        flux.close();
                }
                catch( Exception e )
                {
                        System.out.println( "Impossible d'acceder � la liste des chaines distante : " + e );
                }
                        
                //possibilit� de sp�cifier une nouvelle adresse (REDIRECTION:http://...)
                Pattern masqueRedir = Pattern.compile( "REDIRECTION\\s*:\\s*(\\S+)" );
                Matcher trouveurRedir = masqueRedir.matcher( contenu );
                if( trouveurRedir.find() )
                {
                        String nouvUrl = trouveurRedir.group( 1 );
                        try
                        {
                                URL testURL = new URL( nouvUrl );
                                urlListeChaines = nouvUrl;
                                enregistrerOptions();
                                importerListeChaines();
                        }
                        catch( Exception e )
                        {
                                
                        }
                }
                else
                {
                        //Ecriture dans le fichier local de liste des chaines
                        try
                        {       
                                 FileWriter cible = new FileWriter( nomFicChaines );
                                 cible.write( contenu );
                                 cible.close();
                                 //on affiche les nouvelles chaines
                                 lireListeChaines();
                                 
                        }
                        catch( Exception e )
                        {
                                System.out.println( "Erreur d'ecriture du fichier de liste des chaines : " + e );
                        }
                }
        }
        
/* Fonctions agissant sur les enregistrements en cours */
        
        //met � jour l'interface pour la liste des enregistrements en cours
        void majListeEnrEnCours( )
        {
                //m�j enrEnCours : suppression enregistrements termin�s
                for( int k=0; k < enrEnCours.size(); k++ )
                {
                        EnrEnCours element = (EnrEnCours) enrEnCours.elementAt( k );
                        if(! element.enCours )
                                enrEnCours.removeElementAt( k );
                }
                //Cr�ation si n�cessaire
                if(! listeAffEnrOk )
                {
                        listeAffEnr.setCellRenderer( new RenduListeEnr( ) );
                        listeAffEnrOk = true;
                }
                
                listeAffEnr.setListData( enrEnCours );
                //gestion de la validit� des boutons
                if( enrEnCours.size() > 0 )
                {
                        listeAffEnr.setSelectedIndex(0);
                        majBtnEnr();
                        lireEnr.setEnabled( true );
                }
                else
                {
                        lireEnr.setEnabled( false );
                }
                //met � jour la liste des fichiers en m�me temps
                majListeFic();
        }
        
        //m�j de la validit� des boutons de l'onglet enregistrement
        //selon l'enregistrement s�lectionn�
        void majBtnEnr()
        {
                int indEnr;
                indEnr = listeAffEnr.getSelectedIndex();
                if( indEnr >= 0 )
                {
                        EnrEnCours enr = (EnrEnCours) enrEnCours.elementAt( indEnr );
                        if( enr.enrProgramme )
                        {
                                arrEnr.setEnabled( false );
                                progFinEnr.setEnabled( false );
                        }
                        else
                        {
                                arrEnr.setEnabled( true );
                                progFinEnr.setEnabled( true );
                        }
                }
                else
                {
                        arrEnr.setEnabled( false );
                        lireEnr.setEnabled( false );
                        progFinEnr.setEnabled( false );                        
                }
        }
        
/* Fonctions agissant sur les programmations */
        
        //met � jour l'interface pour la liste des programmations en cours
        void majListeProg()
        {
                //suppression des programmations termin�es
                for( int k=0; k < listeProgrammes.size(); k++ )
                {
                        Programmation element = (Programmation) listeProgrammes.elementAt( k );
                        if( element.fini )
                        {
                                listeProgrammes.removeElementAt( k );
                                k--;
                        }
                }
                //Cr�ation si n�cessaire de la liste affich�e
                if(! listeAffProgOk )
                {
                        listeAffProg.setCellRenderer( new RenduListeProg( ) );
                        listeAffProgOk = true;
                }
                                
                listeAffProg.setListData( listeProgrammes );
                
                //gestion de la validit� des boutons
                if( listeProgrammes.size() > 0 )
                {
                        listeAffProg.setSelectedIndex( 0 );
                        majBtnProg();
                }
                else
                {
                        arretEnrProg.setEnabled( false );
                        supprProg.setEnabled( false );
                }
                majListeFic();
        }
        
        //g�re la validit� des boutons de l'onglet programmations
        //en fonction de la programmation s�lectionn�e
        void majBtnProg()
        {
                //modification des boutons valides
                int indProg;
                indProg = listeAffProg.getSelectedIndex();
                if( indProg >= 0 )
                {
                        Programmation prog = (Programmation) listeProgrammes.elementAt( indProg );
                        if( prog.enCours )
                        {
                                arretEnrProg.setEnabled( true );
                                supprProg.setEnabled( false );
                        }
                        else
                        {
                                arretEnrProg.setEnabled( false );
                                supprProg.setEnabled( true );
                        }
                }
                else
                {
                        arretEnrProg.setEnabled( false );
                        supprProg.setEnabled( false );
                }
        }
        
        //Enregistre les programmations en cours dans un fichier
        void enregistrerProg()
        {
                //Cr�ation de la chaine
                //on utilise la fonction bijective repTexte des objets Programmation
                String chaine = "";
                for( int k=0; k < listeProgrammes.size(); k++ )
                {
                        Programmation prog = (Programmation) listeProgrammes.elementAt( k );
                        chaine += "\n\n" + prog.repTexte();
                }
                
                //Ecriture dans le fichier
                try
                {       
                         FileWriter cible = new FileWriter( nomFicProgrammations );
                         cible.write( chaine );
                         cible.close();
                }
                catch( Exception e )
                {
                        System.out.println( "Erreur d'ecriture du fichier des programmations : " + e );
                }
        }
        
        //R�cup�re les programmations dans un fichier, et les r�active en tant qu'objets Programmation
        void importerProg()
        {
                int lu;
                char carLu;
                String chaine = "";
                
                try
                {
                        FileReader liste = new FileReader( nomFicProgrammations );
                        //lecture par caract�re
                        lu = liste.read();
                        while( lu != -1 )
                        {
                                carLu = (char) lu;
                                chaine+= carLu;
                                lu = liste.read();
                        }
                        //on a tout le fichier dans chaine
                        Pattern masqueProg = Pattern.compile( "<programmation>.*?</programmation>", Pattern.DOTALL );
                        Matcher trouveurProg = masqueProg.matcher( chaine );
                        //on parcourt chaque programmation
                        //on recr�e les programmations gr�ce � la m�thode progDeTexte
                        while( trouveurProg.find() )
                        {
                                Programmation prog = (new Programmation()).progDeTexte( trouveurProg.group( 0 ) );
                                if( prog != null && (! prog.fini) )
                                {
                                        listeProgrammes.add( prog );
                                }
                        }
                        //on met � jour la liste (interface)
                        majListeProg();
                        
                }
                catch( Exception e )
                {
                        System.out.println( "Erreur de lecture du fichier de programmations : " + e );
                }
                
        }
        
/* Fonctions agissant sur la liste des fichiers */
        
        //met � jour l'interface pour la liste des fichiers
        void majListeFic( )
        {
                //Cr�ation si n�cessaire de la liste affich�e                
                if(! listeAffFicOk )
                {
                        listeAffFic.setCellRenderer( new RenduListeFic( ) );
                        listeAffFicOk = true;
                }
                
                //Parcours du dossier
                File doss = new File( chmEnregistrements );
                String [] listeTemp = doss.list();
                
                if( listeTemp != null )
                {
                        //Remise � 0 liste
                        listeFic = new Vector();
                        for( int i =0; i < listeTemp.length; i++)
                        {
                                File ficAct = new File( chmEnregistrements + sepDoss + listeTemp[i] );
                                if(! new File( chmEnregistrements + sepDoss + listeTemp[i] ).isDirectory() )
                                {
                                        listeFic.add( new Fichier( listeTemp[i], ( new Long( ficAct.length() / ( 1000 * 1000) ) ).intValue() ) );
                                }
                        }
                        listeAffFic.setListData( listeFic );
                }

                //gestion de la validit� des boutons
                if( listeFic.size() > 0 )
                {
                        supprFic.setEnabled( true );
                        lireFic.setEnabled( true );
                        listeAffFic.setSelectedIndex(0);
                }
                else
                {
                        supprFic.setEnabled( false );
                        lireFic.setEnabled( false );
                }
                        
        }
        
/* Fonctions agissant sur les options */
        
        //lecture des options dans le fichier local config.txt
        void lireOptions()
        {
                //Lecture du fichier par ligne
                int lu;
                char carLu;
                String ligne;
                
                try
                {
                        FileReader liste = new FileReader( nomFicOptions );
                        //lecture par caract�re
                        lu = liste.read();
                        while( lu != -1 )
                        {
                                carLu = (char) lu;
                                ligne = "";
                                while( carLu != '\n' && lu != -1 )
                                {
                                        ligne+= carLu;
                                        lu = liste.read();
                                        if( lu != -1 )
                                                carLu = (char) lu;
                                }
                                //on a toute une ligne

                                Pattern masque = Pattern.compile( "^ *([a-zA-Z_-]+) *= *([^#]*) *(#.*)?$" );
                                Matcher trouveur = masque.matcher( ligne );
                                if( trouveur.find() )
                                {
                                        //si variable connue, on la charge
                                        String nomVar = trouveur.group( 1 );
                                        String contVar = trouveur.group( 2 );
                                        if( nomVar.equals(  "nomFicChaines" ) )
                                                nomFicChaines = contVar;
                                        else if( nomVar.equals( "chmVlc" ) )
                                                chmVlc = contVar;
                                        else if( nomVar.equals( "chmEnregistrements" ) )
                                                chmEnregistrements = contVar;
                                        else if( nomVar.equals( "urlListeChaines" ) )
                                                urlListeChaines = contVar;
                                        else if( nomVar.equals( "premierDemarrage" ) )
                                                premierDemarrage = (contVar.equals( "1" ) );
                                        else
                                                System.out.println( "Variable de configuration inconnue : "+nomVar );
                                }
                                //on continue
                                lu = liste.read();
                        }
                }
                catch( Exception e )
                {
                        System.out.println( "Erreur de lecture du fichier de configuration : " + e );
                        sortir();
                }
        }
        
        //Enregistre dans le fichier de configuration les options actuelles
        void enregistrerOptions()
        {
                //Lecture du fichier d'options
                int lu;
                char carLu;
                String ligne;
                String chaineAEnregistrer = "";
                //Variables � enregistrer obligatoirement
                boolean nomFicChainesOk = false;
                boolean chmVlcOk = false;
                boolean chmEnregistrementsOk = false;
                boolean urlListeChainesOk = false;
                boolean premierDemarrageOk = false;
                
                
                try
                {
                        //on lit d'abord le fichier pour conserver sa structure
                        FileReader liste = new FileReader( nomFicOptions );
                        //lecture par caract�re
                        lu = liste.read();
                        while( lu != -1 )
                        {
                                carLu = (char) lu;
                                ligne = "";
                                while( carLu != '\n' && lu != -1 )
                                {
                                        ligne+= carLu;
                                        lu = liste.read();
                                        if( lu != -1 )
                                                carLu = (char) lu;
                                }
                                //on a toute une ligne

                                Pattern masque = Pattern.compile( "^ *([a-zA-Z_-]+) *= *([^#]*)( *(#.*)?)$" );
                                Matcher trouveur = masque.matcher( ligne );
                                if( trouveur.find() )
                                {
                                        //si on reconnait la ligne, on m�j la valeur de la variable
                                        //sinon on laisse la ligne
                                        String nomVar = trouveur.group( 1 );
                                        String contVar = trouveur.group( 2 );
                                        String commentaires = trouveur.group( 3 );
                                        if( nomVar.equals(  "nomFicChaines" ) )
                                        {
                                                chaineAEnregistrer+= "nomFicChaines = "+nomFicChaines;
                                                nomFicChainesOk = true;
                                        }
                                        else if( nomVar.equals( "chmVlc" ) )
                                        {
                                                chaineAEnregistrer+= "chmVlc = "+chmVlc;
                                                chmVlcOk = true;
                                        }
                                        else if( nomVar.equals( "chmEnregistrements" ) )
                                        {
                                                chaineAEnregistrer+= "chmEnregistrements = "+chmEnregistrements;
                                                chmEnregistrementsOk = true;
                                        }
                                        else if( nomVar.equals( "urlListeChaines" ) )
                                        {
                                                chaineAEnregistrer+= "urlListeChaines = "+urlListeChaines;
                                                urlListeChainesOk = true;
                                        }
                                        else if( nomVar.equals( "premierDemarrage" ) )
                                        {
                                                if( premierDemarrage )
                                                        chaineAEnregistrer+= "premierDemarrage = 1";
                                                else
                                                        chaineAEnregistrer+= "premierDemarrage = 0";
                                                        
                                                premierDemarrageOk = true;
                                        }
                                        else
                                                chaineAEnregistrer+= nomVar+" = "+contVar;
                                        chaineAEnregistrer+= commentaires;
                                }
                                else
                                {
                                        chaineAEnregistrer+= ligne;
                                }
                                chaineAEnregistrer+= "\n";
                                //on continue
                                lu = liste.read();
                        }

                        //Cas des variables non trouv�es dans le fichier de config
                        //on les ajoute � la fin
                        if(! nomFicChainesOk )
                                chaineAEnregistrer+= "\nnomFicChaines = "+nomFicChaines;
                        if(! chmVlcOk )
                                chaineAEnregistrer+= "\nchmVlc = "+chmVlc;
                        if(! chmEnregistrementsOk )
                                chaineAEnregistrer+= "\nchmEnregistrements = "+chmEnregistrements;
                        if(! urlListeChainesOk )
                                chaineAEnregistrer+= "\nurlListeChaines = "+urlListeChaines;
                        if(! premierDemarrageOk )
                                if( premierDemarrage )
                                        chaineAEnregistrer+= "\npremierDemarrage = 1";
                                else
                                        chaineAEnregistrer+= "\npremierDemarrage = 0";
                
                        //Ecriture du nouveau fichier
                        try
                        {       
                                 FileWriter cible = new FileWriter( nomFicOptions );
                                 cible.write( chaineAEnregistrer );
                                 cible.close();
                        }
                        catch( Exception e )
                        {
                                System.out.println( "Erreur d'ecriture du fichier de configuration : " + e );
                        }
                }
                catch( Exception e )
                {
                        System.out.println( "Erreur de lecture du fichier de configuration : " + e );
                }
                
        }
        
/***********************************
 * Classes pour decrire les objets
 * manipules dans ce programme
 **********************************/
        
/* Classes simples de description */
        
        //Decrit une chaine
        class Chaine
        {
                public String adresse;
                public String nom;
                Chaine( String adr, String nomChaine )
                {
                        adresse = adr;
                        nom = nomChaine;
                }
        }
        
        //Decrit un fichier
        class Fichier
        {
                public int taille;
                public String nom;
                Fichier( String nomF, int tailleF )
                {
                        taille = tailleF;
                        nom = nomF;
                }
        }
        
        //Decrit un parametre à passer à vlc (dépend du système)
        class ParametreVlc
        {
                String nom;
                String valeur;
                String precisions;
                String paramSeul = "";
                
                //vrai paramètre avec precisions
                ParametreVlc( String n, String v, String p )
                {
                        nom = n;
                        valeur = v;
                        precisions = p;
                }
                
                //vrai paramètre sans precisions
                ParametreVlc( String n, String v )
                {
                        nom = n;
                        valeur = v;
                        precisions = "";
                }
                
                //faux paramètre : fichier...
                ParametreVlc( String p )
                {
                        paramSeul = p;
                }
                
                //renvoie la chaine du paramètre selon l'OS
                String chaine()
                {
                        if(! paramSeul.equals( "" ) )
                                return paramSeul;
                        String systeme = System.getProperty( "os.name" );
                        Pattern masqueWin = Pattern.compile( "windows" );
                        Matcher trouveurWin = masqueWin.matcher( systeme.toLowerCase() );
                        if( trouveurWin.find() )
                        {
                                return "--" + nom + "=\"" + valeur + "\"" + precisions;
                        }
                        else
                        {
                                System.out.println( nom + "=" + valeur + precisions );
                                return "--" + nom + "=" + valeur + precisions;
                        }
                }
        }
        
/* classe qui lance et surveille un processus VLC (thread) */
                
        //Gere les process de controle vlc
        //fonctionne en parrall�le du reste
        class GereProcessus extends Thread
        {
                ParametreVlc[] commande; //commande � executer arguments s�par�s
                public Process processus;
                public boolean enCours = false;
                boolean reagirFinProc = true;
                EncadreProc appelant;        //objet appelant, � pr�venir en cas de fin
                
                GereProcessus( ParametreVlc[] comm, EncadreProc objAppelant )
                {
                        super();
                        commande = comm;
                        appelant = objAppelant;
                }
                
                public void terminer()
                {
                        if( enCours )
                        {
                                processus.destroy();
                        }
                }
                
                public void terminer( boolean reagir )
                {
                        if( enCours )
                        {
                                reagirFinProc = reagir;
                                processus.destroy();
                                enCours = false;
                        }
                }

                public void run()
                {
                        //Lancement du processus
                        if(! enCours )
                        {                                
                                String[] commComp = new String[commande.length + 1];
                                commComp[0] = chmVlc;
                                for( int k=1; k < commande.length + 1; k++ )
                                {
                                    commComp[k] = commande[k-1].chaine();
                                }
                                try
                                {
                                        Runtime r = Runtime.getRuntime();
                                        processus = r.exec( commComp );
                                        enCours = true;
                                        processus.waitFor();
                                        enCours = false;
                                        //on attend la fin du processus
                                        if( reagirFinProc )
                                                appelant.reagirFinProcessus( );
                                }
                                catch(Exception e)
                                {
                                        System.out.println("erreur d'execution VLC : " + e.toString() );
                                        enCours = false;
                                }
                        }
                }
        }
        
/* Classes qui utilisent gereProcessus pour lire ou enregistrer */
        
        //interface pour d�finir les actions communes
        //de EnrEnCours et LectureEnCours
        interface EncadreProc
        {
                public void reagirFinProcessus();
                public void arreter();
        }
        
        //Gere la lecture en cours
        class LectureEnCours implements EncadreProc
        {
                public boolean enCours = false;
                GereProcessus processus = null;
                
                LectureEnCours()
                {
                        //Cr�ation sans lecture
                }
        
                public void lancerFichier( String nomFichier )
                {
                        if( enCours ) arreter();
                        enCours = true;
                        //lancement du fichier s�lectionn�
                        processus =  new GereProcessus( new ParametreVlc[]{ new ParametreVlc( chmEnregistrements + sepDoss + nomFichier ) }, this );
                        processus.start();
                        
                        
                        //Modif interface
                        labelEnCours.setText( "En cours : " + nomFichier );
                        regarder.setText( "Arreter la lecture" );
                }

                public void lancerChaine()
                {
                        if( enCours ) arreter();
                        enCours = true;
                        //lancement de la chaine s�lectionn�e
                        int indChaine;
                        indChaine = listeAff.getSelectedIndex();
                        if( indChaine >= 0 )
                        {
                                String nomChaine = ((Chaine) listeChaines.elementAt( indChaine ) ).nom;
                                String adresseChaine = ((Chaine) listeChaines.elementAt( indChaine ) ).adresse;

                                processus = new GereProcessus( new ParametreVlc[]{ new ParametreVlc ( adresseChaine ) }, this );
                                processus.start();

                                //Modif interface
                                labelEnCours.setText( "En cours : " + nomChaine );
                                regarder.setText( "Arreter la lecture" );
                        }
                }

                //Arret de la lecture en cours
                public void arreter()
                {
                        //arret de la chaine en cours
                        if( enCours )
                        {
                                processus.terminer( false );
                                reagirFinProcessus();
                        }
                }        
                
                //Action en fin de lecture (appele par processus)
                public void reagirFinProcessus()
                {
                        enCours = false;
                        labelEnCours.setText( "En cours :" );
                        regarder.setText( "Regarder la chaine" );                
                }
        }
        
        //Gere un enregistrement en cours
        class EnrEnCours implements EncadreProc
        {
                public boolean enCours = false;
                GereProcessus processus = null;
                public Date momentDep = null;
                public String nomFichier = "";
                public int indChaine = 0;
                public boolean enrProgramme = false;
                Programmation progParent = null;
                
                EnrEnCours( int chaine, String fichier )
                {
                        //Cr�ation d'un enregistrement en cours 
                        Calendar maintenant = Calendar.getInstance();
                        String adresseChaine = ((Chaine) listeChaines.elementAt( chaine )).adresse;
                        ParametreVlc[] aFaire = new ParametreVlc[]{ new ParametreVlc( adresseChaine ), new ParametreVlc( "sout", "#standard", "{access=file,mux=ts,url=" + chmEnregistrements + sepDoss + fichier + "}" ), new ParametreVlc( "intf", "dummy" ) };
                        processus = new GereProcessus( aFaire, this );
                        //on lance le thread
                        processus.start();

                        indChaine = chaine;
                        momentDep = maintenant.getTime();
                        nomFichier = fichier;
                        enCours = true;
                }
                
                public void setProgParent( Programmation progParent )
                {
                        //on attribue � l'enregistrement une programmation
                        //dont il d�pend
                        //il l'apellera s'il s'arrete
                        this.progParent = progParent;
                        enrProgramme = ( progParent != null );
                }
                
                public Programmation getProgParent()
                {
                        return progParent;
                }
                
                //Arret de l'enregistrement
                public void arreter()
                {
                        if( enCours )
                        {
                                processus.terminer( false );
                                reagirFinProcessus();
                        }
                }
        
                //Action en fin d'enregistrement
                public void reagirFinProcessus()
                {
                        enCours = false;
                        majListeEnrEnCours();
                        if( progParent != null )
                                progParent.reagirFinEnregistrement();
                }
        }
        
/* Classe qui g�re les programmations : utilise la classe EnrEnCours */
        
        //Repr�sente un enregistrement programm�
        //fonctionne en parrall�le du reste
        class Programmation extends Thread
        {
                
                //infos enregitrement
                public String nom;
                public int idChaine;
                
                //infos �tat
                public boolean enCours = false;
                public boolean fini = false;
                
                //Heures
                public int heureDep;
                public int minuteDep;
                public int heureFin;
                public int minuteFin;
                
                //Date ponctuelle
                public int jour;
                public int mois;
                public int annee;
                
                //Dates r�p�titives
                public Vector jours;
                
                //r�p�titif ou ponctuel
                public boolean estPonctuel;
                
                //reprises si erreurs
                public int nbrReprises = 0;
                String suffixeReprises = "";
                
                
                //Utiles
                Calendar momentDep;
                Calendar momentFin;
                EnrEnCours enr = null;
                java.util.Timer chrono;
                
                public Programmation( String nom, int idChaine, int jour, int mois, int annee, int heureDep, int minuteDep, int heureFin, int minuteFin )
                {
                        //Cr�e une programmation � partir d'une date ponctuelle
                        this.estPonctuel = true;
                        this.nom = nom;
                        this.idChaine = idChaine;
                        this.jour = jour;
                        this.mois = mois;
                        this.annee = annee;
                        this.heureDep = heureDep;
                        this.minuteDep = minuteDep;
                        this.heureFin = heureFin;
                        this.minuteFin = minuteFin;
                        
                        momentDep = Calendar.getInstance();
                        momentFin = Calendar.getInstance();
                        momentDep.set( annee, mois, jour, heureDep, minuteDep, 0 );
                        momentFin.set( annee, mois, jour, heureFin, minuteFin, 0 );
                        
                        //Si changement de jour
                        if( momentFin.before( momentDep ) )
                        {
                                Date tmpFin = momentFin.getTime();
                                tmpFin.setTime( tmpFin.getTime() + 24 * 60 * 60 * 1000 );
                                momentFin.setTime( tmpFin );
                        }
                        
                        //on est parti
                        start();
                }
                
                public Programmation( String nom, int idChaine, Vector jours, int heureDep, int minuteDep, int heureFin, int minuteFin )
                {
                        //Cr�e une programmation � partir d'une repetition
                        this.estPonctuel = false;
                        this.nom = nom;
                        this.idChaine = idChaine;
                        this.jours = jours;
                        this.heureDep = heureDep;
                        this.minuteDep = minuteDep;
                        this.heureFin = heureFin;
                        this.minuteFin = minuteFin;
                        
                        preparerProgRep( true );
                        
                        //on est parti
                        start();
                }
                
                public Programmation( String nom, EnrEnCours enr, int heureFin, int minuteFin )
                {
                        //Cr�e une programmation � partir d'un enregistrement d�j� en cours
                        this.enr = enr;
                        enr.setProgParent( this );
                        this.estPonctuel = true;
                        this.nom = nom;
                        idChaine = enr.indChaine;
                        
                        momentDep = Calendar.getInstance();                        
                        momentDep.setTime( enr.momentDep );
                                                
                        momentFin = Calendar.getInstance();
                        momentFin.set( Calendar.HOUR_OF_DAY, heureFin );
                        momentFin.set( Calendar.MINUTE, minuteFin );
                        momentFin.set( Calendar.SECOND, 0 );
                        
                        //Si changement de jour
                        if( momentFin.before( momentDep ) )
                        {
                                Date tmpFin = momentFin.getTime();
                                tmpFin.setTime( tmpFin.getTime() + 24 * 60 * 60 * 1000 );
                                momentFin.setTime( tmpFin );
                        }
                        enCours = true;
                        
                        jour = momentDep.get( Calendar.DAY_OF_MONTH );
                        mois = momentDep.get( Calendar.MONTH );
                        annee = momentDep.get( Calendar.YEAR );
                        heureDep = momentDep.get( Calendar.HOUR_OF_DAY );
                        minuteDep = momentDep.get( Calendar.MINUTE );
                        this.heureFin = momentFin.get( Calendar.HOUR_OF_DAY );
                        this.minuteFin = momentFin.get( Calendar.MINUTE );
                        
                        //on est parti
                        start();
                        
                        majListeEnrEnCours();
                }
                
                public Programmation()
                {
                        //Cr�e un objet vide pour appel de progDeTexte
                }
                
                //renvoie une repr�sentation textuelle de la programmation
                public String repTexte()
                {
                        String chaine = "";
                        chaine+= "<programmation>";
                        chaine+= "\n\t<nom>" + nom.replaceAll( "<", "&lt;" ).replaceAll( ">", "&gt;" ) + "</nom>";
                        chaine+= "\n\t<adresseChaine>" + ((Chaine) listeChaines.elementAt( idChaine )).adresse.replaceAll( "<", "&lt;" ).replaceAll( ">", "&gt;" ) + "</adresseChaine>";
                        chaine+= "\n\t<heureDep>" + heureDep + ":" + minuteDep + "</heureDep>";
                        chaine+=  "\n\t<heureFin>" + heureFin + ":" + minuteFin + "</heureFin>";
                        if( estPonctuel )
                        {
                                chaine+= "\n\t<date>" + jour + "/" + mois + "/" + annee + "</date>";
                        }
                        else
                        {
                                for( int k=0; k < jours.size(); k++ )
                                {
                                        chaine+= "\n\t<jour>";
                                        switch( ((Integer) jours.elementAt( k )).intValue() )
                                        {
                                                case Calendar.MONDAY:
                                                        chaine+= "lundi";
                                                        break;
                                                case Calendar.TUESDAY:
                                                        chaine+= "mardi";
                                                        break;
                                                case Calendar.WEDNESDAY:
                                                        chaine+= "mercredi";
                                                        break;
                                                case Calendar.THURSDAY:
                                                        chaine+= "jeudi";
                                                        break;
                                                case Calendar.FRIDAY:
                                                        chaine+= "vendredi";
                                                        break;
                                                case Calendar.SATURDAY:
                                                        chaine+= "samedi";
                                                        break;
                                                case Calendar.SUNDAY:
                                                        chaine+= "dimanche";
                                                        break;
                                        }
                                        chaine+= "</jour>";
                                }
                        }
                        chaine+= "\n</programmation>";
                        return chaine;
                }
                
                //Cr�e et renvoie une programmation � partir d'une repr�sentation textuelle
                public Programmation progDeTexte( String chaine )
                {
                        Pattern masqueProg = Pattern.compile( "<programmation>(.*?)</programmation>", Pattern.DOTALL );
                        Matcher trouveurProg = masqueProg.matcher( chaine );
                        if(! trouveurProg.find() )
                                return null;
                        String strProg = trouveurProg.group( 1 );
                        
                        Pattern masqueNom = Pattern.compile( "<nom>\\s*([^<>]*)\\s*</nom>" );
                        Matcher trouveurNom = masqueNom.matcher( strProg );
                        if(! trouveurNom.find() )
                                return null;
                        String nomO = trouveurNom.group( 1 );
                        
                        Pattern masqueChaine = Pattern.compile( "<adresseChaine>\\s*([^<>]*)\\s*</adresseChaine>" );
                        Matcher trouveurChaine = masqueChaine.matcher( strProg );
                        if(! trouveurChaine.find() )
                                return null;
                        String addrChaineO = trouveurChaine.group( 1 );
                        int idChaineO = -1;
                        int k = 0;
                        while( k < listeChaines.size() && idChaineO == -1 )
                        {
                                Chaine chaineT = (Chaine) listeChaines.elementAt( k );
                                if( chaineT.adresse.equals( addrChaineO ) )
                                        idChaineO = k;
                                k++;
                        }
                        if( idChaineO == -1 )
                                return null;
                        
                        Pattern masqueHeureDep = Pattern.compile( "<heureDep>\\s*([0-9]{1,2}):([0-9]{1,2})\\s*</heureDep>" );
                        Matcher trouveurHeureDep = masqueHeureDep.matcher( strProg );
                        if(! trouveurHeureDep.find() )
                                return null;
                        int heureDepO = Integer.parseInt( trouveurHeureDep.group( 1 ) );
                        int minuteDepO = Integer.parseInt( trouveurHeureDep.group( 2 ) );
                        
                        Pattern masqueHeureFin = Pattern.compile( "<heureFin>\\s*([0-9]{1,2}):([0-9]{1,2})\\s*</heureFin>" );
                        Matcher trouveurHeureFin = masqueHeureFin.matcher( strProg );
                        if(! trouveurHeureFin.find() )
                                return null;
                        int heureFinO = Integer.parseInt( trouveurHeureFin.group( 1 ) );
                        int minuteFinO = Integer.parseInt( trouveurHeureFin.group( 2 ) );
                        
                        Pattern masqueDate = Pattern.compile( "<date>\\s*([0-9]{1,2})/([0-9]{1,2})/([0-9]{4})\\s*</date>" );
                        Matcher trouveurDate = masqueDate.matcher( strProg );
                        if( trouveurDate.find() )
                        {
                                int jourO = Integer.parseInt( trouveurDate.group( 1 ) );
                                int moisO = Integer.parseInt( trouveurDate.group( 2 ) );
                                int anneeO = Integer.parseInt( trouveurDate.group( 3 ) );
                                return new Programmation( nomO, idChaineO, jourO, moisO, anneeO, heureDepO, minuteDepO, heureFinO, minuteFinO );
                        }
                        else
                        {
                                Pattern masqueJour = Pattern.compile( "<jour>\\s*([^<>]*?)\\s*</jour>" );
                                Matcher trouveurJour = masqueJour.matcher( strProg );
                                Vector joursO = new Vector();
                                while( trouveurJour.find() )
                                {
                                        String repJour = trouveurJour.group( 1 );
                                        if( repJour.equals( "lundi" ) )
                                                joursO.add( new Integer( Calendar.MONDAY ) );
                                        else if( repJour.equals( "mardi" ) )
                                                joursO.add( new Integer( Calendar.TUESDAY ) );
                                        else if( repJour.equals( "mercredi" ) )
                                                joursO.add( new Integer( Calendar.WEDNESDAY ) );
                                        else if( repJour.equals( "jeudi" ) )
                                                joursO.add( new Integer( Calendar.THURSDAY ) );
                                        else if( repJour.equals( "vendredi" ) )
                                                joursO.add( new Integer( Calendar.FRIDAY ) );
                                        else if( repJour.equals( "samedi" ) )
                                                joursO.add( new Integer( Calendar.SATURDAY ) );
                                        else if( repJour.equals( "dimanche" ) )
                                                joursO.add( new Integer( Calendar.SUNDAY ) );
                                }
                                if( joursO.size() == 0 )
                                        return null;
                                return new Programmation( nomO, idChaineO, joursO, heureDepO, minuteDepO, heureFinO, minuteFinO );
                        }
                }
                
                //Pr�pare le prochain enregistrement r�p�t�
                void preparerProgRep( boolean accepterEnrDejaCommence )
                {
                        //accepterEnrDejaCommence : seulement pour la premi�re fois
                        //on place le calendrier de d�part � aujourd'hui
                        momentDep = Calendar.getInstance();
                        momentFin = Calendar.getInstance();
                        momentDep.set( Calendar.HOUR_OF_DAY, heureDep );
                        momentDep.set( Calendar.MINUTE, minuteDep );
                        momentDep.set( Calendar.SECOND, 0 );
                        momentFin.set( Calendar.HOUR_OF_DAY, heureFin );
                        momentFin.set( Calendar.MINUTE, minuteFin );
                        momentFin.set( Calendar.SECOND, 0 );
                        
                        boolean aujourdhuiOk;
                        if( accepterEnrDejaCommence )
                                aujourdhuiOk = momentFin.after( Calendar.getInstance() );
                        else
                                aujourdhuiOk = momentDep.after( Calendar.getInstance() );
                        
                        //jour actuel
                        int jourAct = Calendar.getInstance().get( Calendar.DAY_OF_WEEK );
                        int minJoursAj = 10;
                        
                        for( int k=0; k < jours.size(); k++ )
                        {
                                int joursAj = ((Integer) jours.elementAt( k )).intValue() - jourAct;
                                if( joursAj < 0 || ( joursAj == 0 && ! aujourdhuiOk ) )
                                        joursAj += 7;
                                if( joursAj < minJoursAj )
                                        minJoursAj = joursAj;
                        }
                        //on a le nombre minimum de jours � ajouter
                        Date dtDep = momentDep.getTime();
                        dtDep.setTime( dtDep.getTime() + minJoursAj * 24 * 60 * 60 * 1000 );
                        momentDep.setTime( dtDep );
                        Date dtFin = momentFin.getTime();
                        dtFin.setTime( dtFin.getTime() + minJoursAj * 24 * 60 * 60 * 1000 );
                        momentFin.setTime( dtFin );
                        
                        //Si changement de jour
                        if( momentFin.before( momentDep ) )
                        {
                                Date tmpFin = momentFin.getTime();
                                tmpFin.setTime( tmpFin.getTime() + 24 * 60 * 60 * 1000 );
                                momentFin.setTime( tmpFin );
                        }
                }
                
                void lancerEnr()
                {
                        //lance l'enregistrement et le timer de fin
                        if( momentFin.after( Calendar.getInstance() ))
                        {
                                String nomChaine = ((Chaine) listeChaines.elementAt( idChaine ) ).nom;
                                Calendar maintenant = Calendar.getInstance();
                                String prefFichier = simpChaine( nomChaine ) + "-" + maintenant.get( Calendar.DAY_OF_MONTH ) + "-" + maintenant.get( Calendar.MONTH ) + "-" + maintenant.get( Calendar.YEAR ) + "-" + maintenant.get( Calendar.HOUR_OF_DAY ) + "h" + maintenant.get( Calendar.MINUTE ) + "-";
                                enr = new EnrEnCours( idChaine, prefFichier + nom + suffixeReprises + extVideo );
                                enr.setProgParent( this );
                                
                                enrEnCours.add( enr );
                                majListeEnrEnCours();
                                
                                enCours = true;
                                chrono = new java.util.Timer();
                                chrono.schedule( new TacheTimer( TacheTimer.FINIR ), momentFin.getTime() );
                        }
                        else
                        {
                                rafraichirFinEnregistrement();
                        }
                        majListeProg();                        
                }
                
                //un enregistrement est termin�
                //on arrete si ponctuel
                //ou on relance
                void rafraichirFinEnregistrement( )
                {
                        if( estPonctuel )
                        {
                                fini = true;
                        }
                        else
                        {
                                preparerProgRep( false );
                                chrono = new java.util.Timer();
                                chrono.schedule( new TacheTimer( TacheTimer.LANCER ), momentDep.getTime() );
                        }                        
                }
                
                void finirEnr()
                {
                        //termine l'enregistrement
                        //et supprime la programmation
                        //ou la r�initialise
                        enr.setProgParent( null );      //�vite d'etre pr�venu de la fin du process
                        chrono.cancel();
                        enCours = false;
                        enr.arreter();
                        rafraichirFinEnregistrement();
                        majListeProg();
                }
                
                public void arreterEnrEnCours()
                {
                        //On arrete l'enregistrement et on supprime la programmation si n�cessaire
                        finirEnr();
                }
                
                public void reagirFinEnregistrement()
                {
                        //reaction � la fin de l'enregistrement demand�
                        //fin non pr�vue !!!
                        nbrReprises++;
                        suffixeReprises = "_reprise" + nbrReprises;
                        lancerEnr();
                }
                
                public void supprimer()
                {
                        if( enCours )
                                arreterEnrEnCours();
                        chrono.cancel();
                }
                
                public void run()
                {
                        //Lance le timer de d�but
                        //ou l'enregistrement si necessaire
                        //si l'enregistrement est deja la, lance le timer de fin
                        if(! enCours )
                        {
                                if( momentDep.before( Calendar.getInstance() ) )
                                {
                                        lancerEnr();
                                }
                                else
                                {
                                        chrono = new java.util.Timer();
                                        chrono.schedule( new TacheTimer( TacheTimer.LANCER ), momentDep.getTime() );
                                }
                        }
                        else
                        {
                                if( momentFin.before( Calendar.getInstance() ) )
                                {
                                        finirEnr();
                                }
                                else
                                {
                                        chrono = new java.util.Timer();
                                        chrono.schedule( new TacheTimer( TacheTimer.FINIR ), momentFin.getTime() );
                                }
                        }
                }
                
                //objet qui effectue lancerEnr ou finirEnr quand pr�vu
                class TacheTimer extends TimerTask
                {
                        int tache;
                        static final int LANCER = 0;
                        static final int FINIR = 1;
                        public TacheTimer( int tache )
                        {
                                this.tache = tache;
                        }
                        
                        public void run()
                        {
                                if( tache == LANCER )
                                {
                                        lancerEnr();
                                }
                                else if( tache == FINIR )
                                {
                                        finirEnr();
                                }
                        }
                }
        }
}
