Serial CD 2

Ernesto Hernandez-Novich emhn at telcel.net.ve
Fri May 4 14:14:13 CDT 2001


On 4 May 2001, mou ef wrote:
> en el mail anterior les pedi como averiguar el numero serial de un CD
> pero pido disculpas por no explicarme bien lo que en realidad necesito
> es algun programa que pueda leer el numero serial del CD y guardarlo en
> un archivo de texto... lo necesito por favor ya que tengo que registrar 
> bastantes CD y si pudiera hacerlo un programa seria mejor...
> 
> (si no conocen algun programa como este pero tienen idea de como hacer 
> uno que lo haga "en leguaje C o Basic" por favor haganla llegar tambien y yo
> tratare de inventarme el programa...) 

Los CD-ROMs o CD-AUDIO no tienen ningún identificador único tal y como lo
define el Red Book y los subsiguientes Yellow Book, Green Book y Orange Book,
de manera que no existe "firma" o "serial" escrito en ellos (contrariamente
a lo que cree todo el mundo :-). Sin embargo, la tabla de contenidos del
disco puede ser usada como un identificador bastante confiable, porque es
muy poco probable que existan dos CD's diferentes con la misma cantidad
de pistas con _exactamente_ la misma duración y longitud. En esto se basa el
mecanismo de indizado que utliza CDDB para registrar los discos; no es
perfecto, pero en general funciona.

Entonces, para obtener un "serial" de un CD de audio, simplemente utiliza
cualquier software de reproducción de CD que soporte CDDB y verás que en
los archivos de inventario generados aparece la "firma" CDDB, que no es
más que aplicar ciertas operaciones aritméticas combinando los datos de
la tabla de contenidos. Por ejemplo, usando kscd en KDE, en los directorios
$KDEBASE/share/apps/kscd/cddb/* encontrarás archivos cuyos nombres son las
"firmas" de los CDs.

Puedes usar la opción -toc de cdrecord para obtener la tabla de contenidos
(conocida como PMA) de un CD. Pero por supuesto...

#!/usr/bin/perl
# Los IOCTLs tomados desde /usr/include/linux/cdrom.h
my $CDREADTOCHDR   = 0x5305;
my $CDREADTOCENTRY = 0x5306;
my $CDMSF          = 0x02;

my $be = unpack("h*",pack("s",1)) =~ /01/;

sub ReadTOC {
  my $device = shift;

  my $tochdr;
  sysopen(CD,$device,O_RDONLY|O_NONBLOCK) or die "Pon un CD! [$!]";
  ioctl(CD,$CDREADTOCHDR,$tochdr) or die "Pon un CD de audio! [$!]";
  my ($start,$end) = unpack "CC",$tochdr;
  my @tracks;
  for ($start..$end) {
    push @tracks,$_;
  }
  push @tracks, 0xAA;
  
  my @r;
  my $tocentry;
  my $toc = '';
  my $size = 0;
  for (@tracks) {
    $toc .= (" " x 8);
    $size += 8;
  }
  my $count = 0;
  foreach my $i (@tracks) {
    $tocentry = pack "CCC", $i,0,$CDMSF;
    ioctl(CD,$CDREADTOCENTRY,$tocentry) or die "Pista $i chimba [$!]";
    my ($min,$sec,$frame) = unpack "CCCC", substr($tocentry,4,4);
    $count += 8;
    push @r, { min    => $min, 
               sec    => $sec, 
               frame  => $frame,
               frames => $frame + $sec * 75 + $min * 60 * 75
             };
  }
  close CD;
  return @r;
}

sub CDDBSum {
  my $n   = shift;
  my $ret = 0;

  while ($n > 0) {
    $ret += ($n % 10);
    $n    = int $n / 10;
  }
  return $ret;
}

sub CDDBId {
  my ($total,$toc) = @_;
  my ($i,$t,$n) = (0,0,0);
  while ($i < $total) {
    $n += CDDBSum(($toc->[$i]->{min} * 60) + $toc->[$i]->{sec});
    $i++;
  }
  $t = (($toc->[$total]->{min} * 60) + $toc->[$total]->{sec}) -
       (($toc->[0]->{min} * 60) + $toc->[0]->{sec});
  return (($n % 0xff) << 24 | $t << 8 | $total);
}

sub GetCDId {
  my $cd = shift;
  
  my @toc   = ReadTOC($cd);
  my $total = $#toc;
  my $id    = CDDBId($total,\@toc);
  return ($id,$total,\@toc);
}

my ($id,$total,$rtoc) = GetCDId("/dev/cdrom");

printf "Id:    %lu CDDB Id %08X\n",$id,$id;
printf "Total: %2d\n",$total;
my $t = 1;
foreach (@$rtoc) {
  printf "Trk %2d: %02d:%02d, %8ld frames\n",
         $t, $_->{min}, $_->{sec}, $_->{frames};
  $t++;
}

Este programa es específico para Linux y muestra el Id "calculado" para
el CD de _audio_ tal como lo sugiere CDDB tanto en decimal como en hexadecimal.
Si quieres hacerlo funcionar en otro Unix debes cambiar los IOCTLs según
corresponda (afirmo que funciona en (Free|Net|Open)BSD :-).
-- 
Ernesto Hernández-Novich - Running Linux 2.4.2 i686 - Unix: Live free or die!
-----BEGIN GEEK CODE BLOCK-----
Version: 3.1
GCS/E d+(++) s+: a C+++$ UBLAVHIOSC*++++$ P++++$ L+++$ E- W+ N++ o K++ w--- O-
M- V PS+ PE Y+ PGP>++ t+ 5 X+ R* tv+ b++ DI+++$ D++ G++ e++ h r++ y+
-----END GEEK CODE BLOCK-----


------------------------------------------------------------------------
Enviar e-mail a <majordomo at pm.org> colocando en el cuerpo:
"UNSUBSCRIBE caracas-pm-list" para desuscribirse.
"INFO caracas-pm-list" para conocer las reglas de etiqueta.
------------------------------------------------------------------------



More information about the caracas-pm mailing list