Sto creando una piccola applicazione per un progetto, un player mp3 che preso in imput un file mp3 visualizzi l'id3 tag, lo riproduca e che renda possibile metterlo in pausa o riprenderne l'esecuzione e che una volta terminato il file esca dal programma... Pensavo fosse più facile purtroppo mi trovo invece di fronte a vari problemi che sembrano insormontabili, ma spero che con il vostro aiuto si riesca a risolverli e a migliorare dove possibile Grazie. Dopo questa sviolinata ecco il codice:
codice:
#include <gst/gst.h>
GstElement *player; // bin
char carattere; // variabile controllo riproduzione
static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
{
GMainLoop *loop = (GMainLoop *) data;
// esegue una diversa azione a seconda del messaggio su bus
switch (GST_MESSAGE_TYPE (msg))
{
// termina l'applicazione all'End Of Stream
case GST_MESSAGE_EOS:
g_print ("Fine del file\n");
g_main_loop_quit (loop);
break;
// termina l'applicazione ad un qualsiasi errore
case GST_MESSAGE_ERROR:
g_print ("Errorore\n");
g_main_loop_quit (loop);
break;
// controllo sulla riproduzione (CONTROLLARE [PUNTO 1])
default:
scanf(" %c", &carattere);
// mette la bin in riproduzione se è inserito il carattere
// corretto e la bin era in pausa
if(carattere == 'p'&& GST_STATE (player) == GST_STATE_PAUSED)
{
gst_element_set_state(player, GST_STATE_PLAYING);
g_print ("Riprendo l'esecuzione\n");
}
// mette la bin in pausa se è inserito il carattere
// corretto e la bin era in riproduzione
if(carattere == 'p' && GST_STATE (player) == GST_STATE_PLAYING)
{
gst_element_set_state(player, GST_STATE_PAUSED);
g_print ("Esecuzione interrotta\n");
}
// esce dall'applicazione inserendo il carattere corretto
if(carattere == 'q')
{
g_print ("Chiusura programma\n");
g_main_loop_quit (loop);
}
break;
}
return TRUE;
}
int main ()
{
const gchar *nano_str; // variabili per la versione di gstreamer utilizzata
guint major, minor, micro, nano; // variabili per la versione di gstreamer utilizzata
GstElement *sorgente, *decoder, *sink; // elementi
GMainLoop *loop; // loop
GstBus *bus; // bus
// inizializzazione
gst_init (NULL, NULL);
loop = g_main_loop_new (NULL, FALSE);
// visualizza versione delle librerie
gst_version (&major, &minor, µ, &nano);
if (nano == 1)
nano_str = "(CVS)";
else if (nano == 2)
nano_str = "(Prerelease)";
else
nano_str = "";
g_print ("Questo programma utilizza le librerie gstreamer %d.%d.%d %s\n", major, minor, micro, nano_str);
// messaggi vari
g_print ("Comandi: \n p - PAUSA/RIPRENDI\n q - ESCI\n");
// creazione elementi
player = gst_pipeline_new("mp3_player"); // creazione bin
sorgente = gst_element_factory_make("filesrc", "sorgente"); // creazione sorgente
decoder = gst_element_factory_make("mad", "filtro"); // creazione decoder
sink = gst_element_factory_make("alsasink", "destinazione"); // creazione destinazione
// controllo sulla corretta creazione degli elementi
if (!player || !sorgente || !decoder || !sink)
{
g_print ("Un elemento non può essere creato\n");
return -1;
}
// selezionare la locazione della sorgente
g_object_set(G_OBJECT(sorgente), "location", "pinopino.mp3", NULL);
// inserisci un message handler
bus = gst_pipeline_get_bus (GST_PIPELINE (player));
gst_bus_add_watch (bus, bus_call, loop);
gst_object_unref (bus);
// incapsuliamo gli elementi nella bin
gst_bin_add_many(GST_BIN(player), sorgente, decoder, sink, NULL);
// linkiamo gli elementi
gst_element_link_many(sorgente, decoder, sink, NULL);
// modifichiamo lo stato della bin in play
gst_element_set_state(player, GST_STATE_PLAYING);
g_main_loop_run (loop);
// dealloca gli elementi
gst_element_set_state (player, GST_STATE_NULL);
gst_object_unref (GST_OBJECT(player));
g_main_loop_unref (loop);
return 0;
}
Cominciamo ad indicare i punti dove c'è errore:
[PUNTO 1] questo piccolo ciclo dovrebbe restare in attesa durante la riproduzione ed aspettare l'inserimento del carattere p per andare in pausa/riproduzione o uscire dal programma:
- la riproduzione va in pausa, ma al rientro dalla pausa mi esegue di seguito gst_element_set_state(player, GST_STATE_PLAYING) e gst_element_set_state(player, GST_STATE_PAUSED), mantenendo di fatto la bin in pausa, consigli? Eventualmente (ancora meglio) sarebbe possibile associare i vari stati alla pressione di un tasto?
- al termine del file mp3 ovviamente ho lo scanf che aspetta un input e quindi non mi chiude l'applicazione... c'è un modo per forzarne l'uscita?
- (parecchio utopica come cosa) sarebbe possibile aggiungere a seguito dei comandi una barra di progressione che avanzi all'avanzare della riproduzione (come la barra del chdsk su linux)?
Ovviamente il file fisso in riproduzione è voluto ed è stato fatto per semplificare le operazioni durante le prove dell'app... Per ora non ho inserito la stampa del tag mp3, la metterò in seguito.