gst/gstmodule.c (init_gst): Add constants for GST_*SECOND.

Original commit message from CVS:
* gst/gstmodule.c (init_gst): Add constants for GST_*SECOND.
(python_do_pending_calls): New idler handler, similar to pygtk, so
python events (eg KeyboardInterrupt) can be raised during mainloop

* gst/gst.override (_wrap_gst_bin_get_list):
(_wrap_gst_pad_tp_repr, caps_length, caps_item)
(structure_length, structure_subscript)
(_wrap_gst_structure_tp_repr): Impl.
(_wrap_gst_main): Override with threading blocking.

* gst/gst-types.defs (Object): add flags field.
(Structure): Add copy/release funcs

* gst/__init__.py (devloc): Don't initialize threads

* gst/Makefile.am: clean up

* examples/gst/player.py: Prettify and simplify. Uses GstThread now.

* examples/gstplay/player.py: Update to new api and make it work.
This commit is contained in:
Johan Dahlin 2004-03-24 10:31:35 +00:00
parent b39ba9ed25
commit 15f1eb48cf
8 changed files with 260 additions and 180 deletions

View file

@ -1,3 +1,26 @@
2004-03-24 Johan Dahlin <johan@gnome.org>
* gst/gstmodule.c (init_gst): Add constants for GST_*SECOND.
(python_do_pending_calls): New idler handler, similar to pygtk, so
python events (eg KeyboardInterrupt) can be raised during mainloop
* gst/gst.override (_wrap_gst_bin_get_list):
(_wrap_gst_pad_tp_repr, caps_length, caps_item)
(structure_length, structure_subscript)
(_wrap_gst_structure_tp_repr): Impl.
(_wrap_gst_main): Override with threading blocking.
* gst/gst-types.defs (Object): add flags field.
(Structure): Add copy/release funcs
* gst/__init__.py (devloc): Don't initialize threads
* gst/Makefile.am: clean up
* examples/gst/player.py: Prettify and simplify. Uses GstThread now.
* examples/gstplay/player.py: Update to new api and make it work.
2004-03-18 Johan Dahlin <johan@gnome.org>
* configure.ac: s/GST_*_INCLUDES/GST_*_LIBS/

View file

@ -4,28 +4,23 @@ import sys
import gst
def found_tags(element, source, tags):
def found_tags_cb(element, source, tags):
for tag in tags.keys():
print "%s: %s" % (gst.tag_get_nick(tag), tags[tag])
#def error(source, error, debug):
def deep_notify(*args):
pass
def error(*args):
def error_cb(*args):
print args
def playfile(filename):
bin = gst.Pipeline('player')
bin.connect('deep-notify', deep_notify)
bin.connect('error', error)
bin = gst.Thread('player')
bin.connect('eos', lambda x: gst.main_quit())
bin.connect('error', error_cb)
source = gst.Element('filesrc', 'src')
source.set_property('location', filename)
spider = gst.Element('spider', 'spider')
spider.connect('found-tag', found_tags)
spider.connect('found-tag', found_tags_cb)
sink = gst.Element('osssink', 'sink')
#sink.set_property('release-device', 1)
@ -33,36 +28,20 @@ def playfile(filename):
bin.add_many(source, spider, sink)
if not gst.element_link_many(source, spider, sink):
print "ERROR: could not link"
sys.exit (1)
return 2
print 'Playing:', os.path.basename(filename)
if not bin.set_state(gst.STATE_PLAYING):
print "ERROR: could not set bin to playing"
sys.exit (1)
return 2
playing = 1
while playing:
try:
if not bin.iterate():
playing = 0
except KeyboardInterrupt:
if not bin.set_state(gst.STATE_PAUSED):
print "ERROR: could not set bin to paused"
sys.exit (1)
print "Paused. Press Enter to go back to playing."
try:
sys.stdin.readline ()
if not bin.set_state(gst.STATE_PLAYING):
print "ERROR: could not set bin to playing"
sys.exit (1)
print "Playing."
except KeyboardInterrupt:
playing = 0
print "DONE playing"
bin.set_state(gst.STATE_NULL)
gst.main()
def main(args):
map(playfile, args[1:])
if len(args) != 2:
print 'Usage; player.py filename'
return 1
return playfile(args[1])
if __name__ == '__main__':
sys.exit(main(sys.argv))

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python
#
# gst-python
# Copyright (C) 2004 David I. Lehn
# 2004 Johan Dahlin
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
@ -17,121 +17,52 @@
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
# Author: David I. Lehn <dlehn@users.sourceforge.net>
#
#
# GstPlay wrapper demo
#
import sys
import gobject
from gstreamer import *
from gstplay import Play
import gst
import gst.play
try:
threads_init()
except Exception, e:
print e
def nano2str(nanos):
ts = nanos / gst.SECOND
return '%02d:%02d:%02d.%06d' % (ts / 3600,
ts / 60,
ts % 60,
nanos % gst.SECOND)
def nano_time_string(nanos):
ts = nanos / 1000000000
h = ts / 3600
m = ts / 60
s = ts % 60
us = nanos % 1000000000
return '%02d:%02d:%02d.%06d' % (h, m, s, us)
def stream_length_cb(play, ns):
print 'stream length: %s' % nano2str(ns)
def got_time_tick(sender, nanos):
print 'time tick %s (%d)' % (nano_time_string(nanos), nanos)
def got_stream_length(sender, nanos):
print 'stream length %s (%d)' % (nano_time_string(nanos), nanos)
def got_have_video_size(sender, w, h):
def have_video_size_cb(play, w, h):
print 'video size %d %d' % (w, h)
def got_found_tag(sender, src, tags, *args):
def fe(tl, tag):
c = tl.get_tag_size(tag)
#print tl, tag, c
for i in range(c):
v = tl.get_value_index(tag, i)
#print tag, type(v)
if i == 0:
s = gst_tag_get_nick(tag)
else:
s = ' '
print "%15s: %s" % (s, v)
print 'found tag', src, tags, args
tags.foreach(fe)
def found_tag_cb(play, src, tags):
for tag in tags.keys():
print "%s: %s" % (gst.tag_get_nick(tag), tags[tag])
def got_eos(sender, loop):
print 'eos', args
loop.quit()
def idle_iterate(sender):
#threads_enter()
return sender.iterate()
#threads_leave()
#return sender.get_state() == STATE_PLAYING
def main():
"Basic example to play a media stream with GstPlay"
#gst_debug_set_default_threshold(LEVEL_INFO)
if len(sys.argv) != 2:
print 'usage: %s <media file>' % (sys.argv[0])
def main(args):
if len(args) != 2:
print 'Usage: %s file' % args[0]
return -1
#threads_enter()
filename = args[1]
play = gst.play.Play()
play.connect('stream-length', stream_length_cb)
play.connect('have-video-size', have_video_size_cb)
play.connect('found-tag', found_tag_cb)
play.connect('eos', lambda p: gst.main_quit())
loop = gobject.MainLoop()
# Setup source and sinks
play.set_data_src(gst.Element('filesrc'))
play.set_audio_sink(gst.Element('osssink'))
play.set_video_sink(gst.Element('fakesink'))
# the player
play = Play ()
play.connect('time_tick', got_time_tick)
play.connect('stream_length', got_stream_length)
play.connect('have_video_size', got_have_video_size)
play.connect('found_tag', got_found_tag)
play.connect('eos', got_eos, loop)
data_src = Element ('gnomevfssrc', 'data_src')
#audio_sink = Element ('osssink', 'audio_sink')
audio_sink = Element ('fakesink', 'audio_sink')
video_sink = Element ('fakesink', 'video_sink')
#video_sink = Element ('aasink', 'video_sink')
#video_sink.set_property('driver', 4)
#vis_sink = Element ('fakesink', 'vis_sink')
# setup the player
play.set_data_src(data_src)
play.set_audio_sink(audio_sink)
play.set_video_sink(video_sink)
#play.set_visualization(vis_sink)
play.set_location(sys.argv[1])
# start playing
play.set_state(STATE_PLAYING);
#while play.iterate(): pass
#while play.iterate(): print '.'
gobject.idle_add(idle_iterate, play)
#iterid = add_iterate_bin(play)
#import gtk
#gtk.threads_enter()
loop.run()
#gtk.threads_leave()
#threads_leave()
# stop the bin
play.set_state(STATE_NULL)
return 0
# Point location to our filename
play.set_location(filename)
# Start playing the stream
play.set_state(gst.STATE_PLAYING)
gst.main()
if __name__ == '__main__':
ret = main()
sys.exit(ret)
sys.exit(main(sys.argv))

View file

@ -1,26 +1,16 @@
INCLUDES = $(PYTHON_INCLUDES) $(PYGTK_CFLAGS)
PYGTK_DEFSDIR = @PYGTK_DEFSDIR@
defs_DATA =
defsdir = $(pkgdatadir)/2.0/defs
EXTRA_DIST = $(defs_DATA) arg-types.py
common_cflags = $(GST_CFLAGS) -fno-strict-aliasing
common_libadd = $(GST_LIBS)
common_ldflags = -module -avoid-version
pkgpythondir = $(pythondir)/gst
pkgpyexecdir = $(pyexecdir)/gst
common_ldflags = -module -avoid-version
pygstdir = $(pkgpythondir)
pygst_PYTHON = __init__.py
pygstexecdir = $(pkgpyexecdir)
pygstexec_LTLIBRARIES = _gst.la $(interface_lib) $(play_lib)
# GStreamer bindings
GST_OVERRIDES = gst.override gstpad-handlers.override
GST_DEFS = gst.defs gst-types.defs
# what shall we build ?
if BUILD_INTERFACES
interface_lib = interfaces.la
else
@ -32,42 +22,47 @@ else
play_lib =
endif
pygstexec_LTLIBRARIES = _gst.la $(interface_lib) $(play_lib)
defs_DATA =
defsdir = $(pkgdatadir)/2.0/defs
# how shall we build them ?
_gst_la_CFLAGS = $(GST_CFLAGS) -fno-strict-aliasing
_gst_la_LIBADD = $(GST_LIBS)
INCLUDES = $(PYTHON_INCLUDES) $(PYGTK_CFLAGS)
EXTRA_DIST = $(defs_DATA) arg-types.py
PYGTK_DEFSDIR = @PYGTK_DEFSDIR@
# GStreamer bindings
_gst_la_CFLAGS = $(common_cflags)
_gst_la_LIBADD = $(common_libadd)
_gst_la_LDFLAGS = $(common_ldflags) -export-symbols-regex init_gst
_gst_la_SOURCES = gst-argtypes.c gstmodule.c
nodist__gst_la_SOURCES = gst.c
GST_OVERRIDES = gst.override gstpad-handlers.override
GST_DEFS = gst.defs gst-types.defs
CLEANFILES = gst.c
EXTRA_DIST += $(GST_OVERRIDES)
defs_DATA += $(GST_DEFS)
gst.c: $(GST_DEFS) $(GST_OVERRIDES)
# gst-play bindings
PLAY_OVERRIDES = play.override
PLAY_DEFS = play.defs
play_la_CFLAGS = $(GST_CFLAGS) $(GST_PLAY_CFLAGS) -fno-strict-aliasing
play_la_LIBADD = $(GST_LIBS) $(GST_PLAY_LIBS)
play_la_CFLAGS = $(common_cflags) $(GST_PLAY_CFLAGS)
play_la_LIBADD = $(common_libadd) $(GST_PLAY_LIBS)
play_la_LDFLAGS = $(common_ldflags) -export-symbols-regex initplay
play_la_SOURCES = playmodule.c
nodist_play_la_SOURCES = play.c
PLAY_OVERRIDES = play.override
PLAY_DEFS = play.defs
CLEANFILES += play.c
EXTRA_DIST += $(PLAY_OVERRIDES)
defs_DATA += $(PLAY_DEFS)
play.c: $(PLAY_DEFS) $(PLAY_OVERRIDES)
# GStreamer interfaces bindings
INTERFACES_OVERRIDES = interfaces.override xoverlay.override
INTERFACES_DEFS = interfaces.defs xoverlay.defs xwindowlistener.defs
interfaces_la_CFLAGS = $(GST_CFLAGS) $(GST_INTERFACES_CFLAGS) -fno-strict-aliasing
interfaces_la_LIBADD = $(GST_LIBS) $(GST_INTERFACES_LIBS)
interfaces_la_CFLAGS = $(common_cflags) $(GST_INTERFACES_CFLAGS)
interfaces_la_LIBADD = $(common_libadd) $(GST_INTERFACES_LIBS)
interfaces_la_LDFLAGS = $(common_ldflags) -export-symbols-regex initinterface
interfaces_la_SOURCES = interfacesmodule.c
nodist_interfaces_la_SOURCES = interfaces.c
INTERFACES_OVERRIDES = interfaces.override xoverlay.override
INTERFACES_DEFS = interfaces.defs xoverlay.defs xwindowlistener.defs
CLEANFILES += interfaces.c
EXTRA_DIST += $(INTERFACES_OVERRIDES)
defs_DATA += $(INTERFACES_DEFS)

View file

@ -36,7 +36,3 @@ sys.setdlopenflags(dl.RTLD_LAZY | dl.RTLD_GLOBAL)
del devloc, sys, os, dl
from _gst import *
def threads_init():
import gtk
gtk.threads_init()

View file

@ -6,6 +6,9 @@
(parent "GObject")
(c-name "GstObject")
(gtype-id "GST_TYPE_OBJECT")
(fields
'("guint32" "flags")
)
)
(define-object Index
@ -195,14 +198,12 @@
)
;;
;; 0.7 Boxed types
;;
(define-boxed Structure
(in-module "Gst")
(c-name "GstStructure")
(gtype-id "GST_TYPE_STRUCTURE")
(copy-func "gst_structure_copy")
(release-func "gst_structure_unref")
)
(define-boxed TagList

View file

@ -153,6 +153,26 @@ _wrap_gst_bin_iterate(PyGObject *self)
return PyInt_FromLong(ret);
}
%%
override gst_bin_get_list
static PyObject *
_wrap_gst_bin_get_list(PyGObject *self)
{
GList *elements, *l;
PyObject *tuple;
int i;
elements = (GList*)gst_bin_get_list(GST_BIN(self->obj));
tuple = PyTuple_New(g_list_length(elements));
for (i = 0, l = elements; l; l = l->next, i++) {
GstElement *element = (GstElement*)l->data;
if (!element)
continue;
PyTuple_SetItem(tuple, i, pygobject_new(G_OBJECT(element)));
}
return tuple;
}
%%
override gst_element_get_pad_list noargs
static PyObject *
_wrap_gst_element_get_pad_list(PyGObject *self)
@ -190,6 +210,22 @@ _wrap_gst_element_set_state(PyGObject *self, PyObject *args, PyObject *kwargs)
return PyInt_FromLong(ret);
}
%%
override-slot GstPad.tp_repr
static PyObject *
_wrap_gst_pad_tp_repr (PyGObject *self)
{
char *buf;
PyObject *retval;
buf = g_strdup_printf("<GstPad (%s) at %lx>",
gst_pad_get_name(GST_PAD(self->obj)),
(long)self->obj);
retval = PyString_FromString(buf);
g_free(buf);
return retval;
}
%%
override gst_pad_query kwargs
static PyObject *
_wrap_gst_pad_query(PyGObject *self, PyObject *args, PyObject *kwargs)
@ -439,6 +475,39 @@ _wrap_gst_pad_get_negotiated_caps(PyGObject *self)
return pyg_boxed_new(GST_TYPE_CAPS, ret, TRUE, TRUE);
}
%%
override-slot GstCaps.tp_as_sequence
static int
caps_length(PyGObject *self)
{
return gst_caps_get_size((GstCaps*)self->obj);
}
static PyObject *
caps_item(PyGObject *self, int i)
{
GstStructure *structure;
if (i < 0 || i >= gst_caps_get_size((GstCaps*)self->obj)) {
PyErr_SetString(PyExc_IndexError, "list index out of range");
return NULL;
}
structure = gst_caps_get_structure((GstCaps*)self->obj, i);
return pyg_boxed_new(GST_TYPE_STRUCTURE, structure, TRUE, TRUE);
}
static PySequenceMethods _wrap_gst_caps_tp_as_sequence = {
(inquiry)caps_length, /* mp_length */
NULL,
NULL,
(intargfunc)caps_item,
NULL,
NULL,
NULL,
NULL,
};
%%
override gst_buffer_new kwargs
static int
_wrap_gst_buffer_new(PyGBoxed *self, PyObject *args, PyObject *kwargs)
@ -676,6 +745,40 @@ _wrap_gst_structure_set_value(PyObject *self, PyObject *args, PyObject *kwargs)
Py_INCREF(Py_None);
return Py_None;
}
%%
override-slot GstStructure.tp_as_mapping
static int
_wrap_gst_structure_length(PyGObject *self)
{
return gst_structure_n_fields((GstStructure*)self->obj);
}
static PyObject *
_wrap_gst_structure_subscript(PyGObject *self, PyObject *py_key)
{
PyObject *v = NULL;
const char *field = PyString_AsString(py_key);
if (gst_structure_has_field((GstStructure*)self->obj, field)) {
const GValue *gvalue;
gvalue = gst_structure_get_value((GstStructure*)self->obj, field);
g_assert(gvalue != NULL);
v = pyg_value_as_pyobject(gvalue, TRUE);
} else {
PyErr_SetString(PyExc_KeyError, field);
}
if (v != NULL)
Py_INCREF(v);
return v;
}
static PySequenceMethods _wrap_gst_structure_tp_as_mapping = {
(inquiry)_wrap_gst_structure_length, /* mp_length */
(binaryfunc)_wrap_gst_structure_subscript, /* mp_subscript */
NULL,
};
%%
override gst_structure_foreach kwargs
static gboolean
@ -691,9 +794,6 @@ pygst_structure_foreach_marshal(GQuark field_id,
pyg_block_threads();
//py_model = pygobject_new((GObject *)model);
//py_path = pygtk_tree_path_to_pyobject(path);
//py_iter = pyg_boxed_new(GTK_TYPE_TREE_ITER, iter, TRUE, TRUE);
py_field = Py_BuildValue("s", g_quark_to_string(field_id));
py_value = pyg_value_as_pyobject(value, FALSE);
if (cunote->data)
@ -749,8 +849,23 @@ _wrap_gst_structure_foreach (PyGObject *self,
return Py_None;
}
%%
override gst_tag_list_foreach kwargs
override-slot GstStructure.tp_repr
static PyObject *
_wrap_gst_structure_tp_repr (PyGObject *self)
{
char *buf;
PyObject *retval;
buf = g_strdup_printf("<GstStructure (%s) at %lx>",
gst_structure_get_name((GstStructure*)self->obj),
(long)self->obj);
retval = PyString_FromString(buf);
g_free(buf);
return retval;
}
%%
override gst_tag_list_foreach kwargs
static gboolean
pygst_tag_list_foreach_marshal(GstTagList *list,
const gchar *tag,
@ -912,3 +1027,19 @@ _wrap_gst_g_error_tp_str(PyGObject *self)
return PyString_FromString(gst_error_get_message (error->domain,
error->code));
}
%%
override gst_main noargs
static PyObject *
_wrap_gst_main(PyObject *self)
{
pyg_unblock_threads();
gst_main();
pyg_block_threads();
if (PyErr_Occurred())
return NULL;
Py_INCREF(Py_None);
return Py_None;
}

View file

@ -34,6 +34,24 @@ void pygst_add_constants(PyObject *module, const gchar *strip_prefix);
extern PyMethodDef pygst_functions[];
static gboolean
python_do_pending_calls(gpointer data)
{
gboolean quit = FALSE;
pyg_block_threads();
if (PyErr_CheckSignals() == -1) {
PyErr_SetNone(PyExc_KeyboardInterrupt);
quit = TRUE;
}
pyg_unblock_threads();
if (quit)
gst_main_quit();
return TRUE;
}
DL_EXPORT(void)
init_gst (void)
{
@ -85,9 +103,15 @@ init_gst (void)
PYGST_MICRO_VERSION);
PyDict_SetItemString(d, "pygst_version", tuple);
Py_DECREF(tuple);
PyModule_AddIntConstant(m, "SECOND", GST_SECOND);
PyModule_AddIntConstant(m, "MSECOND", GST_MSECOND);
PyModule_AddIntConstant(m, "NSECOND", GST_NSECOND);
pygst_register_classes (d);
pygst_add_constants (m, "GST_");
g_timeout_add_full (0, 100, python_do_pending_calls, NULL, NULL);
if (PyErr_Occurred ()) {
Py_FatalError ("can't initialize module gst");