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

Da Gambas-it.org - Wikipedia.
 
(9 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
 
====Premessa====
 
====Premessa====
 
 
Alcune funzioni esterne del API di Alsa consentono di conoscere i dispositivi Midi dell'hardware audio presenti nel proprio sistema, con i quali poter ricevere ed inviare dati Midi grezzi.
 
Alcune funzioni esterne del API di Alsa consentono di conoscere i dispositivi Midi dell'hardware audio presenti nel proprio sistema, con i quali poter ricevere ed inviare dati Midi grezzi.
  
Riga 7: Riga 6:
 
* un numero che rappresenta il dispositivo;
 
* un numero che rappresenta il dispositivo;
 
* un numero che rappresenta il sub-dispositivo.
 
* un numero che rappresenta il sub-dispositivo.
 +
Questi tre elementi costituiscono una stringa che identifica una scheda audio. <SUP>&#91;[[#Note|nota 1]]&#93;</sup>
  
Gli esempi, che seguono, mostrano come accedere appunto a questi tre numeri rappresentativi. Avendo a disposizione tali numeri, è possibile aprire una porta MIDI di Entrata o di Uscita con la funzione ''snd_rawmidi_open()'' usando una stringa simile:
+
Gli esempi, che seguono, mostrano come accedere appunto a questi tre numeri rappresentativi. Avendo a disposizione tali numeri, è possibile aprire una porta MIDI di Entrata o di Uscita con la funzione "snd_rawmidi_open()" o aprire una scheda audio (un'interfaccia di controllo) con la funzione "snd_ctl_open()", usando una stringa simile:
 
  hw:x,y,z
 
  hw:x,y,z
laddove x, y, z sono i tre numeri che rappresentano e specificano una particolare porta MIDI di Entrata o di Uscita, come ad esempio:
+
laddove x, y, z sono i tre numeri che rappresentano e specificano una particolare porta MIDI di Entrata o di Uscita (l'interfaccia di controllo scheda audio), come ad esempio:
 
  hw:1,0,0
 
  hw:1,0,0
  
  
 
Mostriamo di seguito tre codici, che dovranno essere lanciati dopo aver collegato, ad esempio, uno o più dispositivi Midi esterni hardware (ad esempio una o più tastiere Midi) al proprio computer.
 
Mostriamo di seguito tre codici, che dovranno essere lanciati dopo aver collegato, ad esempio, uno o più dispositivi Midi esterni hardware (ad esempio una o più tastiere Midi) al proprio computer.
 
  
 
====Primo esempio====
 
====Primo esempio====
 
Cominciamo con il primo esempio più semplice:
 
Cominciamo con il primo esempio più semplice:
  Library "libasound:2"
+
  Library "libasound:2.0.0"
 
   
 
   
 
  Private Const SND_RAWMIDI_STREAM_OUTPUT As Byte = 0
 
  Private Const SND_RAWMIDI_STREAM_OUTPUT As Byte = 0
Riga 28: Riga 27:
 
   
 
   
 
  <FONT color=gray>' ''int snd_ctl_open (snd_ctl_t **ctl, const char *name, int mode)
 
  <FONT color=gray>' ''int snd_ctl_open (snd_ctl_t **ctl, const char *name, int mode)
  ' ''Opens a CTL.''</font>
+
  ' ''Opens a sound card.''</font>
 
  Private Extern snd_ctl_open(card As Pointer, name As String, mode As Integer) As Integer
 
  Private Extern snd_ctl_open(card As Pointer, name As String, mode As Integer) As Integer
 
   
 
   
Riga 72: Riga 71:
 
   
 
   
 
   
 
   
  '''Public''' Sub Main()
+
  Public Sub Main()
 
   
 
   
 
   Dim err, cardNum, devNum, subDevCount, i As Integer
 
   Dim err, cardNum, devNum, subDevCount, i As Integer
Riga 79: Riga 78:
 
   Dim j, k As Byte
 
   Dim j, k As Byte
 
   
 
   
+
  Print "---- DISPOSITIVI HARDWARE MIDI PRESENTI ----\n"
  Print "---- DISPOSITIVI HARDWARE MIDI PRESENTI ----\n"
 
 
 
  cardNum = -1
 
 
    
 
    
    
+
   cardNum = -1
  While True
 
 
   
 
   
    err = snd_card_next(VarPtr(cardNum))
+
  Do
    If err < 0 Then Error.Raise("Impossibile ottenere il numero della scheda audio successiva !")
+
    err = snd_card_next(VarPtr(cardNum))
 +
    If err < 0 Then Error.Raise("Impossibile ottenere il numero della scheda audio successiva !")
 
      
 
      
 
  <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 Break
     
+
    $str = "hw:" & CStr(cardNum)  
    $str = "hw:" & CStr(cardNum)
+
    err = snd_ctl_open(VarPtr(cardHandle), $Str, 0)
+
    If err < 0 Then Error.Raise("Impossibile aprire la connessione con la scheda audio !")
    err = snd_ctl_open(VarPtr(cardHandle), $Str, 0)
 
    If err < 0 Then Error.Raise("Impossibile aprire la connessione con la scheda audio !")
 
 
          
 
          
 
  <FONT color=gray>' ''Parte con il primo dispositivo Midi sulla scheda individuata:''</font>
 
  <FONT color=gray>' ''Parte con il primo dispositivo Midi 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_rawmidi_next_device(cardHandle, VarPtr(devNum))
+
      err = snd_ctl_rawmidi_next_device(cardHandle, VarPtr(devNum))
        If err < 0 Then Error.Raise("Impossibile ottenere il numero del successivo dispositivo Midi !")
+
      If err < 0 Then Error.Raise("Impossibile ottenere il numero del successivo dispositivo Midi !")
 
 
  <FONT color=gray>' ''Se non ci sono altri dispositivi Midi sulla scheda audio, Alsa imposta "devNum" a -1.''
 
  <FONT color=gray>' ''Se non ci sono altri dispositivi Midi 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 Midi:''</font>
 
  ' ''NOTA: E' possibile che la scheda audio (ad esempio una scheda audio digitale) possa non avere dispositivi Midi:''</font>
        If devNum < 0 Then Exit
+
      If devNum < 0 Then Break       
       
+
  <FONT color=gray>' ''Per ottenere informazioni sui sub-dispositivi del presente dispositivo Midi (sulla scheda), bisogna chiamare la funzione "snd_rawmidi_info_t", previa allocazione di memoria sullo stack:''</font>
  <FONT color=gray>' ''Per ottenere informazioni sui sub-dispositivi del presente dispositivo Midi (sulla scheda),''
+
      snd_rawmidi_info_malloc(VarPtr(rawMidiInfo))
' ''bisogna chiamare la funzione "snd_rawmidi_info_t", previa allocazione di memoria sullo stack:''</font>
+
      memset(rawMidiInfo, 0, snd_rawmidi_info_sizeof())        
        snd_rawmidi_info_malloc(VarPtr(rawMidiInfo))
 
        memset(rawMidiInfo, 0, snd_rawmidi_info_sizeof())
 
         
 
 
  <FONT color=gray>' ''Si dice ad Alsa di quale numero di dispositivo vogliamo ottenere informazioni:''</font>
 
  <FONT color=gray>' ''Si dice ad Alsa di quale numero di dispositivo vogliamo ottenere informazioni:''</font>
        snd_rawmidi_info_set_device(rawMidiInfo, devNum)
+
      snd_rawmidi_info_set_device(rawMidiInfo, devNum)        
       
 
 
  <FONT color=gray>' ''Si ottengono le informazioni Midi del dispositivo:''</font>
 
  <FONT color=gray>' ''Si ottengono le informazioni Midi del dispositivo:''</font>
        snd_rawmidi_info_set_stream(rawMidiInfo, SND_RAWMIDI_STREAM_OUTPUT)
+
      snd_rawmidi_info_set_stream(rawMidiInfo, SND_RAWMIDI_STREAM_OUTPUT)
       
+
      i = -1
        i = -1
+
      subDevCount = 1
       
+
      While (i < subDevCount - 1)
        subDevCount = 1
+
        Inc i
       
 
        While (i < subDevCount - 1)
 
          Inc i
 
 
  <FONT color=gray>' ''Si dice ad Alsa di riempire la funzione "our snd_rawmidi_info_t" con le informazioni sul presente sub-dispositivo:''</font>
 
  <FONT color=gray>' ''Si dice ad Alsa di riempire la funzione "our snd_rawmidi_info_t" con le informazioni sul presente sub-dispositivo:''</font>
          snd_rawmidi_info_set_subdevice(rawMidiInfo, i)
+
        snd_rawmidi_info_set_subdevice(rawMidiInfo, i)
          err = snd_ctl_rawmidi_info(cardHandle, rawMidiInfo)
+
        err = snd_ctl_rawmidi_info(cardHandle, rawMidiInfo)
          If err < 0 Then Error.Raise("Impossibile ottenere informazioni dal subdispositivo Midi output !")
+
        If err < 0 Then Error.Raise("Impossibile ottenere informazioni dal subdispositivo Midi output !")
             
+
  <FONT color=gray>' ''NOTA: Se v'è un solo subdevice, allora il numero del subdispositivo è virtuale, e può essere omesso quando viene specificato il nome dell'hardware Midi:''</font>
  <FONT color=gray>' ''NOTA: Se v'è un solo subdevice, allora il numero del subdispositivo è virtuale,''
+
        If subDevCount > 1 Then
' ''e può essere omesso quando viene specificato il nome dell'hardware Midi:''</font>
+
          Print "hw:"; cardNum; ","; devNum; ","; i; Chr(10)
          If subDevCount > 1 Then
+
        Else
            Print "hw:"; cardNum; ","; devNum; ","; i; Chr(10)
+
          Print"hw:"; cardNum; ","; devNum; Chr(10)
          Else
+
        Endif
            Print"hw:"; cardNum; ","; devNum; Chr(10)
 
          Endif
 
        Wend
 
       
 
       
 
 
       Wend
 
       Wend
 +
    Loop
 +
    snd_ctl_close(cardHandle)
 +
  Loop
 
   
 
   
    snd_ctl_close(cardHandle)
+
  snd_config_update_free_global()
   
 
  Wend
 
 
  snd_config_update_free_global()
 
 
   
 
   
  '''End'''
+
  End
 
 
  
 
====Secondo esempio====
 
====Secondo esempio====
 
Mostriamo il secondo esempio più complesso del precedente.
 
Mostriamo il secondo esempio più complesso del precedente.
  Library "libasound:2"
+
Private Const ENXIO As Integer = 6
 +
 +
 +
  Library "libasound:2.0.0"
 
   
 
   
 
  Private Const SND_RAWMIDI_STREAM_OUTPUT As Integer = 0
 
  Private Const SND_RAWMIDI_STREAM_OUTPUT As Integer = 0
Riga 222: Riga 202:
 
   
 
   
 
   
 
   
  '''Public''' Sub Main()
+
  Public Sub Main()
 
  Dim err, scheda As Integer
 
  Dim nomecorto, nomeesteso As Pointer
 
 
 
   
 
   
 +
  Dim err, scheda As Integer
 +
  Dim nomecorto, nomeesteso As Pointer
 +
 
 
   Print "---- DISPOSITIVI HARDWARE MIDI PRESENTI ----\n"
 
   Print "---- DISPOSITIVI HARDWARE MIDI PRESENTI ----\n"
 
    
 
    
Riga 259: Riga 238:
 
   
 
   
 
   
 
   
  <FONT color=gray>'''Individua i dispositivi ed i subdispositivi Midi e le rispettive porte'''
+
  <FONT color=gray>' '''Individua i dispositivi ed i subdispositivi Midi e le rispettive porte'''
  '''in grado di leggere e scrivere dati Midi in Entrata ed in Uscita.'''</font>
+
  ' '''in grado di leggere e scrivere dati Midi in Entrata ed in Uscita.'''</font>
 
   err = snd_card_next(VarPtr(scheda))
 
   err = snd_card_next(VarPtr(scheda))
 
   If err < 0 Then Error.Raise("Impossibile ottenere il numero della scheda audio: " & snd_strerror(err))
 
   If err < 0 Then Error.Raise("Impossibile ottenere il numero della scheda audio: " & snd_strerror(err))
Riga 279: Riga 258:
 
      
 
      
 
      
 
      
  '''End'''
+
  End
 
      
 
      
 
      
 
      
  <FONT color=gray>'''Ottiene informazioni circa i dispositivi hardware Midi'''
+
  <FONT color=gray>' '''Ottiene informazioni circa i dispositivi hardware Midi in grado di gestire i dati Midi in Entrata ed in Uscita.'''</font>
'''in grado di gestire i dati Midi in Entrata ed in Uscita.'''</font>
 
 
   
 
   
  '''Private''' Procedure lista_dispositivi_midi(dispSc As Integer)
+
  Private Procedure lista_dispositivi_midi(dispSc As Integer)
 
   
 
   
 
   Dim nome As String
 
   Dim nome As String
 
   Dim err, disp As Integer
 
   Dim err, disp As Integer
 
   Dim ctl As Pointer
 
   Dim ctl As Pointer
 
 
 
 
  disp = -1
 
   
 
  nome = "hw:" & CStr(dispSc)
 
  err = snd_ctl_open(VarPtr(ctl), nome, 0)
 
  If err < 0 Then Error.Raise("Impossibile aprire un controllo della scheda audio " & CStr(dispSc) & ": " & snd_strerror(err))
 
   
 
  Do
 
     
 
    err = snd_ctl_rawmidi_next_device(ctl, VarPtr(disp))
 
    If err < 0 Then Error.Raise("Impossibile ottenere il numero del dispositivo: " & snd_strerror(err))
 
 
   
 
   
    If disp >= 0 Then lista_subdispositivi_midi(ctl, dispSc, disp)
+
  disp = -1
 +
 +
  nome = "hw:" & CStr(dispSc)
 +
  err = snd_ctl_open(VarPtr(ctl), nome, 0)
 +
  If err < 0 Then Error.Raise("Impossibile aprire un controllo della scheda audio " & CStr(dispSc) & ": " & snd_strerror(err))
 +
 +
  Repeat
 +
    err = snd_ctl_rawmidi_next_device(ctl, VarPtr(disp))
 +
    If err < 0 Then Error.Raise("Impossibile ottenere il numero del dispositivo: " & snd_strerror(err))
 +
    If disp >= 0 Then lista_subdispositivi_midi(ctl, dispSc, disp)
 +
  Until disp < 0
 
   
 
   
  Loop Until disp < 0
+
  snd_ctl_close(ctl)
 
 
  snd_ctl_close(ctl)
 
 
   
 
   
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  <FONT color=gray>'''Ottiene informazioni circa i subdispositivi hardware Midi'''
+
  <FONT color=gray>' '''Ottiene informazioni circa i subdispositivi hardware Midi in grado di gestire i dati Midi in Entrata ed in Uscita.'''</font>
'''in grado di gestire i dati Midi in Entrata ed in Uscita.'''</font>
 
 
   
 
   
  '''Private''' Procedure lista_subdispositivi_midi(subCtl As Pointer, subSc As Integer, subDi As Integer)
+
  Private Procedure lista_subdispositivi_midi(subCtl As Pointer, subSc As Integer, subDi As Integer)
 
    
 
    
 
   Dim mdInfo As Pointer
 
   Dim mdInfo As Pointer
Riga 321: Riga 294:
 
   Dim nome, subnome, io As String
 
   Dim nome, subnome, io As String
 
    
 
    
  snd_rawmidi_info_malloc(VarPtr(mdInfo))
+
  snd_rawmidi_info_malloc(VarPtr(mdInfo))
  snd_rawmidi_info_set_device(mdInfo, subDi)
+
  snd_rawmidi_info_set_device(mdInfo, subDi)
 
      
 
      
  snd_rawmidi_info_set_stream(mdInfo, SND_RAWMIDI_STREAM_INPUT)
+
  snd_rawmidi_info_set_stream(mdInfo, SND_RAWMIDI_STREAM_INPUT)
  snd_ctl_rawmidi_info(subCtl, mdInfo)
+
  snd_ctl_rawmidi_info(subCtl, mdInfo)
  subIn = snd_rawmidi_info_get_subdevices_count(mdInfo)
+
  subIn = snd_rawmidi_info_get_subdevices_count(mdInfo)
  snd_rawmidi_info_set_stream(mdInfo, SND_RAWMIDI_STREAM_OUTPUT)
+
  snd_rawmidi_info_set_stream(mdInfo, SND_RAWMIDI_STREAM_OUTPUT)
  snd_ctl_rawmidi_info(subCtl, mdInfo)
+
  snd_ctl_rawmidi_info(subCtl, mdInfo)
  subEx = snd_rawmidi_info_get_subdevices_count(mdInfo)
+
  subEx = snd_rawmidi_info_get_subdevices_count(mdInfo)
  If subIn > subEx Then
+
  If subIn > subEx Then
    subs = subIn
+
    subs = subIn
  Else
+
  Else
    subs = subEx
+
    subs = subEx
  Endif
+
  Endif
 +
 +
  err = emissio(subCtl, subDi, su)
 +
  If err < 0 Then
 +
    Error.Raise("Impossibile ottenere informazioni 'rawmidi': " & CStr(subSc) & ":" & subDi & ": " & snd_strerror(err))
 +
  Else If err Then
 +
    ex = 1
 +
  Endif
 +
 +
  err = immissio(subCtl, subDi, su)
 +
  If err < 0 Then
 +
    Error.Raise("Impossibile ottenere informazioni 'rawmidi': " & CStr(subSc) & ":" & subDi & ": " & snd_strerror(err))
 +
  Else If err Then
 +
    en = 1
 +
  Endif
 +
 +
  If err = 0 Then Return
 
      
 
      
  err = emissio(subCtl, subDi, su)
+
  nome = snd_rawmidi_info_get_name(mdInfo)
  If err < 0 Then
+
  subnome = snd_rawmidi_info_get_subdevice_name(mdInfo)
    Error.Raise("Impossibile ottenere informazioni 'rawmidi': " & CStr(subSc) & ":" & subDi & ": " & snd_strerror(err))
+
  Else If err Then
+
  If Left(subnome, 1) = Chr(0) Then
    ex = 1
+
    If subs = 1 Then
  Endif
+
      If en Then io = "In "
 +
      If ex Then io &= "Out"
 +
      Print io, " hw:"; subSc; ","; subDi, nome
 +
    Else
 +
      If en Then io = "In "
 +
      If ex Then io &= "Out"
 +
      Print io, " hw:"; subSc; ","; subDi, nome; " ("; subs; "subdispositivi)"
 +
    Endif
 +
  Else
 +
    su = 0
 +
    Do
 +
      If en Then io = "In "
 +
      If ex Then io &= "Out"
 +
      Print io, " hw:"; subSc; ","; subDi; ","; su, subnome
 +
      Inc su
 +
      If su >= subs Then Break
 +
      en = immissio(subCtl, subDi, su)
 +
      ex = emissio(subCtl, subDi, su)
 +
      snd_rawmidi_info_set_subdevice(mdInfo, su)
 +
      If ex Then
 +
        snd_rawmidi_info_set_stream(mdInfo, SND_RAWMIDI_STREAM_OUTPUT)
 +
        err = snd_ctl_rawmidi_info(subCtl, mdInfo)
 +
          If err < 0 Then
 +
            Error.Raise("Impossibile ottenere informazioni 'rawmidi': " & CStr(subSc) & ":" & subDi & ":" & su & ": " & snd_strerror(err))
 +
            Break
 +
          Endif
 +
      Else
 +
        snd_rawmidi_info_set_stream(mdInfo, SND_RAWMIDI_STREAM_INPUT)
 +
        err = snd_ctl_rawmidi_info(subCtl, mdInfo)
 +
          If err < 0 Then
 +
            Error.Raise("Impossibile ottenere informazioni 'rawmidi': " & CStr(subSc) & ":" & subDi & ":" & su & ": " & snd_strerror(err))
 +
            Break
 +
          Endif
 +
      Endif
 +
      subnome = snd_rawmidi_info_get_subdevice_name(mdInfo)
 +
    Loop
 +
  Endif
 
   
 
   
  err = immissio(subCtl, subDi, su)
+
End
  If err < 0 Then
 
    Error.Raise("Impossibile ottenere informazioni 'rawmidi': " & CStr(subSc) & ":" & subDi & ": " & snd_strerror(err))
 
  Else If err Then
 
    en = 1
 
  Endif
 
 
      
 
      
  If err = 0 Then Return
 
   
 
  nome = snd_rawmidi_info_get_name(mdInfo)
 
  subnome = snd_rawmidi_info_get_subdevice_name(mdInfo)
 
   
 
  If Left(subnome, 1) = Chr(0) Then
 
    If subs = 1 Then
 
      If en Then io = "In "
 
      If ex Then io &= "Out"
 
      Print io, " hw:"; subSc; ","; subDi, nome
 
    Else
 
      If en Then io = "In "
 
      If ex Then io &= "Out"
 
      Print io, " hw:"; subSc; ","; subDi, nome; " ("; subs; "subdispositivi)"
 
    Endif
 
  Else
 
    su = 0
 
    While True
 
     
 
      If en Then io = "In "
 
      If ex Then io &= "Out"
 
      Print io, " hw:"; subSc; ","; subDi; ","; su, subnome
 
      Inc su
 
      If su >= subs Then Exit
 
     
 
      en = immissio(subCtl, subDi, su)
 
      ex = emissio(subCtl, subDi, su)
 
      snd_rawmidi_info_set_subdevice(mdInfo, su)
 
       
 
      If ex Then
 
        snd_rawmidi_info_set_stream(mdInfo, SND_RAWMIDI_STREAM_OUTPUT)
 
        err = snd_ctl_rawmidi_info(subCtl, mdInfo)
 
          If err < 0 Then
 
            Error.Raise("Impossibile ottenere informazioni 'rawmidi': " & CStr(subSc) & ":" & subDi & ":" & su & ": " & snd_strerror(err))
 
            Exit
 
          Endif
 
      Else
 
        snd_rawmidi_info_set_stream(mdInfo, SND_RAWMIDI_STREAM_INPUT)
 
        err = snd_ctl_rawmidi_info(subCtl, mdInfo)
 
          If err < 0 Then
 
            Error.Raise("Impossibile ottenere informazioni 'rawmidi': " & CStr(subSc) & ":" & subDi & ":" & su & ": " & snd_strerror(err))
 
            Exit
 
          Endif
 
      Endif
 
     
 
      subnome = snd_rawmidi_info_get_subdevice_name(mdInfo)
 
       
 
    Wend
 
     
 
  Endif
 
 
 
'''End'''
 
 
   
 
   
   
+
  Private Function emissio(subCtl As Pointer, subDi As Integer, su As Integer) As Integer
  '''Private''' Function emissio(subCtl As Pointer, subDi As Integer, su As Integer) As Integer
 
 
    
 
    
 
   Dim eInfo As Pointer
 
   Dim eInfo As Pointer
 
   Dim err As Integer
 
   Dim err As Integer
 
 
  snd_rawmidi_info_malloc(VarPtr(eInfo))
 
  snd_rawmidi_info_set_device(eInfo, subDi)
 
  snd_rawmidi_info_set_subdevice(eInfo, su)
 
  snd_rawmidi_info_set_stream(eInfo, SND_RAWMIDI_STREAM_OUTPUT)
 
 
   
 
   
  err = snd_ctl_rawmidi_info(subCtl, eInfo)
+
  snd_rawmidi_info_malloc(VarPtr(eInfo))
 +
  snd_rawmidi_info_set_device(eInfo, subDi)
 +
  snd_rawmidi_info_set_subdevice(eInfo, su)
 +
  snd_rawmidi_info_set_stream(eInfo, SND_RAWMIDI_STREAM_OUTPUT)
 +
 +
  err = snd_ctl_rawmidi_info(subCtl, eInfo)
 
   
 
   
  If (err < 0) And (err <> - ENXIO) Then
+
  If (err < 0) And (err <> - ENXIO) Then
    Return err
+
    Return err
  Else If err = 0 Then
+
  Else If err = 0 Then
 
  <FONT color=gray>' ''Ritorna "1", se gli specificati scheda/device/subdevice hanno la capacità di inviare dati MIDI in uscita:''</font>
 
  <FONT color=gray>' ''Ritorna "1", se gli specificati scheda/device/subdevice hanno la capacità di inviare dati MIDI in uscita:''</font>
    Return 1
+
    Return 1
  Endif
+
  Endif
 
+
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Private''' Function immissio(subCtl As Pointer, subDi As Integer, su As Integer) As Integer
+
  Private Function immissio(subCtl As Pointer, subDi As Integer, su As Integer) As Integer
 
    
 
    
 
   Dim iInfo As Pointer
 
   Dim iInfo As Pointer
 
   Dim err As Integer
 
   Dim err As Integer
 
 
  snd_rawmidi_info_malloc(VarPtr(iInfo))
 
  snd_rawmidi_info_set_device(iInfo, subDi)
 
  snd_rawmidi_info_set_subdevice(iInfo, su)
 
  snd_rawmidi_info_set_stream(iInfo, SND_RAWMIDI_STREAM_INPUT)
 
 
   
 
   
  err = snd_ctl_rawmidi_info(subCtl, iInfo)
+
  snd_rawmidi_info_malloc(VarPtr(iInfo))
  If (err < 0) And (err <> - ENXIO) Then
+
  snd_rawmidi_info_set_device(iInfo, subDi)
    Return err
+
  snd_rawmidi_info_set_subdevice(iInfo, su)
  Else If err = 0 Then
+
  snd_rawmidi_info_set_stream(iInfo, SND_RAWMIDI_STREAM_INPUT)
 +
 +
  err = snd_ctl_rawmidi_info(subCtl, iInfo)
 +
  If (err < 0) And (err <> - ENXIO) Then
 +
    Return err
 +
  Else If err = 0 Then
 
  <FONT color=gray>' ''Ritorna "1", se gli specificati scheda/device/subdevice hanno la capacità di inviare dati MIDI in entrata:''</font>
 
  <FONT color=gray>' ''Ritorna "1", se gli specificati scheda/device/subdevice hanno la capacità di inviare dati MIDI in entrata:''</font>
    Return 1
+
    Return 1
  Endif
+
  Endif
 
+
  '''End'''
+
  End
  
  
 
====Terzo esempio====
 
====Terzo esempio====
 
Mostriamo infine il terzo esempio, che consentirà di ottenere maggiori e più dettagliate informazioni relativamente all'hardware Midi, al dispositivo ed all'eventuale subdispositivo:
 
Mostriamo infine il terzo esempio, che consentirà di ottenere maggiori e più dettagliate informazioni relativamente all'hardware Midi, al dispositivo ed all'eventuale subdispositivo:
  Library "libasound:2"
+
  Library "libasound:2.0.0"
 
   
 
   
 
  Private Const SND_RAWMIDI_STREAM_OUTPUT As Integer = 0
 
  Private Const SND_RAWMIDI_STREAM_OUTPUT As Integer = 0
Riga 559: Riga 526:
 
   
 
   
 
   
 
   
  '''Public''' Sub Main()
+
  Public Sub Main()
 
  Dim err, cardNum, devNum, unaVolta As Integer
 
  Dim midiHandle, cardInfo As Pointer
 
  Dim $str As String
 
 
   
 
   
 +
  Dim err, cardNum, devNum, unaVolta As Integer
 +
  Dim midiHandle, cardInfo As Pointer
 +
  Dim $str As String
 
   
 
   
 
   Print "---- DISPOSITIVI HARDWARE MIDI PRESENTI ----"
 
   Print "---- DISPOSITIVI HARDWARE MIDI PRESENTI ----"
Riga 570: Riga 536:
 
   cardNum = -1
 
   cardNum = -1
 
    
 
    
 
 
   While True
 
   While True
 
   
 
   
Riga 636: Riga 601:
 
   snd_config_update_free_global()
 
   snd_config_update_free_global()
 
   
 
   
  '''End'''
+
  End
 
   
 
   
 
   
 
   
 +
Private Procedure lista_subdevice(midiH As Pointer, cardN As Integer, devN As Integer, tipo As Integer)
 +
 
 +
  Dim rawMidiInfo As Pointer
 +
  Dim subDevCount, i, err As Integer
 +
  Dim stringa As String
 
   
 
   
'''Private''' Procedure lista_subdevice(midiH As Pointer, cardN As Integer, devN As Integer, tipo As Integer)
 
 
 
  Dim rawMidiInfo As Pointer
 
  Dim subDevCount, i, err As Integer
 
  Dim stringa As String
 
 
 
 
 
 
   If tipo = SND_RAWMIDI_STREAM_OUTPUT Then
 
   If tipo = SND_RAWMIDI_STREAM_OUTPUT Then
 
     stringa = "Output"
 
     stringa = "Output"
Riga 695: Riga 658:
 
     Wend
 
     Wend
 
    
 
    
  '''End'''
+
  End
 +
 
 +
 
 +
 
 +
=Note=
 +
[1] Vedere la seguente pagina: https://www.alsa-project.org/alsa-doc/alsa-lib/control.html#control_cards_id

Versione attuale delle 11:02, 19 giu 2024

Premessa

Alcune funzioni esterne del API di Alsa consentono di conoscere i dispositivi Midi dell'hardware audio presenti nel proprio sistema, con i quali poter ricevere ed inviare dati Midi grezzi.

L'accesso ad una porta MIDI richiede tre Interi:

  • un numero che rappresenta la scheda audio;
  • un numero che rappresenta il dispositivo;
  • un numero che rappresenta il sub-dispositivo.

Questi tre elementi costituiscono una stringa che identifica una scheda audio. [nota 1]

Gli esempi, che seguono, mostrano come accedere appunto a questi tre numeri rappresentativi. Avendo a disposizione tali numeri, è possibile aprire una porta MIDI di Entrata o di Uscita con la funzione "snd_rawmidi_open()" o aprire una scheda audio (un'interfaccia di controllo) con la funzione "snd_ctl_open()", usando una stringa simile:

hw:x,y,z

laddove x, y, z sono i tre numeri che rappresentano e specificano una particolare porta MIDI di Entrata o di Uscita (l'interfaccia di controllo scheda audio), come ad esempio:

hw:1,0,0


Mostriamo di seguito tre codici, che dovranno essere lanciati dopo aver collegato, ad esempio, uno o più dispositivi Midi esterni hardware (ad esempio una o più tastiere Midi) al proprio computer.

Primo esempio

Cominciamo con il primo esempio più semplice:

Library "libasound:2.0.0"

Private Const SND_RAWMIDI_STREAM_OUTPUT As Byte = 0
  
' int snd_card_next (int *card)
' Try To determine the Next card.
Private Extern snd_card_next(card As Pointer) As Integer

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

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

' int snd_rawmidi_info_malloc (snd_rawmidi_info_t **ptr)
' Allocate a new snd_rawmidi_info_t structure.
Private Extern snd_rawmidi_info_malloc(ptr As Pointer) As Integer

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

' void snd_rawmidi_info_set_device (snd_rawmidi_info_t *obj, unsigned int val)
' Set rawmidi device number.
Private Extern snd_rawmidi_info_set_device(obj As Pointer, ValInt As Integer)

' void snd_rawmidi_info_set_stream (snd_rawmidi_info_t *obj, snd_rawmidi_stream_t val)
' Set rawmidi stream identifier.
Private Extern snd_rawmidi_info_set_stream(obj As Pointer, ValInt As Integer)

' void snd_rawmidi_info_set_subdevice (snd_rawmidi_info_t *obj, unsigned int val)
' Set rawmidi subdevice number.
Private Extern snd_rawmidi_info_set_subdevice(obj As Pointer, ValInt As Integer)

' int snd_ctl_rawmidi_info (snd_ctl_t *ctl, snd_rawmidi_info_t *info)
' Get info about a RawMidi device.
Private Extern snd_ctl_rawmidi_info(ctl As Pointer, info As Pointer) As Integer

' 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

' 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 Main()

 Dim err, cardNum, devNum, subDevCount, i As Integer
 Dim cardHandle, rawMidiInfo As Pointer
 Dim $str As String
 Dim j, k As Byte

 Print "---- DISPOSITIVI HARDWARE MIDI PRESENTI ----\n"
 
 cardNum = -1

 Do
   err = snd_card_next(VarPtr(cardNum))
   If err < 0 Then Error.Raise("Impossibile ottenere il numero della scheda audio successiva !")
   
' Se non vi sono più schede, Alsa imposta "cardNum" a -1:
   If cardNum < 0 Then Break
   $str = "hw:" & CStr(cardNum) 
   err = snd_ctl_open(VarPtr(cardHandle), $Str, 0)
   If err < 0 Then Error.Raise("Impossibile aprire la connessione con la scheda audio !")
       
' Parte con il primo dispositivo Midi sulla scheda individuata:
   devNum = -1
   Do 
' Ricava il numero del successivo dispositivo Midi sulla scheda attuale:
     err = snd_ctl_rawmidi_next_device(cardHandle, VarPtr(devNum))
     If err < 0 Then Error.Raise("Impossibile ottenere il numero del successivo dispositivo Midi !")
' Se non ci sono altri dispositivi Midi 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 Midi:
     If devNum < 0 Then Break        
' Per ottenere informazioni sui sub-dispositivi del presente dispositivo Midi (sulla scheda), bisogna chiamare la funzione "snd_rawmidi_info_t", previa allocazione di memoria sullo stack:
     snd_rawmidi_info_malloc(VarPtr(rawMidiInfo))
     memset(rawMidiInfo, 0, snd_rawmidi_info_sizeof())          
' Si dice ad Alsa di quale numero di dispositivo vogliamo ottenere informazioni:
     snd_rawmidi_info_set_device(rawMidiInfo, devNum)         
' Si ottengono le informazioni Midi del dispositivo:
     snd_rawmidi_info_set_stream(rawMidiInfo, SND_RAWMIDI_STREAM_OUTPUT)
     i = -1
     subDevCount = 1
     While (i < subDevCount - 1)
       Inc i
' Si dice ad Alsa di riempire la funzione "our snd_rawmidi_info_t" con le informazioni sul presente sub-dispositivo:
       snd_rawmidi_info_set_subdevice(rawMidiInfo, i)
       err = snd_ctl_rawmidi_info(cardHandle, rawMidiInfo)
       If err < 0 Then Error.Raise("Impossibile ottenere informazioni dal subdispositivo Midi output !")
' NOTA: Se v'è un solo subdevice, allora il numero del subdispositivo è virtuale, e può essere omesso quando viene specificato il nome dell'hardware Midi:
       If subDevCount > 1 Then
         Print "hw:"; cardNum; ","; devNum; ","; i; Chr(10)
       Else
         Print"hw:"; cardNum; ","; devNum; Chr(10)
       Endif
     Wend
   Loop
   snd_ctl_close(cardHandle)
 Loop

 snd_config_update_free_global()

End

Secondo esempio

Mostriamo il secondo esempio più complesso del precedente.

Private Const ENXIO As Integer = 6


Library "libasound:2.0.0"

Private Const SND_RAWMIDI_STREAM_OUTPUT As Integer = 0
Private Const SND_RAWMIDI_STREAM_INPUT As Integer = 1

' int snd_card_next (int *card)
' Try To determine the Next card.
Private Extern snd_card_next(card As Pointer) As Integer

' int snd_card_get_name (int card, char **name)
' Obtain the card name.
Private Extern snd_card_get_name(card As Integer, name As Pointer) As Integer

' int snd_card_get_longname (int card, char **name)
' Obtain the card long name.
Private Extern snd_card_get_longname(card As Integer, name 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_rawmidi_next_device (snd_ctl_t *ctl, int *device)
' Get Next RawMidi device number.
Private Extern snd_ctl_rawmidi_next_device(ctl As Pointer, device As Pointer) As Integer

' int snd_rawmidi_info_malloc (snd_rawmidi_info_t **ptr)
' Allocate a new snd_rawmidi_info_t structure.
Private Extern snd_rawmidi_info_malloc(ptr As Pointer) As Integer

' void snd_rawmidi_info_set_device (snd_rawmidi_info_t *obj, unsigned int val)
' Set rawmidi device number.
Private Extern snd_rawmidi_info_set_device(obj As Pointer, ValInt As Integer)

' void snd_rawmidi_info_set_stream (snd_rawmidi_info_t *obj, snd_rawmidi_stream_t val)
' Set rawmidi stream identifier.
Private Extern snd_rawmidi_info_set_stream(obj As Pointer, ValInt As Integer)

' int snd_ctl_rawmidi_info (snd_ctl_t *ctl, snd_rawmidi_info_t *info)
' Get info about a RawMidi device.
Private Extern snd_ctl_rawmidi_info(ctl As Pointer, info As Pointer) As Integer

' unsigned int snd_rawmidi_info_get_subdevices_count (const snd_rawmidi_info_t *obj)
' Get rawmidi count of subdevices.
Private Extern snd_rawmidi_info_get_subdevices_count(obj As Pointer) As Integer

' const char * snd_rawmidi_info_get_name (const snd_rawmidi_info_t *obj)
' Get rawmidi hardware driver name.
Private Extern snd_rawmidi_info_get_name(obj As Pointer) As String

' const char * snd_rawmidi_info_get_subdevice_name (const snd_rawmidi_info_t *obj)
' Get rawmidi subdevice name.
Private Extern snd_rawmidi_info_get_subdevice_name(obj As Pointer) As String

' void snd_rawmidi_info_set_subdevice (snd_rawmidi_info_t *obj, unsigned int val)
' Set rawmidi subdevice number.
Private Extern snd_rawmidi_info_set_subdevice(obj As Pointer, ValInt As Integer)
 
' int snd_ctl_close (snd_ctl_t *ctl)
' Closes CTL handle.
Private Extern snd_ctl_close(ctl As Pointer) As Integer
 
' const char * snd_strerror (int errnum)
' Returns the message For an Error code.
Private Extern snd_strerror(errore As Integer) As String


Public Sub Main()

  Dim err, scheda As Integer
  Dim nomecorto, nomeesteso As Pointer
 
  Print "---- DISPOSITIVI HARDWARE MIDI PRESENTI ----\n"
 
  scheda = -1
 
' Individua le schede audio disponibili nel sistema ALSA, mostrando il loro numero ed il nome di ciascuna:
  err = snd_card_next(VarPtr(scheda))
  If err < 0 Then Error.Raise("Impossibile ottenere il numero della scheda audio: " & snd_strerror(err))
   
  If scheda < 0 Then
    Print "Nessuna scheda audio trovata nel sistema !"
    Quit
  Endif  
 
  While scheda >= 0
   
    Print "Scheda: "; scheda
    err = snd_card_get_name(scheda, VarPtr(nomecorto))
    If err < 0 Then Error.Raise("Impossibile ottenere il nome breve della scheda audio !")
   
    err = snd_card_get_longname(scheda, VarPtr(nomeesteso))
    If err < 0 Then Error.Raise("Impossibile ottenere il nome esteso della scheda audio !")
   
    Print "     NOME INTERO:  "; String@(nomeesteso)
    Print "     NOME ABBREV.: "; String@(nomecorto)
   
    err = snd_card_next(VarPtr(scheda))
    If err < 0 Then Error.Raise("Impossibile ottenere il numero della scheda audio: " & snd_strerror(err))
   
  Wend


' Individua i dispositivi ed i subdispositivi Midi e le rispettive porte
' in grado di leggere e scrivere dati Midi in Entrata ed in Uscita.
  err = snd_card_next(VarPtr(scheda))
  If err < 0 Then Error.Raise("Impossibile ottenere il numero della scheda audio: " & snd_strerror(err))
   
  If scheda < 0 Then
    Print "Nessuna scheda audio trovata nel sistema !"
    Quit
  Endif
   
  Print "\nDir      Dispositivo    Nome"
  Print "====================================\n"
   
  While scheda >= 0
    lista_dispositivi_midi(scheda)
    err = snd_card_next(VarPtr(scheda))
    If err < 0 Then Error.Raise("Impossibile ottenere il numero della scheda audio: " & snd_strerror(err))
  Wend 
   
   
End
   
   
' Ottiene informazioni circa i dispositivi hardware Midi in grado di gestire i dati Midi in Entrata ed in Uscita.

Private Procedure lista_dispositivi_midi(dispSc As Integer)

 Dim nome As String
 Dim err, disp As Integer
 Dim ctl As Pointer

 disp = -1

 nome = "hw:" & CStr(dispSc)
 err = snd_ctl_open(VarPtr(ctl), nome, 0)
 If err < 0 Then Error.Raise("Impossibile aprire un controllo della scheda audio " & CStr(dispSc) & ": " & snd_strerror(err))

 Repeat
   err = snd_ctl_rawmidi_next_device(ctl, VarPtr(disp))
   If err < 0 Then Error.Raise("Impossibile ottenere il numero del dispositivo: " & snd_strerror(err))
   If disp >= 0 Then lista_subdispositivi_midi(ctl, dispSc, disp)
 Until disp < 0

 snd_ctl_close(ctl)

End


' Ottiene informazioni circa i subdispositivi hardware Midi in grado di gestire i dati Midi in Entrata ed in Uscita.

Private Procedure lista_subdispositivi_midi(subCtl As Pointer, subSc As Integer, subDi As Integer)
 
 Dim mdInfo As Pointer
 Dim subIn, subEx, subs, su, en, ex, err As Integer
 Dim nome, subnome, io As String
 
 snd_rawmidi_info_malloc(VarPtr(mdInfo))
 snd_rawmidi_info_set_device(mdInfo, subDi)
   
 snd_rawmidi_info_set_stream(mdInfo, SND_RAWMIDI_STREAM_INPUT)
 snd_ctl_rawmidi_info(subCtl, mdInfo)
 subIn = snd_rawmidi_info_get_subdevices_count(mdInfo)
 snd_rawmidi_info_set_stream(mdInfo, SND_RAWMIDI_STREAM_OUTPUT)
 snd_ctl_rawmidi_info(subCtl, mdInfo)
 subEx = snd_rawmidi_info_get_subdevices_count(mdInfo)
 If subIn > subEx Then
   subs = subIn
 Else
   subs = subEx
 Endif

 err = emissio(subCtl, subDi, su)
 If err < 0 Then
   Error.Raise("Impossibile ottenere informazioni 'rawmidi': " & CStr(subSc) & ":" & subDi & ": " & snd_strerror(err))
 Else If err Then
   ex = 1
 Endif

 err = immissio(subCtl, subDi, su)
 If err < 0 Then
   Error.Raise("Impossibile ottenere informazioni 'rawmidi': " & CStr(subSc) & ":" & subDi & ": " & snd_strerror(err))
 Else If err Then
   en = 1
 Endif

 If err = 0 Then Return
   
 nome = snd_rawmidi_info_get_name(mdInfo)
 subnome = snd_rawmidi_info_get_subdevice_name(mdInfo)

 If Left(subnome, 1) = Chr(0) Then
   If subs = 1 Then
     If en Then io = "In "
     If ex Then io &= "Out"
     Print io, " hw:"; subSc; ","; subDi, nome
   Else
     If en Then io = "In "
     If ex Then io &= "Out"
     Print io, " hw:"; subSc; ","; subDi, nome; " ("; subs; "subdispositivi)"
   Endif
 Else
   su = 0
   Do
     If en Then io = "In "
     If ex Then io &= "Out"
     Print io, " hw:"; subSc; ","; subDi; ","; su, subnome
     Inc su
     If su >= subs Then Break
     en = immissio(subCtl, subDi, su)
     ex = emissio(subCtl, subDi, su)
     snd_rawmidi_info_set_subdevice(mdInfo, su)
     If ex Then
       snd_rawmidi_info_set_stream(mdInfo, SND_RAWMIDI_STREAM_OUTPUT)
       err = snd_ctl_rawmidi_info(subCtl, mdInfo)
         If err < 0 Then
           Error.Raise("Impossibile ottenere informazioni 'rawmidi': " & CStr(subSc) & ":" & subDi & ":" & su & ": " & snd_strerror(err))
           Break
         Endif
     Else
       snd_rawmidi_info_set_stream(mdInfo, SND_RAWMIDI_STREAM_INPUT)
       err = snd_ctl_rawmidi_info(subCtl, mdInfo)
         If err < 0 Then
           Error.Raise("Impossibile ottenere informazioni 'rawmidi': " & CStr(subSc) & ":" & subDi & ":" & su & ": " & snd_strerror(err))
           Break
         Endif
     Endif
     subnome = snd_rawmidi_info_get_subdevice_name(mdInfo)
   Loop
 Endif

End
   

Private Function emissio(subCtl As Pointer, subDi As Integer, su As Integer) As Integer
 
 Dim eInfo As Pointer
 Dim err As Integer

 snd_rawmidi_info_malloc(VarPtr(eInfo))
 snd_rawmidi_info_set_device(eInfo, subDi)
 snd_rawmidi_info_set_subdevice(eInfo, su)
 snd_rawmidi_info_set_stream(eInfo, SND_RAWMIDI_STREAM_OUTPUT)

 err = snd_ctl_rawmidi_info(subCtl, eInfo)

 If (err < 0) And (err <> - ENXIO) Then
   Return err
 Else If err = 0 Then
' Ritorna "1", se gli specificati scheda/device/subdevice hanno la capacità di inviare dati MIDI in uscita:
   Return 1
 Endif

End


Private Function immissio(subCtl As Pointer, subDi As Integer, su As Integer) As Integer
 
 Dim iInfo As Pointer
 Dim err As Integer

 snd_rawmidi_info_malloc(VarPtr(iInfo))
 snd_rawmidi_info_set_device(iInfo, subDi)
 snd_rawmidi_info_set_subdevice(iInfo, su)
 snd_rawmidi_info_set_stream(iInfo, SND_RAWMIDI_STREAM_INPUT)

 err = snd_ctl_rawmidi_info(subCtl, iInfo)
 If (err < 0) And (err <> - ENXIO) Then
   Return err
 Else If err = 0 Then
' Ritorna "1", se gli specificati scheda/device/subdevice hanno la capacità di inviare dati MIDI in entrata:
   Return 1
 Endif

End


Terzo esempio

Mostriamo infine il terzo esempio, che consentirà di ottenere maggiori e più dettagliate informazioni relativamente all'hardware Midi, al dispositivo ed all'eventuale subdispositivo:

Library "libasound:2.0.0"

Private Const SND_RAWMIDI_STREAM_OUTPUT As Integer = 0
Private Const SND_RAWMIDI_STREAM_INPUT As Integer = 1

' int snd_card_next (int *card)
' Try To determine the Next card.
Private Extern snd_card_next(card 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_rawmidi_next_device (snd_ctl_t *ctl, int *device)
' Get Next RawMidi device number.
Private Extern snd_ctl_rawmidi_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_rawmidi_info_malloc (snd_rawmidi_info_t **ptr)
' Allocate a New Snd_rawmidi_info_t structure.
Private Extern snd_rawmidi_info_malloc(ptr As Pointer) As Integer

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

' void snd_rawmidi_info_set_device (snd_rawmidi_info_t *obj, unsigned int val)
' Set rawmidi device number.
Private Extern snd_rawmidi_info_set_device(obj As Pointer, ValInt As Integer)

' void snd_rawmidi_info_set_stream (snd_rawmidi_info_t *obj, snd_rawmidi_stream_t val)
' Set rawmidi stream identifier.
Private Extern snd_rawmidi_info_set_stream(obj As Pointer, ValInt As Integer)

' void snd_rawmidi_info_set_subdevice (snd_rawmidi_info_t *obj, unsigned int val)
' Set rawmidi subdevice number.
Private Extern snd_rawmidi_info_set_subdevice(obj As Pointer, ValInt As Integer)

' int snd_ctl_rawmidi_info (snd_ctl_t *ctl, snd_rawmidi_info_t *info)
' Get info about a RawMidi device.
Private Extern snd_ctl_rawmidi_info(ctl As Pointer, info As Pointer) As Integer

' unsigned int snd_rawmidi_info_get_subdevices_count (const snd_rawmidi_info_t *obj)
' Get rawmidi count of subdevices.
Private Extern snd_rawmidi_info_get_subdevices_count(obj As Pointer) As Integer

' unsigned int snd_rawmidi_info_get_subdevices_avail (const snd_rawmidi_info_t *obj)
' Get rawmidi available count of subdevices.
Private Extern snd_rawmidi_info_get_subdevices_avail(obj As Pointer) As Integer

' const char * snd_rawmidi_info_get_id (const snd_rawmidi_info_t *obj)
' Get rawmidi hardware driver identifier.
Private Extern snd_rawmidi_info_get_id(obj As Pointer) As String

' const char * snd_rawmidi_info_get_name (const snd_rawmidi_info_t *obj)
' Get rawmidi hardware driver name.
Private Extern snd_rawmidi_info_get_name(obj As Pointer) As String

' const char * snd_rawmidi_info_get_subdevice_name (const snd_rawmidi_info_t *obj)
' Get rawmidi subdevice name.
Private Extern snd_rawmidi_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 Main()

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

  Print "---- DISPOSITIVI HARDWARE MIDI PRESENTI ----"

  cardNum = -1
 
  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))
  
' 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(midiHandle), $Str, 0)
    If err < 0 Then Error.Raise("Impossibile aprire la connessione con la scheda audio: " & snd_strerror(err))
      
' Parte con il primo dispositivo Midi sulla scheda individuata:
    devNum = -1

    While True

' Ricava il numero del successivo dispositivo Midi sulla scheda attuale:
      err = snd_ctl_rawmidi_next_device(midiHandle, VarPtr(devNum))
      If err < 0 Then Error.Raise("Impossibile ottenere il numero del successivo dispositivo Midi: " & snd_strerror(err))

' Se non ci sono altri dispositivi Midi 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 Midi:
      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(midiHandle, cardInfo)
        If err < 0 Then
          Error.Raise("Impossibile ottenere informazioni sulla scheda audio: " & snd_strerror(err))
        Else
          Print "\n\n================================================================================="
          Print snd_ctl_card_info_get_longname(cardInfo)
          Print "=================================================================================\n"
          Print "id = "; snd_ctl_card_info_get_id(cardInfo)
          Print "\nnome = "; snd_ctl_card_info_get_name(cardInfo)
          Print "\ndriver = "; snd_ctl_card_info_get_driver(cardInfo)
          Print "\nmixername = "; snd_ctl_card_info_get_mixername(cardInfo)
          Print "\ncomponenti = "; snd_ctl_card_info_get_components(cardInfo)
        Endif
     
      Endif
     
' Mostra le informazioni relative ai subdispositivi MIDI Output del corrente dispositivo MIDI:
      lista_subdevice(midiHandle, cardNum, devNum, SND_RAWMIDI_STREAM_OUTPUT)
   
' Mostra le informazioni relative ai subdispositivi MIDI Input del corrente dispositivo MIDI:
      lista_subdevice(midiHandle, cardNum, devNum, SND_RAWMIDI_STREAM_INPUT)

    Wend

    snd_ctl_close(midiHandle)
  
  Wend

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

End


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

  If tipo = SND_RAWMIDI_STREAM_OUTPUT Then
    stringa = "Output"
  Else
    stringa = "Input"
  Endif
   
  snd_rawmidi_info_malloc(VarPtr(rawMidiInfo))
  memset(rawMidiInfo, 0, snd_rawmidi_info_sizeof())
 
' Dice ad ALSA di quale dispositivo Midi si richiedono le informazioni:
   snd_rawmidi_info_set_device(rawMidiInfo, devN)
   
' Si ottengono informazioni sull'uscita Midi o in sezione del corrente dispositivo:
   snd_rawmidi_info_set_stream(rawMidiInfo, tipo)
    
   i = -1
   subDevCount = 1
   
   Inc i
   While i < subDevCount
 
' Dice ad ALSA di riempire 'snd_rawmidi_info_t' con le informazioni sul corrente subdispositivo:
     snd_rawmidi_info_set_subdevice(rawMidiInfo, i)
 
     err = snd_ctl_rawmidi_info(midiH, rawMidiInfo)
     If err < 0 Then Error.Raise("Impossibile ottenere informazioni sul subdevice " & stringa & " Midi 'hw:" & CStr(cardN) & "," & CStr(devN) & "," & CStr(i) & " : " & snd_strerror(err))
   
' Scrive quanti subdispositivi Midi sono presenti:
     If Not i Then
       subDevCount = snd_rawmidi_info_get_subdevices_count(rawMidiInfo)
       Print "\n ------ "; subDevCount; " "; stringa; " subdevice ("; snd_rawmidi_info_get_subdevices_avail(rawMidiInfo); " disponibili)"
       Print "id = "; snd_rawmidi_info_get_id(rawMidiInfo)
       Print "nome = "; snd_rawmidi_info_get_name(rawMidiInfo)
     Endif
   
' NOTA: Se è presente un solo subdispositivo, allora il numero del subdispositivo è immateriale, e può essere omesso:
     If subDevCount > 1 Then
       Print "   MIDI "; stringa; " 'hw:"; cardN; ","; devN; ","; i; "'"
     Else
       Print "   MIDI "; stringa; " 'hw:"; cardN; ","; devN; "'"
     Endif

     Print "   sottonome = '"; snd_rawmidi_info_get_subdevice_name(rawMidiInfo); "'"
   
     Inc i
 
   Wend
 
End


Note

[1] Vedere la seguente pagina: https://www.alsa-project.org/alsa-doc/alsa-lib/control.html#control_cards_id