summaryrefslogtreecommitdiffstats
path: root/examples/directfb/gstdfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/directfb/gstdfb.c')
-rw-r--r--examples/directfb/gstdfb.c514
1 files changed, 514 insertions, 0 deletions
diff --git a/examples/directfb/gstdfb.c b/examples/directfb/gstdfb.c
new file mode 100644
index 00000000..58114204
--- /dev/null
+++ b/examples/directfb/gstdfb.c
@@ -0,0 +1,514 @@
+/*
+ (c) Copyright 2000-2002 convergence integrated media GmbH.
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org> and
+ Julien Moutte <julien@moutte.net>.
+
+ This file is subject to the terms and conditions of the MIT License:
+
+ Permission is hereby granted, free of charge, to any person
+ obtaining a copy of this software and associated documentation
+ files (the "Software"), to deal in the Software without restriction,
+ including without limitation the rights to use, copy, modify, merge,
+ publish, distribute, sublicense, and/or sell copies of the Software,
+ and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <math.h>
+#include <time.h>
+
+#include <directfb.h>
+#include <gst/gst.h>
+#include <string.h>
+
+/* macro for a safe call to DirectFB functions */
+#define DFBCHECK(x...) \
+ { \
+ err = x; \
+ if (err != DFB_OK) { \
+ fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \
+ DirectFBErrorFatal( #x, err ); \
+ } \
+ }
+
+typedef struct
+{
+ const gchar *padname;
+ GstPad *target;
+ GstElement *bin;
+} dyn_link;
+
+static inline long
+myclock ()
+{
+ struct timeval tv;
+
+ gettimeofday (&tv, NULL);
+ return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
+}
+
+static void
+dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data)
+{
+ dyn_link *connect = (dyn_link *) data;
+
+ if (connect->padname == NULL ||
+ !strcmp (gst_pad_get_name (newpad), connect->padname)) {
+ gst_pad_link (newpad, connect->target);
+ }
+}
+
+static void
+size_changed (GObject * obj, GParamSpec * pspec, IDirectFBWindow * window)
+{
+ GstPad *pad = GST_PAD (obj);
+ GstStructure *s;
+ GstCaps *caps;
+
+ if (!(caps = gst_pad_get_negotiated_caps (pad)))
+ return;
+
+ s = gst_caps_get_structure (caps, 0);
+ if (s) {
+ gint width, height;
+
+ if (!(gst_structure_get_int (s, "width", &width) &&
+ gst_structure_get_int (s, "height", &height)))
+ return;
+
+ window->Resize (window, width, height);
+ }
+}
+
+static void
+setup_dynamic_link (GstElement * element, const gchar * padname,
+ GstPad * target, GstElement * bin)
+{
+ dyn_link *connect;
+
+ connect = g_new0 (dyn_link, 1);
+ connect->padname = g_strdup (padname);
+ connect->target = target;
+ connect->bin = bin;
+
+ g_signal_connect (G_OBJECT (element), "pad-added", G_CALLBACK (dynamic_link),
+ connect);
+}
+
+int
+main (int argc, char *argv[])
+{
+ IDirectFB *dfb;
+ IDirectFBDisplayLayer *layer;
+
+ IDirectFBImageProvider *provider;
+ IDirectFBVideoProvider *video_provider;
+
+ IDirectFBSurface *bgsurface;
+
+ IDirectFBWindow *window1;
+ IDirectFBWindow *window2;
+ IDirectFBWindow *window3;
+ IDirectFBSurface *window_surface1;
+ IDirectFBSurface *window_surface2;
+ IDirectFBSurface *window_surface3;
+
+ GstElement *pipeline;
+
+ IDirectFBEventBuffer *buffer;
+
+ IDirectFBFont *font;
+
+ DFBDisplayLayerConfig layer_config;
+ DFBGraphicsDeviceDescription gdesc;
+ DFBWindowID id1;
+ DFBWindowID id2;
+ DFBWindowID id3;
+
+ int fontheight;
+ int err;
+ int quit = 0;
+
+
+ DFBCHECK (DirectFBInit (&argc, &argv));
+ gst_init (&argc, &argv);
+ DFBCHECK (DirectFBCreate (&dfb));
+
+ dfb->GetDeviceDescription (dfb, &gdesc);
+
+ DFBCHECK (dfb->GetDisplayLayer (dfb, DLID_PRIMARY, &layer));
+
+ layer->SetCooperativeLevel (layer, DLSCL_ADMINISTRATIVE);
+
+ if (!((gdesc.blitting_flags & DSBLIT_BLEND_ALPHACHANNEL) &&
+ (gdesc.blitting_flags & DSBLIT_BLEND_COLORALPHA))) {
+ layer_config.flags = DLCONF_BUFFERMODE;
+ layer_config.buffermode = DLBM_BACKSYSTEM;
+
+ layer->SetConfiguration (layer, &layer_config);
+ }
+
+ layer->GetConfiguration (layer, &layer_config);
+ layer->EnableCursor (layer, 1);
+
+ {
+ DFBFontDescription desc;
+
+ desc.flags = DFDESC_HEIGHT;
+ desc.height = layer_config.width / 50;
+
+ DFBCHECK (dfb->CreateFont (dfb, "decker.ttf", &desc, &font));
+ font->GetHeight (font, &fontheight);
+ }
+
+ if (argc < 2 ||
+ dfb->CreateVideoProvider (dfb, argv[1], &video_provider) != DFB_OK) {
+ video_provider = NULL;
+ }
+
+ {
+ DFBSurfaceDescription desc;
+
+ desc.flags = DSDESC_WIDTH | DSDESC_HEIGHT;
+ desc.width = layer_config.width;
+ desc.height = layer_config.height;
+
+ DFBCHECK (dfb->CreateSurface (dfb, &desc, &bgsurface));
+
+ DFBCHECK (bgsurface->SetFont (bgsurface, font));
+
+ bgsurface->SetColor (bgsurface, 0xCF, 0xCF, 0xFF, 0xFF);
+ bgsurface->DrawString (bgsurface,
+ "Move the mouse over a window to activate it.",
+ -1, 0, 0, DSTF_LEFT | DSTF_TOP);
+
+ bgsurface->SetColor (bgsurface, 0xCF, 0xDF, 0xCF, 0xFF);
+ bgsurface->DrawString (bgsurface,
+ "Press left mouse button and drag to move the window.",
+ -1, 0, fontheight, DSTF_LEFT | DSTF_TOP);
+
+ bgsurface->SetColor (bgsurface, 0xCF, 0xEF, 0x9F, 0xFF);
+ bgsurface->DrawString (bgsurface,
+ "Press middle mouse button to raise/lower the window.",
+ -1, 0, fontheight * 2, DSTF_LEFT | DSTF_TOP);
+
+ bgsurface->SetColor (bgsurface, 0xCF, 0xFF, 0x6F, 0xFF);
+ bgsurface->DrawString (bgsurface,
+ "Press right mouse button when you are done.", -1,
+ 0, fontheight * 3, DSTF_LEFT | DSTF_TOP);
+
+ layer->SetBackgroundImage (layer, bgsurface);
+ layer->SetBackgroundMode (layer, DLBM_IMAGE);
+ }
+
+ {
+ DFBSurfaceDescription sdsc;
+ DFBWindowDescription desc;
+
+ desc.flags = (DWDESC_POSX | DWDESC_POSY | DWDESC_WIDTH | DWDESC_HEIGHT);
+
+ if (!video_provider) {
+ desc.caps = DWCAPS_ALPHACHANNEL;
+ desc.flags |= DWDESC_CAPS;
+
+ sdsc.width = 300;
+ sdsc.height = 200;
+ } else {
+ video_provider->GetSurfaceDescription (video_provider, &sdsc);
+
+ if (sdsc.flags & DSDESC_CAPS) {
+ desc.flags |= DWDESC_SURFACE_CAPS;
+ desc.surface_caps = sdsc.caps;
+ }
+ }
+
+ desc.posx = 20;
+ desc.posy = 120;
+ desc.width = sdsc.width;
+ desc.height = sdsc.height;
+
+ DFBCHECK (layer->CreateWindow (layer, &desc, &window2));
+ window2->GetSurface (window2, &window_surface2);
+
+ window2->SetOpacity (window2, 0xFF);
+
+ window2->GetID (window2, &id2);
+
+ window2->CreateEventBuffer (window2, &buffer);
+
+ if (video_provider) {
+ video_provider->PlayTo (video_provider, window_surface2,
+ NULL, NULL, NULL);
+ } else {
+ window_surface2->SetColor (window_surface2, 0x00, 0x30, 0x10, 0xc0);
+ window_surface2->DrawRectangle (window_surface2,
+ 0, 0, desc.width, desc.height);
+ window_surface2->SetColor (window_surface2, 0x80, 0xa0, 0x00, 0x90);
+ window_surface2->FillRectangle (window_surface2,
+ 1, 1, desc.width - 2, desc.height - 2);
+ }
+
+ window_surface2->Flip (window_surface2, NULL, 0);
+ }
+
+ {
+ DFBWindowDescription desc;
+
+ desc.flags = (DWDESC_POSX | DWDESC_POSY |
+ DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_CAPS);
+ desc.posx = 200;
+ desc.posy = 200;
+ desc.width = 512;
+ desc.height = 145;
+ desc.caps = DWCAPS_ALPHACHANNEL;
+
+ DFBCHECK (layer->CreateWindow (layer, &desc, &window1));
+ window1->GetSurface (window1, &window_surface1);
+
+ DFBCHECK (dfb->CreateImageProvider (dfb, "dfblogo.png", &provider));
+ provider->RenderTo (provider, window_surface1, NULL);
+
+ window_surface1->SetColor (window_surface1, 0xFF, 0x20, 0x20, 0x90);
+ window_surface1->DrawRectangle (window_surface1,
+ 0, 0, desc.width, desc.height);
+
+ window_surface1->Flip (window_surface1, NULL, 0);
+
+ provider->Release (provider);
+
+ window1->AttachEventBuffer (window1, buffer);
+
+ window1->SetOpacity (window1, 0xFF);
+
+ window1->GetID (window1, &id1);
+ }
+
+ {
+ DFBWindowDescription desc;
+ GstElement *src, *decode;
+ GstElement *v_queue, *v_scale, *cs, *v_sink;
+ GstElement *a_queue, *conv, *a_sink;
+ GstPad *v_pad, *a_pad;
+
+ desc.flags = (DWDESC_POSX | DWDESC_POSY |
+ DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_CAPS);
+ desc.posx = 10;
+ desc.posy = 10;
+ desc.width = 100;
+ desc.height = 100;
+ desc.caps = DWCAPS_ALPHACHANNEL;
+
+ DFBCHECK (layer->CreateWindow (layer, &desc, &window3));
+ window3->GetSurface (window3, &window_surface3);
+
+ window3->AttachEventBuffer (window3, buffer);
+
+ window3->SetOpacity (window3, 0xFF);
+
+ window3->GetID (window3, &id3);
+
+ pipeline = gst_pipeline_new ("pipeline");
+
+ src = gst_element_factory_make ("gnomevfssrc", "src");
+ g_object_set (src, "location", argv[1], NULL);
+ decode = gst_element_factory_make ("decodebin", "decode");
+
+ v_queue = gst_element_factory_make ("queue", "v_queue");
+ v_scale = gst_element_factory_make ("videoscale", "v_scale");
+ cs = gst_element_factory_make ("ffmpegcolorspace", "cs");
+ v_sink = gst_element_factory_make ("dfbvideosink", "v_sink");
+ g_object_set (v_sink, "surface", window_surface3, NULL);
+
+ a_queue = gst_element_factory_make ("queue", "a_queue");
+ conv = gst_element_factory_make ("audioconvert", "conv");
+ a_sink = gst_element_factory_make ("alsasink", "a_sink");
+
+ gst_bin_add_many (GST_BIN (pipeline), src, decode, NULL);
+ gst_bin_add_many (GST_BIN (pipeline), v_queue, v_scale, cs, v_sink, NULL);
+ gst_bin_add_many (GST_BIN (pipeline), a_queue, conv, a_sink, NULL);
+
+ gst_element_link (src, decode);
+ gst_element_link_many (v_queue, v_scale, cs, v_sink, NULL);
+ gst_element_link_many (a_queue, conv, a_sink, NULL);
+
+ v_pad = gst_element_get_pad (v_queue, "sink");
+ a_pad = gst_element_get_pad (a_queue, "sink");
+
+ setup_dynamic_link (decode, NULL, v_pad, NULL);
+ setup_dynamic_link (decode, NULL, a_pad, NULL);
+
+ /* We want to know when the size is defined */
+ g_signal_connect (v_pad, "notify::caps", G_CALLBACK (size_changed),
+ window3);
+
+ gst_object_unref (a_pad);
+ gst_object_unref (v_pad);
+
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+ }
+
+ window1->RequestFocus (window1);
+ window1->RaiseToTop (window1);
+
+ while (!quit) {
+ static IDirectFBWindow *active = NULL;
+ static int grabbed = 0;
+ static int startx = 0;
+ static int starty = 0;
+ static int endx = 0;
+ static int endy = 0;
+ DFBWindowEvent evt;
+
+ buffer->WaitForEventWithTimeout (buffer, 0, 10);
+
+ while (buffer->GetEvent (buffer, DFB_EVENT (&evt)) == DFB_OK) {
+ IDirectFBWindow *window;
+
+ if (evt.window_id == id1)
+ window = window1;
+ else if (evt.window_id == id3)
+ window = window3;
+ else
+ window = window2;
+
+ if (evt.type == DWET_GOTFOCUS) {
+ active = window;
+ } else if (active) {
+ switch (evt.type) {
+
+ case DWET_BUTTONDOWN:
+ if (!grabbed && evt.button == DIBI_LEFT) {
+ grabbed = 1;
+ startx = evt.cx;
+ starty = evt.cy;
+ window->GrabPointer (window);
+ }
+ break;
+
+ case DWET_BUTTONUP:
+ switch (evt.button) {
+ case DIBI_LEFT:
+ if (grabbed) {
+ window->UngrabPointer (window);
+ grabbed = 0;
+ }
+ break;
+ case DIBI_MIDDLE:
+ active->RaiseToTop (active);
+ break;
+ case DIBI_RIGHT:
+ quit = DIKS_DOWN;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case DWET_KEYDOWN:
+ if (grabbed)
+ break;
+ switch (evt.key_id) {
+ case DIKI_RIGHT:
+ active->Move (active, 1, 0);
+ break;
+ case DIKI_LEFT:
+ active->Move (active, -1, 0);
+ break;
+ case DIKI_UP:
+ active->Move (active, 0, -1);
+ break;
+ case DIKI_DOWN:
+ active->Move (active, 0, 1);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case DWET_LOSTFOCUS:
+ if (!grabbed && active == window)
+ active = NULL;
+ break;
+
+ default:
+ break;
+
+ }
+ }
+
+ switch (evt.type) {
+
+ case DWET_MOTION:
+ endx = evt.cx;
+ endy = evt.cy;
+ break;
+
+ case DWET_KEYDOWN:
+ switch (evt.key_symbol) {
+ case DIKS_ESCAPE:
+ case DIKS_SMALL_Q:
+ case DIKS_CAPITAL_Q:
+ case DIKS_BACK:
+ case DIKS_STOP:
+ quit = 1;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (video_provider)
+ window_surface2->Flip (window_surface2, NULL, 0);
+
+ if (active) {
+ if (grabbed) {
+ active->Move (active, endx - startx, endy - starty);
+ startx = endx;
+ starty = endy;
+ }
+ active->SetOpacity (active, (sin (myclock () / 300.0) * 85) + 170);
+ }
+ }
+
+ if (video_provider)
+ video_provider->Release (video_provider);
+
+ gst_element_set_state (pipeline, GST_STATE_NULL);
+
+ buffer->Release (buffer);
+ font->Release (font);
+ window_surface2->Release (window_surface2);
+ window_surface1->Release (window_surface1);
+ window_surface3->Release (window_surface3);
+ window2->Release (window2);
+ window1->Release (window1);
+ window3->Release (window3);
+ layer->Release (layer);
+ bgsurface->Release (bgsurface);
+ dfb->Release (dfb);
+
+ return 42;
+}