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 				writefln("Unknown message type.");
50 			break;
51 			case GstMessageType.EOS:
52 				writefln("End-of-stream.");
53 				Main.quit();
54 			break;
55 
56 			case GstMessageType.ERROR:
57 			{
58 				string dbug;
59 				ErrorG err;
60 				msg.parseError(err, dbug);
61 				//g_free (dbug);
62 				writefln("Error: %s dbug: %s", Str.toString(err.getErrorGStruct().message), dbug);
63 				Main.quit();
64 			break;
65 			}
66 			default:
67 			break;
68 		}
69 
70 		return true;
71 	}
72 
73 	this(string file)
74 	{
75 		// create elements
76 		
77 		pipeline = new Pipeline("audio-player");
78 
79 		source = ElementFactory.make("filesrc", "file-source");
80 		parser = ElementFactory.make("oggdemux", "ogg-parser");
81 		decoder = ElementFactory.make("vorbisdec", "vorbis-decoder");
82 		conv = ElementFactory.make("audioconvert", "converter");
83 		sink = ElementFactory.make("alsasink", "alsa-output");
84 
85 		if( pipeline is null || source is null || parser is null || decoder is null || conv is null || sink is null )
86 		{
87 			writefln("One or more element could not be created");
88 
89 			if( pipeline is null ) writefln(" : no pipeline.");
90 			if( source is null ) writefln(" : no source.");
91 			if( parser is null ) writefln(" : no parser.");
92 			if( decoder is null ) writefln(" : no decoder.");
93 			if( conv is null ) writefln(" : no conv.");
94 			if( sink is null ) writefln(" : no sink.");
95 			
96 			throw new Exception("One or more gstreamerD elements could not be created.");
97 		}
98 		
99 		// set filename property on the file source. Also add a message handler.
100 
101 		source.location( file ); //You can also use this like a D property: source.location = file;
102 		//Or you can also do: source.setProperty("location", file);
103 
104 		pipeline.getBus().addWatch( &busCall );
105 
106 		// put all elements in a bin
107 		pipeline.addMany( source, parser, decoder, conv, sink );
108 		
109 		// link together - note that we cannot link the parser and
110 		// decoder yet, because the parser uses dynamic pads. For that,
111 		// we set a pad-added signal handler.
112 		source.link( parser );
113 
114 		//shouldbe, but doesn't work yet:
115 		//decoder.linkMany( conv, sink );
116 		decoder.link( conv );
117 		conv.link( sink );
118 		//Here's where we set the pad-added signal handler. It will
119 		//connect the dynamic pads when they become available.
120 		parser.addOnPadAdded(&newPad);
121 
122 		// Now set to playing and iterate.
123 		writefln("Setting to PLAYING.");
124 		pipeline.setState( GstState.PLAYING );
125 		writefln("Running.");
126 	}
127 
128 	~this()
129 	{
130 		pipeline.setState( GstState.NULL );
131 	}
132 
133 	void newPad( Pad pad, Element element )
134 	{
135 		writefln("newPad callback called. START.");
136 
137 		Pad sinkpad;
138 
139 		// We can now link this pad with the audio decoder
140 		writefln("Dynamic pad created, linking parser/decoder");
141 
142 		sinkpad = decoder.getStaticPad("sink");
143 
144 		writefln("doing a gst_pad_link.");
145 
146 		pad.link( sinkpad );
147 
148 		writefln("Done. That was ok.");
149 	}
150 
151 protected:
152 
153 	Pipeline pipeline;
154 	Element source, parser, decoder, conv, sink;
155 }
156 
157 
158 int main(string[] args)
159 {
160 	writefln("gstreamerD Hello World!");
161 
162 	uint major, minor, micro, nano;
163 
164 	writefln("Trying to init...");
165 
166 	//Main.init(args);
167 	GStreamer.init(args);
168 
169 	// check input arguments
170 	if (args.length != 2)
171 	{
172 		writefln("Usage: %s <Ogg/Vorbis filename>", args[0]);
173 
174 		return -1;
175 	}
176 
177 	writefln("Checking version of GStreamer...");
178 
179 	GStreamer.versio(major, minor, micro, nano);
180 
181 	writefln("The installed version of GStreamer is %s.%s.%s", major, minor, micro );
182 	writefln( "The file is: %s", args[1] );
183 
184 	GstHello gstHello = new GstHello( args[1] );
185 
186 	//We must use the gtkD mainloop to run gstreamerD apps.
187 	Main.run();
188 
189 	return 0;
190 }