File: Demo.py.md

package info (click to toggle)
pitivi 2023.03-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 22,468 kB
  • sloc: python: 33,616; ansic: 104; sh: 82; makefile: 6
file content (162 lines) | stat: -rw-r--r-- 5,850 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# PyGST Tutorial/Demos/Demo.py

    #!/usr/bin/env python

    """Basic Framework for writing GStreamer Demos in Python"""
    #<excerpt 2>
    import gobject
    gobject.threads_init()
    import gst
    #</excerpt>
    import pygtk
    pygtk.require("2.0")
    import gtk
    gtk.gdk.threads_init()
    import sys
    import os


    class DemoException(Exception):
        """Base exception class for errors which occur during demos"""

        def __init__(self, reason):
            self.reason = reason

    class Demo:
        """Base class implementing boring, boiler-plate code.
        Sets up a basic gstreamer environment which includes:

        * a window containing a drawing area and basic media controls
        * a basic gstreamer pipeline using an ximagesink
        * connects the ximagesink to the window's drawing area

        Derived classes need only override magic(), __name__,
        and __usage__ to create new demos."""

        __name__ = "Basic Demo"
        __usage__ = "python demo.py -- runs a simple test demo"
        __def_win_size__ = (320, 240)

        # this comment allows us to include only a portion of the file
        # in the tutorial for this demo
        # <excerpt 1>     ...

        def magic(self, pipeline, sink, args):
            """This is where the magic happens"""
            src = gst.element_factory_make("videotestsrc", "src")
            pipeline.add(src)
            src.link(sink)


        def createPipeline(self, w):
            """Given a window, creates a pipeline and connects it to the window"""

            # code will make the ximagesink output in the specified window
            def set_xid(window):
                gtk.gdk.threads_enter()
                sink.set_xwindow_id(window.window.xid)
                sink.expose()
                gtk.gdk.threads_leave()

            # this code receives the messages from the pipeline. if we
            # need to set X11 id, then we call set_xid
            def bus_handler(unused_bus, message):
                if message.type == gst.MESSAGE_ELEMENT:
                    if message.structure.get_name() == 'prepare-xwindow-id':
                        set_xid(w)
                return gst.BUS_PASS

            # create our pipeline, and connect our bus_handler
            self.pipeline = gst.Pipeline()
            bus = self.pipeline.get_bus()
            bus.set_sync_handler(bus_handler)

            sink = gst.element_factory_make("ximagesink", "sink")
            sink.set_property("force-aspect-ratio", True)
            sink.set_property("handle-expose", True)
            scale = gst.element_factory_make("videoscale", "scale")
            cspace = gst.element_factory_make("ffmpegcolorspace", "cspace")

            # our pipeline looks like this: ... ! cspace ! scale ! sink
            self.pipeline.add(cspace, scale, sink)
            scale.link(sink)
            cspace.link(scale)
            return (self.pipeline, cspace)

        # ... end of excerpt </excerpt>

        # subclasses can override this method to provide custom controls
        def customWidgets(self):
            return gtk.HBox()

        def createWindow(self):
            """Creates a top-level window, sets various boring attributes,
            creates a place to put the video sink, adds some and finally
            connects some basic signal handlers. Really, really boring.
            """

            # create window, set basic attributes
            w = gtk.Window()
            w.set_size_request(*self.__def_win_size__)
            w.set_title("Gstreamer " + self.__name__)
            w.connect("destroy", gtk.main_quit)

            # declare buttons and their associated handlers
            controls = (
                ("play_button", gtk.ToolButton(gtk.STOCK_MEDIA_PLAY), self.onPlay),
                ("stop_button", gtk.ToolButton(gtk.STOCK_MEDIA_STOP), self.onStop),
                ("quit_button", gtk.ToolButton(gtk.STOCK_QUIT), gtk.main_quit)
            )

            # as well as the container in which to put them
            box = gtk.HButtonBox()

            # for every widget, connect to its clicked signal and add it
            # to the enclosing box
            for name, widget, handler in controls:
                widget.connect("clicked", handler)
                box.pack_start(widget, True)
                setattr(self, name, widget)

            viewer = gtk.DrawingArea()
            viewer.modify_bg(gtk.STATE_NORMAL, viewer.style.black)

            # we will need this later
            self.xid = None

            # now finally do the top-level layout for the window
            layout = gtk.VBox(False)
            layout.pack_start(viewer)

            # subclasses can override childWidgets() to supply
            # custom controls
            layout.pack_start(self.customWidgets(), False, False)
            layout.pack_end(box, False, False)
            w.add(layout)
            w.show_all()

            # we want to return only the portion of the window which will
            # be used to display the video, not the whole top-level
            # window. a DrawingArea widget is, in fact, an X11 window.
            return viewer

        def onPlay(self, unused_button):
            self.pipeline.set_state(gst.STATE_PLAYING)

        def onStop(self, unused_button):
            self.pipeline.set_state(gst.STATE_READY)

        def run(self):
            w = self.createWindow()
            p, s = self.createPipeline(w)
            try:
                self.magic(p, s, sys.argv[1:])
                gtk.main()
            except DemoException, e:
                print e.reason
                print self.__usage__
                sys.exit(-1)

    # if this file is being run directly, create the demo and run it
    if __name__ == '__main__':
        Demo().run()