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

Da Gambas-it.org - Wikipedia.
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 in questo caso avere installata nel proprio sistema e richiamare in Gambas la libreria condivisa: "''libpulse.so.0.24.1 ''"  
+
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, scritta in C.
Riga 15: Riga 15:
 
   
 
   
 
   
 
   
  Library "libpulse:0.24.1"
+
  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 57: Riga 57:
 
   
 
   
 
   
 
   
  '''Public''' Sub Form_Open()
+
  Public Sub Form_Open()
 
    
 
    
 
   Dim ml, mlgapi As Pointer
 
   Dim ml, mlgapi As Pointer
Riga 63: Riga 63:
 
    
 
    
 
  <FONT Color=gray>' ''Crea l'apposita libreria dinamica condivisa esterna per la corretta gestione delle funzioni esterne di "callback":</font>
 
  <FONT Color=gray>' ''Crea l'apposita libreria dinamica condivisa esterna per la corretta gestione delle funzioni esterne di "callback":</font>
  CreaSo()
+
  CreaSo()
 
      
 
      
  Object.Lock(Dial1)
+
  Object.Lock(Dial1)
 
      
 
      
  With Dial1
+
  With Dial1
    .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(Dial1)
 
      
 
      
  sink = Lista_Sink()
+
  sink = Lista_Sink()
  exemplum = Replace(Split(sink, ">")[0], "\tname: <", Null)
+
  exemplum = Replace(Split(sink, ">")[0], "\tname: <", Null)
  dispositivo = InputBox("Immettere il sorgente output audio:", Null, exemplum)
+
  dispositivo = InputBox("Immettere il sorgente output audio:", Null, exemplum)
 
    
 
    
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Public''' Sub Dial1_Change()
+
  Public Sub Dial1_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(Dial1.Value)
 
    
 
    
  Valore_TextBox(vlm)
+
  Valore_TextBox(vlm)
 
    
 
    
  pa_cvolume_set(vol, canali, vlm)
+
  pa_cvolume_set(vol, canali, vlm)
 
        
 
        
  Imposta_Volume(context, dispositivo, 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()  <FONT Color=gray>' ''Scrive in C e crea l'apposita libreria .so esterna per la gestione delle funzioni esterne di "callback":</font>
 
 
 
 
   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 169: Riga 169:
 
   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 delle 17:47, 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.


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(Dial1)
   
 With Dial1
   .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(Dial1)
   
 sink = Lista_Sink()
 exemplum = Replace(Split(sink, ">")[0], "\tname: <", Null)
 dispositivo = InputBox("Immettere il sorgente output audio:", Null, exemplum)
  
End


Public Sub Dial1_Change()
 
 Dim vlm As Long
 Dim canali As Integer = 2
  
 vlm = CLong(Dial1.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