fullscreen-renderer.c 6.6 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 * Copyright (C) 2012 Openismus GmbH.
 *
 * Author: Jens Georg <jensg@openismus.com>
 *
 * This file is part of Rygel.
 *
 * Rygel is free software; you can redistribute it and/or modify
9 10 11
 * it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
12 13 14
 *
 * Rygel is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
17
 *
18 19 20
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21 22 23 24 25 26 27 28 29
 */

/*
 * Demo application for librygel-renderer-gst.
 *
 * Creates a simple stand-alone UPnP renderer that renders any visual content
 * fullscreen.
 *
 * Usage:
Jens Georg's avatar
Jens Georg committed
30
 *   fullscreen-renderer [<network device>]
31 32 33 34 35 36 37 38 39
 *
 * If no network device is given on the commandline, the program falls back to
 * eth0.
 *
 * To do anything useful, another UPnP server + UPnP controller is necessary
 * to tell it which media file to show.
 */

#include <gst/video/videooverlay.h>
40
#include <gdk/gdkkeysyms.h>
41 42
#include <gtk/gtk.h>

43 44 45 46 47 48 49
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
#ifdef GDK_WINDOWING_WAYLAND
#include <gdk/gdkwayland.h>
#endif

50 51 52
#include "rygel-renderer-gst.h"
#include "rygel-core.h"

53 54
#define LOGO_PATH "/org/gnome/Rygel/FullscreenRenderer/rygel-full.svg"

55 56
struct _MainData {
    GtkWindow *window;
57
    GtkWidget *video;
58
    GstElement *playbin;
59 60 61
    GdkPixbuf *pixbuf;
    gint logo_width;
    gint logo_height;
62 63 64 65 66 67 68 69 70 71 72 73 74
};
typedef struct _MainData MainData;

static void on_realize (GtkWidget *widget, gpointer user_data)
{
    GdkWindow *window;
    guintptr window_handle;
    MainData *data = (MainData *) user_data;

    window = gtk_widget_get_window (widget);
    if (!gdk_window_ensure_native (window))
        g_error ("Could not create native window for overlay");

75
#ifdef GDK_WINDOWING_WAYLAND
76
    if (GDK_IS_WAYLAND_WINDOW (window)) {
77
        window_handle = (guintptr) gdk_wayland_window_get_wl_surface (window);
78 79 80 81
    } else
#endif
#ifdef GDK_WINDOWING_X11
    if (GDK_IS_X11_WINDOW (window)) {
82
        window_handle = (guintptr) GDK_WINDOW_XID (window);
83 84 85
    } else
#endif
    {
86 87 88
        g_error ("Unsupported windowing system");
    }

89 90 91 92
    gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (data->playbin),
                                         window_handle);
}

Jens Georg's avatar
Jens Georg committed
93 94 95 96 97 98 99 100
static gboolean on_draw (GtkWidget *widget, cairo_t *cr, gpointer user_data)
{
    MainData *data = (MainData *) user_data;
    GstState state;

    gst_element_get_state (data->playbin, &state, NULL, GST_CLOCK_TIME_NONE);

    if (state < GST_STATE_PAUSED) {
101
        gint width, height, logo_x, logo_y;
Jens Georg's avatar
Jens Georg committed
102 103 104 105 106 107 108

        width = gtk_widget_get_allocated_width (widget);
        height = gtk_widget_get_allocated_height (widget);

        cairo_set_source_rgb (cr, 0, 0, 0);
        cairo_rectangle (cr, 0, 0, width, height);
        cairo_fill (cr);
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127

        if (data->pixbuf == NULL) {
            data->pixbuf = gdk_pixbuf_new_from_resource_at_scale
                                        (LOGO_PATH,
                                         (int) width * 0.6,
                                         (int) height * 0.6,
                                         TRUE,
                                         NULL);
            data->logo_width = gdk_pixbuf_get_width (data->pixbuf);
            data->logo_height = gdk_pixbuf_get_height (data->pixbuf);
        }


        logo_x = (width - data->logo_width) / 2;
        logo_y = (height - data->logo_height) / 2;

        gdk_cairo_set_source_pixbuf (cr, data->pixbuf, logo_x, logo_y);

        cairo_paint (cr);
Jens Georg's avatar
Jens Georg committed
128
    }
129 130

    return TRUE;
Jens Georg's avatar
Jens Georg committed
131 132
}

133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
static void toggle_play_pause (GstElement *element)
{
    GstStateChangeReturn ret;
    GstState current = GST_STATE_NULL, pending = GST_STATE_NULL;

    ret = gst_element_get_state (element, &current, &pending, GST_CLOCK_TIME_NONE);

    if (ret != GST_STATE_CHANGE_SUCCESS)
        return;

    if (current == GST_STATE_PAUSED) {
        gst_element_set_state (element, GST_STATE_PLAYING);
    }

    if (current == GST_STATE_PLAYING)  {
        gst_element_set_state (element, GST_STATE_PAUSED);
    }
}

152
static gboolean on_key_released (GtkWidget *widget,
153 154
                                 GdkEvent *event,
                                 gpointer user_data)
155 156
{
    GdkEventKey *key_event = (GdkEventKey *) event;
157
    MainData *data = (MainData *) user_data;
158 159

    switch (key_event->keyval) {
160 161 162 163
        case GDK_KEY_space:
            toggle_play_pause (data->playbin);

            return FALSE;
164 165 166 167 168 169 170 171 172 173 174
        case GDK_KEY_Escape:
        case GDK_KEY_q:
        case GDK_KEY_Q:
            gtk_main_quit ();

            return TRUE;
        default:
            return FALSE;
    }
}

175 176 177
int main (int argc, char *argv[])
{
    RygelPlaybinRenderer *renderer;
178
    MainData data  = { 0 };
Jens Georg's avatar
Jens Georg committed
179
    GdkCursor *cursor;
180 181 182 183 184 185

    gtk_init (&argc, &argv);
    gst_init (&argc, &argv);

    g_set_application_name ("Rygel-Fullscreen-Renderer");

186
    renderer = rygel_playbin_renderer_new ("Rygel Fullscreen renderer demo");
187 188
    data.playbin = rygel_playbin_renderer_get_playbin (renderer);

189
    data.window = GTK_WINDOW (gtk_window_new (GTK_WINDOW_TOPLEVEL));
190 191 192
    data.video = gtk_drawing_area_new ();
    gtk_container_add (GTK_CONTAINER (data.window), data.video);
    g_signal_connect (data.video, "realize", G_CALLBACK (on_realize), &data);
193 194 195 196
    gtk_widget_add_events (data.video,
                           GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK);
    gtk_widget_set_can_focus (data.video, TRUE);
    gtk_widget_grab_focus (data.video);
Jens Georg's avatar
Jens Georg committed
197 198 199 200
    g_signal_connect (data.video,
                      "draw",
                      G_CALLBACK (on_draw),
                      &data);
201 202 203 204
    g_signal_connect (data.video,
                      "key-release-event",
                      G_CALLBACK (on_key_released),
                      &data);
205
    gtk_window_fullscreen (data.window);
206
    gtk_widget_show_all (GTK_WIDGET (data.window));
Jens Georg's avatar
Jens Georg committed
207 208 209
    cursor = gdk_cursor_new_for_display (gtk_widget_get_display (data.video),
                                         GDK_BLANK_CURSOR);
    gdk_window_set_cursor (gtk_widget_get_window (data.video), cursor);
210 211 212 213 214 215 216 217

    if (argc >= 2) {
        rygel_media_device_add_interface (RYGEL_MEDIA_DEVICE (renderer), argv[1]);
    } else {
        rygel_media_device_add_interface (RYGEL_MEDIA_DEVICE (renderer), "eth0");
    }

    gtk_main ();
218
    gtk_widget_hide (GTK_WIDGET (data.window));
219
    g_object_unref (renderer);
220 221 222

    return 0;
}