Differenze tra le versioni di "Gestione dei dati media con GStreamer"

Da Gambas-it.org - Wikipedia.
Riga 169: Riga 169:
  
 
Riportiamo un esempio pratico funzionante con un'applicazione in ambiente grafico:
 
Riportiamo un esempio pratico funzionante con un'applicazione in ambiente grafico:
  Private play As Pointer
+
  Private elem As Pointer
 +
Private tempus As Timer
 +
 
   
 
   
 
  Library "libgstreamer-1.0"
 
  Library "libgstreamer-1.0"
 
   
 
   
  Private Const GST_STATE_NULL As Integer = 1
+
  Private Enum GST_STATE_VOID_PENDING = 0, GST_STATE_NULL, GST_STATE_READY, GST_STATE_PAUSED, GST_STATE_PLAYING
  Private Const GST_STATE_PLAYING As Integer = 4
+
  Private GST_FORMAT_TIME As Integer = 3
 
   
 
   
 
  <FONT color=gray>' ''gst_init (int *argc, char **argv[])''
 
  <FONT color=gray>' ''gst_init (int *argc, char **argv[])''
Riga 194: Riga 196:
 
  <FONT color=gray>' ''GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state)''
 
  <FONT color=gray>' ''GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state)''
 
  ' ''Sets the state of the element.''</font>
 
  ' ''Sets the state of the element.''</font>
  Private Extern gst_element_set_state(gstobject As Pointer, state As Integer) As Integer
+
  Private Extern gst_element_set_state(gstelement As Pointer, state As Integer) As Integer
 +
 +
<FONT color=gray>' ''gboolean gst_element_query_duration (GstElement *element, GstFormat format, gint64 *duration)''
 +
' ''Queries an element for the total stream duration in nanoseconds.''</font>
 +
Private Extern gst_element_query_duration(gstelement As Pointer, gstformat As Pointer, duration As Pointer) As Boolean
 +
 +
<FONT color=gray>' ''gboolean gst_element_query_position (GstElement *element, GstFormat format, gint64 *cur)''
 +
' ''Queries an element for the stream position in nanoseconds.''</font>
 +
Private Extern gst_element_query_position(gstelement As Pointer, gstformat As Pointer, cur As Pointer) As Boolean
 
   
 
   
 
  <FONT color=gray>' ''void gst_object_unref(gpointer object)''
 
  <FONT color=gray>' ''void gst_object_unref(gpointer object)''
Riga 202: Riga 212:
 
   
 
   
 
  '''Public''' Sub Form_Open()
 
  '''Public''' Sub Form_Open()
 +
 +
  gst_init(0, 0)
 +
 +
  With tempus = New Timer As "Tempus"
 +
    .Delay = 70
 +
  End With
 +
 
 +
'''End'''
 +
 +
 +
'''Public''' Sub Button1_Click()  <FONT color=gray>' ''Avvia la riproduzione del file mediale''</font>
 
   
 
   
 
   Dim fileaudio as string
 
   Dim fileaudio as string
 
  gst_init(0, Null)
 
 
   
 
   
 
   play = gst_element_factory_make("playbin", "Riproduzione")
 
   play = gst_element_factory_make("playbin", "Riproduzione")
Riga 212: Riga 231:
 
   
 
   
 
   g_object_set(play, "uri", g_filename_to_uri(fileaudio, Null, 0), Null)
 
   g_object_set(play, "uri", g_filename_to_uri(fileaudio, Null, 0), Null)
+
   
 
  <FONT color=gray>' ''Avviamo la riproduzione audio:''</font>
 
  <FONT color=gray>' ''Avviamo la riproduzione audio:''</font>
 
   gst_element_set_state(play, GST_STATE_PLAYING)
 
   gst_element_set_state(play, GST_STATE_PLAYING)
 +
 +
  tempus.Start
 
    
 
    
 
  '''End'''
 
  '''End'''
 
   
 
   
 
   
 
   
  '''Public''' Sub Button1_Click()   <FONT color=gray>' ''Arrestiamo la riproduzione audio''</font>
+
  '''Public''' Sub Button2_Click()   <FONT color=gray>' ''Arresta la riproduzione del file mediale''</font>
 
   
 
   
 
   Dim rit As Integer
 
   Dim rit As Integer
 
+
 +
  tempus.Stop
 +
 
 
   rit = gst_element_set_state(play, GST_STATE_NULL)
 
   rit = gst_element_set_state(play, GST_STATE_NULL)
 
   Print "Stato di cambiamento = "; rit
 
   Print "Stato di cambiamento = "; rit
Riga 231: Riga 254:
 
   
 
   
 
   
 
   
  '''Public''' Sub ToggleButton1_Click()  <FONT color=gray>' ''Poniamo in pausa e riprendiamo la riproduzione audio''</font>
+
  '''Public''' Sub ToggleButton1_Click()  <FONT color=gray>' ''Pone in pausa e riprende la riproduzione del file mediale''</font>
 
   
 
   
 
   Dim rit As Integer
 
   Dim rit As Integer
 
   
 
   
 
   If ToggleButton1.Value Then
 
   If ToggleButton1.Value Then
 +
    tempus.Stop
 
     rit = gst_element_set_state(play, GST_STATE_PAUSED)
 
     rit = gst_element_set_state(play, GST_STATE_PAUSED)
 
   Else
 
   Else
 
     rit = gst_element_set_state(play, GST_STATE_PLAYING)
 
     rit = gst_element_set_state(play, GST_STATE_PLAYING)
 +
    tempus.Start
 
   Endif
 
   Endif
 
   
 
   
Riga 244: Riga 269:
 
   
 
   
 
  '''End'''
 
  '''End'''
 +
 +
 +
'''Public''' Sub Tempus_Timer()
 +
 
 +
  Dim positio, durata As Long
 +
 
 +
  gst_element_query_duration(elem, GST_FORMAT_TIME, VarPtr(durata))
 +
 
 +
  gst_element_query_position(elem, GST_FORMAT_TIME, VarPtr(positio))
 +
 
 +
  Write #File.Out, "\rDurata: " & Date(0, 0, 0, 0, 0, 0, durata / 1000000) & "  -  Posizione: " & Date(0, 0, 0, 0, 0, 0, positio / 1000000)
 +
 
 +
  If (positio > 0) And (durata = positio) Then
 +
    tempus.Stop
 +
    gst_element_set_state(elem, GST_STATE_NULL)
 +
    gst_object_unref(elem)
 +
  Endif
 +
 +
'''End'''
 +
  
  
Riga 276: Riga 321:
 
  <FONT color=gray>' ''gboolean gst_element_query_duration (GstElement *element, GstFormat format, gint64 *duration)''
 
  <FONT color=gray>' ''gboolean gst_element_query_duration (GstElement *element, GstFormat format, gint64 *duration)''
 
  ' ''Queries an element for the total stream duration in nanoseconds.''</font>
 
  ' ''Queries an element for the total stream duration in nanoseconds.''</font>
  Private Extern gst_element_query_duration(gstelement As Pointer, GstFormat As Pointer, duration As Pointer) As Boolean
+
  Private Extern gst_element_query_duration(gstelement As Pointer, gstformat As Pointer, duration As Pointer) As Boolean
 
   
 
   
 
  <FONT color=gray>' ''gboolean gst_element_query_position (GstElement *element, GstFormat format, gint64 *cur)''
 
  <FONT color=gray>' ''gboolean gst_element_query_position (GstElement *element, GstFormat format, gint64 *cur)''
 
  ' ''Queries an element for the stream position in nanoseconds.''</font>
 
  ' ''Queries an element for the stream position in nanoseconds.''</font>
  Private Extern gst_element_query_position(gstelement As Pointer, GstFormat As Pointer, cur As Pointer) As Boolean
+
  Private Extern gst_element_query_position(gstelement As Pointer, gstformat As Pointer, cur As Pointer) As Boolean
 
   
 
   
 
  <FONT color=gray>' ''void gst_object_unref(gpointer object)''
 
  <FONT color=gray>' ''void gst_object_unref(gpointer object)''

Versione delle 07:12, 11 ago 2015

Per gestire i dati, al fine di ottenere il risultato ed il fine desiderato: esecuzione sonora, video o altro, bisognerà utilizzare specifiche funzioni, anche finalizzate alla creazione ed all'uso delle funzionalità degli Elementi di GStreamer.


Impostare un Elemento per la gestione del flusso dei dati

Un Elemento è la Classe di oggetti più importante in GStreamer. Esso svolge una determinata funzione, ed è utilizzato per gestire il flusso di dati, come ad esempio lettura, decodifica ed invio dei medesimi alla scheda audio. Concatenando più Elementi (pipeline) è possibile sfruttare le loro funzionalità ed ottenere gli obiettivi desiderati (come ad esmepio la riproduzione audio) multimediali.

Il modo più semplice per creare un Elemento è utilizzare la funzione:

GstElement * gst_element_factory_make(const gchar *factoryname, const gchar *name)

alla quale si passa il nome di un Elemento fra quelli predisposti da GStreamer ed una denominazione per l'Elemento appena creato. È possibile passare NULL come argomento name per ottenere un unico nome predefinito.
Quando un Elemento viene creato, esso assume un riferimento numerico pari ad un'unità pari al numero di elementi in quel momento creati. Così se ad esempio il nuovo Elemento creato è il secondo, esso assumerà un riferimento numerico uguale a 2.
Detta funzione restituisce una variabile di tipo Puntatore al nuovo Elemento creato, che sarà utilizzata per richiamare appunto quell'Elemento.
Il nuovo Elemento creato con un nome previsto da GStreamer è in grado di gestire solitamente file audio e video, nonché, a seconda dell'Elemento richiamato, altre determinate caratteristiche.
In Gambas dichiareremo la funzione nel seguente modo:

Private Extern gst_element_factory_make(factoryname As String, name As String) As Pointer

e la richiameremo in routine ad esempio così:

Private elem As Pointer

Public Sub ......()

 elem = gst_element_factory_make("playbin", "esegui")
......


Eliminare un Elemento

Per eliminare un Elemento, precedentemente creato, si utilizza la funzione:

void gst_object_unref(gpointer object)

alla quale va passata la variabile di tipo Pointer che punta all'Elemento creato.
La distruzione dell'Elemento determina il decremento del riferimento numerico di un'unità.
In Gambas la funzione sarà così dichiarata:

Private Extern gst_object_unref(object As Pointer)

e sarà richiamata in routine ad esempio così:

gst_object_unref(elem)


Impostare lo stato di un Elemento

Per impostare un particolare stato di un Elemento, si utilizzerà la funzione:

GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state)

La funzione può ritornare uno dei seguenti valori:

  • GST_STATE_CHANGE_FAILURE, uguale a 0, se l'ultimo stato di cambiamento è fallito;
  • GST_STATE_CHANGE_SUCCESS, uguale a 1, se l'Elemento non ha stato più attesa e l'ultimo cambiamento di stato è riuscito;
  • GST_STATE_CHANGE_ASYNC, uguale a 2, se l'Elemento sta ancora eseguendo un cambiamento di stato;
  • GST_STATE_CHANGE_NO_PREROLL, uguale a 3, se il cambiamento di stato è riuscito, ma l'Elemento non è in grado di produrre i dati in GST_STATE_PAUSED.

La funzione in Gambas sarà così dichiarata:

Private Extern gst_element_set_state(gstobject As Pointer, state As Integer) As Integer

Variando il parametro state, si varierà lo stato dell'Elemento di GStreamer. I possibili valori di stato di un Elemento sono:

  • GST_STATE_VOID_PENDING = 0 ' nessuno stato sospeso
  • GST_STATE_NULL = 1 ' lo stato con valore Null o lo stato iniziale di un "Elemento"
  • GST_STATE_READY = 2 ' l'Elemento è "pronto" per essere posto in pausa
  • GST_STATE_PAUSED = 3 ' l'Elemento è in "pausa"
  • GST_STATE_PLAYING = 4 ' l'Elemento sta eseguendo i dati che fluiscono


Impostare lo stato per la Riproduzione di un flusso di dati

Per poter ottenere la riproduzione di un flusso di dati, ad esempio caricati da un file audio, si imposterà il parametro state con la costante GST_STATE_PLAYING di GStreamer, che equivale al valore 4. Pertanto la predetta funzione sarà in routine impostata:

Private Const GST_STATE_PLAYING As Integer = 4

Public Sub ......()

gst_element_set_state(elem, GST_STATE_PLAYING)
......

Richiamata detta funzione, si avrà la riproduzione audio dei dati caricati.


Caricare un file da gestire

Per far gestire (ad esempio farlo eseguire) un file audio, è necessario attribuire detto file come proprietà all'Elemento creato. Si utilizzerà la seguente funzione esterna:

void g_object_set(gpointer object, const gchar *first_property_name, const gchar *value, Null)

laddove in particolare la varibile di tipo Puntatore *value conterrà il percorso del file da gestire.
In Gambas detta funzione sarà così dichiarata:

Private Extern g_object_set(object As Pointer, nomeProprietà As String, value As String, nl As String)

Va precisato che il nom del file va passato con la codifica della Universal Resource Identifiers (URIs). Per trasformare un ordinario indirizzo del file nella sua codifica URI, potremo servirci della funzione esterna:

gchar * g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **error)

che dichiareremo come segue:

Private Extern g_filename_to_uri(filename As String, hostname As String, GError As Pointer) As String

Pertanto avremo in routine ad esempio:

Dim percorsoFile As String

 percorsoFile = Dialog.Path

 g_object_set(elem, "nome", g_filename_to_uri(percorsoFile, Null, 0), Null)


Conoscere la durata del flusso di dati da eseguire

Per conoscere la durata del flusso di dati da eseguire, ad esempio la durata di un brano audio, si utilizzerà la funzione esterna:

gboolean gst_element_query_duration(GstElement *element, GstFormat format, gint64 *duration)

laddove il parametro format è un intero che può assumere uno dei seguenti valori da impostare preventivamente a seconda del bisogno:

  • GST_FORMAT_UNDEFINED = 0 ' formato indefinito
  • GST_FORMAT_DEFAULT = 1 ' il formato di default dell'lemento, che può essere in campioni per l'audio, fotogrammi per il video
  • GST_FORMAT_BYTES = 2 ' byte
  • GST_FORMAT_TIME = 3 ' nanosecondi
  • GST_FORMAT_BUFFERS = 4 ' buffer
  • GST_FORMAT_PERCENT = 5 ' percentuale di dati

Il parametro duration è la variabile di tipo Pointer nella quale viene immagazzinata la durata complessiva. Parametro per i ritorni derivanti. Il default è il trasferimento completo. Può assumere il valore 0.
La funzione ritorna un valore booleano True se l'interrogazione, al fine di conoscere la durata dei dati, può essere effettuata. In Gambas questa funzione sarà così dichiarata:

Private Extern gst_element_query_duration(gselement As Pointer, formatI As Integer, duration As Pointer) As Boolean

e sarà richiamata in routine ad esempio così:

Dim Dim GST_FORMAT_TIME As Integer = 3
Dim durata As Long

 gst_element_query_duration(elem, GST_FORMAT_TIME, VarPtr(durata))
 
 Print durata


Conoscere durante l'esecuzione la posizione nel flusso dei dati

Per conoscere la posizione corrente all'interno dei dati da processare, si farà uso della funzione esterna:

gboolean gst_element_query_position(GstElement *element, GstFormat format, gint64 *cur)

laddove il parametro format è un intero che può assumere uno dei seguenti valori da impostare preventivamente a seconda del bisogno:

  • GST_FORMAT_UNDEFINED = 0 ' formato indefinito
  • GST_FORMAT_DEFAULT = 1 ' il formato di default dell'lemento, che può essere in campioni per l'audio, fotogrammi per il video
  • GST_FORMAT_BYTES = 2 ' byte
  • GST_FORMAT_TIME = 3 ' nanosecondi
  • GST_FORMAT_BUFFERS = 4 ' buffer
  • GST_FORMAT_PERCENT = 5 ' percentuale di dati

Il parametro cur è la variabile di tipo Pointer nella quale viene immagazzinata la posizione corrente.
La funzione ritorna un valore booleano True se l'interrogazione, al fine di conoscere la durata dei dati, può essere effettuata. In Gambas questa funzione sarà così dichiarata:

Private Extern gst_element_query_position(gselement As Pointer, formatI As Integer, cur As Pointer) As Boolean

e sarà richiamata in routine ad esempio così:

Dim GST_FORMAT_TIME As Integer = 3
Dim pos As Long

 gst_element_query_position(elem, GST_FORMAT_TIME, VarPtr(pos))

 Print pos


Conocere lo stato dell'Elemento

Per conoscere lo stato corrente di un Elemento, si utilizzerà la funzione esterna:

GstStateChangeReturn gst_element_get_state(GstElement *element, GstState *state, GstState *pending, GstClockTime timeout)

laddove il parametro state è una variabile di tipo Pointer che punta alla zona di memoria, nella quale è contenuto il valore dello stato corrente dell'Elemento. La funzione può ritornare uno dei seguenti valori:

  • GST_STATE_CHANGE_FAILURE, uguale a 0, se l'ultimo stato di cambiamento è fallito;
  • GST_STATE_CHANGE_SUCCESS, uguale a 1, se l'elemento non ha stato più attesa e l'ultimo cambiamento di stato è riuscito;
  • GST_STATE_CHANGE_ASYNC, uguale a 2, se l'elemento sta ancora eseguendo un cambiamento di stato.

Per gli elementi che non ritornano il valore GST_STATE_CHANGE_ASYNC, questa funzione restituisce immediatamente lo stato attuale e in sospeso.
In Gambas questa funzione sarà così dichiarata:

Private Extern gst_element_get_state(gstobject As Pointer, stateP As Pointer, pendingP As Pointer, timeLout As Long) As Integer

e sarà richiamata in routine ad esempio così:

Dim state, pending As Pointer
Dim timeout As Long

 state = Alloc(4)
 pending = Alloc(4)

 gst_element_get_state(player, state, pending, timeout)

 Print Int@(state)


Termine e chiusura di GStreamer

Nel caso in cui si intendano chiudere o comunque interrompere le risorse di GStreamer, ad esempio quando si procede alla chiusura del programma, è buona abitudine effettuare la chiusura mediante la funzione:

void gst_object_unref(gpointer object)

precedentementre vista, che eliminerà l'Elemento; nonché la funzione:

GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state)

anche questa precedentementre vista, alla quale in Gambas attribuiremo il secondo parametro a Null:

gst_element_set_state(elem, GST_STATE_NULL)


Riassunto essenziale per la Riproduzione audio

In conclusione possiamo dire che bastano solo poche funzioni esterne del API di GStreamer per effettuare la riproduzione di un file audio.

Riportiamo un esempio pratico funzionante con un'applicazione in ambiente grafico:

Private elem As Pointer
Private tempus As Timer


Library "libgstreamer-1.0"

Private Enum GST_STATE_VOID_PENDING = 0, GST_STATE_NULL, GST_STATE_READY, GST_STATE_PAUSED, GST_STATE_PLAYING
Private GST_FORMAT_TIME As Integer = 3

' gst_init (int *argc, char **argv[])
' Initializes the GStreamer library, setting up internal path lists, registering built-in elements, and loading standard plugins.
Private Extern gst_init(argc As Pointer, argv As Pointer)

' GstElement * gst_element_factory_make(const gchar *factoryname, Const gchar * name)
' Create a new element of the type defined by the given element factory.
Private Extern gst_element_factory_make(factoryname As String, name As String) As Pointer

' gchar * g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **error)
' Converts an absolute filename to an escaped ASCII-encoded URI.
Private Extern g_filename_to_uri(filename As String, hostname As String, GError As Pointer) As String

' void g_object_set(gpointer object, const gchar *first_property_name, ...)
' Sets properties on an object.
Private Extern g_object_set(gobject As Pointer, key As String, value As String, tertium As String)

' GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state)
' Sets the state of the element.
Private Extern gst_element_set_state(gstelement As Pointer, state As Integer) As Integer

' gboolean gst_element_query_duration (GstElement *element, GstFormat format, gint64 *duration)
' Queries an element for the total stream duration in nanoseconds.
Private Extern gst_element_query_duration(gstelement As Pointer, gstformat As Pointer, duration As Pointer) As Boolean

' gboolean gst_element_query_position (GstElement *element, GstFormat format, gint64 *cur)
' Queries an element for the stream position in nanoseconds.
Private Extern gst_element_query_position(gstelement As Pointer, gstformat As Pointer, cur As Pointer) As Boolean

' void gst_object_unref(gpointer object)
' Decrements the reference count on object .
Private Extern gst_object_unref(gobject As Pointer)


Public Sub Form_Open()

  gst_init(0, 0)

  With tempus = New Timer As "Tempus"
    .Delay = 70
  End With
  
End


Public Sub Button1_Click()   ' Avvia la riproduzione del file mediale

 Dim fileaudio as string

  play = gst_element_factory_make("playbin", "Riproduzione")

  fileaudio = "/percorso/del/file/audio"

  g_object_set(play, "uri", g_filename_to_uri(fileaudio, Null, 0), Null)
   
' Avviamo la riproduzione audio:
  gst_element_set_state(play, GST_STATE_PLAYING)

  tempus.Start
 
End


Public Sub Button2_Click()   ' Arresta la riproduzione del file mediale

 Dim rit As Integer

  tempus.Stop
  
  rit = gst_element_set_state(play, GST_STATE_NULL)
  Print "Stato di cambiamento = "; rit
   
  gst_object_unref(play)

End


Public Sub ToggleButton1_Click()   ' Pone in pausa e riprende la riproduzione del file mediale

 Dim rit As Integer

  If ToggleButton1.Value Then
    tempus.Stop
    rit = gst_element_set_state(play, GST_STATE_PAUSED)
  Else
    rit = gst_element_set_state(play, GST_STATE_PLAYING)
    tempus.Start
  Endif

  Print "Stato di cambiamento = "; rit

End


Public Sub Tempus_Timer()
 
 Dim positio, durata As Long
 
  gst_element_query_duration(elem, GST_FORMAT_TIME, VarPtr(durata))
 
  gst_element_query_position(elem, GST_FORMAT_TIME, VarPtr(positio))
  
  Write #File.Out, "\rDurata: " & Date(0, 0, 0, 0, 0, 0, durata / 1000000) & "  -   Posizione: " & Date(0, 0, 0, 0, 0, 0, positio / 1000000)
  
  If (positio > 0) And (durata = positio) Then
    tempus.Stop
    gst_element_set_state(elem, GST_STATE_NULL)
    gst_object_unref(elem)
  Endif

End



Quest'altro esempio, invece, prevede un'applicazione a riga di comando. Saranno mostrati anche la durata del brano e la posizione temporale corrente durante l'esecuzione:

Library "libgstreamer-1.0"

Private Const GST_STATE_NULL As Integer = 1
Private Const GST_FORMAT_TIME As Integer = 3
Private Const GST_STATE_PLAYING As Integer = 4

' gst_init (int *argc, char **argv[])
' Initializes the GStreamer library, setting up internal path lists, registering built-in elements, and loading standard plugins.
Private Extern gst_init(argc As Pointer, argv As Pointer)

' GstElement * gst_element_factory_make(const gchar *factoryname, Const gchar * name)
' Create a new element of the type defined by the given element factory.
Private Extern gst_element_factory_make(factoryname As String, name As String) As Pointer

' gchar * g_filename_to_uri (const gchar *filename, const gchar *hostname, GError **error)
' Converts an absolute filename to an escaped ASCII-encoded URI.
Private Extern g_filename_to_uri(filename As String, hostname As String, GError As Pointer) As String

' void g_object_set(gpointer object, const gchar *first_property_name, ...)
' Sets properties on an object.
Private Extern g_object_set(gobject As Pointer, key As String, value As String, tertium As String)

' GstStateChangeReturn gst_element_set_state(GstElement *element, GstState state)
' Sets the state of the element.
Private Extern gst_element_set_state(gstelement As Pointer, state As Integer) As Integer

' gboolean gst_element_query_duration (GstElement *element, GstFormat format, gint64 *duration)
' Queries an element for the total stream duration in nanoseconds.
Private Extern gst_element_query_duration(gstelement As Pointer, gstformat As Pointer, duration As Pointer) As Boolean

' gboolean gst_element_query_position (GstElement *element, GstFormat format, gint64 *cur)
' Queries an element for the stream position in nanoseconds.
Private Extern gst_element_query_position(gstelement As Pointer, gstformat As Pointer, cur As Pointer) As Boolean

' void gst_object_unref(gpointer object)
' Decrements the reference count on object .
Private Extern gst_object_unref(gobject As Pointer)


Public Sub Main()

 Dim play As Pointer
 Dim fileaudio as string
 Dim posizione, durata As Long

  gst_init(0, Null)

  play = gst_element_factory_make("playbin", "audio")

  fileaudio = "/percorso/del/file/audio"

  g_object_set(play, "uri", g_filename_to_uri(fileaudio, Null, 0), Null)

' Avviamo la riproduzione audio:
  gst_element_set_state(play, GST_STATE_PLAYING)
 
  While (posizione = 0) Or (durata > posizione)
    gst_element_query_duration(play, GST_FORMAT_TIME, VarPtr(durata))
    gst_element_query_position(play, GST_FORMAT_TIME, VarPtr(posizione))
    Write #File.Out, "\rDurata: " & Date(0, 0, 0, 0, 0, 0, durata / 1000000) & "      Pos. " & Date(0, 0, 0, 0, 0, 0, posizione / 1000000)
  Wend
   
  gst_object_unref(play)
  
End