summaryrefslogtreecommitdiff
path: root/clients/content_protection.c
diff options
context:
space:
mode:
authorAnkit Nautiyal <ankit.k.nautiyal@intel.com>2019-01-08 17:45:35 +0530
committerAnkit Nautiyal <ankit.k.nautiyal@intel.com>2019-07-05 14:13:30 +0530
commit8b40deaaaaf845c1b965c2888b1f036ef1f19d76 (patch)
tree6976081e2ae3d7e3153fd2cc70fd8cc45f0f0fc5 /clients/content_protection.c
parent62626cbfec08ac58b8419ca30566fae322b46763 (diff)
downloadweston-8b40deaaaaf845c1b965c2888b1f036ef1f19d76.tar.gz
clients: Add content-protection client app
This patch adds a client app which can be used to show the implementation of weston content-protection protocol. The app can request for Type-0 and Type-1 content or request for disabling content-protection to the content-protection server. It listens for the content-protection status change event from the server and accordingly display the required content. The content Type-0, Type-1 and unprotected contents are prepared using cairo surface, with different color and text to distinguish between the contents. Signed-off-by: Ankit Nautiyal <ankit.k.nautiyal@intel.com>
Diffstat (limited to 'clients/content_protection.c')
-rw-r--r--clients/content_protection.c384
1 files changed, 384 insertions, 0 deletions
diff --git a/clients/content_protection.c b/clients/content_protection.c
new file mode 100644
index 00000000..27e2b8a9
--- /dev/null
+++ b/clients/content_protection.c
@@ -0,0 +1,384 @@
+/*
+ * Copyright © 2018 Intel Corporation
+ *
+ * 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 (including the next
+ * paragraph) 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 "config.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include <cairo.h>
+#include <sys/time.h>
+
+#include <linux/input.h>
+#include <wayland-client.h>
+#include "weston-content-protection-client-protocol.h"
+#include "window.h"
+#include <wayland-client-protocol.h>
+
+#define WIDTH 500
+#define HEIGHT 400
+#define FRAME_H 18
+#define FRAME_W 5
+#define BUTTON_WIDTH 65
+#define BUTTON_HEIGHT 20
+
+enum protection_mode {
+ RELAXED,
+ ENFORCED
+};
+
+struct protected_content_player {
+ struct weston_content_protection *protection;
+ struct weston_protected_surface *psurface;
+ struct display *display;
+ struct window *window;
+ struct widget *widget;
+ struct button_t *b0, *b1, *off, *enforced, *relaxed;
+ int width, height, x, y;
+ enum weston_protected_surface_type protection_type;
+ enum protection_mode mode;
+};
+
+struct button_t {
+ struct window *window;
+ struct widget *widget;
+ struct protected_content_player *pc_player;
+ const char *name;
+};
+/**
+ * An event to tell the client that there is a change in protection status
+ *
+ * This event is sent whenever there is a change in content
+ * protection. The content protection status can be ON or OFF. ON
+ * in case of the desired protection type is accepted on all
+ * connectors, and Off in case of any of the connector
+ * content-protection property is changed from "enabled"
+ */
+static void
+handle_status_changed(void *data, struct weston_protected_surface *psurface,
+ uint32_t status)
+{
+ struct protected_content_player *pc_player = data;
+ enum weston_protected_surface_type event_status = status;
+
+ switch (event_status) {
+ case WESTON_PROTECTED_SURFACE_TYPE_HDCP_0:
+ pc_player->protection_type = WESTON_PROTECTED_SURFACE_TYPE_HDCP_0;
+ break;
+ case WESTON_PROTECTED_SURFACE_TYPE_HDCP_1:
+ pc_player->protection_type = WESTON_PROTECTED_SURFACE_TYPE_HDCP_1;
+ break;
+ case WESTON_PROTECTED_SURFACE_TYPE_UNPROTECTED:
+ default:
+ pc_player->protection_type = WESTON_PROTECTED_SURFACE_TYPE_UNPROTECTED;
+ }
+ window_schedule_redraw(pc_player->window);
+}
+
+static const struct weston_protected_surface_listener pc_player_listener = {
+ handle_status_changed,
+};
+
+static void
+draw_content(cairo_surface_t *surface, int x, int y, int width, int height,
+ enum weston_protected_surface_type type, enum protection_mode mode)
+{
+ cairo_t *cr;
+ cairo_text_extents_t extents;
+ const char *content_text;
+ const char *mode_text;
+
+ cr = cairo_create(surface);
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+ cairo_rectangle(cr, x, y, width, height);
+ if (type == WESTON_PROTECTED_SURFACE_TYPE_HDCP_0)
+ cairo_set_source_rgba(cr, 0, 1.0, 0, 1.0);
+ else if (type == WESTON_PROTECTED_SURFACE_TYPE_HDCP_1)
+ cairo_set_source_rgba(cr, 0, 0, 1.0, 1.0);
+ else
+ cairo_set_source_rgba(cr, 1.0, 0, 0, 1.0);
+ cairo_fill(cr);
+
+ cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
+ cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font_size(cr, 15);
+ if (type == WESTON_PROTECTED_SURFACE_TYPE_HDCP_0)
+ content_text = "Content-Type : Type-0";
+ else if (type == WESTON_PROTECTED_SURFACE_TYPE_HDCP_1)
+ content_text = "Content-Type : Type-1";
+ else
+ content_text = "Content-Type : Unprotected";
+ cairo_text_extents(cr, content_text, &extents);
+ cairo_move_to(cr, width/2 - (extents.width/2),
+ height/2 - (extents.height/2));
+ cairo_show_text(cr, content_text);
+
+ if (mode == ENFORCED)
+ mode_text = "Mode : Enforced";
+ else
+ mode_text = "Mode : Relaxed";
+ cairo_text_extents(cr, mode_text, &extents);
+ cairo_move_to(cr, width / 2 - (extents.width / 2),
+ 2 * height / 3 - (2 * extents.height / 3));
+ cairo_show_text(cr, mode_text);
+
+ cairo_fill(cr);
+ cairo_destroy(cr);
+}
+
+static void
+redraw_handler(struct widget *widget, void *data)
+{
+ struct protected_content_player *pc_player = data;
+ cairo_surface_t *surface;
+ struct rectangle rect;
+
+ widget_get_allocation(pc_player->widget, &rect);
+ surface = window_get_surface(pc_player->window);
+ if (surface == NULL ||
+ cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
+ fprintf(stderr, "failed to create cairo egl surface\n");
+ return;
+ }
+ draw_content(surface, rect.x, rect.y, rect.width, rect.height,
+ pc_player->protection_type, pc_player->mode);
+ cairo_surface_destroy(surface);
+}
+
+static void
+resize_handler(struct widget *widget, int32_t width, int32_t height, void *data)
+{
+ struct rectangle allocation;
+ struct protected_content_player *pc_player = data;
+
+ widget_get_allocation(pc_player->widget, &allocation);
+ widget_set_allocation(pc_player->b0->widget,
+ allocation.x + 20, allocation.y + 30,
+ BUTTON_WIDTH, BUTTON_HEIGHT);
+ widget_set_allocation(pc_player->b1->widget,
+ allocation.x + 20 + BUTTON_WIDTH + 5,
+ allocation.y + 30,
+ BUTTON_WIDTH, BUTTON_HEIGHT);
+ widget_set_allocation(pc_player->off->widget,
+ allocation.x + 20 + 2 * (BUTTON_WIDTH + 5),
+ allocation.y + 30,
+ BUTTON_WIDTH, BUTTON_HEIGHT);
+ widget_set_allocation(pc_player->enforced->widget,
+ allocation.x + 20 + 3 * (BUTTON_WIDTH + 5),
+ allocation.y + 30,
+ BUTTON_WIDTH, BUTTON_HEIGHT);
+ widget_set_allocation(pc_player->relaxed->widget,
+ allocation.x + 20 + 4 * (BUTTON_WIDTH + 5),
+ allocation.y + 30,
+ BUTTON_WIDTH, BUTTON_HEIGHT);
+}
+
+static void
+buttons_handler(struct widget *widget, struct input *input, uint32_t time,
+ uint32_t button, enum wl_pointer_button_state state, void *data)
+{
+ struct button_t *b = data;
+ struct protected_content_player *pc_player = b->pc_player;
+ struct wl_surface *surface;
+
+ if (strcmp(b->name, "ENFORCED") == 0) {
+ weston_protected_surface_enforce(pc_player->psurface);
+ pc_player->mode = ENFORCED;
+ window_schedule_redraw(pc_player->window);
+ }
+ else if (strcmp(b->name, "RELAXED") == 0) {
+ weston_protected_surface_relax(pc_player->psurface);
+ pc_player->mode = RELAXED;
+ window_schedule_redraw(pc_player->window);
+ }
+ else if (strcmp(b->name, "TYPE-0") == 0)
+ weston_protected_surface_set_type(pc_player->psurface,
+ WESTON_PROTECTED_SURFACE_TYPE_HDCP_0);
+ else if (strcmp(b->name, "TYPE-1") == 0)
+ weston_protected_surface_set_type(pc_player->psurface,
+ WESTON_PROTECTED_SURFACE_TYPE_HDCP_1);
+ else
+ weston_protected_surface_set_type(pc_player->psurface,
+ WESTON_PROTECTED_SURFACE_TYPE_UNPROTECTED);
+
+ surface = window_get_wl_surface(pc_player->window);
+ wl_surface_commit(surface);
+}
+
+static void
+handle_global(struct display *display, uint32_t name, const char *interface,
+ uint32_t version, void *data)
+{
+ struct protected_content_player *pc_player = data;
+
+ if (strcmp(interface, "weston_content_protection") == 0) {
+ pc_player->protection = display_bind(display, name,
+ &weston_content_protection_interface,
+ 1);
+ }
+}
+
+static void
+buttons_redraw_handler(struct widget *widget, void *data)
+{
+ struct button_t *b = data;
+ cairo_surface_t *surface;
+ struct rectangle allocation;
+ cairo_t *cr;
+
+ surface = window_get_surface(b->window);
+ widget_get_allocation(b->widget, &allocation);
+
+ cr = cairo_create(surface);
+ cairo_rectangle(cr, allocation.x, allocation.y, allocation.width,
+ allocation.height);
+
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+
+ cairo_set_source_rgba(cr, 1, 1, 1, 1);
+ cairo_fill(cr);
+
+ cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
+ cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
+ CAIRO_FONT_WEIGHT_NORMAL);
+ cairo_set_font_size(cr, 10);
+ cairo_move_to(cr, allocation.x + 5, allocation.y + 15);
+ cairo_show_text(cr, b->name);
+ cairo_fill(cr);
+
+ cairo_destroy(cr);
+ cairo_surface_destroy(surface);
+}
+
+static struct button_t*
+create_button(struct protected_content_player *pc_player, const char *name)
+{
+ struct button_t *b;
+
+ b = zalloc(sizeof(struct button_t));
+ if (b == NULL) {
+ fprintf(stderr, "Failed to allocate memory for button.\n");
+ exit(0);
+ }
+ b->widget = widget_add_widget(pc_player->widget, b);
+ b->window = pc_player->window;
+ b->pc_player = pc_player;
+ b->name = name;
+ widget_set_redraw_handler(b->widget, buttons_redraw_handler);
+ widget_set_button_handler(b->widget, buttons_handler);
+ return b;
+}
+
+static void
+destroy_button(struct button_t *b)
+{
+ if (!b)
+ return;
+ widget_destroy(b->widget);
+ free(b);
+}
+
+static void free_pc_player(struct protected_content_player *pc_player)
+{
+ if (!pc_player)
+ return;
+
+ destroy_button(pc_player->b0);
+ destroy_button(pc_player->b1);
+ destroy_button(pc_player->off);
+ destroy_button(pc_player->enforced);
+ destroy_button(pc_player->relaxed);
+ widget_destroy(pc_player->widget);
+ window_destroy(pc_player->window);
+ free(pc_player);
+}
+
+int main(int argc, char *argv[])
+{
+ struct protected_content_player *pc_player;
+ struct display *d;
+ static const char str_type_0[] = "TYPE-0";
+ static const char str_type_1[] = "TYPE-1";
+ static const char str_type_off[] = "OFF";
+ static const char str_type_enforced[] = "ENFORCED";
+ static const char str_type_relaxed[] = "RELAXED";
+ struct wl_surface *surface;
+
+ pc_player = zalloc(sizeof(struct protected_content_player));
+ if (pc_player == NULL) {
+ fprintf(stderr, "failed to allocate memory: %m\n");
+ return -1;
+ }
+ d = display_create(&argc, argv);
+ if (d == NULL) {
+ fprintf(stderr, "failed to create display: %m\n");
+ return -1;
+ }
+ pc_player->protection_type = WESTON_PROTECTED_SURFACE_TYPE_UNPROTECTED;
+ pc_player->mode = RELAXED;
+ pc_player->width = WIDTH * 2.0/4.0;
+ pc_player->height = HEIGHT * 2.0/4.0;
+ pc_player->x = WIDTH * 1.0/4.0;
+ pc_player->y = HEIGHT * 1.0/4.0;
+ pc_player->window = window_create(d);
+ pc_player->widget = window_frame_create(pc_player->window, pc_player);
+ pc_player->display = d;
+ display_set_user_data(d, pc_player);
+
+ display_set_global_handler(d, handle_global);
+ surface = window_get_wl_surface(pc_player->window);
+ if (pc_player->protection == NULL) {
+ printf("The content-protection object is NULL\n");
+ return -1;
+ }
+ pc_player->psurface = weston_content_protection_get_protection(pc_player->protection,
+ surface);
+ weston_protected_surface_add_listener(pc_player->psurface,
+ &pc_player_listener,
+ pc_player);
+
+ pc_player->b0 = create_button(pc_player, str_type_0);
+ pc_player->b1 = create_button(pc_player, str_type_1);
+ pc_player->off = create_button(pc_player, str_type_off);
+ pc_player->enforced = create_button(pc_player, str_type_enforced);
+ pc_player->relaxed = create_button(pc_player, str_type_relaxed);
+
+ window_set_title(pc_player->window, "Player");
+ widget_set_redraw_handler(pc_player->widget, redraw_handler);
+ widget_set_resize_handler(pc_player->widget, resize_handler);
+ window_schedule_resize(pc_player->window, WIDTH, HEIGHT);
+ widget_schedule_redraw(pc_player->b0->widget);
+ widget_schedule_redraw(pc_player->b1->widget);
+ widget_schedule_redraw(pc_player->off->widget);
+
+ display_run(d);
+ weston_protected_surface_destroy(pc_player->psurface);
+ weston_content_protection_destroy(pc_player->protection);
+ free_pc_player(pc_player);
+ display_destroy(d);
+ return 0;
+}