• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2018 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "config.h"
25 
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <time.h>
31 #include <math.h>
32 #include <cairo.h>
33 #include <sys/time.h>
34 
35 #include <linux/input.h>
36 #include <wayland-client.h>
37 #include "weston-content-protection-client-protocol.h"
38 #include "window.h"
39 #include <wayland-client-protocol.h>
40 
41 #define WIDTH 500
42 #define HEIGHT 400
43 #define FRAME_H 18
44 #define FRAME_W 5
45 #define BUTTON_WIDTH 65
46 #define BUTTON_HEIGHT 20
47 
48 enum protection_mode {
49 	RELAXED,
50 	ENFORCED
51 };
52 
53 struct protected_content_player {
54 	struct weston_content_protection *protection;
55 	struct weston_protected_surface *psurface;
56 	struct display *display;
57 	struct window *window;
58 	struct widget *widget;
59 	struct button_t *b0, *b1, *off, *enforced, *relaxed;
60 	int width, height, x, y;
61 	enum weston_protected_surface_type protection_type;
62 	enum protection_mode mode;
63 };
64 
65 struct button_t {
66 	struct window *window;
67 	struct widget *widget;
68 	struct protected_content_player *pc_player;
69 	const char *name;
70 };
71 /**
72  * An event to tell the client that there is a change in protection status
73  *
74  * This event is sent whenever there is a change in content
75  * protection. The content protection status can be ON or OFF. ON
76  * in case of the desired protection type is accepted on all
77  * connectors, and Off in case of any of the connector
78  * content-protection property is changed from "enabled"
79  */
80 static void
handle_status_changed(void * data,struct weston_protected_surface * psurface,uint32_t status)81 handle_status_changed(void *data, struct weston_protected_surface *psurface,
82 		      uint32_t status)
83 {
84 	struct protected_content_player *pc_player = data;
85 	enum weston_protected_surface_type event_status = status;
86 
87 	switch (event_status) {
88 	case WESTON_PROTECTED_SURFACE_TYPE_HDCP_0:
89 		pc_player->protection_type = WESTON_PROTECTED_SURFACE_TYPE_HDCP_0;
90 		break;
91 	case WESTON_PROTECTED_SURFACE_TYPE_HDCP_1:
92 		pc_player->protection_type = WESTON_PROTECTED_SURFACE_TYPE_HDCP_1;
93 		break;
94 	case WESTON_PROTECTED_SURFACE_TYPE_UNPROTECTED:
95 	default:
96 		pc_player->protection_type = WESTON_PROTECTED_SURFACE_TYPE_UNPROTECTED;
97 	}
98 	window_schedule_redraw(pc_player->window);
99 }
100 
101 static const struct weston_protected_surface_listener pc_player_listener = {
102 	handle_status_changed,
103 };
104 
105 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)106 draw_content(cairo_surface_t *surface, int x, int y, int width, int height,
107 	     enum weston_protected_surface_type type, enum protection_mode mode)
108 {
109 	cairo_t *cr;
110 	cairo_text_extents_t extents;
111 	const char *content_text;
112 	const char *mode_text;
113 
114 	cr = cairo_create(surface);
115 	cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
116 	cairo_rectangle(cr, x, y, width, height);
117 	if (type == WESTON_PROTECTED_SURFACE_TYPE_HDCP_0)
118 		cairo_set_source_rgba(cr, 0, 1.0, 0, 1.0);
119 	else if (type == WESTON_PROTECTED_SURFACE_TYPE_HDCP_1)
120 		cairo_set_source_rgba(cr, 0, 0, 1.0, 1.0);
121 	else
122 		cairo_set_source_rgba(cr, 1.0, 0, 0, 1.0);
123 	cairo_fill(cr);
124 
125 	cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
126 	cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
127 			       CAIRO_FONT_WEIGHT_NORMAL);
128 	cairo_set_font_size(cr, 15);
129 	if (type == WESTON_PROTECTED_SURFACE_TYPE_HDCP_0)
130 		content_text = "Content-Type : Type-0";
131 	else if (type == WESTON_PROTECTED_SURFACE_TYPE_HDCP_1)
132 		content_text = "Content-Type : Type-1";
133 	else
134 		content_text = "Content-Type : Unprotected";
135 	cairo_text_extents(cr, content_text, &extents);
136 	cairo_move_to(cr, width/2 - (extents.width/2),
137 		      height/2 - (extents.height/2));
138 	cairo_show_text(cr, content_text);
139 
140 	if (mode == ENFORCED)
141 		mode_text = "Mode : Enforced";
142 	else
143 		mode_text = "Mode : Relaxed";
144 	cairo_text_extents(cr, mode_text, &extents);
145 	cairo_move_to(cr, width / 2 - (extents.width / 2),
146 		      2 * height / 3 - (2 * extents.height / 3));
147 	cairo_show_text(cr, mode_text);
148 
149 	cairo_fill(cr);
150 	cairo_destroy(cr);
151 }
152 
153 static void
redraw_handler(struct widget * widget,void * data)154 redraw_handler(struct widget *widget, void *data)
155 {
156 	struct protected_content_player *pc_player = data;
157 	cairo_surface_t *surface;
158 	struct rectangle rect;
159 
160 	widget_get_allocation(pc_player->widget, &rect);
161 	surface = window_get_surface(pc_player->window);
162 	if (surface == NULL ||
163 			cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
164 		fprintf(stderr, "failed to create cairo egl surface\n");
165 		return;
166 	}
167 	draw_content(surface, rect.x, rect.y, rect.width, rect.height,
168 		     pc_player->protection_type, pc_player->mode);
169 	cairo_surface_destroy(surface);
170 }
171 
172 static void
resize_handler(struct widget * widget,int32_t width,int32_t height,void * data)173 resize_handler(struct widget *widget, int32_t width, int32_t height, void *data)
174 {
175 	struct rectangle allocation;
176 	struct protected_content_player *pc_player = data;
177 
178 	widget_get_allocation(pc_player->widget, &allocation);
179 	widget_set_allocation(pc_player->b0->widget,
180 			      allocation.x + 20, allocation.y + 30,
181 			      BUTTON_WIDTH, BUTTON_HEIGHT);
182 	widget_set_allocation(pc_player->b1->widget,
183 			      allocation.x + 20 + BUTTON_WIDTH + 5,
184 			      allocation.y + 30,
185 			      BUTTON_WIDTH, BUTTON_HEIGHT);
186 	widget_set_allocation(pc_player->off->widget,
187 			      allocation.x + 20 + 2 * (BUTTON_WIDTH + 5),
188 			      allocation.y + 30,
189 			      BUTTON_WIDTH, BUTTON_HEIGHT);
190 	widget_set_allocation(pc_player->enforced->widget,
191 			      allocation.x + 20 + 3 * (BUTTON_WIDTH + 5),
192 			      allocation.y + 30,
193 			      BUTTON_WIDTH, BUTTON_HEIGHT);
194 	widget_set_allocation(pc_player->relaxed->widget,
195 			      allocation.x + 20 + 4 * (BUTTON_WIDTH + 5),
196 			      allocation.y + 30,
197 			      BUTTON_WIDTH, BUTTON_HEIGHT);
198 }
199 
200 static void
buttons_handler(struct widget * widget,struct input * input,uint32_t time,uint32_t button,enum wl_pointer_button_state state,void * data)201 buttons_handler(struct widget *widget, struct input *input, uint32_t time,
202 		uint32_t button, enum wl_pointer_button_state state, void *data)
203 {
204 	struct button_t *b = data;
205 	struct protected_content_player *pc_player = b->pc_player;
206 	struct wl_surface *surface;
207 
208 	if (strcmp(b->name, "ENFORCED") == 0) {
209 		weston_protected_surface_enforce(pc_player->psurface);
210 		pc_player->mode = ENFORCED;
211 		window_schedule_redraw(pc_player->window);
212 	}
213 	else if (strcmp(b->name, "RELAXED") == 0) {
214 		weston_protected_surface_relax(pc_player->psurface);
215 		pc_player->mode = RELAXED;
216 		window_schedule_redraw(pc_player->window);
217 	}
218 	else if (strcmp(b->name, "TYPE-0") == 0)
219 		weston_protected_surface_set_type(pc_player->psurface,
220 						  WESTON_PROTECTED_SURFACE_TYPE_HDCP_0);
221 	else if (strcmp(b->name, "TYPE-1") == 0)
222 		weston_protected_surface_set_type(pc_player->psurface,
223 						  WESTON_PROTECTED_SURFACE_TYPE_HDCP_1);
224 	else
225 		weston_protected_surface_set_type(pc_player->psurface,
226 						  WESTON_PROTECTED_SURFACE_TYPE_UNPROTECTED);
227 
228 	surface = window_get_wl_surface(pc_player->window);
229 	wl_surface_commit(surface);
230 }
231 
232 static void
handle_global(struct display * display,uint32_t name,const char * interface,uint32_t version,void * data)233 handle_global(struct display *display, uint32_t name, const char *interface,
234 	      uint32_t version, void *data)
235 {
236 	struct protected_content_player *pc_player = data;
237 
238 	if (strcmp(interface, "weston_content_protection") == 0) {
239 		pc_player->protection = display_bind(display, name,
240 					   &weston_content_protection_interface,
241 					   1);
242 	}
243 }
244 
245 static void
buttons_redraw_handler(struct widget * widget,void * data)246 buttons_redraw_handler(struct widget *widget, void *data)
247 {
248 	struct button_t *b = data;
249 	cairo_surface_t *surface;
250 	struct rectangle allocation;
251 	cairo_t *cr;
252 
253 	surface = window_get_surface(b->window);
254 	widget_get_allocation(b->widget, &allocation);
255 
256 	cr = cairo_create(surface);
257 	cairo_rectangle(cr, allocation.x, allocation.y, allocation.width,
258 			allocation.height);
259 
260 	cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
261 
262 	cairo_set_source_rgba(cr, 1, 1, 1, 1);
263 	cairo_fill(cr);
264 
265 	cairo_set_source_rgba(cr, 0, 0, 0, 1.0);
266 	cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
267 			       CAIRO_FONT_WEIGHT_NORMAL);
268 	cairo_set_font_size(cr, 10);
269 	cairo_move_to(cr, allocation.x + 5, allocation.y + 15);
270 	cairo_show_text(cr, b->name);
271 	cairo_fill(cr);
272 
273 	cairo_destroy(cr);
274 	cairo_surface_destroy(surface);
275 }
276 
277 static struct button_t*
create_button(struct protected_content_player * pc_player,const char * name)278 create_button(struct protected_content_player *pc_player, const char *name)
279 {
280 	struct button_t *b;
281 
282 	b = zalloc(sizeof(struct button_t));
283 	if (b == NULL) {
284 		fprintf(stderr, "Failed to allocate memory for button.\n");
285 		exit(0);
286 	}
287 	b->widget = widget_add_widget(pc_player->widget, b);
288 	b->window = pc_player->window;
289 	b->pc_player = pc_player;
290 	b->name = name;
291 	widget_set_redraw_handler(b->widget, buttons_redraw_handler);
292 	widget_set_button_handler(b->widget, buttons_handler);
293 	return b;
294 }
295 
296 static void
destroy_button(struct button_t * b)297 destroy_button(struct button_t *b)
298 {
299 	if (!b)
300 		return;
301 	widget_destroy(b->widget);
302 	free(b);
303 }
304 
free_pc_player(struct protected_content_player * pc_player)305 static void free_pc_player(struct protected_content_player *pc_player)
306 {
307 	if (!pc_player)
308 		return;
309 
310 	destroy_button(pc_player->b0);
311 	destroy_button(pc_player->b1);
312 	destroy_button(pc_player->off);
313 	destroy_button(pc_player->enforced);
314 	destroy_button(pc_player->relaxed);
315 	widget_destroy(pc_player->widget);
316 	window_destroy(pc_player->window);
317 	free(pc_player);
318 }
319 
main(int argc,char * argv[])320 int main(int argc, char *argv[])
321 {
322 	struct protected_content_player *pc_player;
323 	struct display *d;
324 	static const char str_type_0[] = "TYPE-0";
325 	static const char str_type_1[] = "TYPE-1";
326 	static const char str_type_off[] = "OFF";
327 	static const char str_type_enforced[] = "ENFORCED";
328 	static const char str_type_relaxed[] = "RELAXED";
329 	struct wl_surface *surface;
330 
331 	pc_player = zalloc(sizeof(struct protected_content_player));
332 	if (pc_player == NULL) {
333 		fprintf(stderr, "failed to allocate memory: %m\n");
334 		return -1;
335 	}
336 	d = display_create(&argc, argv);
337 	if (d == NULL) {
338 		fprintf(stderr, "failed to create display: %m\n");
339 		return -1;
340 	}
341 	pc_player->protection_type = WESTON_PROTECTED_SURFACE_TYPE_UNPROTECTED;
342 	pc_player->mode = RELAXED;
343 	pc_player->width = WIDTH * 2.0/4.0;
344 	pc_player->height = HEIGHT * 2.0/4.0;
345 	pc_player->x = WIDTH * 1.0/4.0;
346 	pc_player->y = HEIGHT * 1.0/4.0;
347 	pc_player->window = window_create(d);
348 	pc_player->widget = window_frame_create(pc_player->window, pc_player);
349 	pc_player->display = d;
350 	display_set_user_data(d, pc_player);
351 
352 	display_set_global_handler(d, handle_global);
353 	surface = window_get_wl_surface(pc_player->window);
354 	if (pc_player->protection == NULL) {
355 		printf("The content-protection object is NULL\n");
356 		return -1;
357 	}
358 	pc_player->psurface = weston_content_protection_get_protection(pc_player->protection,
359 								       surface);
360 	weston_protected_surface_add_listener(pc_player->psurface,
361 					      &pc_player_listener,
362 					      pc_player);
363 
364 	pc_player->b0 = create_button(pc_player, str_type_0);
365 	pc_player->b1 = create_button(pc_player, str_type_1);
366 	pc_player->off = create_button(pc_player, str_type_off);
367 	pc_player->enforced = create_button(pc_player, str_type_enforced);
368 	pc_player->relaxed = create_button(pc_player, str_type_relaxed);
369 
370 	window_set_title(pc_player->window, "Player");
371 	widget_set_redraw_handler(pc_player->widget, redraw_handler);
372 	widget_set_resize_handler(pc_player->widget, resize_handler);
373 	window_schedule_resize(pc_player->window, WIDTH, HEIGHT);
374 	widget_schedule_redraw(pc_player->b0->widget);
375 	widget_schedule_redraw(pc_player->b1->widget);
376 	widget_schedule_redraw(pc_player->off->widget);
377 
378 	display_run(d);
379 	weston_protected_surface_destroy(pc_player->psurface);
380 	weston_content_protection_destroy(pc_player->protection);
381 	free_pc_player(pc_player);
382 	display_destroy(d);
383 	return 0;
384 }
385