;; path must be a valid URI to media
(bind-func xtm_play
  (lambda (path)
    (if (and vplay1 vplay2 vplay3 vplay4)
        (begin (printf "No available video slots! Try again later!\n") #f)
        (let ((playz (gst_element_factory_make "playbin" "play"))
              (sinkz (gst_element_factory_make "appsink" "app_sink"))
              (bus (gst_pipeline_get_bus (cast playz GstPipeline*)))
              (caps:GstCaps* (gst_caps_from_string "video/x-raw,format=RGB,width=600,height=400"))
              (rgbFilter:GstElement* (gst_element_factory_make "capsfilter" "rgb_filter"))
              (appBin:GstElement* (gst_bin_new "app_bin"))
              (rgbSinkPad:GstPad* null)
              (ghostPad:GstPad* null)
              (data:userdata* (halloc))
              (callbacks:GstAppSinkCallbacks* (halloc))
              (gv:GValue* (halloc)))
          ;; Listen for messages on the playbin pipeline bus.
          (gst_bus_add_watch bus (cast (llvm_get_function_ptr "playbin_bus_call_native") GstBusFunc) (cast data gpointer))
          (gst_object_unref bus)
          ;;(printf "playz(%p) sinkz(%p) bus(%p) bin(%p)\n" playz sinkz bus appBin)
          ;; force video decode to RGB 600x400
          (gst_app_sink_set_caps (cast sinkz i8*) caps)
          ;; set callbacks
          (tfill! callbacks
                  (llvm_get_function_ptr "eos_native")
                  (llvm_get_function_ptr "new_preroll_native")
                  (llvm_get_function_ptr "new_sample_native"))
          (cond ((not vplay1) (tset! data 0 1))
                ((not vplay2) (tset! data 0 2))
                ((not vplay3) (tset! data 0 3))
                ((not vplay4) (tset! data 0 4)))
          (tset! data 1 playz)
          (gst_app_sink_set_callbacks (cast sinkz i8*) callbacks (cast data gpointer) null)
          ;; Replace the default window sink with appsink,
          ;;(g_value_unset gv)
          (g_value_init gv G_TYPE_OBJECT)
          (g_value_set_object gv (cast sinkz gpointer))
          (g_object_set_property (cast playz GObject*) "video-sink" gv)
          ;; URI to load media from
          (g_value_unset gv)
          (g_value_init gv G_TYPE_STRING)
          (g_value_set_string gv path)
          (g_object_set_property (cast playz GObject*) "uri" gv)
          ;; start decoding the media!
          (let ((res (gst_element_set_state playz GST_STATE_PLAYING)))
            (if (or (= res 1) (= res 2))
                (begin (printf "Start Decoding[%d]\n" (tref data 0)) #t)
                (begin (printf "Failed To Open[%d]\n" (tref data 0))
                       (gst_element_set_state playz GST_STATE_NULL)
                       (gst_object_unref (cast playz i8*))
                       (free data)
                       #f)))))))