Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 25/11/2014, à 00:31

ubuntuforce

Jouer un CD grâce a ioctl et les pseudo fichier-driver.

Salut les C Linux,

Comme le titre l'indique je cherche a jouer un CD avec la fonction ioctl (Input/Output Control) en ouvrant le pseudo fichier-driver du cdrom.

Voici le code:

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#include <sys/ioctl.h>

#include <linux/cdrom.h>

int main(int argc, char *argv[]) {
  
  /** Programme who should play the first track from an CD with ioctl(...) calls */

  int fd ;
  
  
  struct cdrom_tochdr   table_of_content_headers  ; // First && Last Track infos.
  struct cdrom_tocentry table_of_content_entries  ; // Offsets every track on the CD.
  
  struct cdrom_msf      msf_playing_data_structur ; // Used by CDROMPLAYMSF to set the Start and playing End.
  
  struct cdrom_subchnl  playing_data_informations ; // Keep status, current position min,sec,frame infos...
  
  if ((fd=open("/dev/cdrom",O_RDONLY)) == -1) {
    perror("Error open device") ;
    exit(EXIT_FAILURE) ;
  }
  
  fprintf(stdout,"Press any key to initialise the CD...\n") ; 
  getchar() ;
  
  if ( ioctl(fd, CDROMREADTOCHDR, &table_of_content_headers) == -1) {
    perror("ioctl read cdrom T.O.C headers error") ;
    exit(EXIT_FAILURE) ;
  }
  
  uint8_t first   = table_of_content_headers.cdth_trk0 ; // First track from the CD number.
  uint8_t last    = table_of_content_headers.cdth_trk1 ; // Last track  from the CD number.
  
  table_of_content_entries.cdte_track  = first     ;  // We set the first track to get Table of Content offset for playing starting offset.
  table_of_content_entries.cdte_format = CDROM_MSF ;  // Set the format.
  
  if ( ioctl(fd, CDROMREADTOCENTRY, &table_of_content_entries) == -1) {
    perror("ioctl read cdrom T.O.C entries error") ;
    exit(EXIT_FAILURE) ;
  }
  
  msf_playing_data_structur.cdmsf_min0=table_of_content_entries.cdte_addr.msf.minute  ;  // Set playing the start offset.
  msf_playing_data_structur.cdmsf_sec0=table_of_content_entries.cdte_addr.msf.second  ;  // Set playing the start offset.
  msf_playing_data_structur.cdmsf_frame0=table_of_content_entries.cdte_addr.msf.frame ;  // Set playing the start offset.
  
  table_of_content_entries.cdte_track  = first+1   ; // We set the second track to get Table of Content offset for playing end offset.  /** Alternative: CD end definition CDROM_LEADOUT */
  table_of_content_entries.cdte_format = CDROM_MSF ; // Playing management format.
  
  if ( ioctl(fd, CDROMREADTOCENTRY, &table_of_content_entries) == -1) {
    perror("ioctl read cdrom T.O.C entries error") ;
    exit(EXIT_FAILURE) ;
  }
  
  msf_playing_data_structur.cdmsf_min1=table_of_content_entries.cdte_addr.msf.minute  ;  // Set playing the end offset.
  msf_playing_data_structur.cdmsf_sec1=table_of_content_entries.cdte_addr.msf.second  ;  // Set playing the end offset. 
  msf_playing_data_structur.cdmsf_frame1=table_of_content_entries.cdte_addr.msf.frame ;  // Set playing the end offset.
  
  fprintf(stdout,"Press any key to ear the first track...\n") ;
  getchar() ;
  
  if ( ioctl(fd, CDROMPLAYMSF, &msf_playing_data_structur) == -1) {
    perror("ioctl cdrom playing error") ;
    exit(EXIT_FAILURE) ;
  }
  
  
  playing_data_informations.cdsc_format=CDROM_MSF ;
  if ( ioctl(fd, CDROMSUBCHNL, &playing_data_informations) == -1) {
    perror("ioctl cdrom get informations error") ;
    exit(EXIT_FAILURE) ;
  }
  
  
  
  while (playing_data_informations.cdsc_audiostatus != CDROM_AUDIO_COMPLETED ) {
    /* This part is experimental because i cannot play the CD from this programme actually */
    
   /** Get 
   * 
   * playing_data_informations.cdsc_audiostatus 
   * 
   * values with command:
   * 
   * $ grep AUDIO_ /usr/include/linux/cdrom.h
   * ******************************************/
    
    fprintf(stdout,"Press any key to pause the CD...\n") ;
    getchar() ;
    
    if ( ioctl(fd, CDROMPAUSE) == -1) {
      perror("ioctl cdrom pause error") ;
      exit(EXIT_FAILURE) ;
    }
    
    fprintf(stdout,"Press any key to resume the CD...\n") ;
    getchar() ;
    
    if ( ioctl(fd, CDROMRESUME) == -1) {
      perror("ioctl cdrom resume error") ;
      exit(EXIT_FAILURE) ;
    }
    
    /** Update the informations struct to display progressbar per example. */
    if ( ioctl(fd, CDROMSUBCHNL, &playing_data_informations) == -1) {
      perror("ioctl cdrom get informations error") ;
      exit(EXIT_FAILURE) ;
    }
  }
  
  close(fd) ;
}

Mais ce n'est pas le cas, dans le bouquin qui date du 8. Avril 2010, il est dit qu'il faut définir le lecteur de cdrom comme source sonore active, pour que cela fonctionne, ce qui peut être fait grace au programme aumix.

Extrait de aptitude show aumix:

Description : Programme de contrôle de mixeur audio simple en mode texte
aumix est un petit programme simple à utiliser pour contrôler le mélangeur de
votre carte son.

Par la commande:

$ auxmix -c 100

Mais ça ne fonctionne pas car dès que l'on insère le CD il est pris en charge par le démon udev qui vous sape le droit sur votre lecteur CDROM comme l'atteste le petit programme suivant:

#include <stdio.h>
#include <stdlib.h>  

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#include <sys/ioctl.h>

#include <linux/cdrom.h>

int main(int argc, char *argv[]) {
  
  int fd ;
  
  if ((fd=open("/dev/cdrom",O_RDONLY | O_NONBLOCK)) == -1) {
    perror("Error open device") ;
    exit(EXIT_FAILURE) ;
  }
  
  
  
  fprintf(stdout,"Press any key to eject CDROM...\n") ; 
  getchar() ;
  
  if ( ioctl(fd, CDROMEJECT) == -1) {
    perror("ioctl cdrom eject error") ;
    exit(EXIT_FAILURE) ;
  }
  
  exit(EXIT_SUCCESS) ;
}

Qui fonctionne parfaitement quand aucun média n'est dans le lecteur de CDROM mais si l'on insère un CD ca ne fonctionne plus:

$./a.out
Press any key to eject CDROM...

ioctl cdrom eject error: Input/output error

Bref le problème est le demon udev qui je crois est un module du kernel, qui nous prives, en général des accès au pseudo fichier-driver contenus dans le répertoire:

/dev/

Le problème se voit quand ont essaie d'accéder aux pseudo fichier-driver pour par exemple enregistrer un son et le jouer car ALSA ou ESound ont remplacer OSS celui ne pouvant ne jouer qu'une seule source sonore a la fois et je crois est devenus propriétaire et donc obsolète.

Bon il a été définis que la sacré rétrocompatibilité devait être assurer en émulant les pseudo fichier-driver de OSS:

-) /dev/audio
-) /dev/sequencer
-) /dev/mixer
-) /dev/dsp

Mais ce n'est guère le cas sur mon système dans /dev, je trouve le répertoire /dev/snd qui comportes des nom barbares par rapport a la logique des fichiers-driver évoquer ci-dessus:

cd /dev/snd ;  ls -l 
total 0
drwxr-xr-x  2 root root       60 nov.  24 23:15 by-path
crw-rw----+ 1 root audio 116,  7 nov.  24 23:15 controlC0
crw-rw----+ 1 root audio 116,  6 nov.  24 23:15 hwC0D0
crw-rw----+ 1 root audio 116,  5 nov.  24 23:17 pcmC0D0c
crw-rw----+ 1 root audio 116,  4 nov.  25 00:01 pcmC0D0p
crw-rw----+ 1 root audio 116,  3 nov.  24 23:17 pcmC0D1p
crw-rw----+ 1 root audio 116,  2 nov.  24 23:15 pcmC0D2c
crw-rw----+ 1 root audio 116,  1 nov.  24 23:15 seq
crw-rw----+ 1 root audio 116, 33 nov.  24 23:15 timer

Bref moi qui comprend pas grand chose au son mais qui trouve la logique de OSS assez explicite et qui aurai sûrement permis a mon petit lecteur de CD de fonctionner en son temps. Je trouve que Linux devient de plus en plus fermée a sa logique (Un kernel module nous barre la route a la philosophie tout est "simplement" fichier) : l'intervention d'un kernel-module sur le cdrom qui vous en barre l'accès n'en n'est qu'une démonstration.

Maintenant faut-t-il que j'écrive un driver de carte audio ou y a-t-il un moyen pour que le kernel-module ne vous ôte pas la pain de la bouche: sûrement, seulement je ne le connais pas...

Merci pour vos réponses, réactions, avis sur la question.


Rendez-vous sur mon site présentant mes créations open-source: http://www.open-source-projects.net/
Rendez-vous sur mon site dédier a mes créations d'imagerie 3D: http://www.3dreaming-imaging.net/
Testez pendant une semaine l'éditeur avec terminaux intégrées http://www.open-source-projects.net/it-edit/it-edit Vous l'adopterai sûrement !

Hors ligne