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