#include <stdio.h>

#include <gst/gst.h>
#include <gst/video/video.h>

#include <windows.h>
#include <cassert>
#include <stdlib.h>

static GstElement* m_pipeline;
static GMainLoop* m_gstMainLoop;

static DWORD WINAPI threadFunc(LPVOID param)
{
    g_main_loop_run(m_gstMainLoop);
    assert(false); //not reached
    return 0;
}

gboolean s_busCallback(GstBus *bus, GstMessage *msg, gpointer data)
{
    GstMessageType msgType = GST_MESSAGE_TYPE(msg);
    if( msgType==GST_MESSAGE_STATE_CHANGED )
    {
        GstState oldState, newState, pendingState;
        gst_message_parse_state_changed (msg, &oldState, &newState, &pendingState);
        if( (GstElement*)msg->src==m_pipeline )
        {
            printf("Pipeline %s changed state from %s to %s pending %s\n", GST_OBJECT_NAME(msg->src), gst_element_state_get_name(oldState), gst_element_state_get_name(newState), gst_element_state_get_name(pendingState));
            if( newState==GST_STATE_PLAYING )
            {
                printf("Playing -> exit\n");
                exit(0);
            }
        }
    }
    return TRUE;
}

int main(int argc, char **argv)
{   
    gst_init(&argc, &argv);
    
    m_gstMainLoop = g_main_loop_new(NULL, FALSE);
    assert(m_gstMainLoop);
    CreateThread(NULL, 0, threadFunc, NULL, 0, NULL);
    
    const char *m_uri = someValidUriStringHere;
    
    m_pipeline = gst_element_factory_make("playbin", "playbin0");
    assert(m_pipeline);
    
    GstBus *bus = gst_pipeline_get_bus(GST_PIPELINE(m_pipeline));
    assert(bus);

    guint m_busWatchId = gst_bus_add_watch (bus, s_busCallback, NULL);
    gst_object_unref(bus);      
        
    g_object_set(G_OBJECT (m_pipeline), "uri", m_uri, NULL); 
    gst_element_set_state(m_pipeline, GST_STATE_PAUSED);

    Sleep(38);
    
    gst_element_set_state(m_pipeline, GST_STATE_PLAYING);
    
    Sleep(10*1000);
    
    printf("Never changed state to playing\n");
}
