[21447] | 1 | <chapter id="chapter-helloworld"> |
---|
| 2 | <title>Your first application</title> |
---|
| 3 | <para> |
---|
| 4 | This chapter will summarize everything you've learned in the previous |
---|
| 5 | chapters. It describes all aspects of a simple &GStreamer; application, |
---|
| 6 | including initializing libraries, creating elements, packing elements |
---|
| 7 | together in a pipeline and playing this pipeline. By doing all this, |
---|
| 8 | you will be able to build a simple Ogg/Vorbis audio player. |
---|
| 9 | </para> |
---|
| 10 | |
---|
| 11 | <sect1 id="section-helloworld"> |
---|
| 12 | <title>Hello world</title> |
---|
| 13 | <para> |
---|
| 14 | We're going to create a simple first application, a simple Ogg/Vorbis |
---|
| 15 | command-line audio player. For this, we will use only standard |
---|
| 16 | &GStreamer; components. The player will read a file specified on |
---|
| 17 | the command-line. Let's get started! |
---|
| 18 | </para> |
---|
| 19 | <para> |
---|
| 20 | We've learned, in <xref linkend="chapter-init"/>, that the first thing |
---|
| 21 | to do in your application is to initialize &GStreamer; by calling |
---|
| 22 | <function>gst_init ()</function>. Also, make sure that the application |
---|
| 23 | includes <filename>gst/gst.h</filename> so all function names and |
---|
| 24 | objects are properly defined. Use <function>#include |
---|
| 25 | <gst/gst.h></function> to do that. |
---|
| 26 | </para> |
---|
| 27 | <para> |
---|
| 28 | Next, you'll want to create the different elements using |
---|
| 29 | <function>gst_element_factory_make ()</function>. For an Ogg/Vorbis |
---|
| 30 | audio player, we'll need a source element that reads files from a |
---|
| 31 | disk. &GStreamer; includes this element under the name |
---|
| 32 | <quote>filesrc</quote>. Next, we'll need something to parse the |
---|
| 33 | file and decoder it into raw audio. &GStreamer; has two elements |
---|
| 34 | for this: the first parses Ogg streams into elementary streams (video, |
---|
| 35 | audio) and is called <quote>oggdemux</quote>. The second is a Vorbis |
---|
| 36 | audio decoder, it's conveniently called <quote>vorbisdec</quote>. |
---|
| 37 | Since <quote>oggdemux</quote> creates dynamic pads for each elementary |
---|
| 38 | stream, you'll need to set a <quote>new-pad</quote> event handler |
---|
| 39 | on the <quote>oggdemux</quote> element, like you've learned in |
---|
| 40 | <xref linkend="section-pads-dynamic"/>, to link the Ogg parser and |
---|
| 41 | the Vorbis decoder elements together. At last, we'll also need an |
---|
| 42 | audio output element, we will use <quote>alsasink</quote>, which |
---|
| 43 | outputs sound to an ALSA audio device. |
---|
| 44 | </para> |
---|
| 45 | <para> |
---|
| 46 | The last thing left to do is to add all elements into a container |
---|
| 47 | element, a <classname>GstPipeline</classname>, and iterate this |
---|
| 48 | pipeline until we've played the whole song. We've previously |
---|
| 49 | learned how to add elements to a container bin in <xref |
---|
| 50 | linkend="chapter-bins"/>, and we've learned about element states |
---|
| 51 | in <xref linkend="section-elements-states"/>. We will use the function |
---|
| 52 | <function>gst_bin_sync_children_state ()</function> to synchronize |
---|
| 53 | the state of a bin on all of its contained children. |
---|
| 54 | </para> |
---|
| 55 | <para> |
---|
| 56 | Let's now add all the code together to get our very first audio |
---|
| 57 | player: |
---|
| 58 | </para> |
---|
| 59 | <programlisting> |
---|
| 60 | <!-- example-begin helloworld.c --> |
---|
| 61 | #include <gst/gst.h> |
---|
| 62 | |
---|
| 63 | /* |
---|
| 64 | * Global objects are usually a bad thing. For the purpose of this |
---|
| 65 | * example, we will use them, however. |
---|
| 66 | */ |
---|
| 67 | |
---|
| 68 | GstElement *pipeline, *source, *parser, *decoder, *sink; |
---|
| 69 | |
---|
| 70 | static void |
---|
| 71 | new_pad (GstElement *element, |
---|
| 72 | GstPad *pad, |
---|
| 73 | gpointer data) |
---|
| 74 | { |
---|
| 75 | /* We can now link this pad with the audio decoder and |
---|
| 76 | * add both decoder and audio output to the pipeline. */ |
---|
| 77 | gst_pad_link (pad, gst_element_get_pad (decoder, "sink")); |
---|
| 78 | gst_bin_add_many (GST_BIN (pipeline), decoder, sink, NULL); |
---|
| 79 | |
---|
| 80 | /* This function synchronizes a bins state on all of its |
---|
| 81 | * contained children. */ |
---|
| 82 | gst_bin_sync_children_state (GST_BIN (pipeline)); |
---|
| 83 | } |
---|
| 84 | |
---|
| 85 | int |
---|
| 86 | main (int argc, |
---|
| 87 | char *argv[]) |
---|
| 88 | { |
---|
| 89 | /* initialize GStreamer */ |
---|
| 90 | gst_init (&argc, &argv); |
---|
| 91 | |
---|
| 92 | /* check input arguments */ |
---|
| 93 | if (argc != 2) { |
---|
| 94 | g_print ("Usage: %s <Ogg/Vorbis filename>\n", argv[0]); |
---|
| 95 | return -1; |
---|
| 96 | } |
---|
| 97 | |
---|
| 98 | /* create elements */ |
---|
| 99 | pipeline = gst_pipeline_new ("audio-player"); |
---|
| 100 | source = gst_element_factory_make ("filesrc", "file-source"); |
---|
| 101 | parser = gst_element_factory_make ("oggdemux", "ogg-parser"); |
---|
| 102 | decoder = gst_element_factory_make ("vorbisdec", "vorbis-decoder"); |
---|
| 103 | sink = gst_element_factory_make ("alsasink", "alsa-output"); |
---|
| 104 | |
---|
| 105 | /* set filename property on the file source */ |
---|
| 106 | g_object_set (G_OBJECT (source), "location", argv[1], NULL); |
---|
| 107 | |
---|
| 108 | /* link together - note that we cannot link the parser and |
---|
| 109 | * decoder yet, becuse the parser uses dynamic pads. For that, |
---|
| 110 | * we set a new-pad signal handler. */ |
---|
| 111 | gst_element_link (source, parser); |
---|
| 112 | gst_element_link (decoder, sink); |
---|
| 113 | g_signal_connect (parser, "new-pad", G_CALLBACK (new_pad), NULL); |
---|
| 114 | |
---|
| 115 | /* put all elements in a bin - or at least the ones we will use |
---|
| 116 | * instantly. */ |
---|
| 117 | gst_bin_add_many (GST_BIN (pipeline), source, parser, NULL); |
---|
| 118 | |
---|
| 119 | /* Now set to playing and iterate. We will set the decoder and |
---|
| 120 | * audio output to ready so they initialize their memory already. |
---|
| 121 | * This will decrease the amount of time spent on linking these |
---|
| 122 | * elements when the Ogg parser emits the new-pad signal. */ |
---|
| 123 | gst_element_set_state (decoder, GST_STATE_READY); |
---|
| 124 | gst_element_set_state (sink, GST_STATE_READY); |
---|
| 125 | gst_element_set_state (pipeline, GST_STATE_PLAYING); |
---|
| 126 | |
---|
| 127 | /* and now iterate - the rest will be automatic from here on. |
---|
| 128 | * When the file is finished, gst_bin_iterate () will return |
---|
| 129 | * FALSE, thereby terminating this loop. */ |
---|
| 130 | while (gst_bin_iterate (GST_BIN (pipeline))) ; |
---|
| 131 | |
---|
| 132 | /* clean up nicely */ |
---|
| 133 | gst_element_set_state (pipeline, GST_STATE_NULL); |
---|
| 134 | gst_object_unref (GST_OBJECT (pipeline)); |
---|
| 135 | |
---|
| 136 | return 0; |
---|
| 137 | } |
---|
| 138 | <!-- example-end helloworld.c --> |
---|
| 139 | </programlisting> |
---|
| 140 | <!-- FIXME: this image needs updating --> |
---|
| 141 | <para> |
---|
| 142 | We now have created a complete pipeline. We can visualise the |
---|
| 143 | pipeline as follows: |
---|
| 144 | </para> |
---|
| 145 | <figure float="1" id="section-hello-img"> |
---|
| 146 | <title>The "hello world" pipeline</title> |
---|
| 147 | <mediaobject> |
---|
| 148 | <imageobject> |
---|
| 149 | <imagedata fileref="images/hello-world.ℑ" format="&IMAGE;" /> |
---|
| 150 | </imageobject> |
---|
| 151 | </mediaobject> |
---|
| 152 | </figure> |
---|
| 153 | </sect1> |
---|
| 154 | |
---|
| 155 | <sect1 id="section-helloworld-compilerun"> |
---|
| 156 | <title>Compiling and Running helloworld.c</title> |
---|
| 157 | <para> |
---|
| 158 | To compile the helloworld example, use: <command>gcc -Wall |
---|
| 159 | $(pkg-config --cflags --libs gstreamer-&GST_MAJORMINOR;) |
---|
| 160 | helloworld.c -o helloworld</command>. &GStreamer; makes use of |
---|
| 161 | <command>pkg-config</command> to get compiler and linker flags |
---|
| 162 | needed to compile this application. If you're running a |
---|
| 163 | non-standard installation, make sure the |
---|
| 164 | <classname>PKG_CONFIG_PATH</classname> environment variable is |
---|
| 165 | set to the correct location (<filename>$libdir/pkgconfig</filename>). |
---|
| 166 | application against the uninstalled location. |
---|
| 167 | </para> |
---|
| 168 | <para> |
---|
| 169 | You can run this example application with <command>./helloworld |
---|
| 170 | file.ogg</command>. Substitute <filename>file.ogg</filename> |
---|
| 171 | with your favourite Ogg/Vorbis file. |
---|
| 172 | </para> |
---|
| 173 | </sect1> |
---|
| 174 | |
---|
| 175 | <sect1 id="section-hello-world-conclusion"> |
---|
| 176 | <title>Conclusion</title> |
---|
| 177 | <para> |
---|
| 178 | This concludes our first example. As you see, setting up a pipeline |
---|
| 179 | is very low-level but powerful. You will see later in this manual how |
---|
| 180 | you can create a more powerful media player with even less effort |
---|
| 181 | using higher-level interfaces. We will discuss all that in <xref |
---|
| 182 | linkend="part-highlevel"/>. We will first, however, go more in-depth |
---|
| 183 | into more advanced &GStreamer; internals. |
---|
| 184 | </para> |
---|
| 185 | <para> |
---|
| 186 | It should be clear from the example that we can very easily replace |
---|
| 187 | the <quote>filesrc</quote> element with some other element that |
---|
| 188 | reads data from a network, or some other data source element that |
---|
| 189 | is better integrated with your desktop environment. Also, you can |
---|
| 190 | use other decoders and parsers to support other media types. You |
---|
| 191 | can use another audio sink if you're not running Linux, but Mac OS X, |
---|
| 192 | Windows or FreeBSD, or you can instead use a filesink to write audio |
---|
| 193 | files to disk instead of playing them back. By using an audio card |
---|
| 194 | source, you can even do audio capture instead of playback. All this |
---|
| 195 | shows the reusability of &GStreamer; elements, which is its greatest |
---|
| 196 | advantage. |
---|
| 197 | </para> |
---|
| 198 | </sect1> |
---|
| 199 | </chapter> |
---|