1 /* 2 * gstreamer_helloworld is placed in the 3 * public domain. 4 */ 5 6 module gstreamer_helloworld; 7 8 version(Tango) 9 import tango.util.log.Trace;//Thread safe console output. 10 else 11 import std.stdio; 12 13 //gtkD imports: 14 15 import glib.Str; 16 import gtk.Main; 17 18 //gstreamerD imports: 19 20 import gstreamer.gstreamer; 21 22 import gobject.ObjectG; 23 import glib.ErrorG; 24 import gstreamer.Element; 25 import gstreamer.Pipeline; 26 import gstreamer.ElementFactory; 27 import gstreamer.Pad; 28 import gstreamer.Message; 29 import gstreamer.Bus; 30 31 import gstreamerc.gstreamertypes; 32 import gstreamerc.gstreamer; 33 34 import gtkc.glib; 35 36 37 class GstHello 38 { 39 public: 40 41 bool busCall( Message msg ) 42 { 43 version(Tango) debug(gstreamer) 44 { 45 Trace.formatln("GstHello.busCall(msg) START."); 46 scope(exit) Trace.formatln("GstHello.busCall(msg) END."); 47 } 48 else debug(gstreamer) 49 { 50 writefln("GstHello.busCall(msg) START."); 51 scope(exit) writefln("GstHello.busCall(msg) END."); 52 } 53 54 switch( msg.type ) 55 { 56 case GstMessageType.UNKNOWN: 57 version(Tango) Trace.formatln("Unknown message type."); 58 else writefln("Unknown message type."); 59 break; 60 case GstMessageType.EOS: 61 version(Tango) Trace.formatln("End-of-stream."); 62 else writefln("End-of-stream."); 63 Main.quit(); 64 break; 65 66 case GstMessageType.ERROR: 67 { 68 string dbug; 69 ErrorG err; 70 msg.parseError(err, dbug); 71 //g_free (dbug); 72 version(Tango) Trace.formatln("Error: {} dbug: {}", Str.toString(err.getErrorGStruct().message), dbug ); 73 else writefln("Error: %s dbug: %s", Str.toString(err.getErrorGStruct().message), dbug); 74 Main.quit(); 75 break; 76 } 77 default: 78 break; 79 } 80 81 return true; 82 } 83 84 this(string file) 85 { 86 // create elements 87 88 pipeline = new Pipeline("audio-player"); 89 90 source = ElementFactory.make("filesrc", "file-source"); 91 parser = ElementFactory.make("oggdemux", "ogg-parser"); 92 decoder = ElementFactory.make("vorbisdec", "vorbis-decoder"); 93 conv = ElementFactory.make("audioconvert", "converter"); 94 sink = ElementFactory.make("alsasink", "alsa-output"); 95 96 if( pipeline is null || source is null || parser is null || decoder is null || conv is null || sink is null ) 97 { 98 version(Tango) 99 { 100 Trace.formatln("One or more element could not be created"); 101 102 if( pipeline is null ) Trace.formatln(" : no pipeline."); 103 if( source is null ) Trace.formatln(" : no source."); 104 if( parser is null ) Trace.formatln(" : no parser."); 105 if( decoder is null ) Trace.formatln(" : no decoder."); 106 if( conv is null ) Trace.formatln(" : no conv."); 107 if( sink is null ) Trace.formatln(" : no sink."); 108 } 109 else 110 { 111 writefln("One or more element could not be created"); 112 113 if( pipeline is null ) writefln(" : no pipeline."); 114 if( source is null ) writefln(" : no source."); 115 if( parser is null ) writefln(" : no parser."); 116 if( decoder is null ) writefln(" : no decoder."); 117 if( conv is null ) writefln(" : no conv."); 118 if( sink is null ) writefln(" : no sink."); 119 } 120 121 throw new Exception("One or more gstreamerD elements could not be created."); 122 } 123 124 // set filename property on the file source. Also add a message handler. 125 126 source.location( file ); //You can also use this like a D property: source.location = file; 127 //Or you can also do: source.setProperty("location", file); 128 129 pipeline.getBus().addWatch( &busCall ); 130 131 // put all elements in a bin 132 133 //shouldbe, but doesn't work yet: 134 //pipeline.addMany( source, parser, decoder, conv, sink ); 135 //TODO, add variable number of arguments (...) support to GtkWrapper 136 pipeline.add( source ); 137 pipeline.add( parser ); 138 pipeline.add( decoder ); 139 pipeline.add( conv ); 140 pipeline.add( sink ); 141 142 // link together - note that we cannot link the parser and 143 // decoder yet, because the parser uses dynamic pads. For that, 144 // we set a pad-added signal handler. 145 source.link( parser ); 146 147 //shouldbe, but doesn't work yet: 148 //decoder.linkMany( conv, sink ); 149 decoder.link( conv ); 150 conv.link( sink ); 151 //Here's where we set the pad-added signal handler. It will 152 //connect the dynamic pads when they become available. 153 parser.addOnPadAdded(&newPad); 154 155 // Now set to playing and iterate. 156 version(Tango) Trace.formatln("Setting to PLAYING."); 157 else writefln("Setting to PLAYING."); 158 pipeline.setState( GstState.PLAYING ); 159 version(Tango) Trace.formatln("Running."); 160 else writefln("Running."); 161 } 162 163 ~this() 164 { 165 pipeline.setState( GstState.NULL ); 166 } 167 168 void newPad( Pad pad, Element element ) 169 { 170 version(Tango) Trace.formatln("newPad callback called. START."); 171 else writefln("newPad callback called. START."); 172 173 Pad sinkpad; 174 175 // We can now link this pad with the audio decoder 176 version(Tango) Trace.formatln("Dynamic pad created, linking parser/decoder"); 177 else writefln("Dynamic pad created, linking parser/decoder"); 178 179 sinkpad = decoder.getStaticPad("sink"); 180 181 version(Tango) Trace.formatln("doing a gst_pad_link."); 182 else writefln("doing a gst_pad_link."); 183 184 pad.link( sinkpad ); 185 186 version(Tango) Trace.formatln("Done. That was ok."); 187 else writefln("Done. That was ok."); 188 189 } 190 191 protected: 192 193 Pipeline pipeline; 194 Element source, parser, decoder, conv, sink; 195 } 196 197 198 int main(string[] args) 199 { 200 version(Tango) Trace.formatln("gstreamerD Hello World!"); 201 else writefln("gstreamerD Hello World!"); 202 203 uint major, minor, micro, nano; 204 205 version(Tango) Trace.formatln("Trying to init..."); 206 else writefln("Trying to init..."); 207 208 //Main.init(args); 209 GStreamer.init(args); 210 211 // check input arguments 212 if (args.length != 2) 213 { 214 version(Tango) Trace.formatln("Usage: {} <Ogg/Vorbis filename>", args[0]); 215 else writefln("Usage: %s <Ogg/Vorbis filename>", args[0]); 216 217 return -1; 218 } 219 220 version(Tango) Trace.formatln("Checking version of GStreamer..."); 221 else writefln("Checking version of GStreamer..."); 222 223 GStreamer.versio(major, minor, micro, nano); 224 225 version(Tango) Trace.formatln("The installed version of GStreamer is {}.{}.{}", major, minor, micro ); 226 else writefln("The installed version of GStreamer is %s.%s.%s", major, minor, micro ); 227 228 version(Tango) Trace.formatln( "The file is: {}", args[1] ); 229 else writefln( "The file is: %s", args[1] ); 230 231 GstHello gstHello = new GstHello( args[1] ); 232 233 //We must use the gtkD mainloop to run gstreamerD apps. 234 Main.run(); 235 236 return 0; 237 }