Differenze tra le versioni di "Modificare il volume generale mediante le funzioni esterne del API di PulseAudio"

Da Gambas-it.org - Wikipedia.
(Creata pagina con "Il sistema ''PulseAudio'' consente anche di modificare in tempo reale il volume generale dell'audio. E' necessario richiamare in Gambas la libreria dinamica condivisa: "''lib...")
 
 
(14 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
 
Il sistema ''PulseAudio'' consente anche di modificare in tempo reale il volume generale dell'audio.
 
Il sistema ''PulseAudio'' consente anche di modificare in tempo reale il volume generale dell'audio.
  
E' necessario richiamare in Gambas la libreria dinamica condivisa: "''libpulse.so.0.16.2''"
+
E' necessario in questo caso avere installata nel proprio sistema e richiamare in Gambas la libreria condivisa: "''libpulse.so.0.24.2 ''"  
  
 +
Poiché bisogna utilizzare la modalità ''asincrona'' con l'uso di funzioni esterne per il richiamo di funzioni di ''callback'', prevista dalle risorse di ''PulseAudio'', sarà necessario prevedere la creazione e l'uso di un'apposita libreria dinamica condivisa esterna, scritta in C.
  
Poiché bisogna utilizzare la modalità ''asincrona'' con l'uso di funzioni esterne per il richiamo di funzioni di ''callback'', prevista dalle risorse di ''PulseAudio'', sarà necessario prevedere la creazione e l'uso di un'apposita libreria dinamica condivisa esterna.
+
Ricordare che si dovrà inserire nell'oggetto ''InputBox'' la stringa identificativa (ad esempio: <FONT Color=gray>''alsa_output.pci-0000_01_00.1.hdmi-stereo''</font>) del ''sink'' dell'uscita audio, corrispondente alla corrente scheda audio attiva, e che potrà essere individuata lanciando in Terminale la seguente riga di comando:
 
+
~ $ pactl list sinks
Ricordare che si dovrà inserire nell'oggetto ''InputBox'' la stringa identificativa (ad esempio: <FONT Color=gray>''alsa_output.pci-0000_01_00.1.hdmi-stereo''</font>) del ''sink'' dell'uscita audio, corrispondente alla corrente scheda audio attiva.
+
o anche:
 +
~ $ pacmd list-sinks | grep -e 'name:' -e 'index:'
 +
La stringa identificativa sarà presente nella linea: "''Nome:'' ".
  
  
Riga 12: Riga 15:
 
  Private context As Pointer
 
  Private context As Pointer
 
  Private vol As Pointer
 
  Private vol As Pointer
  Private DEVICE As String
+
  Private dispositivo As String
 
  Private Const MASSIMO_VOLUME As Integer = 65536
 
  Private Const MASSIMO_VOLUME As Integer = 65536
 
   
 
   
 
   
 
   
  Library "libpulse:0.16.2"
+
  Library "libpulse:0.24.2"
 
   
 
   
 
  <FONT Color=gray>' ''pa_threaded_mainloop *pa_threaded_mainloop_new(void)''
 
  <FONT Color=gray>' ''pa_threaded_mainloop *pa_threaded_mainloop_new(void)''
Riga 55: Riga 58:
 
  <FONT Color=gray>' ''void Imposta_Volume(pa_context *c, char *device, struct pa_cvolume *v)''
 
  <FONT Color=gray>' ''void Imposta_Volume(pa_context *c, char *device, struct pa_cvolume *v)''
 
  ' ''Chiama la libreria .so appositamente creata per usare la funzione esterna 'pa_context_set_sink_volume_by_name( )'''</font>
 
  ' ''Chiama la libreria .so appositamente creata per usare la funzione esterna 'pa_context_set_sink_volume_by_name( )'''</font>
  Private Extern Imposta_Volume(c As Pointer, name As String, volume As Pointer)
+
  Private Extern Imposta_Volume(c As Pointer, device As String, v As Pointer)
 
   
 
   
 
   
 
   
  '''Public''' Sub Form_Open()
+
  Public Sub Form_Open()
 
    
 
    
 
   Dim ml, mlgapi As Pointer
 
   Dim ml, mlgapi As Pointer
   Dim sink As String
+
   Dim sink, exemplum As String
 
    
 
    
  CreaSo()
+
<FONT Color=gray>' ''Crea l'apposita libreria dinamica condivisa esterna per la corretta gestione delle funzioni esterne di "callback":</font>
 +
  CreaSo()
 
      
 
      
  Object.Lock(Dial1)
+
  Object.Lock(SpinBox1)
 
      
 
      
  With Dial1
+
  With SpinBox1
    .MaxValue = MASSIMO_VOLUME
+
    .MaxValue = MASSIMO_VOLUME
    .MinValue = 656
+
    .MinValue = 656
    .Value = MASSIMO_VOLUME \ 2
+
    .Value = MASSIMO_VOLUME \ 2
      Valore_TextBox(.Value)
+
    Valore_TextBox(.Value)
  End With
+
  End With
 
      
 
      
 
  <FONT Color=gray>' ''Crea un mainloop API e una connessione al server audio predefinito:''</font>
 
  <FONT Color=gray>' ''Crea un mainloop API e una connessione al server audio predefinito:''</font>
  ml = pa_threaded_mainloop_new()
+
  ml = pa_threaded_mainloop_new()
  mlgapi = pa_threaded_mainloop_get_api(ml)
+
  mlgapi = pa_threaded_mainloop_get_api(ml)
  context = pa_context_new(mlgapi, "Controllo volume")
+
  context = pa_context_new(mlgapi, "Controllo volume")
 
      
 
      
 
  <FONT Color=gray>' ''Effettua la connessione al server di PulseAudio:''</font>
 
  <FONT Color=gray>' ''Effettua la connessione al server di PulseAudio:''</font>
  pa_context_connect(context, Null, 0, 0)
+
  pa_context_connect(context, Null, 0, 0)
 
    
 
    
  State_Callback(context)
+
  State_Callback(context)
 
      
 
      
  pa_threaded_mainloop_start(ml)
+
  pa_threaded_mainloop_start(ml)
 
      
 
      
  vol = Alloc(256)  
+
  vol = Alloc(256)  
 
    
 
    
  pa_cvolume_init(vol)
+
  pa_cvolume_init(vol)
 
      
 
      
  Object.Unlock(Dial1)
+
  Object.Unlock(SpinBox1)
 
      
 
      
  sink = Lista_Sink()
+
  sink = Lista_Sink()
  DEVICE = InputBox("Immettere il sorgente output audio:", Null, "alsa_output.pci-0000_01_00.1.hdmi-stereo")
+
  exemplum = Replace(Split(sink, ">")[0], "\tname: <", Null)
 +
  dispositivo = InputBox("Immettere il sorgente output audio:", Null, exemplum)
 
    
 
    
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Public''' Sub Dial1_Change()
+
  Public Sub SpinBox1_Change()
 
    
 
    
 
   Dim vlm As Long
 
   Dim vlm As Long
 
   Dim canali As Integer = 2
 
   Dim canali As Integer = 2
 
    
 
    
  vlm = CLong(Dial1.Value)
+
  vlm = CLong(SpinBox1.Value)
 
    
 
    
  Valore_TextBox(vlm)
+
  Valore_TextBox(vlm)
 
    
 
    
  pa_cvolume_set(vol, canali, vlm)
+
  pa_cvolume_set(vol, canali, vlm)
 
        
 
        
  Imposta_Volume(context, DEVICE, vol)
+
  Imposta_Volume(context, dispositivo, vol)
 
    
 
    
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Private''' Procedure Valore_TextBox(v As Long)
+
  Private Procedure Valore_TextBox(v As Long)
 
    
 
    
 
   TextBox1.Text = Format((v * 100) / MASSIMO_VOLUME, "###.00")
 
   TextBox1.Text = Format((v * 100) / MASSIMO_VOLUME, "###.00")
 
    
 
    
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Public''' Sub Form_Close()
+
  Public Sub Form_Close()
 
    
 
    
 
   Free(vol)
 
   Free(vol)
 
    
 
    
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Private''' Function Lista_Sink() As String
+
  Private Function Lista_Sink() As String
 
    
 
    
 
   Dim lista As String
 
   Dim lista As String
 
        
 
        
  Shell "pacmd list-sinks | grep -e 'alsa.card_name' -e 'name:'" To lista
+
  Shell "pacmd list-sinks | grep -e 'alsa.card_name' -e 'name:'" To lista
  Print "Lista sorgenti audio disponibili:\n\n"; lista
+
  Print "Lista sorgenti audio disponibili:\n\n"; lista
 
    
 
    
  Return lista
+
  Return lista
 
+
  '''End'''
+
  End
 +
 
   
 
   
 +
Private Procedure CreaSo()  <FONT Color=gray>' ''Scrive in C e crea l'apposita libreria .so esterna per la gestione delle funzioni esterne di "callback":</font>
 
   
 
   
'''Private''' Procedure CreaSo()
 
 
 
 
   File.Save("/tmp/libadhoc.c", "#include <pulse/pulseaudio.h>\n" &
 
   File.Save("/tmp/libadhoc.c", "#include <pulse/pulseaudio.h>\n" &
 
             "#include <stdio.h>"
 
             "#include <stdio.h>"
Riga 168: Riga 173:
 
   Shell "gcc -o /tmp/libadhoc.so /tmp/libadhoc.c -lpulse -shared -fPIC" Wait
 
   Shell "gcc -o /tmp/libadhoc.so /tmp/libadhoc.c -lpulse -shared -fPIC" Wait
 
    
 
    
  '''End'''
+
  End
 
 
  
  

Versione attuale delle 18:23, 13 gen 2024

Il sistema PulseAudio consente anche di modificare in tempo reale il volume generale dell'audio.

E' necessario in questo caso avere installata nel proprio sistema e richiamare in Gambas la libreria condivisa: "libpulse.so.0.24.2 "

Poiché bisogna utilizzare la modalità asincrona con l'uso di funzioni esterne per il richiamo di funzioni di callback, prevista dalle risorse di PulseAudio, sarà necessario prevedere la creazione e l'uso di un'apposita libreria dinamica condivisa esterna, scritta in C.

Ricordare che si dovrà inserire nell'oggetto InputBox la stringa identificativa (ad esempio: alsa_output.pci-0000_01_00.1.hdmi-stereo) del sink dell'uscita audio, corrispondente alla corrente scheda audio attiva, e che potrà essere individuata lanciando in Terminale la seguente riga di comando:

~ $ pactl list sinks

o anche:

~ $ pacmd list-sinks | grep -e 'name:' -e 'index:'

La stringa identificativa sarà presente nella linea: "Nome: ".


Mostriamo un esempio pratico in ambiente grafico:

Private context As Pointer
Private vol As Pointer
Private dispositivo As String
Private Const MASSIMO_VOLUME As Integer = 65536


Library "libpulse:0.24.2"

' pa_threaded_mainloop *pa_threaded_mainloop_new(void)
' Allocate a new threaded main loop object.
Private Extern pa_threaded_mainloop_new() As Pointer

' pa_mainloop_api* pa_threaded_mainloop_get_api(pa_threaded_mainloop*m)
' Return the main loop abstraction layer vtable for this main loop.
Private Extern pa_threaded_mainloop_get_api(m As Pointer) As Pointer

' pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name)
' Instantiate a new connection context with an abstract mainloop API and an application name.
Private Extern pa_context_new(mainloop As Pointer, name As String) As Pointer

' int pa_context_connect(pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api)
' Connect the context to the specified server.
Private Extern pa_context_connect(c As Pointer, server As String, flags As Integer, api As Pointer) As Integer

' int pa_threaded_mainloop_start(pa_threaded_mainloop *m)
' Start the event loop thread.
Private Extern pa_threaded_mainloop_start(m As Pointer) As Integer

' pa_cvolume* pa_cvolume_init(pa_cvolume *a)
' Initialize the specified volume and return a pointer to it.
Private Extern pa_cvolume_init(a As Pointer)

' pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v)
' Set the volume of the specified number of channels to the volume v.
Private Extern pa_cvolume_set(a As Pointer, channels As Byte, v As Long) As Pointer


Library "/tmp/libadhoc"

' void State_Callback(pa_context *c)
' Chiama la libreria .so appositamente creata per usare la funzione esterna 'pa_context_set_state_callback( )'
Private Extern State_Callback(c As Pointer)

' void Imposta_Volume(pa_context *c, char *device, struct pa_cvolume *v)
' Chiama la libreria .so appositamente creata per usare la funzione esterna 'pa_context_set_sink_volume_by_name( )'
Private Extern Imposta_Volume(c As Pointer, device As String, v As Pointer)


Public Sub Form_Open()
 
 Dim ml, mlgapi As Pointer
 Dim sink, exemplum As String
 
' Crea l'apposita libreria dinamica condivisa esterna per la corretta gestione delle funzioni esterne di "callback":
 CreaSo()
   
 Object.Lock(SpinBox1)
   
 With SpinBox1
   .MaxValue = MASSIMO_VOLUME
   .MinValue = 656
   .Value = MASSIMO_VOLUME \ 2
    Valore_TextBox(.Value)
 End With
   
' Crea un mainloop API e una connessione al server audio predefinito:
 ml = pa_threaded_mainloop_new()
 mlgapi = pa_threaded_mainloop_get_api(ml)
 context = pa_context_new(mlgapi, "Controllo volume")
   
' Effettua la connessione al server di PulseAudio:
 pa_context_connect(context, Null, 0, 0)
  
 State_Callback(context)
   
 pa_threaded_mainloop_start(ml)
   
 vol = Alloc(256) 
  
 pa_cvolume_init(vol)
   
 Object.Unlock(SpinBox1)
   
 sink = Lista_Sink()
 exemplum = Replace(Split(sink, ">")[0], "\tname: <", Null)
 dispositivo = InputBox("Immettere il sorgente output audio:", Null, exemplum)
  
End


Public Sub SpinBox1_Change()
 
 Dim vlm As Long
 Dim canali As Integer = 2
  
 vlm = CLong(SpinBox1.Value)
  
 Valore_TextBox(vlm)
  
 pa_cvolume_set(vol, canali, vlm)
     
 Imposta_Volume(context, dispositivo, vol)
  
End


Private Procedure Valore_TextBox(v As Long)
 
 TextBox1.Text = Format((v * 100) / MASSIMO_VOLUME, "###.00")
 
End


Public Sub Form_Close()
 
 Free(vol)
 
End


Private Function Lista_Sink() As String
 
 Dim lista As String
     
 Shell "pacmd list-sinks | grep -e 'alsa.card_name' -e 'name:'" To lista
 Print "Lista sorgenti audio disponibili:\n\n"; lista
  
 Return lista

End


Private Procedure CreaSo()   ' Scrive in C e crea l'apposita libreria .so esterna per la gestione delle funzioni esterne di "callback":

 File.Save("/tmp/libadhoc.c", "#include <pulse/pulseaudio.h>\n" &
           "#include <stdio.h>"
           "\n\n" &
           "void context_state_cb(pa_context *c, void *userdata) {" &
           "\n\n}" &
           "\n\n" &
           "void State_Callback(pa_context *context) {" &
           "\n\n" &
           "   pa_context_set_state_callback(context, context_state_cb, NULL);" &
           "\n\n}" &
           "\n\n" &
           "void volume_cb(pa_context *c, int risultato, void *userdata) {" &
           "\n\n" &
           "   if (risultato)\n" &
           "     printf(\"\\rVolume impostato    \");\n" &
           "   else\n" &
           "     printf(\"\\rVolume non impostato\");" &
           "\n\n}" &
           "\n\n" &
           "void Imposta_Volume(pa_context *c, char *device, struct pa_cvolume *v) {" &
           "\n\n" &
           "   pa_context_set_sink_volume_by_name(c, device, v, volume_cb, NULL); " &
           "\n\n}")
           
 Shell "gcc -o /tmp/libadhoc.so /tmp/libadhoc.c -lpulse -shared -fPIC" Wait
 
End


Riferimenti