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