// playbin func playbin() { pipeline, err := NewElement("playbin", "playbin") if err != nil { log.Fatal(err) } uri := os.Args[1] if !strings.Contains(uri, "://") { uri, err = filepath.Abs(uri) if err != nil { log.Fatal(err) } uri = "file://" + uri } ObjSet(asGObj(pipeline), "uri", uri) messages := PipelineWatchBus(asGstPipeline(pipeline)) go func() { for msg := range messages { MessageDump(msg) } }() C.gst_element_set_state(pipeline, C.GST_STATE_PLAYING) loop := C.g_main_loop_new(nil, False()) C.g_main_loop_run(loop) }
func MainLoopNew(context *GMainContext, is_running bool) *GMainLoop { var ctx *C.GMainContext if context != nil { ctx = context.MainContext } return &GMainLoop{C.g_main_loop_new(ctx, bool2gboolean(is_running))} }
func oggplayer() { pipeline := C.gst_pipeline_new(toGStr("audio-player")) source, err := NewElement("filesrc", "file-source") if err != nil { log.Fatal(err) } demuxer, err := NewElement("oggdemux", "ogg-demuxer") if err != nil { log.Fatal(err) } decoder, err := NewElement("vorbisdec", "vorbis-decoder") if err != nil { log.Fatal(err) } conv, err := NewElement("audioconvert", "converter") if err != nil { log.Fatal(err) } sink, err := NewElement("autoaudiosink", "audio-output") if err != nil { log.Fatal(err) } ObjSet(asGObj(source), "location", os.Args[1]) messages := PipelineWatchBus(asGstPipeline(pipeline)) BinAdd(pipeline, source, demuxer, decoder, conv, sink) ElementLink(source, demuxer) ElementLink(decoder, conv, sink) ObjConnect(asGObj(demuxer), "pad-added", func(elem *C.GstElement, pad *C.GstPad) { sink := C.gst_element_get_static_pad(decoder, toGStr("sink")) C.gst_pad_link(pad, sink) C.gst_object_unref(asGPtr(sink)) }) C.gst_element_set_state(pipeline, C.GST_STATE_PLAYING) go func() { for msg := range messages { MessageDump(msg) } }() go func() { var pos, length C.gint64 for _ = range time.NewTicker(time.Second * 1).C { C.gst_element_query_position(pipeline, C.GST_FORMAT_TIME, &pos) C.gst_element_query_duration(pipeline, C.GST_FORMAT_TIME, &length) p("%v / %v\n", time.Duration(pos), time.Duration(length)) if time.Duration(pos) > time.Second*5 { C.gst_element_seek(pipeline, 1.0, C.GST_FORMAT_TIME, C.GST_SEEK_FLAG_FLUSH, C.GST_SEEK_TYPE_SET, 10, C.GST_SEEK_TYPE_NONE, C.GST_CLOCK_TIME_NONE) } } }() loop := C.g_main_loop_new(nil, False()) C.g_main_loop_run(loop) }
func NewMainLoop(ctx *MainContext) *MainLoop { l := new(MainLoop) var c *C.GMainContext if ctx != nil { c = ctx.GMainContext() } l.SetPtr(Pointer(C.g_main_loop_new(c, 0))) return l }
func main() { var loop *C.GMainLoop var s0 byte mdir := "" flag.StringVar(&mdir, "mdir", "", "mp3文件目录") flag.BoolVar(&g_isOutOfOrder, "rand", false, "是否乱序播放") flag.Parse() if mdir == "" { flag.PrintDefaults() return } g_list = list.New() g_wg = new(sync.WaitGroup) C.gst_init((*C.int)(unsafe.Pointer(nil)), (***C.char)(unsafe.Pointer(nil))) loop = C.g_main_loop_new((*C.GMainContext)(unsafe.Pointer(nil)), C.gboolean(0)) // 创建主循环,在执行 g_main_loop_run后正式开始循环 if err := filepath.Walk(mdir, walkFunc); err != nil { fmt.Printf("Error: %v\n", err) return } g_wg.Add(1) s := make(chan byte) defer close(s) go mp3_play_process(s, loop) LOOP0: for { fmt.Fscanf(os.Stdin, "%c\n", &s0) switch s0 { case 's': s <- s0 case 'r': s <- s0 case 'n': s <- s0 case 'p': s <- s0 case 'q': s <- s0 break LOOP0 case 'h': fmt.Print("'s' -> 暂停\n" + "'r' -> 继续\n" + "'n' -> 下一首\n" + "'p' -> 上一首\n" + "'q' -> 退出\n") } s0 = 0 } g_wg.Wait() }
// ranged playing func ranged() { pipeline := C.gst_pipeline_new(toGStr("pipeline")) src, err := NewElement("uridecodebin", "src") if err != nil { log.Fatal(err) } csp, err := NewElement("videoconvert", "csp") if err != nil { log.Fatal(err) } vs, err := NewElement("videoscale", "vs") if err != nil { log.Fatal(err) } sink, err := NewElement("autovideosink", "sink") if err != nil { log.Fatal(err) } ObjSet(asGObj(src), "uri", os.Args[1]) BinAdd(pipeline, src, csp, vs, sink) ElementLink(csp, vs, sink) //TODO sinkpad := ObjConnect(asGObj(src), "pad-added", func(e *C.GstElement, pad *C.GstPad) { p("====\n") PadAddProbe(pad, C.GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, func(info *C.GstPadProbeInfo) C.GstPadProbeReturn { p("blocked\n") return C.GST_PAD_PROBE_OK }) //C.gst_pad_link(pad, sinkpad) }) ObjConnect(asGObj(src), "no-more-pads", func(e *C.GstElement) { }) C.gst_element_set_state(pipeline, C.GST_STATE_PAUSED) messages := PipelineWatchBus(asGstPipeline(pipeline)) go func() { for msg := range messages { MessageDump(msg) } }() loop := C.g_main_loop_new(nil, False()) C.g_main_loop_run(loop) }
func play() { // element e, err := NewElement("fakesrc", "source") if err != nil { log.Fatal(err) } p("%v\n", e) name := C.gst_object_get_name(asGstObj(e)) p("%s\n", fromGStr(name)) // factory factory, err := NewFactory("fakesrc") if err != nil { log.Fatal(err) } p("%s\n", fromGStr(C.gst_object_get_name(asGstObj(factory)))) p("%s\n", fromGStr(C.gst_element_factory_get_metadata(factory, asGStr(C.CString(C.GST_ELEMENT_METADATA_KLASS))))) p("%s\n", fromGStr(C.gst_element_factory_get_metadata(factory, asGStr(C.CString(C.GST_ELEMENT_METADATA_DESCRIPTION))))) // id pipeline pipeline := C.gst_pipeline_new(toGStr("pipeline")) source, _ := NewElement("fakesrc", "source") filter, _ := NewElement("identity", "filter") sink, _ := NewElement("fakesink", "sink") BinAdd(pipeline, source, filter, sink) ElementLink(source, filter, sink) C.gst_element_set_state(pipeline, C.GST_STATE_PLAYING) C.gst_element_sync_state_with_parent(filter) /* // bin bin := C.gst_bin_new(toGStr("bin")) source, _ = NewElement("fakesrc", "source") sink, _ = NewElement("fakesink", "sink") BinAdd(bin, source, sink) //C.gst_bin_remove(asGstBin(bin), source) ElementLink(source, sink) BinAdd(pipeline, bin) source = C.gst_bin_get_by_name(asGstBin(bin), toGStr("source")) */ // bus messages := PipelineWatchBus(asGstPipeline(pipeline)) loop := C.g_main_loop_new(nil, 0) go func() { C.g_main_loop_run(loop) }() // message loop: for msg := range messages { runtime.GC() p("=> %s from %s\n", fromGStr(C.gst_message_type_get_name(msg._type)), fromGStr(C.gst_object_get_name(asGstObj(msg.src)))) switch msg._type { case C.GST_MESSAGE_ERROR: var err *C.GError var debug *C.gchar C.gst_message_parse_error(msg, &err, &debug) p("Error: %s\n%s\n", fromGStr(err.message), fromGStr(debug)) C.g_error_free(err) C.g_free(asGPtr(debug)) C.g_main_loop_quit(loop) break loop case C.GST_MESSAGE_WARNING: case C.GST_MESSAGE_INFO: case C.GST_MESSAGE_EOS: C.g_main_loop_quit(loop) break loop case C.GST_MESSAGE_TAG: var tags *C.GstTagList C.gst_message_parse_tag(msg, &tags) //TagListForeach(tags, ) TODO C.gst_tag_list_unref(tags) case C.GST_MESSAGE_STATE_CHANGED: var newState, oldState C.GstState C.gst_message_parse_state_changed(msg, &oldState, &newState, nil) p("%s -> %s\n", fromGStr(C.gst_element_state_get_name(oldState)), fromGStr(C.gst_element_state_get_name(newState))) } } }
func play2() { pipeline := C.gst_pipeline_new(toGStr("pipeline")) source, err := NewElement("filesrc", "source") if err != nil { log.Fatal(err) } ObjSet(asGObj(source), "location", os.Args[1]) demux, err := NewElement("oggdemux", "demuxer") if err != nil { log.Fatal(err) } BinAdd(pipeline, source, demux) C.gst_element_link_pads(source, toGStr("src"), demux, toGStr("sink")) ObjConnect(asGObj(demux), "pad-added", func(demuxer *C.GstElement, pad *C.GstPad) { p("pad added %T %v\n", pad, pad) }) // bus messages := PipelineWatchBus(asGstPipeline(pipeline)) C.gst_element_set_state(pipeline, C.GST_STATE_PLAYING) loop := C.g_main_loop_new(nil, 0) go func() { loop: for msg := range messages { runtime.GC() p("=> %s: %s\n", fromGStr(C.gst_object_get_name(asGstObj(msg.src))), fromGStr(C.gst_message_type_get_name(msg._type))) switch msg._type { case C.GST_MESSAGE_ERROR: var err *C.GError var debug *C.gchar C.gst_message_parse_error(msg, &err, &debug) p("Error: %s\n%s\n", fromGStr(err.message), fromGStr(debug)) C.g_error_free(err) C.g_free(asGPtr(debug)) C.g_main_loop_quit(loop) break loop case C.GST_MESSAGE_WARNING: case C.GST_MESSAGE_INFO: case C.GST_MESSAGE_EOS: C.g_main_loop_quit(loop) break loop case C.GST_MESSAGE_TAG: var tags *C.GstTagList C.gst_message_parse_tag(msg, &tags) //TagListForeach(tags, ) TODO C.gst_tag_list_unref(tags) case C.GST_MESSAGE_STATE_CHANGED: var newState, oldState C.GstState C.gst_message_parse_state_changed(msg, &oldState, &newState, nil) p("%s -> %s\n", fromGStr(C.gst_element_state_get_name(oldState)), fromGStr(C.gst_element_state_get_name(newState))) } C.gst_message_unref(msg) } p("loop break.\n") }() runtime.LockOSThread() C.g_main_loop_run(loop) p("quit.\n") }
// pad probe func probe() { pipeline := C.gst_pipeline_new(toGStr("pipeline")) src, err := NewElement("videotestsrc", "src") if err != nil { log.Fatal(err) } filter, err := NewElement("capsfilter", "filter") if err != nil { log.Fatal(err) } csp, err := NewElement("videoconvert", "csp") if err != nil { log.Fatal(err) } sink, err := NewElement("xvimagesink", "sink") if err != nil { log.Fatal(err) } BinAdd(pipeline, src, filter, csp, sink) ElementLink(src, filter, csp, sink) C.gst_element_set_state(pipeline, C.GST_STATE_PLAYING) messages := PipelineWatchBus(asGstPipeline(pipeline)) width, height := 640, 480 filtercaps := NewCapsSimple("video/x-raw", "format", "RGB16", "width", width, "height", height, "framerate", Fraction{25, 1}) ObjSet(asGObj(filter), "caps", filtercaps) n := C.gst_caps_get_size(filtercaps) structure := C.gst_caps_get_structure(filtercaps, n-1) _ = structure C.gst_caps_unref(filtercaps) pad := C.gst_element_get_static_pad(src, toGStr("src")) PadAddProbe(pad, C.GST_PAD_PROBE_TYPE_BUFFER, func(info *C.GstPadProbeInfo) C.GstPadProbeReturn { buffer := (*C.GstBuffer)(unsafe.Pointer(info.data)) buffer = asGstBuffer(C.gst_mini_object_make_writable(asGstMiniObject(buffer))) var mapInfo C.GstMapInfo C.gst_buffer_map(buffer, &mapInfo, C.GST_MAP_WRITE) var ptr []C.guint16 header := (*reflect.SliceHeader)(unsafe.Pointer(&ptr)) header.Len = int(mapInfo.size / 2) header.Cap = header.Len header.Data = uintptr(unsafe.Pointer(mapInfo.data)) for y := 0; y < height; y++ { for x := 0; x < width/2; x++ { ptr[x], ptr[width-1-x] = ptr[width-1-x], ptr[x] } ptr = ptr[width:] } C.gst_buffer_unmap(buffer, &mapInfo) info.data = asGPtr(buffer) return C.GST_PAD_PROBE_OK }) C.gst_object_unref(asGPtr(pad)) go func() { for msg := range messages { MessageDump(msg) } }() loop := C.g_main_loop_new(nil, False()) C.g_main_loop_run(loop) }
func main() { var loop *C.GMainLoop var s0 byte mdir := "" mfile := "" style := "" flag.StringVar(&mdir, "dir", "", "mp3文件目录") flag.StringVar(&mfile, "file", "", "mp3文件") flag.StringVar(&style, "style", "order", "播放方式[顺序:order|乱序:shuffle|单曲:single|单曲循环:sloop|全部循环:aloop]") flag.Parse() switch style { case "shuffle": g_isOutOfOrder = true g_play_style = PLAY_STYLE_SHUFFLE case "order": g_play_style = PLAY_STYLE_ORDER case "single": g_play_style = PLAY_STYLE_SINGLE case "sloop": g_play_style = PLAY_STYLE_SLOOP case "aloop": g_play_style = PLAY_STYLE_ALOOP default: flag.PrintDefaults() return } g_list = list.New() if mfile != "" { p, err := filepath.Abs(mfile) if err != nil { fmt.Printf("Error: %v\n", err) return } C.gst_init((*C.int)(unsafe.Pointer(nil)), (***C.char)(unsafe.Pointer(nil))) loop = C.g_main_loop_new((*C.GMainContext)(unsafe.Pointer(nil)), C.gboolean(0)) // 创建主循环,在执行 g_main_loop_run后正式开始循环 mfile = fmt.Sprintf("file://%s", p) g_list.PushBack(mfile) g_play_style = PLAY_STYLE_SINGLE } else { if mdir == "" { flag.PrintDefaults() return } if err := filepath.Walk(mdir, walkFunc); err != nil { fmt.Printf("Error: %v\n", err) return } } g_wg = new(sync.WaitGroup) C.gst_init((*C.int)(unsafe.Pointer(nil)), (***C.char)(unsafe.Pointer(nil))) loop = C.g_main_loop_new((*C.GMainContext)(unsafe.Pointer(nil)), C.gboolean(0)) // 创建主循环,在执行 g_main_loop_run后正式开始循环 s := make(chan byte) defer close(s) go PlayProcess(s, loop) isQuit := false for !isQuit { fmt.Fscanf(os.Stdin, "%c\n", &s0) switch s0 { case 's': fallthrough case 'r': fallthrough case 'n': fallthrough case 'p': fallthrough case 't': fallthrough case '+': fallthrough case '-': s <- s0 case 'q': s <- s0 isQuit = true case 'h': fmt.Print("'s' -> 暂停\n" + "'r' -> 继续\n" + "'n' -> 下一首\n" + "'p' -> 上一首\n" + "'q' -> 退出\n") } s0 = 0 } g_wg.Wait() }
func g_main_loop_new(context GMainContext, is_running bool) GMainLoop { return GMainLoop(C.g_main_loop_new(Arg(context), Arg(Bool2Int[is_running]))) }