2 (c) Copyright 2000-2002 convergence integrated media GmbH.
5 Written by Denis Oliver Kropp <dok@directfb.org>,
6 Andreas Hundt <andi@fischlustig.de>,
7 Sven Neumann <neo@directfb.org> and
8 Julien Moutte <julien@moutte.net>.
10 This file is subject to the terms and conditions of the MIT License:
12 Permission is hereby granted, free of charge, to any person
13 obtaining a copy of this software and associated documentation
14 files (the "Software"), to deal in the Software without restriction,
15 including without limitation the rights to use, copy, modify, merge,
16 publish, distribute, sublicense, and/or sell copies of the Software,
17 and to permit persons to whom the Software is furnished to do so,
18 subject to the following conditions:
20 The above copyright notice and this permission notice shall be
21 included in all copies or substantial portions of the Software.
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
26 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
27 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
28 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
29 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
42 /* macro for a safe call to DirectFB functions */
43 #define DFBCHECK(x...) \
46 if (err != DFB_OK) { \
47 fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
48 DirectFBErrorFatal( #x, err ); \
64 gettimeofday (&tv, NULL);
65 return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
69 dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data)
71 dyn_link *connect = (dyn_link *) data;
73 if (connect->padname == NULL ||
74 !strcmp (gst_pad_get_name (newpad), connect->padname)) {
75 gst_pad_link (newpad, connect->target);
80 size_changed (GObject * obj, GParamSpec * pspec, IDirectFBWindow * window)
82 GstPad *pad = GST_PAD (obj);
86 if (!(caps = gst_pad_get_negotiated_caps (pad)))
89 s = gst_caps_get_structure (caps, 0);
93 if (!(gst_structure_get_int (s, "width", &width) &&
94 gst_structure_get_int (s, "height", &height)))
97 window->Resize (window, width, height);
102 setup_dynamic_link (GstElement * element, const gchar * padname,
103 GstPad * target, GstElement * bin)
107 connect = g_new0 (dyn_link, 1);
108 connect->padname = g_strdup (padname);
109 connect->target = target;
112 g_signal_connect (G_OBJECT (element), "pad-added", G_CALLBACK (dynamic_link),
117 main (int argc, char *argv[])
120 IDirectFBDisplayLayer *layer;
122 IDirectFBImageProvider *provider;
123 IDirectFBVideoProvider *video_provider;
125 IDirectFBSurface *bgsurface;
127 IDirectFBWindow *window1;
128 IDirectFBWindow *window2;
129 IDirectFBWindow *window3;
130 IDirectFBSurface *window_surface1;
131 IDirectFBSurface *window_surface2;
132 IDirectFBSurface *window_surface3;
134 GstElement *pipeline;
136 IDirectFBEventBuffer *buffer;
140 DFBDisplayLayerConfig layer_config;
141 DFBGraphicsDeviceDescription gdesc;
151 DFBCHECK (DirectFBInit (&argc, &argv));
152 gst_init (&argc, &argv);
153 DFBCHECK (DirectFBCreate (&dfb));
155 dfb->GetDeviceDescription (dfb, &gdesc);
157 DFBCHECK (dfb->GetDisplayLayer (dfb, DLID_PRIMARY, &layer));
159 layer->SetCooperativeLevel (layer, DLSCL_ADMINISTRATIVE);
161 if (!((gdesc.blitting_flags & DSBLIT_BLEND_ALPHACHANNEL) &&
162 (gdesc.blitting_flags & DSBLIT_BLEND_COLORALPHA))) {
163 layer_config.flags = DLCONF_BUFFERMODE;
164 layer_config.buffermode = DLBM_BACKSYSTEM;
166 layer->SetConfiguration (layer, &layer_config);
169 layer->GetConfiguration (layer, &layer_config);
170 layer->EnableCursor (layer, 1);
173 DFBFontDescription desc;
175 desc.flags = DFDESC_HEIGHT;
176 desc.height = layer_config.width / 50;
178 DFBCHECK (dfb->CreateFont (dfb, "decker.ttf", &desc, &font));
179 font->GetHeight (font, &fontheight);
183 dfb->CreateVideoProvider (dfb, argv[1], &video_provider) != DFB_OK) {
184 video_provider = NULL;
188 DFBSurfaceDescription desc;
190 desc.flags = DSDESC_WIDTH | DSDESC_HEIGHT;
191 desc.width = layer_config.width;
192 desc.height = layer_config.height;
194 DFBCHECK (dfb->CreateSurface (dfb, &desc, &bgsurface));
196 DFBCHECK (bgsurface->SetFont (bgsurface, font));
198 bgsurface->SetColor (bgsurface, 0xCF, 0xCF, 0xFF, 0xFF);
199 bgsurface->DrawString (bgsurface,
200 "Move the mouse over a window to activate it.",
201 -1, 0, 0, DSTF_LEFT | DSTF_TOP);
203 bgsurface->SetColor (bgsurface, 0xCF, 0xDF, 0xCF, 0xFF);
204 bgsurface->DrawString (bgsurface,
205 "Press left mouse button and drag to move the window.",
206 -1, 0, fontheight, DSTF_LEFT | DSTF_TOP);
208 bgsurface->SetColor (bgsurface, 0xCF, 0xEF, 0x9F, 0xFF);
209 bgsurface->DrawString (bgsurface,
210 "Press middle mouse button to raise/lower the window.",
211 -1, 0, fontheight * 2, DSTF_LEFT | DSTF_TOP);
213 bgsurface->SetColor (bgsurface, 0xCF, 0xFF, 0x6F, 0xFF);
214 bgsurface->DrawString (bgsurface,
215 "Press right mouse button when you are done.", -1,
216 0, fontheight * 3, DSTF_LEFT | DSTF_TOP);
218 layer->SetBackgroundImage (layer, bgsurface);
219 layer->SetBackgroundMode (layer, DLBM_IMAGE);
223 DFBSurfaceDescription sdsc;
224 DFBWindowDescription desc;
226 desc.flags = (DWDESC_POSX | DWDESC_POSY | DWDESC_WIDTH | DWDESC_HEIGHT);
228 if (!video_provider) {
229 desc.caps = DWCAPS_ALPHACHANNEL;
230 desc.flags |= DWDESC_CAPS;
235 video_provider->GetSurfaceDescription (video_provider, &sdsc);
237 if (sdsc.flags & DSDESC_CAPS) {
238 desc.flags |= DWDESC_SURFACE_CAPS;
239 desc.surface_caps = sdsc.caps;
245 desc.width = sdsc.width;
246 desc.height = sdsc.height;
248 DFBCHECK (layer->CreateWindow (layer, &desc, &window2));
249 window2->GetSurface (window2, &window_surface2);
251 window2->SetOpacity (window2, 0xFF);
253 window2->GetID (window2, &id2);
255 window2->CreateEventBuffer (window2, &buffer);
257 if (video_provider) {
258 video_provider->PlayTo (video_provider, window_surface2,
261 window_surface2->SetColor (window_surface2, 0x00, 0x30, 0x10, 0xc0);
262 window_surface2->DrawRectangle (window_surface2,
263 0, 0, desc.width, desc.height);
264 window_surface2->SetColor (window_surface2, 0x80, 0xa0, 0x00, 0x90);
265 window_surface2->FillRectangle (window_surface2,
266 1, 1, desc.width - 2, desc.height - 2);
269 window_surface2->Flip (window_surface2, NULL, 0);
273 DFBWindowDescription desc;
275 desc.flags = (DWDESC_POSX | DWDESC_POSY |
276 DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_CAPS);
281 desc.caps = DWCAPS_ALPHACHANNEL;
283 DFBCHECK (layer->CreateWindow (layer, &desc, &window1));
284 window1->GetSurface (window1, &window_surface1);
286 DFBCHECK (dfb->CreateImageProvider (dfb, "dfblogo.png", &provider));
287 provider->RenderTo (provider, window_surface1, NULL);
289 window_surface1->SetColor (window_surface1, 0xFF, 0x20, 0x20, 0x90);
290 window_surface1->DrawRectangle (window_surface1,
291 0, 0, desc.width, desc.height);
293 window_surface1->Flip (window_surface1, NULL, 0);
295 provider->Release (provider);
297 window1->AttachEventBuffer (window1, buffer);
299 window1->SetOpacity (window1, 0xFF);
301 window1->GetID (window1, &id1);
305 DFBWindowDescription desc;
306 GstElement *src, *decode;
307 GstElement *v_queue, *v_scale, *cs, *v_sink;
308 GstElement *a_queue, *conv, *a_sink;
309 GstPad *v_pad, *a_pad;
311 desc.flags = (DWDESC_POSX | DWDESC_POSY |
312 DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_CAPS);
317 desc.caps = DWCAPS_ALPHACHANNEL;
319 DFBCHECK (layer->CreateWindow (layer, &desc, &window3));
320 window3->GetSurface (window3, &window_surface3);
322 window3->AttachEventBuffer (window3, buffer);
324 window3->SetOpacity (window3, 0xFF);
326 window3->GetID (window3, &id3);
328 pipeline = gst_pipeline_new ("pipeline");
330 src = gst_element_factory_make ("gnomevfssrc", "src");
331 g_object_set (src, "location", argv[1], NULL);
332 decode = gst_element_factory_make ("decodebin", "decode");
334 v_queue = gst_element_factory_make ("queue", "v_queue");
335 v_scale = gst_element_factory_make ("videoscale", "v_scale");
336 cs = gst_element_factory_make ("ffmpegcolorspace", "cs");
337 v_sink = gst_element_factory_make ("dfbvideosink", "v_sink");
338 g_object_set (v_sink, "surface", window_surface3, NULL);
340 a_queue = gst_element_factory_make ("queue", "a_queue");
341 conv = gst_element_factory_make ("audioconvert", "conv");
342 a_sink = gst_element_factory_make ("alsasink", "a_sink");
344 gst_bin_add_many (GST_BIN (pipeline), src, decode, NULL);
345 gst_bin_add_many (GST_BIN (pipeline), v_queue, v_scale, cs, v_sink, NULL);
346 gst_bin_add_many (GST_BIN (pipeline), a_queue, conv, a_sink, NULL);
348 gst_element_link (src, decode);
349 gst_element_link_many (v_queue, v_scale, cs, v_sink, NULL);
350 gst_element_link_many (a_queue, conv, a_sink, NULL);
352 v_pad = gst_element_get_static_pad (v_queue, "sink");
353 a_pad = gst_element_get_static_pad (a_queue, "sink");
355 setup_dynamic_link (decode, NULL, v_pad, NULL);
356 setup_dynamic_link (decode, NULL, a_pad, NULL);
358 /* We want to know when the size is defined */
359 g_signal_connect (v_pad, "notify::caps", G_CALLBACK (size_changed),
362 gst_object_unref (a_pad);
363 gst_object_unref (v_pad);
365 gst_element_set_state (pipeline, GST_STATE_PLAYING);
368 window1->RequestFocus (window1);
369 window1->RaiseToTop (window1);
372 static IDirectFBWindow *active = NULL;
373 static int grabbed = 0;
374 static int startx = 0;
375 static int starty = 0;
380 buffer->WaitForEventWithTimeout (buffer, 0, 10);
382 while (buffer->GetEvent (buffer, DFB_EVENT (&evt)) == DFB_OK) {
383 IDirectFBWindow *window;
385 if (evt.window_id == id1)
387 else if (evt.window_id == id3)
392 if (evt.type == DWET_GOTFOCUS) {
397 case DWET_BUTTONDOWN:
398 if (!grabbed && evt.button == DIBI_LEFT) {
402 window->GrabPointer (window);
407 switch (evt.button) {
410 window->UngrabPointer (window);
415 active->RaiseToTop (active);
428 switch (evt.key_id) {
430 active->Move (active, 1, 0);
433 active->Move (active, -1, 0);
436 active->Move (active, 0, -1);
439 active->Move (active, 0, 1);
447 if (!grabbed && active == window)
465 switch (evt.key_symbol) {
484 window_surface2->Flip (window_surface2, NULL, 0);
488 active->Move (active, endx - startx, endy - starty);
492 active->SetOpacity (active, (sin (myclock () / 300.0) * 85) + 170);
497 video_provider->Release (video_provider);
499 gst_element_set_state (pipeline, GST_STATE_NULL);
501 buffer->Release (buffer);
502 font->Release (font);
503 window_surface2->Release (window_surface2);
504 window_surface1->Release (window_surface1);
505 window_surface3->Release (window_surface3);
506 window2->Release (window2);
507 window1->Release (window1);
508 window3->Release (window3);
509 layer->Release (layer);
510 bgsurface->Release (bgsurface);