Parseur de tags id3v2 ...

Contenu du snippet

... Ou en tous cas le début.
Avant de parler du code proprement dit, je vais expliquer pourquoi j'ai créé une telle classe ... Ce script appartient à un projet un peu plus vaste qui dépasse un peu le PHP : un lecteur mp3 en Flash. Sauf que le Flash ne gère pas les tags Id3v2 des fichiers mp3, d'où l'utilisation du PHP. J'ai alors cherché des classes de gestions de ces tags et la seule classe opérationnelle que j'ai trouvé est allemande. Du coup, histoire de bien comprendre comment ça marchait, j'ai cherché beaucoup sur le net des informations sur ces tags et il se trouve que c'est tout de même assez élaboré.
Du coup, j'ai revu les opérations binaires, les octets, l'hexadecimal et tout ça et je me suis dit que ça pourrait peut-être interesser quelqu'un. Et histoire de mettre en pratique tout ce que j'ai appris, j'ai mis en place ce début de classe que je tacherais de completer dès que j'aurais un peu plus de temps.
Au niveau du code, c'est en fait assez basique. Il faut juste bien comprendre les fonction ord() et les opérateurs binaires et le tour est joué. Il faut aussi savoir lire l'anglais et lire la structure des tags ID3v2 sur www.id3.org. Ensuite, voilà ! ...

Source / Exemple :


<?php
/* ------------------------- */
   echo '<pre>';
/* ------------------------- */
   class ID3Parser
   {
      // Informations sur le fichier.
      var $Name;
      var $Path;
      var $Content;
      // Informations ID3.
      var $FrameList = array();
      var $Headers = array();
      // Constructeur.
      function __construct($file_directory)
      {
         $i = strrpos($file_path, '/');
         if(!$i) $i = -1;
         $length = strlen($file_directory);
         $this -> Name = substr($file_directory, $i + 1, $length - $i);
         $this -> Path = substr($file_directory, 0, $i + 1);
         return true;
      }
      // Charge le fichier en mémoire.
      function LoadFile()
      {
         $file_directory = ($this -> Path).($this -> Name);
         $fp = fopen($file_directory, 'rb');
         $this -> Content = fread($fp, filesize($file_directory));
         fclose($fp);
         return true;
      }
      // Lit les en-têtes.
      function GetHeader()
      {
         // Extractions des en-têtes.
         $headers = substr($this -> Content, 0, 10);
         // Présence de l'indicateur ID3.
         $this -> Headers['ID3'] = (substr($headers, 0, 3) == 'ID3') ? 0 : 1;
         // Version du tag.
         $this -> Headers['VERSION'] = ord(substr($headers, 3, 1)).'.'.ord(substr($headers, 4, 1));
         $list = &$this -> Headers['FLAGS'];
         $list = array();
         // Extraction des flags.
         $flags = ord(substr($headers, 5, 1));
         // Valeur des propriétés.
	     	$list['UNSYCHRONISATION'] = ($flags & 128) ? 1 : 0; 
		   $list['EXTENDED_HEADER'] = ($flags & 64) ? 1 : 0;
		   $list['EXPERIMENTAL'] = ($flags & 32) ? 1 : 0;
		   $list['FOOTER'] = ($flags & 16) ? 1 : 0;
         // Taille.
         $this -> Headers['SIZE'] = (ord(substr($headers, 6, 1)) & 127) * 2097152 +
                                    (ord(substr($headers, 7, 1)) & 127) * 16384 +
                                    (ord(substr($headers, 8, 1)) & 127) * 128 +
                                    (ord(substr($headers, 9, 1)) & 127);
      }
      // Lit les frames.
      function GetFrames()
      {
         $i = 0;
         $size = $this -> Headers['SIZE'];
         $frames = substr($this -> Content, 10, $size);
         while($i < $size - 1)
         {
            // Extraction de l'ID de la frame.
            $id = substr($frames, $i, 4); $i += 4;
            if(trim($id) == '') break;
            $list = &$this -> Frames[$id];
            $list = array();
            // Taille du tag.
            $list['SIZE'] = (ord(substr($frames, $i + 0, 1)) & 127) * 2097152 +
                            (ord(substr($frames, $i + 1, 1)) & 127) * 16384 +
                            (ord(substr($frames, $i + 2, 1)) & 127) * 128 +
                            (ord(substr($frames, $i + 3, 1)) & 127);
            $i += 4;
            // Extraction des flags.
			   $list['TAG_ALTER_DISCARD'] = (ord(substr($frames, $i, 1)) & 128) ? 1 : 0;
			   $list['FILE_ALTER_DISCARD'] = (ord(substr($frames, $i, 1)) & 64) ? 1 : 0;
			   $list['READ_ONLY'] = (ord(substr($frames, $i, 1) & 32)) ? 1 : 0;
			   $i += 1;
			   $list['GROUP'] = (ord(substr($frames, $i, 1)) & 128) ? 1 : 0;
			   $list['COMPRESSED'] = (ord(substr($frames, $i, 1)) & 16) ? 1 : 0;
			   $list['ENCRYPTED'] = (ord(substr($frames, $i, 1)) & 8) ? 1 : 0;
			   $list['UNSYCHRONISED'] = (ord(substr($frames, $i, 1)) & 4) ? 1 : 0;
			   $list['DATA_LENGTH_INDICATOR'] = (ord(substr($frames, $i, 1)) & 2) ? 1 : 0;
			   $i += 1;
            //Extraction du contenu
            $list['CONTENT'] = trim(substr($frames, $i, $list['SIZE']));
            $i += $list['SIZE'];
         }
      }
      
   }
/* ------------------------- */
   $info = new ID3Parser('zikmu.mp3');
   $info -> LoadFile();
   $info -> GetHeader();
   $info -> GetFrames();
   print_r($info);
/* ------------------------- */
   echo '</pre>';
/* ------------------------- */
?>

Conclusion :


Le code est moche et extrèmement optimisable. Et c'est pourquoi ça me pousse à créer un vrai tutorial sur les opérateurs binaires, quitte à faire des rappels sur les octets, l'hexa et tout ça, parce que c'est vraiment interessant.
Donc ce petit morceau de code n'est qu'un avant gout de quelque chose de bien plus gros sur les opérateurs binaires et les tags mp3. Mais je voulais quand même le poster.
Voilà ... J'espère que c'est pas trop le bordel ce que je raconte, parce que je suis un peu fatigué.
++ !
LocalStone.

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.