IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Jouer un CD avec ioctl et les pseudo file-devices sonores.


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut Jouer un CD avec ioctl et les pseudo file-devices sonores.
    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:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
     
    #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:
    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:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
     
    #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.

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Bonjour,

    • Ce n'est pas « auxmix » mais « aumix » ;
    • Il est important que l'on connaisse ta distribution exacte car beaucoup de ces outils ont tendance à devenir obsolètes ces temps-ci ;
    • udev n'est pas directement en cause : c'est le système qui gère la création à la volée de périphériques sous /dev au fur et à mesure qu'ils sont déclarés ou révoqués (auparavant, sous UNIX, les fichiers spéciaux étaient créés avec mknod uniquement et avec des numéros mineur et majeur). C'est aussi lui qui va se charger de certaines actions associées à ces événements ;
    • udev est en train de se faire absorber par systemd sur les distributions, avec pas mal d'autres choses. Ça ne manque pas de faire grincer les dents de nombreux utilisateurs de Linux ;
    • C'est le même auteur qui a écrit PulseAudio, amené à remplacer également les autres systèmes sonores.


    Quoi qu'il en soit, il est possible de demander le verrouillage du lecteur CD, ce qui t'empêche de l'éjecter avec le bouton. J'imagine que cela neutralise également l'appel ioctl. La commande « eject » s'en accommode par contre fort bien mais je suppose qu'elle doit déverrouiller explicitement le lecteur avant d'éjecter son tiroir. Pour le reste, ce n'est pas udev qui accapare l'accès mais probablement un programme en userspace lancé automatiquement avec la détection de l'insertion d'un CD. Fais un lsof sur /dev/cdrom ainsi que sur le fichier qu'il pointe, puisque « /dev/cdrom » est en fait un lien symbolique sur le fichier spécial gérant le bon lecteur.

Discussions similaires

  1. Se jouer des types avec les void*?
    Par Spidyy dans le forum Débuter
    Réponses: 2
    Dernier message: 15/08/2009, 13h05
  2. controler la musique avec les pseudo-url
    Par legide dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 04/07/2008, 15h47
  3. Problème de SESSION avec les "pseudo-frame" PHP
    Par kergad dans le forum Langage
    Réponses: 10
    Dernier message: 24/05/2008, 01h12
  4. valeurs dans URL avec les pseudo frames
    Par paradeofphp dans le forum Langage
    Réponses: 3
    Dernier message: 05/09/2006, 12h38
  5. [Tableaux] Problème avec un array et les pseudo frame
    Par azerty53 dans le forum Langage
    Réponses: 6
    Dernier message: 10/05/2006, 14h57

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo