Differenze tra le versioni di "Conoscere con le funzioni esterne di ALSA i dispositivi audio presenti nel sistema"

Da Gambas-it.org - Wikipedia.
 
(2 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
 
Alcune funzioni esterne del API di ALSA consentono di conoscere quali sono i dispositivi audio delle schede audio presenti nel proprio sistema.
 
Alcune funzioni esterne del API di ALSA consentono di conoscere quali sono i dispositivi audio delle schede audio presenti nel proprio sistema.
 
  
 
Mostriamo due esempi, nei quali sul ''Form'' dell'applicativo porremo una ''ListBox''.
 
Mostriamo due esempi, nei quali sul ''Form'' dell'applicativo porremo una ''ListBox''.
Riga 8: Riga 7:
 
    
 
    
 
   
 
   
  Library "libasound:2"
+
  Library "libasound:2.0.0"
 
+
 
  Private Const SND_PCM_STREAM_PLAYBACK As Byte = 0  <FONT color=gray>' ''Playback stream''</font>
 
  Private Const SND_PCM_STREAM_PLAYBACK As Byte = 0  <FONT color=gray>' ''Playback stream''</font>
 
   
 
   
Riga 93: Riga 92:
 
    
 
    
 
   
 
   
  '''Public''' Sub Form_Open()
+
  Public Sub Form_Open()
 
   
 
   
 
   Me.show
 
   Me.show
Riga 103: Riga 102:
 
   Lista_Dispositivi()
 
   Lista_Dispositivi()
 
   
 
   
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Private''' Procedure Lista_Dispositivi()
+
  Private Procedure Lista_Dispositivi()
 
   
 
   
 
   Dim handlCtl, info, pcminfo As Pointer
 
   Dim handlCtl, info, pcminfo As Pointer
Riga 211: Riga 210:
 
   Wend
 
   Wend
 
   
 
   
  '''End'''
+
  End
 
 
  
  
 
Di seguito invece il secondo possibile codice:
 
Di seguito invece il secondo possibile codice:
  Library "libasound:2"
+
  Library "libasound:2.0.0"
 
   
 
   
 
  Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0
 
  Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0
Riga 326: Riga 324:
 
   
 
   
 
   
 
   
  '''Public''' Sub Form_Open()
+
  Public Sub Form_Open()
 
   
 
   
 
   Me.show
 
   Me.show
Riga 336: Riga 334:
 
   Lista_Dispositivi()
 
   Lista_Dispositivi()
 
   
 
   
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Public''' Sub Lista_Dispositivi()
+
  Public Sub Lista_Dispositivi()
 
   
 
   
 
   Dim err, cardNum, devNum, unaVolta As Integer
 
   Dim err, cardNum, devNum, unaVolta As Integer
Riga 345: Riga 343:
 
   Dim $str As String
 
   Dim $str As String
 
   
 
   
 +
  ListBox1.Add("---- DISPOSITIVI HARDWARE AUDIO PRESENTI ----")
 
   
 
   
  ListBox1.Add("---- DISPOSITIVI HARDWARE AUDIO PRESENTI ----")
+
  cardNum = -1
 +
 
 +
  Do
 
   
 
   
  cardNum = -1
+
    err = snd_card_next(VarPtr(cardNum))
+
    If err < 0 Then Error.Raise("Impossibile ottenere il numero della scheda audio successiva: " & snd_strerror(err))
 
  While True
 
 
    err = snd_card_next(VarPtr(cardNum))
 
    If err < 0 Then Error.Raise("Impossibile ottenere il numero della scheda audio successiva: " & snd_strerror(err))
 
 
    
 
    
 
  <FONT color=gray>' ''Se non vi sono più schede, Alsa imposta "cardNum" a -1:''</font>
 
  <FONT color=gray>' ''Se non vi sono più schede, Alsa imposta "cardNum" a -1:''</font>
    If cardNum < 0 Then Exit
+
    If cardNum < 0 Then Exit
      
+
     $str = "hw:" & CStr(cardNum)
    $str = "hw:" & CStr(cardNum)
+
    err = snd_ctl_open(VarPtr(audioHandle), $Str, 0)
+
    If err < 0 Then Error.Raise("Impossibile aprire la connessione con la scheda audio: " & snd_strerror(err))
    err = snd_ctl_open(VarPtr(audioHandle), $Str, 0)
+
    unaVolta = 0
    If err < 0 Then Error.Raise("Impossibile aprire la connessione con la scheda audio: " & snd_strerror(err))
 
     
 
    unaVolta = 0
 
 
        
 
        
 
  <FONT color=gray>' ''Parte con il primo dispositivo audio sulla scheda individuata:''</font>
 
  <FONT color=gray>' ''Parte con il primo dispositivo audio sulla scheda individuata:''</font>
    devNum = -1
+
    devNum = -1
+
      Do
    While True
 
 
 
  <FONT color=gray>' ''Ricava il numero del successivo dispositivo Midi sulla scheda attuale:''</font>
 
  <FONT color=gray>' ''Ricava il numero del successivo dispositivo Midi sulla scheda attuale:''</font>
      err = snd_ctl_pcm_next_device(audioHandle, VarPtr(devNum))
+
        err = snd_ctl_pcm_next_device(audioHandle, VarPtr(devNum))
      If err < 0 Then Error.Raise("Impossibile ottenere il numero del successivo dispositivo audio: " & snd_strerror(err))
+
        If err < 0 Then Error.Raise("Impossibile ottenere il numero del successivo dispositivo audio: " & snd_strerror(err))
 
 
  <FONT color=gray>' ''Se non ci sono altri dispositivi audio sulla scheda audio, Alsa imposta "devNum" a -1.
 
  <FONT color=gray>' ''Se non ci sono altri dispositivi audio sulla scheda audio, Alsa imposta "devNum" a -1.
 
  ' ''NOTA: E' possibile che la scheda audio (ad esempio una scheda audio digitale) possa non avere dispositivi audio:''</font>
 
  ' ''NOTA: E' possibile che la scheda audio (ad esempio una scheda audio digitale) possa non avere dispositivi audio:''</font>
      If devNum < 0 Then Exit
+
        If devNum < 0 Then Exit
+
        If Not unaVolta Then
      If Not unaVolta Then
 
 
 
  <FONT color=gray>' ''Esegue il codice qui sotto una sola volta:''</font>
 
  <FONT color=gray>' ''Esegue il codice qui sotto una sola volta:''</font>
        unaVolta = 1      
+
          unaVolta = 1
     
+
          snd_ctl_card_info_malloc(VarPtr(cardInfo))
        snd_ctl_card_info_malloc(VarPtr(cardInfo))
 
   
 
 
  <FONT color=gray>' ''Dice ad ALSA di riempire 'snd_ctl_card_info_t' con informazioni sulla corrente scheda:''</font>
 
  <FONT color=gray>' ''Dice ad ALSA di riempire 'snd_ctl_card_info_t' con informazioni sulla corrente scheda:''</font>
        err = snd_ctl_card_info(audioHandle, cardInfo)
+
          err = snd_ctl_card_info(audioHandle, cardInfo)
        If err < 0 Then
+
          If err < 0 Then
          Error.Raise("Impossibile ottenere informazioni sulla scheda audio: " & snd_strerror(err))
+
            Error.Raise("Impossibile ottenere informazioni sulla scheda audio: " & snd_strerror(err))
        Else
+
          Else
          With ListBox1
+
            With ListBox1
            .Add(" ")
+
              .Add(" ")
            .Add(" ")
+
              .Add(" ")
            .Add("=================================================================================")
+
              .Add("=================================================================================")
            .Add(snd_ctl_card_info_get_longname(cardInfo))
+
              .Add(snd_ctl_card_info_get_longname(cardInfo))
            .Add("=================================================================================")
+
              .Add("=================================================================================")
            .Add("id = " & snd_ctl_card_info_get_id(cardInfo))
+
              .Add("id = " & snd_ctl_card_info_get_id(cardInfo))
            .Add("nome = " & snd_ctl_card_info_get_name(cardInfo))
+
              .Add("nome = " & snd_ctl_card_info_get_name(cardInfo))
            .Add("driver = " & snd_ctl_card_info_get_driver(cardInfo))
+
              .Add("driver = " & snd_ctl_card_info_get_driver(cardInfo))
            .Add("mixername = " & snd_ctl_card_info_get_mixername(cardInfo))
+
              .Add("mixername = " & snd_ctl_card_info_get_mixername(cardInfo))
            .Add("componenti = " & snd_ctl_card_info_get_components(cardInfo))
+
              .Add("componenti = " & snd_ctl_card_info_get_components(cardInfo))
          End With
+
            End With
        Endif
+
          Endif
   
+
        Endif
      Endif
 
   
 
 
  <FONT color=gray>' ''Mostra le informazioni relative ai subdispositivi audio Output del corrente dispositivo audio:''</font>
 
  <FONT color=gray>' ''Mostra le informazioni relative ai subdispositivi audio Output del corrente dispositivo audio:''</font>
      lista_subdevice(audioHandle, cardNum, devNum, SND_PCM_STREAM_PLAYBACK)
+
        lista_subdevice(audioHandle, cardNum, devNum, SND_PCM_STREAM_PLAYBACK)
 
 
 
  <FONT color=gray>' ''Mostra le informazioni relative ai subdispositivi audio Input del corrente dispositivo audio:''</font>
 
  <FONT color=gray>' ''Mostra le informazioni relative ai subdispositivi audio Input del corrente dispositivo audio:''</font>
      lista_subdevice(audioHandle, cardNum, devNum, SND_PCM_STREAM_CAPTURE)
+
        lista_subdevice(audioHandle, cardNum, devNum, SND_PCM_STREAM_CAPTURE)
+
      Loop
    Wend
 
 
   
 
   
    snd_ctl_close(audioHandle)
+
    snd_ctl_close(audioHandle)
 
    
 
    
  Wend
+
  Loop
 
   
 
   
 
  <FONT color=gray>' ''Va in chiusura liberando la memoria precedentemente allocata:''</font>
 
  <FONT color=gray>' ''Va in chiusura liberando la memoria precedentemente allocata:''</font>
  snd_config_update_free_global()
+
  snd_config_update_free_global()
 
   
 
   
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Private''' Procedure lista_subdevice(audioH As Pointer, cardN As Integer, devN As Integer, tipo As Integer)
+
  Private Procedure lista_subdevice(audioH As Pointer, cardN As Integer, devN As Integer, tipo As Integer)
 
    
 
    
 
   Dim pcmInfo As Pointer
 
   Dim pcmInfo As Pointer
Riga 431: Riga 413:
 
   Dim stringa As String
 
   Dim stringa As String
 
   
 
   
+
  If tipo = SND_PCM_STREAM_PLAYBACK Then
  If tipo = SND_PCM_STREAM_PLAYBACK Then
+
    stringa = "Output"
    stringa = "Output"
+
  Else
  Else
+
    stringa = "Input"
    stringa = "Input"
+
  Endif
  Endif
+
 
 
+
  snd_pcm_info_malloc(VarPtr(pcmInfo))
  snd_pcm_info_malloc(VarPtr(pcmInfo))
+
  memset(pcmInfo, 0, snd_pcm_info_sizeof())
  memset(pcmInfo, 0, snd_pcm_info_sizeof())
 
 
   
 
   
 
  <FONT color=gray>' ''Dice ad ALSA di quale dispositivo Audio si richiedono le informazioni:''</font>
 
  <FONT color=gray>' ''Dice ad ALSA di quale dispositivo Audio si richiedono le informazioni:''</font>
  snd_pcm_info_set_device(pcmInfo, devN)
+
  snd_pcm_info_set_device(pcmInfo, devN)
 
      
 
      
 
  <FONT color=gray>' ''Si ottengono informazioni sull'uscita Audio o in sezione del corrente dispositivo:''</font>
 
  <FONT color=gray>' ''Si ottengono informazioni sull'uscita Audio o in sezione del corrente dispositivo:''</font>
  snd_pcm_info_set_stream(pcmInfo, tipo)
+
  snd_pcm_info_set_stream(pcmInfo, tipo)
 
      
 
      
  i = -1
+
  i = -1
  subDevCount = 1
+
  subDevCount = 1
 
    
 
    
  Inc i
+
  Inc i
  While i < subDevCount
+
  While i < subDevCount
 
 
  <FONT color=gray>' ''Dice ad ALSA di riempire 'snd_pcm_info_t' con le informazioni sul corrente subdispositivo:''</font>
 
  <FONT color=gray>' ''Dice ad ALSA di riempire 'snd_pcm_info_t' con le informazioni sul corrente subdispositivo:''</font>
    snd_pcm_info_set_subdevice(pcmInfo, i)
+
    snd_pcm_info_set_subdevice(pcmInfo, i)
+
    err = snd_ctl_pcm_info(audioH, pcmInfo)
    err = snd_ctl_pcm_info(audioH, pcmInfo)
+
    If err < 0 Then
    If err < 0 Then
+
      ListBox1.Add("Impossibile ottenere informazioni sul subdevice " & stringa & " Audio 'hw:" & CStr(cardN) & "," & CStr(devN) & "," & CStr(i) & " : " & snd_strerror(err))
      ListBox1.Add("Impossibile ottenere informazioni sul subdevice " & stringa & " Audio 'hw:" & CStr(cardN) & "," & CStr(devN) & "," & CStr(i) & " : " & snd_strerror(err))
+
      Break
      Exit
+
    Endif
    Endif
 
 
 
 
  <FONT color=gray>' ''Scrive quanti subdispositivi audio sono presenti:''</font>
 
  <FONT color=gray>' ''Scrive quanti subdispositivi audio sono presenti:''</font>
    If Not i Then
+
    If Not i Then
      subDevCount = snd_pcm_info_get_subdevices_count(pcmInfo)
+
      subDevCount = snd_pcm_info_get_subdevices_count(pcmInfo)
      With ListBox1
+
      With ListBox1
        .Add(" ")
+
        .Add(" ")
        .Add("------ " & subDevCount & " " & stringa & " subdevice (" & snd_pcm_info_get_subdevices_avail(pcmInfo) & " disponibili)")
+
        .Add("------ " & subDevCount & " " & stringa & " subdevice (" & snd_pcm_info_get_subdevices_avail(pcmInfo) & " disponibili)")
        .Add("id = " & snd_pcm_info_get_id(pcmInfo))
+
        .Add("id = " & snd_pcm_info_get_id(pcmInfo))
        .Add("nome = " & snd_pcm_info_get_name(pcmInfo))
+
        .Add("nome = " & snd_pcm_info_get_name(pcmInfo))
      End With
+
      End With
    Endif
+
    Endif
 
 
 
  <FONT color=gray>' ''NOTA: Se è presente un solo subdispositivo, allora il numero del subdispositivo è immateriale, e può essere omesso:''</font>
 
  <FONT color=gray>' ''NOTA: Se è presente un solo subdispositivo, allora il numero del subdispositivo è immateriale, e può essere omesso:''</font>
    If subDevCount > 1 Then
+
    If subDevCount > 1 Then
      ListBox1.Add(" ")
+
      ListBox1.Add(" ")
      ListBox1.Add("  AUDIO " & stringa & " 'hw:" & cardN & "," & devN & "," & i & "'")
+
      ListBox1.Add("  AUDIO " & stringa & " 'hw:" & cardN & "," & devN & "," & i & "'")
    Else
+
    Else
      ListBox1.Add(" ")
+
      ListBox1.Add(" ")
      ListBox1.Add("  AUDIO " & stringa & " 'hw:" & cardN & "," & devN & "'")
+
      ListBox1.Add("  AUDIO " & stringa & " 'hw:" & cardN & "," & devN & "'")
    Endif
+
    Endif
+
    ListBox1.Add("  subnome = '" & snd_pcm_info_get_subdevice_name(pcmInfo) & "'")
    ListBox1.Add("  subnome = '" & snd_pcm_info_get_subdevice_name(pcmInfo) & "'")
+
    Inc i
 
+
  Wend
    Inc i
 
 
  Wend
 
 
   
 
   
  '''End'''
+
  End

Versione attuale delle 12:13, 13 gen 2024

Alcune funzioni esterne del API di ALSA consentono di conoscere quali sono i dispositivi audio delle schede audio presenti nel proprio sistema.

Mostriamo due esempi, nei quali sul Form dell'applicativo porremo una ListBox.

Di seguito il primo possibile codice:

Private Const ENOENT As Byte = 2
 

Library "libasound:2.0.0"

Private Const SND_PCM_STREAM_PLAYBACK As Byte = 0   ' Playback stream

' int snd_card_next(int *card)
' Try to determine the next card.
Private Extern snd_card_next(cardI As Pointer) As Integer

' const char* snd_pcm_stream_name(snd_pcm_stream_t stream)
' Get name of PCM stream type
Private Extern snd_pcm_stream_name(streamI As Byte) As String

' int snd_ctl_open(snd_ctl_t **ctl, const char *name, int mode)
' Opens a CTL.
Private Extern snd_ctl_open(ctlP As Pointer, name As String, mode As Integer) As Integer

' snd_ctl_card_info_malloc(ptr)
' Allocate an invalid snd_ctl_card_info_t using standard malloc
Private Extern snd_ctl_card_info_malloc(ptr As Pointer)

' int snd_ctl_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info)
' Get card related information.
Private Extern snd_ctl_card_info(ctlP As Pointer, infoP As Pointer) As Integer

' void snd_ctl_close(snd_ctl_t *ctl)
' Closes a ctl.
Private Extern snd_ctl_close(ctlP As Pointer)

' int snd_ctl_pcm_next_device(snd_ctl_t *ctl, int *device)
' Get Next PCM device number.
Private Extern snd_ctl_pcm_next_device(ctlP As Pointer, device As Pointer) As Integer

' int snd_pcm_info_malloc(snd_pcm_info_t ** ptr)
' Allocate an invalid snd_pcm_info_t using standard malloc.
Private Extern snd_pcm_info_malloc(ptr As Pointer) As Integer

' void snd_pcm_info_set_device (snd_pcm_info_t *obj, unsigned int val)
' Set wanted device inside a PCM info container.
Private Extern snd_pcm_info_set_device(pcminfoP As Pointer, ValI As Integer)

' void snd_pcm_info_set_subdevice(snd_pcm_info_t *obj, unsigned int val)
' Set wanted subdevice inside a PCM info container.
Private Extern snd_pcm_info_set_subdevice(pcminfoP As Pointer, ValI As Integer)

' void snd_pcm_info_set_stream(snd_pcm_info_t *obj, snd_pcm_stream_t val)
' Set wanted stream inside a PCM info container.
Private Extern snd_pcm_info_set_stream(pcminfoP As Pointer, valInt As Integer)

' int snd_ctl_pcm_info (snd_ctl_t *ctl, snd_pcm_info_t *info)
' Get info about a PCM device.
Private Extern snd_ctl_pcm_info(ctlP As Pointer, pcminfoP As Pointer) As Integer

' const char * snd_ctl_card_info_get_id (const snd_ctl_card_info_t *obj)
' Get card identifier From a CTL card info.
Private Extern snd_ctl_card_info_get_id(infoP As Pointer) As String

' const char * snd_ctl_card_info_get_name (const snd_ctl_card_info_t *obj)
' Get card name From a CTL card info.
Private Extern snd_ctl_card_info_get_name(infoP As Pointer) As String

' const char* snd_pcm_info_get_id(const snd_pcm_info_t * obj)
' Get id from a PCM info container.
Private Extern snd_pcm_info_get_id(pcminfoP As Pointer) As String

' const char* snd_pcm_info_get_name (const snd_pcm_info_t * obj)
' Get name From a PCM info container.
Private Extern snd_pcm_info_get_name(pcminfoP As Pointer) As String

' unsigned int  snd_pcm_info_get_subdevices_count (const snd_pcm_info_t *obj)
' Get subdevices count From a PCM info container.
Private Extern snd_pcm_info_get_subdevices_count(pcminfoP As Pointer) As Integer

' unsigned int snd_pcm_info_get_subdevices_avail (const snd_pcm_info_t *obj)
' Get available subdevices count From a PCM info container.
Private Extern snd_pcm_info_get_subdevices_avail(pcminfoP As Pointer) As Integer

' const char * snd_pcm_info_get_subdevice_name (const snd_pcm_info_t *obj)
' Get subdevice name From a PCM info container.
Private Extern snd_pcm_info_get_subdevice_name(pcminfoP As Pointer) As String

' const char * snd_strerror (int errnum)
' Returns the message For an Error code.
Private Extern snd_strerror(errore As Integer) As String
 

Public Sub Form_Open()

 Me.show
 
 Do
   Wait 0.1
 Loop Until Me.Id <> 0

 Lista_Dispositivi()

End


Private Procedure Lista_Dispositivi()

 Dim handlCtl, info, pcminfo As Pointer
 Dim card, dev, count, avail, idx, err As Integer
 Dim name, card_id, card_name, pcm_id, pcm_name, subdevice_name As String

 
  snd_ctl_card_info_malloc(VarPtr(info))
  snd_pcm_info_malloc(VarPtr(pcminfo))
   
  card = -1

  If (snd_card_next(VarPtr(card)) < 0) Or (card < 0) Then
    Error("Nessuna scheda audio trovata !")
    Return
  Endif

  ListBox1.Add("******* LISTA DEI DISPOSITIVI HARDWARE DI RIPRODUZIONE AUDIO *******")
   
  snd_pcm_stream_name(SND_PCM_STREAM_PLAYBACK)

  While card >= 0

    name = "hw:" & card

    err = snd_ctl_open(VarPtr(handlCtl), name, 0)
    If err < 0 Then
      Error("Apertura del Controllo: " & card & ":" & snd_strerror(err))
      Goto next_card
    Endif
    
    err = snd_ctl_card_info(handlCtl, info)
    If err < 0 Then
      Error("Informazione sull'hardware del controllo: " & card & ":" & snd_strerror(err))
      snd_ctl_close(handlCtl)
      Goto next_card
    Endif
     
    dev = -1
     
    While True

      If snd_ctl_pcm_next_device(handlCtl, VarPtr(dev)) < 0 Then Error("Errore alla funzione 'snd_ctl_pcm_next_device' !")

      If dev < 0 Then Break
      
      snd_pcm_info_set_device(pcminfo, dev)
       
      snd_pcm_info_set_subdevice(pcminfo, 0)
       
      snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK)

      err = snd_ctl_pcm_info(handlCtl, pcminfo)

      If err < 0 Then
        If err <> - ENOENT Then Error.Raise("Informazione sull'audio digitale del controllo: " & card & " " & snd_strerror(err))
        Continue
      Endif
       
      card_id = snd_ctl_card_info_get_id(info)
       
      card_name = snd_ctl_card_info_get_name(info)
       
      pcm_id = snd_pcm_info_get_id(pcminfo)
       
      pcm_name = snd_pcm_info_get_name(pcminfo)
       
      With ListBox1
        .Add("_______________________________________________________________________________________")
        .Add(" ")
        .Add("DISPOSITIVO AUDIO: " & name & "  " & card_id & " [" & card_name & "]    Device: " & dev & "  " & pcm_id & " [" & pcm_name & "]")
        .Add(" ")
      End With

      count = snd_pcm_info_get_subdevices_count(pcminfo)
       
      avail = snd_pcm_info_get_subdevices_avail(pcminfo)
       
      With ListBox1
        .Add("Subdevices: " & avail & "/" & count)
        .Add(" ")
      End With
       
      For idx = 0 To count - 1
        snd_pcm_info_set_subdevice(pcminfo, idx)
        err = snd_ctl_pcm_info(handlCtl, pcminfo)
        If err < 0 Then
          Error("Informazione sulla Riproduzione audio digitale del controllo: " & card & " " & snd_strerror(err))
        Else
          subdevice_name = snd_pcm_info_get_subdevice_name(pcminfo)
          ListBox1.Add("Subdevice: #" & idx & ":  " & subdevice_name)
        Endif
      Next
        
    Wend

    snd_ctl_close(handlCtl)
    next_card:
    If snd_card_next(VarPtr(card)) < 0 Then
      Error("Errore in 'next_card' !")
      Break
    Endif
 
  Wend

End


Di seguito invece il secondo possibile codice:

Library "libasound:2.0.0"

Private Const SND_PCM_STREAM_PLAYBACK As Integer = 0
Private Const SND_PCM_STREAM_CAPTURE As Integer = 1

' int snd_card_next(int *card)
' Try to determine the next card.
Private Extern snd_card_next(cardI As Pointer) As Integer

' int snd_ctl_open (snd_ctl_t **ctl, const char *name, int mode)
' Opens a CTL.
Private Extern snd_ctl_open(card As Pointer, name As String, mode As Integer) As Integer

' int snd_ctl_pcm_next_device (snd_ctl_t *ctl, int *device)
' Get Next pcm device number.
Private Extern snd_ctl_pcm_next_device(ctl As Pointer, device As Pointer) As Integer

' int snd_ctl_card_info_malloc (snd_ctl_card_info_t **ptr)
' Allocate an invalid snd_ctl_card_info_t using standard malloc.
Private Extern snd_ctl_card_info_malloc(ptr As Pointer) As Integer

' int snd_ctl_card_info (snd_ctl_t *ctl, snd_ctl_card_info_t *info)
' Get card related information.
Private Extern snd_ctl_card_info(ctl As Pointer, snd_ctl_card_info_t As Pointer) As Integer

' const char * snd_ctl_card_info_get_longname (const snd_ctl_card_info_t *obj)
' Get card long name from a CTL card info.
Private Extern snd_ctl_card_info_get_longname(obj As Pointer) As String

' const char * snd_ctl_card_info_get_id (const snd_ctl_card_info_t *obj)
' Get card identifier from a CTL card info.
Private Extern snd_ctl_card_info_get_id(obj As Pointer) As String

' const char * snd_ctl_card_info_get_name (const snd_ctl_card_info_t *obj)
' Get card name from a CTL card info.
Private Extern snd_ctl_card_info_get_name(obj As Pointer) As String

' const char * snd_ctl_card_info_get_driver (const snd_ctl_card_info_t *obj)
' Get card driver name from a CTL card info.
Private Extern snd_ctl_card_info_get_driver(obj As Pointer) As String

' const char * snd_ctl_card_info_get_mixername (const snd_ctl_card_info_t *obj)
' Get card mixer name from a CTL card info.
Private Extern snd_ctl_card_info_get_mixername(obj As Pointer) As String

' const char * snd_ctl_card_info_get_components (const snd_ctl_card_info_t *obj)
' Get card component list from a CTL card info.
Private Extern snd_ctl_card_info_get_components(obj As Pointer) As String

' int snd_pcm_info_malloc (snd_pcm_info_t **ptr)
' Allocate a New Snd_pcm_info_t structure.
Private Extern snd_pcm_info_malloc(ptr As Pointer) As Integer

' size_t snd_pcm_info_sizeof (void)
' Get size Of the 'snd_pcm_info_t' structure in bytes.
Private Extern snd_pcm_info_sizeof() As Integer

' void snd_pcm_info_set_device (snd_pcm_info_t *obj, unsigned int val)
' Set pcm device number.
Private Extern snd_pcm_info_set_device(obj As Pointer, ValInt As Integer)

' void snd_pcm_info_set_stream (snd_pcm_info_t *obj, snd_pcm_stream_t val)
' Set pcm stream identifier.
Private Extern snd_pcm_info_set_stream(obj As Pointer, ValInt As Integer)

' void snd_pcm_info_set_subdevice (snd_pcm_info_t *obj, unsigned int val)
' Set pcm subdevice number.
Private Extern snd_pcm_info_set_subdevice(obj As Pointer, ValInt As Integer)

' int snd_ctl_pcm_info (snd_ctl_t *ctl, snd_pcm_info_t *info)
' Get info about a pcm device.
Private Extern snd_ctl_pcm_info(ctl As Pointer, info As Pointer) As Integer

' unsigned int snd_pcm_info_get_subdevices_count (const snd_pcm_info_t *obj)
' Get pcm count of subdevices.
Private Extern snd_pcm_info_get_subdevices_count(obj As Pointer) As Integer

' unsigned int snd_pcm_info_get_subdevices_avail (const snd_pcm_info_t *obj)
' Get pcm available count of subdevices.
Private Extern snd_pcm_info_get_subdevices_avail(obj As Pointer) As Integer

' const char * snd_pcm_info_get_id (const snd_pcm_info_t *obj)
' Get pcm hardware driver identifier.
Private Extern snd_pcm_info_get_id(obj As Pointer) As String

' const char * snd_pcm_info_get_name (const snd_pcm_info_t *obj)
' Get pcm hardware driver name.
Private Extern snd_pcm_info_get_name(obj As Pointer) As String

' const char * snd_pcm_info_get_subdevice_name (const snd_pcm_info_t *obj)
' Get pcm subdevice name.
Private Extern snd_pcm_info_get_subdevice_name(obj As Pointer) As String

' int snd_ctl_close (snd_ctl_t *ctl)
' Closes CTL handle.
Private Extern snd_ctl_close(ctl As Pointer) As Integer

' int snd_config_update_free_global (void)
' Frees the global configuration tree In snd_config.
Private Extern snd_config_update_free_global() As Integer

' const char * snd_strerror (int errnum)
' Returns the message For an Error code.
Private Extern snd_strerror(errore As Integer) As String

' void *memset(void *str, int c, size_t n)
' Copies the character c (an unsigned char) to the first n characters of the string pointed to by the argument str.
Private Extern memset(StrP As Pointer, c As Integer, n As Integer) As Pointer In "libc:6"


Public Sub Form_Open()

 Me.show

 Do
   Wait 0.1
 Loop Until Me.Id <> 0

 Lista_Dispositivi()

End


Public Sub Lista_Dispositivi()

 Dim err, cardNum, devNum, unaVolta As Integer
 Dim audioHandle, cardInfo As Pointer
 Dim $str As String

 ListBox1.Add("---- DISPOSITIVI HARDWARE AUDIO PRESENTI ----")

 cardNum = -1
 
 Do

   err = snd_card_next(VarPtr(cardNum))
   If err < 0 Then Error.Raise("Impossibile ottenere il numero della scheda audio successiva: " & snd_strerror(err))
 
' Se non vi sono più schede, Alsa imposta "cardNum" a -1:
   If cardNum < 0 Then Exit
   $str = "hw:" & CStr(cardNum)
   err = snd_ctl_open(VarPtr(audioHandle), $Str, 0)
   If err < 0 Then Error.Raise("Impossibile aprire la connessione con la scheda audio: " & snd_strerror(err))
   unaVolta = 0
     
' Parte con il primo dispositivo audio sulla scheda individuata:
   devNum = -1
     Do
' Ricava il numero del successivo dispositivo Midi sulla scheda attuale:
       err = snd_ctl_pcm_next_device(audioHandle, VarPtr(devNum))
       If err < 0 Then Error.Raise("Impossibile ottenere il numero del successivo dispositivo audio: " & snd_strerror(err))
' Se non ci sono altri dispositivi audio sulla scheda audio, Alsa imposta "devNum" a -1.
' NOTA: E' possibile che la scheda audio (ad esempio una scheda audio digitale) possa non avere dispositivi audio:
       If devNum < 0 Then Exit
       If Not unaVolta Then
' Esegue il codice qui sotto una sola volta:
         unaVolta = 1
         snd_ctl_card_info_malloc(VarPtr(cardInfo))
' Dice ad ALSA di riempire 'snd_ctl_card_info_t' con informazioni sulla corrente scheda:
         err = snd_ctl_card_info(audioHandle, cardInfo)
         If err < 0 Then
           Error.Raise("Impossibile ottenere informazioni sulla scheda audio: " & snd_strerror(err))
         Else
           With ListBox1
             .Add(" ")
             .Add(" ")
             .Add("=================================================================================")
             .Add(snd_ctl_card_info_get_longname(cardInfo))
             .Add("=================================================================================")
             .Add("id = " & snd_ctl_card_info_get_id(cardInfo))
             .Add("nome = " & snd_ctl_card_info_get_name(cardInfo))
             .Add("driver = " & snd_ctl_card_info_get_driver(cardInfo))
             .Add("mixername = " & snd_ctl_card_info_get_mixername(cardInfo))
             .Add("componenti = " & snd_ctl_card_info_get_components(cardInfo))
           End With
         Endif
       Endif
' Mostra le informazioni relative ai subdispositivi audio Output del corrente dispositivo audio:
       lista_subdevice(audioHandle, cardNum, devNum, SND_PCM_STREAM_PLAYBACK)
' Mostra le informazioni relative ai subdispositivi audio Input del corrente dispositivo audio:
       lista_subdevice(audioHandle, cardNum, devNum, SND_PCM_STREAM_CAPTURE)
     Loop

   snd_ctl_close(audioHandle)
 
 Loop

' Va in chiusura liberando la memoria precedentemente allocata:
 snd_config_update_free_global()

End


Private Procedure lista_subdevice(audioH As Pointer, cardN As Integer, devN As Integer, tipo As Integer)
 
 Dim pcmInfo As Pointer
 Dim subDevCount, i, err As Integer
 Dim stringa As String

 If tipo = SND_PCM_STREAM_PLAYBACK Then
   stringa = "Output"
 Else
   stringa = "Input"
 Endif
 
 snd_pcm_info_malloc(VarPtr(pcmInfo))
 memset(pcmInfo, 0, snd_pcm_info_sizeof())

' Dice ad ALSA di quale dispositivo Audio si richiedono le informazioni:
 snd_pcm_info_set_device(pcmInfo, devN)
   
' Si ottengono informazioni sull'uscita Audio o in sezione del corrente dispositivo:
 snd_pcm_info_set_stream(pcmInfo, tipo)
    
 i = -1
 subDevCount = 1
  
 Inc i
 While i < subDevCount
' Dice ad ALSA di riempire 'snd_pcm_info_t' con le informazioni sul corrente subdispositivo:
   snd_pcm_info_set_subdevice(pcmInfo, i)
   err = snd_ctl_pcm_info(audioH, pcmInfo)
   If err < 0 Then
     ListBox1.Add("Impossibile ottenere informazioni sul subdevice " & stringa & " Audio 'hw:" & CStr(cardN) & "," & CStr(devN) & "," & CStr(i) & " : " & snd_strerror(err))
     Break
   Endif
' Scrive quanti subdispositivi audio sono presenti:
   If Not i Then
     subDevCount = snd_pcm_info_get_subdevices_count(pcmInfo)
     With ListBox1
       .Add(" ")
       .Add("------ " & subDevCount & " " & stringa & " subdevice (" & snd_pcm_info_get_subdevices_avail(pcmInfo) & " disponibili)")
       .Add("id = " & snd_pcm_info_get_id(pcmInfo))
       .Add("nome = " & snd_pcm_info_get_name(pcmInfo))
     End With
   Endif
' NOTA: Se è presente un solo subdispositivo, allora il numero del subdispositivo è immateriale, e può essere omesso:
   If subDevCount > 1 Then
     ListBox1.Add(" ")
     ListBox1.Add("   AUDIO " & stringa & " 'hw:" & cardN & "," & devN & "," & i & "'")
   Else
     ListBox1.Add(" ")
     ListBox1.Add("   AUDIO " & stringa & " 'hw:" & cardN & "," & devN & "'")
   Endif
   ListBox1.Add("   subnome = '" & snd_pcm_info_get_subdevice_name(pcmInfo) & "'")
   Inc i
 Wend

End