1 /* Demo Recorder for MAEMO 5
2 * Copyright (C) 2010 Dru Moore <usr@dru-id.co.uk>
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2,
5 * or (at your option) any later version, as published by the Free
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 public class TrackPipeline : GLib.Object {
25 Gst.Element converter;
26 Gst.Element equalizer;
31 Gst.Query duration_query;
32 Gst.Query position_query;
36 public void set_sink(Gst.Element sink) {
40 public void link_track(Gst.Element adder) {
44 //define a delegate function to handle tags
45 private static Gst.TagForeachFunc handle_tags_delegate;
47 public signal void position_duration(int64 position, int64 duration);
48 public signal void tag_parsed(string tag, string val);
49 public signal void end_of_stream();
50 public signal void stream_error(string msg);
52 public TrackPipeline(string name) {
53 //set the tag handling delegate
54 this.handle_tags_delegate = this.handle_tags;
55 //set some default values
58 this.construct_bin(name);
60 duration_query = new Gst.Query.duration(Gst.Format.TIME);
61 position_query = new Gst.Query.position(Gst.Format.TIME);
64 private void construct_bin(string name) {
65 bin = new Gst.Bin(name);
66 src = Gst.ElementFactory.make("fakesrc", "source");
68 decoder = Gst.ElementFactory.make("decodebin", "decoder");
69 decoder.connect ("swapped-object-signal::new-decoded-pad", new_decoded_pad, this);
71 converter = Gst.ElementFactory.make("audioconvert", "converter");
73 panorama = Gst.ElementFactory.make("audiopanorama", "panorama");
75 //echo = ElementFactory.make("audioecho", "echo");
76 //echo.set_property("delay", 500000000);
77 //echo.set_property("feedback", 0.4);
78 //echo.set_property("intensity", 0.5);
79 //echo.set_property("max-delay", 500000000);
81 //converter2 = ElementFactory.make("audioconvert", "converter2");
82 //pipeline.add(converter2);
83 equalizer = Gst.ElementFactory.make("equalizer-10bands", "eq");
85 volume = Gst.ElementFactory.make("volume", "vol");
87 sink = Gst.ElementFactory.make("autoaudiosink", "audio-output");
88 /* TODO How does bin handle this */ //pipeline.add(sink);
89 converter.link(equalizer);
90 equalizer.link(panorama);
91 panorama.link(volume);
92 /* TODO How does bin handle this */ //volume.link(sink);
93 //we need to receive signals from the pipelines bus
94 Gst.Bus bus = this.bin.get_bus( );
95 //make sure we are watching the signals on the bus
96 bus.add_signal_watch();
97 //what do we do when a tag is part of the bus signal?
100 this.bus_message(message);
106 public void foreach_tag (Gst.TagList list, string tag) {
107 stdout.printf("foreach_tag called\n");
111 list.get_string (tag, out track_title);
112 stdout.printf ("%s\n", track_title);
114 //info_label.set_markup("<b>" + track_title + "</b><br>" + track_uri);
121 public void handle_tags(Gst.TagList list, string tag) {
130 string val="Unknown";
131 list.get_string(tag,out val);
132 tag_parsed(tag, val);
137 list.get_uint(tag,out val);
138 //tag_parsed(tag,(string)val);
141 //stdout.printf("%s\n",tag);
149 public void bus_message(Gst.Message message) {
150 Gst.TagList tag_list;
151 switch(message.type) {
152 case Gst.MessageType.ERROR:
155 message.parse_error (out err, out debug);
156 stream_error(err.message);
158 case Gst.MessageType.TAG:
159 message.parse_tag(out tag_list);
160 //we need to get the key and value from the tag
161 tag_list.foreach( this.handle_tags_delegate );
163 case Gst.MessageType.STATE_CHANGED:
164 //stdout.printf("state changed\n");
168 message.parse_state_changed (out oldstate, out newstate, out pending);
169 //stdout.printf ("%s->%s:%s\n", oldstate.to_string(), newstate.to_string(), pending.to_string());
172 case Gst.MessageType.EOS:
180 public bool bus_callback (Gst.Bus bus, Gst.Message message) {
181 stdout.printf("state changed\n");
183 switch (message.type) {
184 case Gst.MessageType.ERROR:
187 message.parse_error (out err, out debug);
188 stdout.printf("%s\n", err.message);
191 case Gst.MessageType.EOS:
192 stdout.printf ("end of stream\n");
195 case Gst.MessageType.STATE_CHANGED:
199 message.parse_state_changed (out oldstate, out newstate, out pending);
200 stdout.printf ("%s->%s:%s\n", oldstate.to_string(), newstate.to_string(), pending.to_string());
203 case Gst.MessageType.TAG:
204 Gst.TagList tag_list;
205 message.parse_tag (out tag_list);
206 tag_list.foreach (foreach_tag);
214 public void get_duration_info() {
215 bool duration_result,position_result;
216 Gst.Format format = Gst.Format.TIME;
217 duration_result = this.bin.query(this.duration_query);
218 position_result = this.bin.query(this.position_query);
219 if ( duration_result && position_result ) {
220 this.duration_query.parse_duration(out format, out this.duration);
221 this.position_query.parse_position(out format, out this.position);
222 this.position_duration(this.position,this.duration);
227 bin.set_state(Gst.State.PLAYING);
230 public void pause() {
231 bin.set_state(Gst.State.PAUSED);
235 bin.set_state(Gst.State.READY);
238 public void move_to(int64 newloc) {
239 if (0 > newloc) newloc = 0;
240 this.converter.seek_simple(Gst.Format.TIME, Gst.SeekFlags.KEY_UNIT | Gst.SeekFlags.FLUSH, newloc);
244 public void seek(int percent) {
245 move_to((int64) this.position + (this.duration * percent / 100));
248 public void seek_forward(int percent) {
252 public void seek_backward(int percent) {
256 public void set_uri(string uri) {
257 this.bin.set_state(Gst.State.NULL);
259 //is there a src pipeline?
260 this.bin.remove(this.src);
262 //do nothing, the src doesn't exist
264 this.src = Gst.Element.make_from_uri(Gst.URIType.SRC, uri, "my_src");
265 Gst.Bus bus = this.src.get_bus();
266 bus.add_watch (bus_callback);
267 this.bin.add(this.src);
268 this.src.link(this.decoder);
271 public void set_volume(double val)
272 requires (val >= 0.0 && val <= 10.0) {
273 volume.set_property("volume",val);
276 public double get_volume() {
277 GLib.Value ret = 0.0;
278 volume.get_property("volume", ref ret);
279 return ret.get_double();
282 public void set_panorama(double val)
283 requires (val >= -1.0 && val <= 1.0) {
284 panorama.set_property("panorama", val);
287 public double get_panorama() {
288 GLib.Value ret = 0.0;
289 panorama.get_property("panorama", ref ret);
290 return ret.get_double();
293 public void set_eq(int band, double val)
294 requires (band > -1 && band < 10)
295 requires (val >= -24 && val <= 12) {
296 equalizer.set_property("band" + band.to_string(), val);
299 public double get_eq(int band) {
300 GLib.Value ret = 0.0;
301 equalizer.get_property("band" + band.to_string(), ref ret);
302 return ret.get_double();
305 public bool new_decoded_pad(Gst.Pad decodebin, bool arg1, void* data) {
306 //link the pad to the audioconverter
307 decodebin.link( converter.get_static_pad("sink") );