From c9a37cf682395ac7c7ae0dabce74f9e37a894fc8 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 1 Jul 2005 12:43:03 +0000 Subject: [PATCH] Enable building the PWG examples. Original commit message from CVS: * configure.ac: * examples/Makefile.am: * examples/pwg/Makefile.am: * examples/pwg/extract.pl: Enable building the PWG examples. * docs/pwg/advanced-interfaces.xml: Add URI interface stub. * docs/pwg/advanced-types.xml: * docs/pwg/other-autoplugger.xml: * docs/pwg/appendix-porting.xml: * docs/pwg/pwg.xml: Add porting guide (mostly stubs), remove autoplugging (see ADM). * docs/pwg/building-boiler.xml: * docs/pwg/building-chainfn.xml: * docs/pwg/building-pads.xml: * docs/pwg/building-props.xml: * docs/pwg/building-state.xml: * docs/pwg/building-testapp.xml: Update the building-*.xml parts for 0.9 changes. All examples code blocks compile in examples/pwg/*. --- ChangeLog | 23 +++++ configure.ac | 1 + docs/pwg/advanced-interfaces.xml | 7 ++ docs/pwg/advanced-types.xml | 4 +- docs/pwg/appendix-porting.xml | 37 +++++++ docs/pwg/building-boiler.xml | 122 +++++++++++++++-------- docs/pwg/building-chainfn.xml | 118 +++++++++++++++++------ docs/pwg/building-pads.xml | 149 +++++++++++++++++++---------- docs/pwg/building-props.xml | 19 +++- docs/pwg/building-state.xml | 38 +++++--- docs/pwg/building-testapp.xml | 54 ++++++++++- docs/pwg/other-autoplugger.xml | 9 -- docs/pwg/pwg.xml | 4 +- examples/Makefile.am | 1 + examples/pwg/Makefile.am | 66 +++++++++++++ examples/pwg/extract.pl | 78 +++++++++++++++ tests/old/examples/Makefile.am | 1 + tests/old/examples/pwg/Makefile.am | 66 +++++++++++++ tests/old/examples/pwg/extract.pl | 78 +++++++++++++++ 19 files changed, 720 insertions(+), 155 deletions(-) create mode 100644 docs/pwg/appendix-porting.xml delete mode 100644 docs/pwg/other-autoplugger.xml create mode 100644 examples/pwg/Makefile.am create mode 100755 examples/pwg/extract.pl create mode 100644 tests/old/examples/pwg/Makefile.am create mode 100755 tests/old/examples/pwg/extract.pl diff --git a/ChangeLog b/ChangeLog index 5a7eb24b0b..6f67bdf49b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,26 @@ +2005-07-01 Ronald S. Bultje + + * configure.ac: + * examples/Makefile.am: + * examples/pwg/Makefile.am: + * examples/pwg/extract.pl: + Enable building the PWG examples. + * docs/pwg/advanced-interfaces.xml: + Add URI interface stub. + * docs/pwg/advanced-types.xml: + * docs/pwg/other-autoplugger.xml: + * docs/pwg/appendix-porting.xml: + * docs/pwg/pwg.xml: + Add porting guide (mostly stubs), remove autoplugging (see ADM). + * docs/pwg/building-boiler.xml: + * docs/pwg/building-chainfn.xml: + * docs/pwg/building-pads.xml: + * docs/pwg/building-props.xml: + * docs/pwg/building-state.xml: + * docs/pwg/building-testapp.xml: + Update the building-*.xml parts for 0.9 changes. All examples + code blocks compile in examples/pwg/*. + 2005-06-30 Ronald S. Bultje * docs/manual/advanced-autoplugging.xml: diff --git a/configure.ac b/configure.ac index 4a5fa89be1..2891b8690c 100644 --- a/configure.ac +++ b/configure.ac @@ -701,6 +701,7 @@ examples/manual/Makefile examples/mixer/Makefile examples/pingpong/Makefile examples/plugins/Makefile +examples/pwg/Makefile examples/queue/Makefile examples/queue2/Makefile examples/queue3/Makefile diff --git a/docs/pwg/advanced-interfaces.xml b/docs/pwg/advanced-interfaces.xml index 7264dadf63..f99118227b 100644 --- a/docs/pwg/advanced-interfaces.xml +++ b/docs/pwg/advanced-interfaces.xml @@ -118,6 +118,13 @@ gst_my_filter_some_interface_init (GstSomeInterface *iface) + + URI interface + + WRITEME + + + Mixer Interface diff --git a/docs/pwg/advanced-types.xml b/docs/pwg/advanced-types.xml index 09710f39d4..3f2f77c14d 100644 --- a/docs/pwg/advanced-types.xml +++ b/docs/pwg/advanced-types.xml @@ -143,8 +143,8 @@ plugin_init (GstPlugin *plugin) typefind functions. - Autoplugging will be discussed in great detail in the chapter called - . + Autoplugging has been discussed in great detail in the Application + Development Manual. diff --git a/docs/pwg/appendix-porting.xml b/docs/pwg/appendix-porting.xml new file mode 100644 index 0000000000..c0a1f1914f --- /dev/null +++ b/docs/pwg/appendix-porting.xml @@ -0,0 +1,37 @@ + + Porting 0.8 plug-ins to 0.9 + + This section of the appendix will discuss shortly what changes to + plugins will be needed to quickly and conveniently port most + applications from &GStreamer;-0.8 to &GStreamer;-0.9, with references + to the relevant sections in this Plugin Writer's Guide where needed. + With this list, it should be possible to port most plugins to + &GStreamer;-0.9 in less than a day. + + + + List of changes + + + + Most functions returning an object or an object property have + been changed to return its own reference rather than a constant + reference of the one owned by the object itself. The reason for + this change is primarily threadsafety. This means, effectively, + that return values of functions such as + gst_element_get_pad (), + gst_pad_get_name () and many more like these + have to be free'ed or unreferenced after use. Check the API + references of each function to know for sure whether return + values should be free'ed or not. + + + + + base classes, async capsnego (caps-on-buffer), async for sinks, + bytestream dead / pull_range, direct scheduling, etc. + + + + + diff --git a/docs/pwg/building-boiler.xml b/docs/pwg/building-boiler.xml index 8758c02f36..a4e74afcb1 100644 --- a/docs/pwg/building-boiler.xml +++ b/docs/pwg/building-boiler.xml @@ -134,40 +134,54 @@ U gst-template/gst-app/src/Makefile.am Example Plugin Header File - - /* Definition of structure storing data for this element. */ - typedef struct _GstExample GstExample; + +#include <gst/gst.h> - struct _GstExample { - GstElement element; +/* Definition of structure storing data for this element. */ +typedef struct _GstMyFilter { + GstElement element; - GstPad *sinkpad, *srcpad; + GstPad *sinkpad, *srcpad; - gboolean silent; - }; + gboolean silent; + + + +} GstMyFilter; - /* Standard definition defining a class for this element. */ - typedef struct _GstExampleClass GstExampleClass; - struct _GstExampleClass { - GstElementClass parent_class; - }; +/* Standard definition defining a class for this element. */ +typedef struct _GstMyFilterClass { + GstElementClass parent_class; +} GstMyFilterClass; - /* Standard macros for defining types for this element. */ - #define GST_TYPE_EXAMPLE \ - (gst_example_get_type()) - #define GST_EXAMPLE(obj) \ - (G_TYPE_CHECK_CAST((obj),GST_TYPE_EXAMPLE,GstExample)) - #define GST_EXAMPLE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_EXAMPLE,GstExample)) - #define GST_IS_EXAMPLE(obj) \ - (G_TYPE_CHECK_TYPE((obj),GST_TYPE_EXAMPLE)) - #define GST_IS_EXAMPLE_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EXAMPLE)) +/* Standard macros for defining types for this element. */ +#define GST_TYPE_MY_FILTER \ + (gst_my_filter_get_type()) +#define GST_MY_FILTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MY_FILTER,GstMyFilter)) +#define GST_MY_FILTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MY_FILTER,GstMyFilterClass)) +#define GST_IS_MY_FILTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MY_FILTER)) +#define GST_IS_MY_FILTER_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MY_FILTER)) - /* Standard function returning type information. */ - GType gst_example_get_type (void); - +/* Standard function returning type information. */ +GType gst_my_filter_get_type (void); + + + Using this header file, you can use the following macro to setup + the GObject basics in your source file so + that all functions will be called appropriately: + + +#include "filter.h" + +GST_BOILERPLATE (GstMyFilter, gst_my_filter, GstElement, GST_TYPE_ELEMENT); + @@ -198,14 +212,14 @@ U gst-template/gst-app/src/Makefile.am For example: - -static GstElementDetails example_details = { + +static GstElementDetails my_filter_details = { "An example plugin", "Example/FirstExample", "Shows the basic structure of a plugin", "your name <your.name@your.isp>" }; - + The element details are registered with the plugin during the _base_init () function, which is part of @@ -213,17 +227,19 @@ static GstElementDetails example_details = { should be set for this GObject in the function where you register the type with Glib. - + static void -gst_my_filter_base_init (GstMyFilterClass *klass) +gst_my_filter_base_init (gpointer klass) { + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + static GstElementDetails my_filter_details = { [..] }; - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); -[..] +[..] gst_element_class_set_details (element_class, &my_filter_details); + } @@ -258,7 +274,7 @@ gst_my_filter_base_init (GstMyFilterClass *klass) For example: - + static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ( "sink", @@ -266,6 +282,16 @@ GST_STATIC_PAD_TEMPLATE ( GST_PAD_ALWAYS, GST_STATIC_CAPS ("ANY") ); + + Those pad templates are registered during the @@ -284,18 +310,30 @@ static GstStaticPadTemplate sink_factory = [..], src_factory = [..]; static void -gst_my_filter_base_init (GstMyFilterClass *klass) +gst_my_filter_base_init (gpointer klass) { -[..] GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - +[..] + gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&src_factory)); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&sink_factory)); -[..] } - + + The last argument in a template is its type or list of supported types. In this example, we use 'ANY', which means @@ -362,7 +400,7 @@ GST_STATIC_PAD_TEMPLATE ( Also, in this function, any supported element type in the plugin should be registered. - + static gboolean plugin_init (GstPlugin *plugin) { @@ -382,7 +420,7 @@ GST_PLUGIN_DEFINE ( "GStreamer", "http://gstreamer.net/" ) - + Note that the information returned by the plugin_init() function will be cached in a central registry. For this reason, it is important that the diff --git a/docs/pwg/building-chainfn.xml b/docs/pwg/building-chainfn.xml index f9887628b5..1cda9393fd 100644 --- a/docs/pwg/building-chainfn.xml +++ b/docs/pwg/building-chainfn.xml @@ -10,61 +10,117 @@ one buffer will go out, too. Below is a very simple implementation of a chain function: - -static void -gst_my_filter_chain (GstPad *pad, - GstData *data) + + +static GstFlowReturn +gst_my_filter_chain (GstPad *pad, + GstBuffer *buf) +{ + GstMyFilter *filter = GST_MY_FILTER (GST_OBJECT_PARENT (pad)); if (!filter->silent) g_print ("Have data of size %u bytes!\n", GST_BUFFER_SIZE (buf)); - gst_pad_push (filter->srcpad, GST_DATA (buf)); + return gst_pad_push (filter->srcpad, buf); } - + + Obviously, the above doesn't do much useful. Instead of printing that the data is in, you would normally process the data there. Remember, however, that buffers are not always writable. In more advanced elements (the ones - that do event processing), the incoming data might not even be a buffer. + that do event processing), you may want to additionally specify an event + handling function, which will be called when stream-events are sent (such + as end-of-stream, discontinuities, tags, etc.). static void -gst_my_filter_chain (GstPad *pad, - GstData *data) +gst_my_filter_init (GstMyFilter * filter) { - GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad)); - GstBuffer *buf, *outbuf; +[..] + gst_pad_set_event_function (filter->sinkpad, + gst_my_filter_event); +[..] +} + + + +static gboolean +gst_my_filter_event (GstPad *pad, + GstEvent *event) +{ + GstMyFilter *filter = GST_MY_FILTER (GST_OBJECT_PARENT (pad)); - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - /* end-of-stream, we should close down all stream leftovers here */ - gst_my_filter_stop_processing (filter); - /* fall-through to default event handling */ - default: - gst_pad_event_default (pad, event); - break; - } - return; + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + /* end-of-stream, we should close down all stream leftovers here */ + gst_my_filter_stop_processing (filter); + break; + default: + break; } - buf = GST_BUFFER (data); - outbuf = gst_my_filter_process_data (buf); + return gst_pad_event_default (pad, event); +} + +static GstFlowReturn +gst_my_filter_chain (GstPad *pad, + GstBuffer *buf) +{ + GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad)); + GstBuffer *outbuf; + + outbuf = gst_my_filter_process_data (filter, buf); gst_buffer_unref (buf); if (!outbuf) { /* something went wrong - signal an error */ - gst_element_error (GST_ELEMENT (filter), STREAM, FAILED, (NULL), (NULL)); - return; + GST_ELEMENT_ERROR (GST_ELEMENT (filter), STREAM, FAILED, (NULL), (NULL)); + return GST_FLOW_ERROR; } - gst_pad_push (filter->srcpad, GST_DATA (outbuf)); + return gst_pad_push (filter->srcpad, outbuf); } - + + In some cases, it might be useful for an element to have control over the input data rate, too. In that case, you probably want to write a so-called diff --git a/docs/pwg/building-pads.xml b/docs/pwg/building-pads.xml index d244ffdfc1..f680085134 100644 --- a/docs/pwg/building-pads.xml +++ b/docs/pwg/building-pads.xml @@ -26,12 +26,65 @@ that, you have to register the pad with the element. This happens like this: - -static GstPadLinkReturn gst_my_filter_link (GstPad *pad, - const GstCaps *caps); + + +static gboolean gst_my_filter_setcaps (GstPad *pad, + GstCaps *caps); static GstCaps * gst_my_filter_getcaps (GstPad *pad); -static void gst_my_filter_chain (GstPad *pad, - GstData *data); +static GstFlowReturn gst_my_filter_chain (GstPad *pad, + GstBuffer *buf); + + + static void gst_my_filter_init (GstMyFilter *filter) @@ -41,20 +94,27 @@ gst_my_filter_init (GstMyFilter *filter) /* pad through which data comes in to the element */ filter->sinkpad = gst_pad_new_from_template ( gst_element_class_get_pad_template (klass, "sink"), "sink"); - gst_pad_set_link_function (filter->sinkpad, gst_my_filter_link); + gst_pad_set_setcaps_function (filter->sinkpad, gst_my_filter_setcaps); gst_pad_set_getcaps_function (filter->sinkpad, gst_my_filter_getcaps); gst_pad_set_chain_function (filter->sinkpad, gst_my_filter_chain); + + + gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); /* pad through which data goes out of the element */ filter->srcpad = gst_pad_new_from_template ( gst_element_class_get_pad_template (klass, "src"), "src"); - gst_pad_set_link_function (filter->srcpad, gst_my_filter_link); + gst_pad_set_setcaps_function (filter->srcpad, gst_my_filter_setcaps); gst_pad_set_getcaps_function (filter->srcpad, gst_my_filter_getcaps); gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); -[..] + + /* properties initial value */ + filter->silent = FALSE; } - + The link function @@ -72,10 +132,10 @@ gst_my_filter_init (GstMyFilter *filter) If the element responds positively towards the streamtype, that type will be used on the pad. An example: - -static GstPadLinkReturn -gst_my_filter_link (GstPad *pad, - const GstCaps *caps) + +static gboolean +gst_my_filter_setcaps (GstPad *pad, + GstCaps *caps) { GstStructure *structure = gst_caps_get_structure (caps, 0); GstMyFilter *filter = GST_MY_FILTER (gst_pad_get_parent (pad)); @@ -97,7 +157,7 @@ gst_my_filter_link (GstPad *pad, /* we're a filter and don't touch the properties of the data. * That means we can set the given caps unmodified on the next * element, and use that negotiation return value as ours. */ - ret = gst_pad_try_set_caps (otherpad, gst_caps_copy (caps)); + ret = gst_pad_set_caps (otherpad, gst_caps_copy (caps)); if (GST_PAD_LINK_FAILED (ret)) return ret; @@ -111,7 +171,7 @@ gst_my_filter_link (GstPad *pad, return ret; } - + In here, we check the mimetype of the provided caps. Normally, you don't need to do that in your own plugin/element, because the core does that @@ -153,7 +213,7 @@ gst_my_filter_link (GstPad *pad, specified on the other pad) on both pads. It explains how a _getcaps () can be used to do this. - + static GstCaps * gst_my_filter_getcaps (GstPad *pad) { @@ -161,7 +221,7 @@ gst_my_filter_getcaps (GstPad *pad) GstPad *otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad; GstCaps *othercaps = gst_pad_get_allowed_caps (otherpad), *caps; - gint n; + gint i; if (gst_caps_is_empty (othercaps)) return othercaps; @@ -174,49 +234,36 @@ gst_my_filter_getcaps (GstPad *pad) gst_structure_remove_field (structure, "rate"); } caps = gst_caps_intersect (othercaps, gst_pad_get_pad_template_caps (pad)); - gst_caps_free (othercaps); + gst_caps_unref (othercaps); return caps; } - + + diff --git a/docs/pwg/building-props.xml b/docs/pwg/building-props.xml index 51f3def472..316140a1a3 100644 --- a/docs/pwg/building-props.xml +++ b/docs/pwg/building-props.xml @@ -12,7 +12,19 @@ and can then fill in the value or take action required for that property to change value internally. - + + /* properties */ enum { ARG_0, @@ -82,7 +94,10 @@ gst_my_filter_get_property (GObject *object, break; } } - + + The above is a very simple example of how arguments are used. Graphical applications - for example GStreamer Editor - will use these properties diff --git a/docs/pwg/building-state.xml b/docs/pwg/building-state.xml index 35286ff9ef..d7ff8bbda5 100644 --- a/docs/pwg/building-state.xml +++ b/docs/pwg/building-state.xml @@ -1,7 +1,5 @@ - - What are states? - + What are states? A state describes whether the element instance is initialized, whether it is ready to transfer data and whether it is currently handling data. There @@ -55,9 +53,7 @@ - - Managing filter state - + Managing filter state An element can be notified of state changes through a virtual function pointer. Inside this function, the element can initialize any sort of @@ -79,7 +75,24 @@ gst_my_filter_class_init (GstMyFilterClass *klass) element_class->change_state = gst_my_filter_change_state; } - + + + static GstElementStateReturn gst_my_filter_change_state (GstElement *element) { @@ -97,11 +110,12 @@ gst_my_filter_change_state (GstElement *element) break; } - if (GST_ELEMENT_CLASS (parent_class)->change_state) - return GST_ELEMENT_CLASS (parent_class)->change_state (element); - - return GST_STATE_SUCCESS; + return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, + change_state, (element), GST_STATE_SUCCESS); } - + + diff --git a/docs/pwg/building-testapp.xml b/docs/pwg/building-testapp.xml index 94135641ec..7e2e9b1955 100644 --- a/docs/pwg/building-testapp.xml +++ b/docs/pwg/building-testapp.xml @@ -63,25 +63,71 @@ the pipeline and make sure it doesn't crash. - + #include <gst/gst.h> +static gboolean +bus_call (GstBus *bus, + GstMessage *msg, + gpointer data) +{ + GMainLoop *loop = data; + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_EOS: + g_print ("End-of-stream\n"); + g_main_loop_quit (loop); + break; + case GST_MESSAGE_ERROR: { + gchar *debug; + GError *err; + + gst_message_parse_error (msg, &err, &debug); + g_free (debug); + + g_print ("Error: %s\n", err->message); + g_error_free (err); + + g_main_loop_quit (loop); + break; + } + default: + break; + } + + return TRUE; +} + gint -main (gint arcg, +main (gint argc, gchar *argv[]) { GstElement *pipeline, *filesrc, *decoder, *filter, *sink; + GMainLoop *loop; /* initialization */ gst_init (&argc, &argv); + loop = g_main_loop_new (NULL, FALSE); /* create elements */ pipeline = gst_pipeline_new ("my_pipeline"); + gst_bus_add_watch (gst_pipeline_get_bus (GST_PIPELINE (pipeline)), + bus_call, loop); filesrc = gst_element_factory_make ("filesrc", "my_filesource"); decoder = gst_element_factory_make ("mad", "my_decoder"); filter = gst_element_factory_make ("my_filter", "my_filter"); sink = gst_element_factory_make ("osssink", "audiosink"); + if (!sink || !decoder) { + g_print ("Decoder or output could not be found - check your install\n"); + return -1; + } else if (!filter) { + g_print ("Your self-written filter could not be found. Make sure it " + "is installed correctly in $(libdir)/gstreamer-0.9/ and that " + "you've ran gst-register-0.9 to register it. Check availability " + "of the plugin afterwards using \"gst-inspect-0.9 my_filter\""); + return -1; + } g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL); @@ -91,7 +137,7 @@ main (gint arcg, /* run */ gst_element_set_state (pipeline, GST_STATE_PLAYING); - while (gst_bin_iterate (GST_BIN (pipeline))); + g_main_loop_run (loop); /* clean up */ gst_element_set_state (pipeline, GST_STATE_NULL); @@ -99,5 +145,5 @@ main (gint arcg, return 0; } - + diff --git a/docs/pwg/other-autoplugger.xml b/docs/pwg/other-autoplugger.xml deleted file mode 100644 index ac4e4fd69f..0000000000 --- a/docs/pwg/other-autoplugger.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - Writing an Autoplugger - - FIXME: write. - - diff --git a/docs/pwg/pwg.xml b/docs/pwg/pwg.xml index 46994f2feb..bcc87b0fe9 100644 --- a/docs/pwg/pwg.xml +++ b/docs/pwg/pwg.xml @@ -36,10 +36,10 @@ - + @@ -172,7 +172,6 @@ &OTHER_ONETON; &OTHER_NTOONE; &OTHER_NTON; - &OTHER_AUTOPLUGGER; &OTHER_MANAGER; @@ -187,6 +186,7 @@ &APPENDIX_CHECKLIST; + &APPENDIX_PORTING; &APPENDIX_LICENSING; &APPENDIX_PYTHON; diff --git a/examples/Makefile.am b/examples/Makefile.am index ed48293d69..3646ccf2aa 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -17,6 +17,7 @@ dirs = \ cutter \ pingpong \ manual \ + pwg \ retag SUBDIRS = $(dirs) \ diff --git a/examples/pwg/Makefile.am b/examples/pwg/Makefile.am new file mode 100644 index 0000000000..505e06de44 --- /dev/null +++ b/examples/pwg/Makefile.am @@ -0,0 +1,66 @@ +INCLUDES = $(GST_OBJ_CFLAGS) \ + -DVERSION="\"0.0.1\"" + +libboilerplate_la_SOURCES = boilerplate.c +libpads_la_SOURCES = pads.c +libchain_la_SOURCES = chain.c +libchain2_la_SOURCES = chain2.c +libstate_la_SOURCES = state.c +libproperties_la_SOURCES = properties.c + +EXTRA_DIST = extract.pl + +EXAMPLES = \ + libboilerplate.la \ + libpads.la \ + libchain.la \ + libchain2.la \ + libstate.la \ + libproperties.la + +EXAMPLE_APPS = \ + test + +filter.h register.func: $(top_srcdir)/docs/pwg/building-boiler.xml + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-boiler.xml + +boilerplate.c: $(top_srcdir)/docs/pwg/building-boiler.xml filter.h register.func + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-boiler.xml + +caps.func init.func: $(top_srcdir)/docs/pwg/building-pads.xml filter.h + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-pads.xml + +pads.c: $(top_srcdir)/docs/pwg/building-pads.xml register.func caps.func init.func + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-pads.xml + +chain.func: $(top_srcdir)/docs/pwg/building-chainfn.xml + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-chainfn.xml + +chain.c chain2.c: $(top_srcdir)/docs/pwg/building-chainfn.xml register.func caps.func init.func chain.func + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-chainfn.xml + +state.func: $(top_srcdir)/docs/pwg/building-state.xml + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-state.xml + +state.c: $(top_srcdir)/docs/pwg/building-state.xml register.func caps.func init.func chain.func state.func + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-state.xml + +properties.c: $(top_srcdir)/docs/pwg/building-props.xml filter.h register.func + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-props.xml + +test.c: $(top_srcdir)/docs/pwg/building-testapp.xml + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-testapp.xml + +noinst_PROGRAMS = $(EXAMPLE_APPS) +noinst_LTLIBRARIES = $(EXAMPLES) +LDADD = $(GST_OBJ_LIBS) diff --git a/examples/pwg/extract.pl b/examples/pwg/extract.pl new file mode 100755 index 0000000000..5c257c70a0 --- /dev/null +++ b/examples/pwg/extract.pl @@ -0,0 +1,78 @@ +#!/usr/bin/perl + +# extract code fragments from xml program listings +# first argument: source code file to find +# second argument: xml files to extract code from + +# main + +# decodes xml by translating & < > back to what they should be +# and also ignore +# and +sub +xml_decode ($) +{ + my $input = shift; + + $input =~ s/\&/&/g; + $input =~ s/<//g; + + if ($input =~ //) { $input = ""; } + if ($input =~ //) { $input = ""; } + + #print "Returning line $input"; + return $input; +} + +# main +my $output = shift @ARGV; + +$found = 0; +%blocks = (); + +foreach $file (@ARGV) +{ + open FILE, $file or die "Cannot open file $file"; + + while ($line = ) + { + if ($line =~ //) + { + $found = 1; + $block_id = $1; + $block = "\n/*** block $block_id from $file ***/\n"; + + print "Extracting $output block $block_id from $file\n"; + + while ($line = ) + { + if ($line =~ //) + { + last; + } + $block .= xml_decode ($line); + } + $blocks{$block_id} = $block; + } + } +} + + +if (!$found) +{ + print "Could not find $output example !\n"; + exit(1); +} + +# now output all the blocks in the right order +open OUTPUT, ">$output"; +@block_ids = keys %blocks; +foreach $block_id (sort @block_ids) +{ + print "Writing $output block $block_id\n"; + print OUTPUT $blocks{$block_id}; +} +close OUTPUT; diff --git a/tests/old/examples/Makefile.am b/tests/old/examples/Makefile.am index ed48293d69..3646ccf2aa 100644 --- a/tests/old/examples/Makefile.am +++ b/tests/old/examples/Makefile.am @@ -17,6 +17,7 @@ dirs = \ cutter \ pingpong \ manual \ + pwg \ retag SUBDIRS = $(dirs) \ diff --git a/tests/old/examples/pwg/Makefile.am b/tests/old/examples/pwg/Makefile.am new file mode 100644 index 0000000000..505e06de44 --- /dev/null +++ b/tests/old/examples/pwg/Makefile.am @@ -0,0 +1,66 @@ +INCLUDES = $(GST_OBJ_CFLAGS) \ + -DVERSION="\"0.0.1\"" + +libboilerplate_la_SOURCES = boilerplate.c +libpads_la_SOURCES = pads.c +libchain_la_SOURCES = chain.c +libchain2_la_SOURCES = chain2.c +libstate_la_SOURCES = state.c +libproperties_la_SOURCES = properties.c + +EXTRA_DIST = extract.pl + +EXAMPLES = \ + libboilerplate.la \ + libpads.la \ + libchain.la \ + libchain2.la \ + libstate.la \ + libproperties.la + +EXAMPLE_APPS = \ + test + +filter.h register.func: $(top_srcdir)/docs/pwg/building-boiler.xml + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-boiler.xml + +boilerplate.c: $(top_srcdir)/docs/pwg/building-boiler.xml filter.h register.func + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-boiler.xml + +caps.func init.func: $(top_srcdir)/docs/pwg/building-pads.xml filter.h + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-pads.xml + +pads.c: $(top_srcdir)/docs/pwg/building-pads.xml register.func caps.func init.func + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-pads.xml + +chain.func: $(top_srcdir)/docs/pwg/building-chainfn.xml + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-chainfn.xml + +chain.c chain2.c: $(top_srcdir)/docs/pwg/building-chainfn.xml register.func caps.func init.func chain.func + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-chainfn.xml + +state.func: $(top_srcdir)/docs/pwg/building-state.xml + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-state.xml + +state.c: $(top_srcdir)/docs/pwg/building-state.xml register.func caps.func init.func chain.func state.func + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-state.xml + +properties.c: $(top_srcdir)/docs/pwg/building-props.xml filter.h register.func + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-props.xml + +test.c: $(top_srcdir)/docs/pwg/building-testapp.xml + $(PERL_PATH) $(srcdir)/extract.pl $@ \ + $(top_srcdir)/docs/pwg/building-testapp.xml + +noinst_PROGRAMS = $(EXAMPLE_APPS) +noinst_LTLIBRARIES = $(EXAMPLES) +LDADD = $(GST_OBJ_LIBS) diff --git a/tests/old/examples/pwg/extract.pl b/tests/old/examples/pwg/extract.pl new file mode 100755 index 0000000000..5c257c70a0 --- /dev/null +++ b/tests/old/examples/pwg/extract.pl @@ -0,0 +1,78 @@ +#!/usr/bin/perl + +# extract code fragments from xml program listings +# first argument: source code file to find +# second argument: xml files to extract code from + +# main + +# decodes xml by translating & < > back to what they should be +# and also ignore +# and +sub +xml_decode ($) +{ + my $input = shift; + + $input =~ s/\&/&/g; + $input =~ s/<//g; + + if ($input =~ //) { $input = ""; } + if ($input =~ //) { $input = ""; } + + #print "Returning line $input"; + return $input; +} + +# main +my $output = shift @ARGV; + +$found = 0; +%blocks = (); + +foreach $file (@ARGV) +{ + open FILE, $file or die "Cannot open file $file"; + + while ($line = ) + { + if ($line =~ //) + { + $found = 1; + $block_id = $1; + $block = "\n/*** block $block_id from $file ***/\n"; + + print "Extracting $output block $block_id from $file\n"; + + while ($line = ) + { + if ($line =~ //) + { + last; + } + $block .= xml_decode ($line); + } + $blocks{$block_id} = $block; + } + } +} + + +if (!$found) +{ + print "Could not find $output example !\n"; + exit(1); +} + +# now output all the blocks in the right order +open OUTPUT, ">$output"; +@block_ids = keys %blocks; +foreach $block_id (sort @block_ids) +{ + print "Writing $output block $block_id\n"; + print OUTPUT $blocks{$block_id}; +} +close OUTPUT;