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

Da Gambas-it.org - Wikipedia.
Riga 5: Riga 5:
 
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.
  
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.
+
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
 +
La stringa identificativa sarà presente nella linea: "''Nome:'' ".
  
 
Mostriamo un esempio pratico in ambiente grafico:
 
Mostriamo un esempio pratico in ambiente grafico:
Riga 65: Riga 66:
 
   CreaSo()
 
   CreaSo()
 
      
 
      
   Object.Lock(Dial1)
+
   Object.Lock(SpinBox1)
 
      
 
      
   With Dial1
+
   With SpinBox1
 
     .MaxValue = MASSIMO_VOLUME
 
     .MaxValue = MASSIMO_VOLUME
 
     .MinValue = 656
 
     .MinValue = 656
Riga 90: Riga 91:
 
   pa_cvolume_init(vol)
 
   pa_cvolume_init(vol)
 
      
 
      
   Object.Unlock(Dial1)
+
   Object.Unlock(SpinBox1)
 
      
 
      
 
   sink = Lista_Sink()
 
   sink = Lista_Sink()
Riga 99: Riga 100:
 
   
 
   
 
   
 
   
  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)

Versione delle 18:20, 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

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