Created
July 7, 2011 21:49
-
-
Save arsfeld/1070632 to your computer and use it in GitHub Desktop.
Slideshow demo to show Clutter + GStreamer exporting (compile with valac -g --save-temps --pkg gdk-pixbuf-2.0 --pkg gstreamer-0.10 --pkg gstreamer-app-0.10 --pkg gio-2.0 --pkg clutter-1.0 slideshow.vala)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Clutter; | |
using Mx; | |
class ClutterDemo { | |
private Stage stage; | |
private Rectangle[] rectangles; | |
private List<string> filenames; | |
private int current; | |
private Queue<string> queue; | |
private uint timeout_id; | |
private Texture image; | |
private DeformTexture widget; | |
const int TRANSITION = 2000; | |
const int TIME = 3; | |
public void add_filename(string filename) { | |
var file = File.new_for_path(filename); | |
if (file.query_file_type(FileQueryInfoFlags.NONE) == FileType.DIRECTORY) { | |
var enumerator = file.enumerate_children (FILE_ATTRIBUTE_STANDARD_NAME, 0); | |
var file_info = enumerator.next_file(); | |
while (file_info != null) { | |
this.add_filename(GLib.Path.build_filename(filename, file_info.get_name())); | |
file_info = enumerator.next_file(); | |
} | |
} else { | |
stdout.printf ("Adding: %s\n", filename); | |
this.filenames.prepend(filename); | |
} | |
} | |
public ClutterDemo (string[] filenames) { | |
this.filenames = new List<string>(); | |
foreach (string filename in filenames) { | |
this.add_filename(filename); | |
} | |
this.filenames.reverse(); | |
this.queue = new Queue<string>(); | |
this.fill_queue(); | |
this.current = -1; | |
this.image = null; | |
stage = (Stage) Stage.get_default (); | |
stage.hide.connect (Clutter.main_quit); | |
this.load_next(); | |
this.timeout_id = Timeout.add_seconds(TIME, this.load_next_timeout); | |
stage.key_press_event.connect((actor, event) => { | |
Source.remove(timeout_id); | |
if (event.keyval == 65363) | |
this.load_next(false); | |
if (event.unicode_value.tolower() == 'q') | |
Clutter.main_quit(); | |
this.timeout_id = Timeout.add_seconds(TIME, this.load_next_timeout); | |
return false; | |
}); | |
stage.color = Color () { alpha = 255 }; | |
stage.show_all (); | |
Idle.add(() => { | |
setup_video(); | |
return false; | |
}); | |
} | |
public void setup_video() { | |
var timer = new Timer(); | |
int width = (int)this.stage.width; | |
int height = (int)this.stage.height; | |
var pipeline_desc = @"appsrc name=mysource ! videoparse width=$width height=$height format=rgb ! ffmpegcolorspace ! videoscale method=1 ! videorate ! theoraenc ! oggmux ! filesink location=video.ogv"; | |
var pipeline = (Gst.Pipeline) Gst.parse_launch(pipeline_desc); | |
var bus = pipeline.get_bus(); | |
var app_src = (Gst.AppSrc) pipeline.get_by_name("mysource"); | |
ulong need_data_id = 0; | |
app_src.need_data.connect(() => { | |
//need_data_id = Idle.add(() => { | |
var ms = timer.elapsed(); | |
debug("Giving data! elapsed %f, %dx%d", ms, width, height); | |
var buffer = new Gst.Buffer(); | |
uint8[] data = this.stage.read_pixels(0, 0, (int) this.stage.width, (int) this.stage.height); | |
debug("Has pixels!"); | |
data.length = (width * height * 4); | |
var pixbuf = new Gdk.Pixbuf.from_data(data, Gdk.Colorspace.RGB, true, 8, width, height, width * 4, null); | |
pixbuf.save("video%u.png".printf(Random.next_int()), "png"); | |
buffer.data = data; | |
app_src.push_buffer(buffer); | |
timer.start(); | |
}); | |
/* set the caps on the source */ | |
var caps = new Gst.Caps.simple("video/x-raw-rgb", | |
"bpp", typeof(int), 32, | |
"depth", typeof(int), 24, | |
"width", typeof(int), width, | |
"height", typeof(int), height | |
); | |
app_src.caps = caps; | |
debug("Playing"); | |
pipeline.set_state(Gst.State.PLAYING); | |
} | |
public bool fill_queue() { | |
this.queue.clear(); | |
foreach (string filename in this.filenames) { | |
this.queue.push_head(filename); | |
} | |
return (queue.get_length() > 0); | |
} | |
public bool load_next_timeout() { | |
return this.load_next(true); | |
} | |
public bool load_next(bool transition = false) { | |
var previous = this.image; | |
var previous_widget = this.widget; | |
if (previous != null) { | |
if (transition) | |
previous.animate(AnimationMode.LINEAR, TRANSITION, opacity: 0).completed.connect(() => { | |
stage.remove_actor(previous); | |
}); | |
else | |
stage.remove_actor(previous); | |
} | |
Texture? image = null; | |
while (image == null) { | |
if (this.queue.is_empty() && !this.fill_queue()) | |
break; | |
var filename = this.queue.pop_nth(Random.int_range(0, (int32)this.queue.get_length())); | |
stdout.printf("Queue: %u\n", this.queue.get_length()); | |
try { | |
image = new Texture(); | |
image.set_from_file(filename); | |
} catch { | |
image = null; | |
stdout.printf("File %s is not a valid image\n", filename); | |
} | |
} | |
if (image == null) { | |
var text = new Text.full ("Bitstream Vera Sans 18", | |
"No valid images found!", | |
Color.from_string ("white")); | |
text.anchor_gravity = Gravity.CENTER; | |
text.x = stage.width / 2; | |
text.y = stage.height / 2; | |
text.opacity = 0; | |
stage.add_actor (text); | |
text.animate (AnimationMode.LINEAR, TRANSITION, | |
opacity: 255); | |
return false; | |
} | |
image.keep_aspect_ratio = true; | |
image.set_request_mode(Clutter.RequestMode.WIDTH_FOR_HEIGHT); | |
image.height = stage.height; | |
if (image.width > stage.width) { | |
image.set_request_mode(Clutter.RequestMode.HEIGHT_FOR_WIDTH); | |
image.width = stage.width; | |
} | |
//image.x = this.stage.width / 2 - image.width / 2; | |
image.x = this.stage.width; | |
//image.y = -image.width; | |
image.y = this.stage.height / 2 - image.height / 2; | |
image.animate(Clutter.AnimationMode.LINEAR, TRANSITION, "x", this.stage.width / 2 - image.width / 2); | |
this.image = image; | |
stage.add_actor(image); | |
return true; | |
} | |
public void start () { | |
var text_group = new Group(); | |
var shadow = new Text.full ("Bitstream Vera Sans 40", | |
"Congratulations!", | |
Color.from_string ("black")); | |
shadow.add_effect(new BlurEffect()); | |
text_group.add_actor(shadow); | |
var text = new Text.full ("Bitstream Vera Sans 40", | |
"Congratulations!", | |
Color.from_string ("white")); | |
text_group.add_actor(text); | |
text_group.anchor_gravity = Gravity.CENTER; | |
text_group.x = stage.width / 2; | |
text_group.y = -text_group.height; // Off-stage | |
text.animate (AnimationMode.EASE_IN_OUT_BOUNCE, 3000, | |
y: stage.height / 2); | |
} | |
} | |
void main (string[] args) { | |
Clutter.init (ref args); | |
Gst.init(ref args); | |
var demo = new ClutterDemo (args[1:args.length]); | |
demo.start (); | |
Clutter.main (); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment