Stefano Mtangoo
Stefano Mtangoo

Reputation: 6550

GStreamer GstBusSyncHandler Stop, Pause and Play States

I use Gstreamer as base for playing videos and audio and so far its working fine. Now I want to know when media is stopped, paused, loaded or started playing and notify the GUI. Now the Messages keep repeating itself (see the attached image). Now in that situation, it will be flooding my GUI. I want to receive event only once (for example when media is stopped or pause or loaded). The only Message that I get consistently (once) is End of Stream.

Is there a way to get the said message only once, when they happen? Here is my current code

extern "C"
{
    static GstBusSyncReply
    bus_sync(GstBus* bus, GstMessage* message, gpointer user_data)
    {
        CustomData* data = reinterpret_cast<CustomData*>(user_data);

        GstState old_state, new_state, pending;             
        gst_message_parse_state_changed(message, &old_state, &new_state, &pending);
        g_print ("State set from %s to %s --- %s\n", gst_element_state_get_name (old_state), gst_element_state_get_name (new_state), gst_element_state_get_name (pending));

        switch(GST_MESSAGE_TYPE(message))
        {
            case GST_MESSAGE_STATE_CHANGED:
            {
                wxGStreamer* win = dynamic_cast<wxGStreamer*>(data->parent);
                if(win)
                {
                    win->SendMessage(wxMEDIASTATE_CHANGED); 
                }               

                if(data->state!=new_state)
                {
                    //state changed, save it
                    data->state = new_state; 

                    if(old_state==GST_STATE_NULL && new_state == GST_STATE_READY && pending== GST_STATE_PLAYING)
                    {
                        g_print ("***Loaded***\n");
                    } 
                    else if(old_state==GST_STATE_PLAYING && new_state == GST_STATE_PAUSED && pending== GST_STATE_VOID_PENDING)
                    {
                        g_print ("***Paused***\n");
                    }
                    else if(old_state==GST_STATE_READY && new_state == GST_STATE_NULL && pending== GST_STATE_VOID_PENDING)
                    {
                        g_print ("***Stopped***\n");
                    } 
                    else if(new_state == GST_STATE_PLAYING &&(old_state==GST_STATE_READY||old_state==GST_STATE_PAUSED) )
                    {
                        g_print ("***Playing***\n");
                    } 
                }
                break;
            }
        }  
    }
}

enter image description here

Upvotes: 1

Views: 551

Answers (1)

Andreas
Andreas

Reputation: 1617

Simply answered: you get more messages from GstBus other than play/stop states. Implement a switch in your code and your if/else statements are called only once:

switch (GST_MESSAGE_TYPE (msg)) {
  case GST_MESSAGE_ERROR:
    break;
  case GST_MESSAGE_WARNING:
    break;
  case GST_MESSAGE_INFO:
    break;
  case GST_MESSAGE_EOS:
    break;
  case GST_MESSAGE_BUFFERING:
    break;
  case GST_MESSAGE_STATE_CHANGED: {
    GstState old_state, new_state, pending_state;
    gst_message_parse_state_changed (msg, &old_state, 
        &new_state, &pending_state);

    if (GST_MESSAGE_SRC (msg) == GST_OBJECT (__YOUR_PIPELINE_POINTER__)) {
      // your code here
    }
  }
  break;
}
// DON'T FORGET TO RETURN
return GST_BUS_DROP;

Hope, that helps ;-)

Upvotes: 1

Related Questions