test
[apps/homescreen.git] / src / gst-wayland-demo.cpp
1 /*
2  * Copyright (C) 2016 Renesas Electronics Corporation
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 #include <gst/gst.h>
21
22 #include <gst/video/video.h>
23 #include <gst/video/videooverlay.h>
24
25 #include <gst/wayland/wayland.h>
26
27 #include <glib-unix.h>
28
29 #include <wayland-client.h>
30
31 #include <linux/input.h>
32
33 #include <sys/types.h>
34 #include <sys/mman.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <string>
40 #include <thread>
41
42 #define INFINITE_LOOP_PLAYBACK          -1
43 #define USE_AGL
44 #define USE_SDL
45
46 #ifdef USE_AGL
47 #include "gst-wayland-demo.hpp"
48 #endif
49
50 #ifdef USE_SDL
51 #include <libwebsockets.h>
52 #include <pthread.h>
53 #include <sys/syscall.h>
54 #include <stdbool.h>
55 #include <ctype.h>
56
57 #include "parson.h"
58
59 #include <math.h>
60 #include <errno.h>
61
62 // Can受信.
63 #include <signal.h>
64 #include <time.h>
65 #include <sys/time.h>
66 #include <sys/socket.h>
67 #include <sys/ioctl.h>
68 #include <sys/uio.h>
69 #include <net/if.h>
70 #include <linux/can.h>
71 #include <linux/can/raw.h>
72 #include <stdint.h>
73 #include <unistd.h>
74
75 #include <libgen.h>
76
77 extern "C" {
78   void websocket_init();
79   void lws_touch_handle_down(uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w);
80   void lws_touch_handle_up(uint32_t time, int32_t id);
81   void lws_touch_handle_motion(uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w);
82 }
83 #endif
84
85 typedef struct
86 {
87   GMainLoop *loop;
88   GSource *source;
89   GstElement *pipeline;
90
91   gint fullscreen;
92   gboolean nloop;
93
94   struct wl_display *display;
95   struct wl_event_queue *queue;
96   struct wl_registry *registry;
97   struct wl_compositor *compositor;
98   struct wl_shell *shell;
99   struct wl_shm *shm;
100   struct wl_seat *seat;
101   struct wl_pointer *pointer;
102   struct wl_touch *touch;
103   GList *surfaces;
104   GList *shell_surfaces;
105   GList *outputs;
106
107   struct wl_surface *focused_surface;
108   gint min_refresh;
109   gint64 frame_cnt;
110
111   guint signal_watch_id;
112 } GstWlDemo;
113
114 #ifdef USE_AGL
115 void fatal(const char* format, ...)
116 {
117   va_list va_args;
118   va_start(va_args, format);
119   vfprintf(stderr, format, va_args);
120   va_end(va_args);
121
122   exit(EXIT_FAILURE);
123 }
124
125 void warn(const char* format, ...)
126 {
127   va_list va_args;
128   va_start(va_args, format);
129   vfprintf(stderr, format, va_args);
130   va_end(va_args);
131 }
132
133 void debug(const char* format, ...)
134 {
135   va_list va_args;
136   va_start(va_args, format);
137   vfprintf(stderr, format, va_args);
138   va_end(va_args);
139 }
140
141 static void event_loop_run(struct sd_event* loop){
142         sd_event_loop(loop);
143         sd_event_unref(loop);
144 }
145
146 /**
147  * websocket
148  */
149
150 static void _on_hangup_static(void *closure, struct afb_wsj1 *wsj)
151 {
152 }
153
154 static void _on_call_static(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg)
155 {
156 }
157
158 static void _on_event_static(void* closure, const char* event, struct afb_wsj1_msg *msg)
159 {
160         static_cast<RunXDG*>(closure)->on_event(NULL,event,msg);
161 }
162
163 static void _on_reply_static(void *closure, struct afb_wsj1_msg *msg)
164 {
165   AGL_DEBUG("_on_reply_static msg: (%s)", afb_wsj1_msg_object_s(msg));
166 }
167
168 void RunXDG::notify_ivi_control_cb (ilmObjectType object, t_ilm_uint id,
169                                     t_ilm_bool created)
170 {
171   if (object == ILM_SURFACE) {
172     struct ilmSurfaceProperties surf_props;
173
174     ilm_getPropertiesOfSurface(id, &surf_props);
175     pid_t surf_pid = surf_props.creatorPid;
176     if (!created) {
177       fprintf(stderr, "ivi surface (id=%d, pid=%d) destroyed. \n", id, surf_pid);
178       return;
179     }
180
181     fprintf(stderr, "ivi surface (id=%d, pid=%d) is created. \n", id, surf_pid);
182     if (surf_pid == m_pid)
183     {
184       m_ivi_id = id;
185       setup_ivi_surface();
186     }
187   }
188   else{
189     fprintf(stderr, "ivi surface is not created. \n");
190   }
191 }
192
193 void RunXDG::notify_ivi_control_cb_static (ilmObjectType object, t_ilm_uint id,
194                                            t_ilm_bool created, void *user_data)
195 {
196   fprintf(stderr, "notify_ivi_control_cb_static called. \n");
197   RunXDG *runxdg = static_cast<RunXDG*>(user_data);
198   runxdg->notify_ivi_control_cb(object, id, created);
199 }
200
201 int RunXDG::init_wm (void)
202 {
203   m_wm = new LibWindowmanager();
204   if (m_wm->init(m_port, m_token.c_str())) {
205     AGL_DEBUG("cannot initialize windowmanager");
206     return -1;
207   }
208
209   std::function< void(json_object*) > h_active = [this](json_object* object) {
210     AGL_DEBUG("Got Event_Active");
211     t_ilm_surface s_ids[1] = { this->m_ivi_id };
212     ilm_setInputFocus(s_ids, 1, ILM_INPUT_DEVICE_KEYBOARD, ILM_TRUE);
213   };
214
215   std::function< void(json_object*) > h_inactive = [this](json_object* object) {
216     AGL_DEBUG("Got Event_Inactive");
217     t_ilm_surface s_ids[1] = { this->m_ivi_id };
218     ilm_setInputFocus(s_ids, 1, ILM_INPUT_DEVICE_KEYBOARD, ILM_FALSE);
219   };
220
221   std::function< void(json_object*) > h_visible = [](json_object* object) {
222     AGL_DEBUG("Got Event_Visible");
223   };
224
225   std::function< void(json_object*) > h_invisible = [](json_object* object) {
226     AGL_DEBUG("Got Event_Invisible");
227   };
228
229   std::function< void(json_object*) > h_syncdraw =
230       [this](json_object* object) {
231     AGL_DEBUG("Got Event_SyncDraw");
232     this->m_wm->endDraw(this->m_role.c_str());
233   };
234
235   std::function< void(json_object*) > h_flushdraw= [](json_object* object) {
236     AGL_DEBUG("Got Event_FlushDraw");
237   };
238
239   m_wm->set_event_handler(LibWindowmanager::Event_Active, h_active);
240   m_wm->set_event_handler(LibWindowmanager::Event_Inactive, h_inactive);
241   m_wm->set_event_handler(LibWindowmanager::Event_Visible, h_visible);
242   m_wm->set_event_handler(LibWindowmanager::Event_Invisible, h_invisible);
243   m_wm->set_event_handler(LibWindowmanager::Event_SyncDraw, h_syncdraw);
244   m_wm->set_event_handler(LibWindowmanager::Event_FlushDraw, h_flushdraw);
245
246   return 0;
247 }
248
249 int RunXDG::init_hs (void)
250 {
251   m_hs = new LibHomeScreen();
252   if (m_hs->init(m_port, m_token.c_str())) {
253     AGL_DEBUG("cannot initialize homescreen");
254     return -1;
255   }
256
257   std::function< void(json_object*) > handler = [this] (json_object* object) {
258     AGL_DEBUG("Activesurface %s ", this->m_role.c_str());
259     this->m_wm->activateWindow(this->m_role.c_str(), "normal.full");
260   };
261   m_hs->set_event_handler(LibHomeScreen::Event_ShowWindow, handler);
262
263   std::function< void(json_object*) > h_default= [](json_object* object) {
264     const char *j_str = json_object_to_json_string(object);
265     AGL_DEBUG("Got event [%s]", j_str);
266   };
267   m_hs->set_event_handler(LibHomeScreen::Event_OnScreenMessage, h_default);
268
269   return 0;
270 }
271
272 int RunXDG::init_carlaclient(void)
273 {
274   memset(&m_carla_info, 0, sizeof(struct Carla_Info));
275   int ret = sd_event_new(&mploop);
276         if(ret < 0)
277         {
278                 AGL_DEBUG("Failed to create event loop");
279                 return -1;
280         }
281
282         {
283                 // enforce context to avoid initialization/goto error
284                 std::thread th(event_loop_run, mploop);
285                 th.detach();
286         }
287
288         /* Initialize interface from websocket */
289         minterface.on_hangup = _on_hangup_static;
290         minterface.on_call = _on_call_static;
291         minterface.on_event = _on_event_static;
292         muri += "ws://localhost:" + std::to_string(m_port) + "/api?token=" + m_token; /*To be modified*/
293         sp_websock = afb_ws_client_connect_wsj1(mploop, muri.c_str(), &minterface, this);
294         if(sp_websock == NULL) {
295                 AGL_DEBUG("Failed to create websocket connection");
296                 return -1;
297         }
298
299   struct json_object* j_obj = json_object_new_object();
300         json_object_object_add(j_obj, "event", json_object_new_int(0));
301
302         ret = afb_wsj1_call_j(sp_websock, "carlaclient", "subscribe", j_obj, _on_reply_static, this);
303         if (ret < 0) {
304                 AGL_DEBUG("Failed to call carlaclient subscribe verb");
305         }
306
307   struct json_object* speed_obj = json_object_new_object();
308         json_object_object_add(speed_obj, "event", json_object_new_string("vehicle.average.speed"));
309
310         ret = afb_wsj1_call_j(sp_websock, "low-can", "subscribe", speed_obj, _on_reply_static, this);
311         if (ret < 0) {
312                 AGL_DEBUG("Failed to call low-can subscribe verb");
313         }
314
315   return 0;
316 }
317
318 void RunXDG::on_event(void *closure, const char *event, struct afb_wsj1_msg *msg)
319 {
320   AGL_DEBUG("event: (%s) msg: (%s).", event, afb_wsj1_msg_object_s(msg));
321   struct json_object* ev_contents = afb_wsj1_msg_object_j(msg);
322   if(!strcasecmp(event, "carlaclient/positionUpdated")) {
323     struct json_object *json_data;
324     if(!json_object_object_get_ex(ev_contents, "data", &json_data)) {
325                   AGL_DEBUG("got ev_contents error.");
326                   return;
327           }
328
329     struct json_object *longitude_obj, *latitude_obj, *yaw_obj;
330     if(json_object_object_get_ex(json_data, "longitude", &longitude_obj)
331     && json_object_object_get_ex(json_data, "latitude", &latitude_obj)
332     && json_object_object_get_ex(json_data, "yaw", &yaw_obj)) {
333       AGL_DEBUG("got yaw(%s) longitude(%s) latitude(%s).", json_object_get_string(yaw_obj), json_object_get_string(longitude_obj), json_object_get_string(latitude_obj));
334       m_carla_info.yaw = json_object_get_string(yaw_obj);
335       std::string::size_type sz; 
336       m_carla_info.longitude = std::stod(json_object_get_string(longitude_obj), &sz);
337       m_carla_info.latitude = std::stod(json_object_get_string(latitude_obj), &sz);
338       // TBD: call sdl interface
339     }
340   }
341   else if(!strcasecmp(event, "low-can/messages.vehicle.average.speed")) {
342     // [5,"low-can/messages.vehicle.average.speed",{"event":"low-can\/messages.vehicle.average.speed","data":{"value":10},"jtype":"afb-event"}]
343     
344     if(json_object_get_type(ev_contents) ==  json_type_array) {
345         int array_len = json_object_array_length(ev_contents);
346         struct json_object *event_obj = json_object_array_get_idx(ev_contents, 2);
347         struct json_object *data_obj, *val_obj;
348         if(json_object_object_get_ex(event_obj, "data", &data_obj)
349         &&json_object_object_get_ex(data_obj, "value", &val_obj)) {
350           m_carla_info.speed = json_object_get_int(val_obj);
351         }
352     }
353   }
354 }
355
356 RunXDG::RunXDG (int port, const char* token, const char* id)
357 {
358   m_id = std::string(id);
359   m_port = port;
360   m_token = std::string(token);
361   m_role = "gstwayland";
362   m_pid = getpid();
363
364   // Setup HomeScreen/WindowManager API
365   if (init_wm())
366     AGL_FATAL("cannot setup wm API");
367
368   if (init_hs())
369     AGL_FATAL("cannot setup hs API");
370
371   if (init_carlaclient())
372     AGL_FATAL("cannot setup carlaclient API");
373
374   // Setup ilmController API
375   m_ic = new ILMControl(notify_ivi_control_cb_static, this);
376   
377   fprintf(stderr, "RunXDG created. \n");
378 }
379
380 void RunXDG::setup_ivi_surface (void)
381 {
382   std::string sid = std::to_string(m_ivi_id);
383
384   // This surface is mine, register pair app_name and ivi id.
385   AGL_DEBUG("requestSurfaceXDG(%s,%d)", m_role.c_str(), m_ivi_id);
386   m_wm->requestSurfaceXDG(this->m_role.c_str(), (unsigned int)m_ivi_id);
387
388   if (m_pending_create) {
389     // Recovering 1st time tap_shortcut is dropped because
390     // the application has not been run yet (1st time launch)
391     m_pending_create = false;
392     // m_wm->activateWindow(this->m_role.c_str(), "normal.full");
393     m_hs->publishSubscription();
394   }
395 }
396
397 void RunXDG::start (void)
398 {
399   // take care 1st time launch
400   AGL_DEBUG("waiting for notification: surafce created");
401   m_pending_create = true;
402
403   ilm_commitChanges();
404 }
405 #endif
406
407 static void
408 pointer_handle_enter (void *data, struct wl_pointer *pointer,
409     uint32_t serial, struct wl_surface *surface, wl_fixed_t sx, wl_fixed_t sy)
410 {
411   fprintf(stderr, "%s called. \n", __func__);
412   // GstWlDemo *priv = data;
413
414   // priv->focused_surface = surface;
415 }
416
417 static void
418 pointer_handle_leave (void *data, struct wl_pointer *pointer,
419     uint32_t serial, struct wl_surface *surface)
420 {
421   fprintf(stderr, "%s called. \n", __func__);
422   // GstWlDemo *priv = data;
423
424   // priv->focused_surface = NULL;
425 }
426
427 static void
428 pointer_handle_motion (void *data, struct wl_pointer *pointer,
429     uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
430 {
431   fprintf(stderr, "%s called. \n", __func__);
432 }
433
434 static void
435 pointer_handle_button (void *data, struct wl_pointer *wl_pointer,
436     uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
437 {
438   fprintf(stderr, "%s called. \n", __func__);
439   // GstWlDemo *priv = data;
440   // struct wl_shell_surface *shell_surface;
441
442   // if (!priv->focused_surface)
443   //   return;
444
445   // shell_surface = wl_surface_get_user_data (priv->focused_surface);
446
447   // if (button == BTN_LEFT && state == WL_POINTER_BUTTON_STATE_PRESSED)
448   //   wl_shell_surface_move (shell_surface, priv->seat, serial);
449 }
450
451 static void
452 pointer_handle_axis (void *data, struct wl_pointer *wl_pointer,
453     uint32_t time, uint32_t axis, wl_fixed_t value)
454 {
455   fprintf(stderr, "%s called. \n", __func__);
456 }
457
458 static const struct wl_pointer_listener pointer_listener = {
459   pointer_handle_enter,
460   pointer_handle_leave,
461   pointer_handle_motion,
462   pointer_handle_button,
463   pointer_handle_axis,
464 };
465
466 static void
467 touch_handle_down (void *data, struct wl_touch *wl_touch,
468     uint32_t serial, uint32_t time, struct wl_surface *surface,
469     int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
470 {
471   fprintf(stderr, "%s called. \n", __func__);
472   if( data ) {
473     double cx = wl_fixed_to_double(x_w);
474     double cy = wl_fixed_to_double(y_w);
475     fprintf(stderr, "log: %s: cx=%f cy=%f", __func__, cx, cy);
476   }
477   // GstWlDemo *priv = data;
478   // struct wl_shell_surface *shell_surface;
479
480   // shell_surface = wl_surface_get_user_data (surface);
481
482   // wl_shell_surface_move (shell_surface, priv->seat, serial);
483   lws_touch_handle_down(time, id, x_w, y_w);
484 }
485
486 static void
487 touch_handle_up (void *data, struct wl_touch *wl_touch,
488     uint32_t serial, uint32_t time, int32_t id)
489 {
490   fprintf(stderr, "%s called. \n", __func__);
491   lws_touch_handle_up(time, id);
492 }
493
494 static void
495 touch_handle_motion (void *data, struct wl_touch *wl_touch,
496     uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
497 {
498   fprintf(stderr, "%s called. \n", __func__);
499   lws_touch_handle_motion(time, id, x_w, y_w);
500 }
501
502 static void
503 touch_handle_frame (void *data, struct wl_touch *wl_touch)
504 {
505   fprintf(stderr, "%s called. \n", __func__);
506 }
507
508 static void
509 touch_handle_cancel (void *data, struct wl_touch *wl_touch)
510 {
511   fprintf(stderr, "%s called. \n", __func__);
512 }
513
514 static const struct wl_touch_listener touch_listener = {
515   touch_handle_down,
516   touch_handle_up,
517   touch_handle_motion,
518   touch_handle_frame,
519   touch_handle_cancel,
520 };
521
522 static void
523 seat_handle_capabilities (void *data, struct wl_seat *seat,
524     enum wl_seat_capability caps)
525 {
526   GstWlDemo *priv = data;
527
528   if ((caps & WL_SEAT_CAPABILITY_POINTER) && !priv->pointer) {
529     priv->pointer = wl_seat_get_pointer (seat);
530     wl_proxy_set_queue ((struct wl_proxy *) priv->pointer, priv->queue);
531     wl_pointer_add_listener (priv->pointer, &pointer_listener, priv);
532   } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && priv->pointer) {
533     wl_pointer_destroy (priv->pointer);
534     priv->pointer = NULL;
535   }
536
537   if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !priv->touch) {
538     priv->touch = wl_seat_get_touch (seat);
539     wl_touch_set_user_data (priv->touch, priv);
540     wl_proxy_set_queue ((struct wl_proxy *) priv->touch, priv->queue);
541     wl_touch_add_listener (priv->touch, &touch_listener, priv);
542   } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && priv->touch) {
543     wl_touch_destroy (priv->touch);
544     priv->touch = NULL;
545   }
546 }
547
548 static const struct wl_seat_listener seat_listener = {
549   seat_handle_capabilities,
550 };
551
552 static void
553 handle_ping (void *data, struct wl_shell_surface *shell_surface,
554     uint32_t serial)
555 {
556   wl_shell_surface_pong (shell_surface, serial);
557 }
558
559 static void
560 handle_configure (void *data, struct wl_shell_surface *shell_surface,
561     uint32_t edges, int32_t width, int32_t height)
562 {
563 }
564
565 static void
566 handle_popup_done (void *data, struct wl_shell_surface *shell_surface)
567 {
568 }
569
570 static const struct wl_shell_surface_listener shell_surface_listener = {
571   handle_ping,
572   handle_configure,
573   handle_popup_done
574 };
575
576 static void
577 shm_format (void *data, struct wl_shm *wl_shm, uint32_t format)
578 {
579   GST_DEBUG ("supported format=%08x", format);
580 }
581
582 static const struct wl_shm_listener shm_listener = {
583   shm_format
584 };
585
586 static void
587 display_handle_geometry (void *data, struct wl_output *wl_output, int x, int y,
588     int physical_width, int physical_height, int subpixel, const char *make,
589     const char *model, int transform)
590 {
591 }
592
593 static void
594 display_handle_mode (void *data, struct wl_output *wl_output, uint32_t flags,
595     int width, int height, int refresh)
596 {
597   GstWlDemo *priv = data;
598
599   if (flags & WL_OUTPUT_MODE_CURRENT && priv->min_refresh > refresh)
600     priv->min_refresh = refresh;
601 }
602
603 static void
604 display_handle_done (void *data, struct wl_output *wl_output)
605 {
606 }
607
608 static void
609 display_handle_scale (void *data, struct wl_output *wl_output, int32_t scale)
610 {
611 }
612
613 static const struct wl_output_listener output_listener = {
614   display_handle_geometry,
615   display_handle_mode,
616   display_handle_done,
617   display_handle_scale
618 };
619
620 static void
621 registry_handle_global (void *data, struct wl_registry *registry,
622     uint32_t id, const char *interface, uint32_t version)
623 {
624   GstWlDemo *priv = data;
625   struct wl_output *output;
626
627   if (g_strcmp0 (interface, "wl_compositor") == 0) {
628     priv->compositor = wl_registry_bind (registry, id, &wl_compositor_interface,
629         MIN (version, 3));
630   } else if (g_strcmp0 (interface, "wl_shell") == 0) {
631     priv->shell = wl_registry_bind (registry, id, &wl_shell_interface, 1);
632   } else if (g_strcmp0 (interface, "wl_shm") == 0) {
633     priv->shm = wl_registry_bind (registry, id, &wl_shm_interface, 1);
634   } else if (g_strcmp0 (interface, "wl_seat") == 0) {
635     priv->seat = wl_registry_bind (registry, id, &wl_seat_interface, 1);
636     wl_proxy_set_queue ((struct wl_proxy *) priv->seat, priv->queue);
637     wl_seat_add_listener (priv->seat, &seat_listener, priv);
638   } else if (g_strcmp0 (interface, "wl_output") == 0) {
639     output = wl_registry_bind (registry, id, &wl_output_interface, 1);
640     wl_proxy_set_queue ((struct wl_proxy *) output, priv->queue);
641     wl_output_add_listener (output, &output_listener, priv);
642     priv->outputs = g_list_append (priv->outputs, output);
643   }
644 }
645
646 static const struct wl_registry_listener registry_listener = {
647   registry_handle_global
648 };
649
650 static gboolean
651 setup_surface (GstWlDemo * priv, struct wl_surface *surface,
652     struct wl_shell_surface *shell_surface, gint width, gint height)
653 {
654   char filename[1024];
655   static int cnt = 0;
656   int fd;
657   GstVideoInfo vinfo;
658   void *data;
659   struct wl_shm_pool *shm_pool;
660   struct wl_buffer *wlbuffer;
661
662   /*
663    * waylandsink creates a wl_subsurface from an external wl_surface passed by
664    * the application and attaches buffers from the upstream to
665    * the wl_subsurface. A wl_subsurface becomes visible by mapping
666    * its parent wl_surface, so we have to draw the wl_surface that will be passed
667    * to waylandsink.
668    */
669   /* Transparently draw the area of the same size as the video resolution
670      by using a shm buffer. */
671   gst_video_info_set_format (&vinfo, GST_VIDEO_FORMAT_BGRA, width, height);
672
673   snprintf (filename, 1024, "%s/%s-demo-%d-%s", g_get_user_runtime_dir (),
674       "wayland-shm", cnt++, "XXXXXX");
675
676   fd = mkstemp (filename);
677   if (fd < 0) {
678     g_printerr ("temp file %s creation failed: %s\n", filename,
679         strerror (errno));
680     return FALSE;
681   }
682
683   if (ftruncate (fd, vinfo.size) < 0) {
684     g_printerr ("ftruncate failed: %s\n", strerror (errno));
685     close (fd);
686     return FALSE;
687   }
688
689   data = mmap (NULL, vinfo.size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
690   if (data == MAP_FAILED) {
691     g_printerr ("mmap failed: %s\n", strerror (errno));
692     close (fd);
693     return FALSE;
694   }
695
696   memset (data, 0, vinfo.size);
697
698   munmap (data, vinfo.size);
699
700   shm_pool = wl_shm_create_pool (priv->shm, fd, vinfo.size);
701   wlbuffer =
702       wl_shm_pool_create_buffer (shm_pool, 0, GST_VIDEO_INFO_WIDTH (&vinfo),
703       GST_VIDEO_INFO_HEIGHT (&vinfo),
704       GST_VIDEO_INFO_PLANE_STRIDE (&vinfo, 0), WL_SHM_FORMAT_ARGB8888);
705   wl_shm_pool_destroy (shm_pool);
706   unlink (filename);
707   close (fd);
708
709   wl_proxy_set_queue ((struct wl_proxy *) shell_surface, priv->queue);
710
711   wl_shell_surface_add_listener (shell_surface, &shell_surface_listener, priv);
712   wl_shell_surface_set_toplevel (shell_surface);
713
714   wl_surface_set_user_data (surface, shell_surface);
715
716   if (priv->fullscreen != -1) {
717     struct wl_event_queue *queue;
718     struct wl_region *region;
719     struct wl_output *output;
720
721     region = wl_compositor_create_region (priv->compositor);
722     wl_region_add (region, 0, 0, width, height);
723     wl_surface_set_opaque_region (surface, region);
724     wl_region_destroy (region);
725
726     output = g_list_nth_data (priv->outputs, priv->fullscreen);
727     if (!output) {
728       g_printerr
729           ("failed to get wl_output object, so could not set fullscreen\n");
730       return FALSE;
731     }
732
733     queue = wl_display_create_queue (priv->display);
734
735     wl_shell_surface_set_fullscreen (shell_surface,
736         WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, output);
737     wl_display_roundtrip_queue (priv->display, queue);
738
739     wl_event_queue_destroy (queue);
740   }
741
742   wl_surface_attach (surface, wlbuffer, 0, 0);
743   wl_surface_damage (surface, 0, 0, GST_VIDEO_INFO_WIDTH (&vinfo),
744       GST_VIDEO_INFO_HEIGHT (&vinfo));
745   wl_surface_commit (surface);
746   wl_display_flush (priv->display);
747
748   return TRUE;
749 }
750
751 static GstBusSyncReply
752 bus_sync_handler (GstBus * bus, GstMessage * message, gpointer user_data)
753 {
754   GstWlDemo *priv = user_data;
755
756   if (gst_is_wayland_display_handle_need_context_message (message)) {
757     GstContext *context;
758
759     context = gst_wayland_display_handle_context_new (priv->display);
760     gst_element_set_context (GST_ELEMENT (GST_MESSAGE_SRC (message)), context);
761
762     goto drop;
763   } else if (gst_is_video_overlay_prepare_window_handle_message (message)) {
764     GstPad *pad;
765     GstCaps *caps;
766     GstStructure *structure;
767     struct wl_surface *surface;
768     struct wl_shell_surface *shell_surface;
769     gint width, height;
770
771     if (!g_str_has_prefix (GST_MESSAGE_SRC_NAME (message), "waylandsink"))
772       return GST_BUS_PASS;
773
774     pad = gst_element_get_static_pad ((GstElement *) GST_MESSAGE_SRC (message),
775         "sink");
776     caps = gst_pad_get_current_caps (pad);
777     structure = gst_caps_get_structure (caps, 0);
778     gst_structure_get_int (structure, "width", &width);
779     gst_structure_get_int (structure, "height", &height);
780     gst_caps_unref (caps);
781     gst_object_unref (pad);
782
783     surface = wl_compositor_create_surface (priv->compositor);
784     shell_surface = wl_shell_get_shell_surface (priv->shell, surface);
785
786     if (!setup_surface (priv, surface, shell_surface, width, height)) {
787       wl_shell_surface_destroy (shell_surface);
788       wl_surface_destroy (surface);
789       return GST_BUS_PASS;
790     }
791
792     priv->surfaces = g_list_append (priv->surfaces, surface);
793     priv->shell_surfaces = g_list_append (priv->shell_surfaces, shell_surface);
794
795     gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC
796             (message)), (guintptr) surface);
797     gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC
798             (message)), 0, 0, width, height);
799
800     goto drop;
801   }
802
803   return GST_BUS_PASS;
804
805 drop:
806   gst_message_unref (message);
807   return GST_BUS_DROP;
808 }
809
810 static gboolean
811 bus_async_handler (GstBus * bus, GstMessage * message, gpointer user_data)
812 {
813   GstWlDemo *priv = user_data;
814
815   switch (GST_MESSAGE_TYPE (message)) {
816     case GST_MESSAGE_ERROR:{
817       GError *err;
818       gchar *debug;
819
820       gst_message_parse_error (message, &err, &debug);
821       g_print ("Error: %s\n", err->message);
822       g_error_free (err);
823       g_free (debug);
824
825       goto quit;
826     }
827     case GST_MESSAGE_APPLICATION:
828     {
829       const GstStructure *s;
830
831       s = gst_message_get_structure (message);
832
833       if (gst_structure_has_name (s, "GstWaylandDemoInterrupt"))
834         goto quit;
835     }
836       break;
837     case GST_MESSAGE_EOS:
838       if (priv->nloop > 1 || priv->nloop == INFINITE_LOOP_PLAYBACK) {
839         if (!gst_element_seek (priv->pipeline,
840                 1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_FLUSH,
841                 GST_SEEK_TYPE_SET, 0,
842                 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE)) {
843           g_printerr ("seek event sending failed\n");
844           goto quit;
845         }
846
847         if (priv->nloop != INFINITE_LOOP_PLAYBACK)
848           priv->nloop--;
849         break;
850       }
851
852       goto quit;
853     default:
854       break;
855   }
856
857   return TRUE;
858
859 quit:
860   g_main_loop_quit (priv->loop);
861   g_source_destroy (priv->source);
862   priv->source = NULL;
863   return TRUE;
864 }
865
866 typedef struct _GstWaylandEventSource
867 {
868   GSource source;
869   GPollFD pfd;
870   struct wl_display *display;
871   struct wl_event_queue *queue;
872   gboolean reading;
873 } GstWaylandEventSource;
874
875 static gboolean
876 event_source_prepare (GSource * source, gint * timeout)
877 {
878   GstWaylandEventSource *wl_source = (GstWaylandEventSource *) source;
879
880   *timeout = -1;
881
882   if (wl_source->reading)
883     return FALSE;
884
885   while (wl_display_prepare_read_queue (wl_source->display,
886           wl_source->queue) != 0) {
887     wl_display_dispatch_queue_pending (wl_source->display, wl_source->queue);
888   }
889   wl_display_flush (wl_source->display);
890
891   wl_source->reading = TRUE;
892
893   return FALSE;
894 }
895
896 static gboolean
897 event_source_check (GSource * source)
898 {
899   GstWaylandEventSource *wl_source = (GstWaylandEventSource *) source;
900
901   return ! !(wl_source->pfd.revents & G_IO_IN);
902 }
903
904 static gboolean
905 event_source_dispatch (GSource * source, GSourceFunc callback,
906     gpointer user_data)
907 {
908   GstWaylandEventSource *wl_source = (GstWaylandEventSource *) source;
909
910   wl_display_read_events (wl_source->display);
911   wl_display_dispatch_queue_pending (wl_source->display, wl_source->queue);
912
913   wl_source->reading = FALSE;
914
915   return TRUE;
916 }
917
918 static void
919 event_source_finalize (GSource * source)
920 {
921   GstWaylandEventSource *wl_source = (GstWaylandEventSource *) source;
922
923   if (wl_source->reading) {
924     wl_display_cancel_read (wl_source->display);
925     wl_source->reading = FALSE;
926   }
927 }
928
929 static GSourceFuncs GstWaylandEventSourceFuncs = {
930   event_source_prepare,
931   event_source_check,
932   event_source_dispatch,
933   event_source_finalize
934 };
935
936 static void
937 setup_framerate_adjustment (const GValue * item, gpointer user_data)
938 {
939   GstWlDemo *priv = user_data;
940   GstElement *elem;
941   GstElement *peer_elem;
942   GstPad *pad;
943   GstPad *peer_pad;
944   GstCaps *caps;
945
946   elem = g_value_get_object (item);
947
948   if (g_str_has_prefix (GST_ELEMENT_NAME (elem), "videorate")) {
949     /* Get the element immediately after this videorate */
950     pad = gst_element_get_static_pad (elem, "src");
951     peer_pad = gst_pad_get_peer (pad);
952     peer_elem = gst_pad_get_parent_element (peer_pad);
953     gst_object_unref (pad);
954     gst_object_unref (peer_pad);
955
956     caps = gst_caps_new_simple ("video/x-raw", "framerate",
957         GST_TYPE_FRACTION, priv->min_refresh / 1000, 1, NULL);
958
959     gst_element_unlink (elem, peer_elem);
960     gst_element_link_filtered (elem, peer_elem, caps);
961     gst_object_unref (peer_elem);
962   }
963 }
964
965 static GstPadProbeReturn
966 cb_have_data (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
967 {
968   GstWlDemo *priv = user_data;
969   time_t t;
970   struct tm *tm;
971   gint64 cur_time;
972   gint64 framesinsec;
973   static gint64 prev_time = 0;
974   static gint64 prev_cnt = 0;
975
976   priv->frame_cnt++;
977
978   if (prev_time == 0) {
979     prev_time = g_get_monotonic_time ();
980     return GST_PAD_PROBE_OK;
981   }
982
983   cur_time = g_get_monotonic_time ();
984
985   if (cur_time - prev_time >= 1000000) {
986     framesinsec = priv->frame_cnt - prev_cnt;
987     t = time (NULL);
988     tm = localtime (&t);
989
990     g_print ("FPS: %3ld  TIME %02d:%02d:%02d\n", framesinsec, tm->tm_hour,
991         tm->tm_min, tm->tm_sec);
992
993     prev_cnt = priv->frame_cnt;
994     prev_time = cur_time;
995   }
996
997   return GST_PAD_PROBE_OK;
998 }
999
1000 static gboolean
1001 sigint_handler (gpointer user_data)
1002 {
1003   GstWlDemo *priv = user_data;
1004
1005   gst_element_post_message (GST_ELEMENT (priv->pipeline),
1006       gst_message_new_application (GST_OBJECT (priv->pipeline),
1007           gst_structure_new ("GstWaylandDemoInterrupt", "message",
1008               G_TYPE_STRING, "Pipeline interrupted", NULL)));
1009
1010   priv->signal_watch_id = 0;
1011
1012   return FALSE;
1013 }
1014
1015 static void
1016 shell_surface_destroy (struct wl_shell_surface *shell_surface)
1017 {
1018   wl_shell_surface_destroy (shell_surface);
1019 }
1020
1021 static void
1022 surface_destroy (struct wl_surface *surface)
1023 {
1024   wl_surface_destroy (surface);
1025 }
1026
1027 static void
1028 output_destroy (struct wl_output *output)
1029 {
1030   wl_output_destroy (output);
1031 }
1032
1033 int
1034 main (int argc, char **argv)
1035 {
1036   GstWaylandEventSource *wl_source;
1037   GstWlDemo *priv;
1038   GOptionContext *context;
1039   GstBus *bus;
1040   GstIterator *it;
1041   GstElement *elem;
1042   GstPad *pad;
1043   GstStateChangeReturn state_ret;
1044   GTimer *timer = NULL;
1045   GError *error = NULL;
1046   guint bus_watch_id;
1047   gint fullscreen = -1;
1048   gint nloop = 0;
1049   gchar *measuring_pad = NULL;
1050   gchar *elem_name;
1051   gchar *pad_name;
1052   gdouble elapsed;
1053   gchar **argvn;
1054   gint i;
1055   int ret = EXIT_FAILURE;
1056   GOptionEntry options[] = {
1057     {"fullscreen", 'f', 0, G_OPTION_ARG_INT, &fullscreen,
1058         "Display in fullscreen mode on dest_num output [-f dest_num]", NULL},
1059     {"loop", 'l', 0, G_OPTION_ARG_INT, &nloop,
1060         "Loop Playback for loop_count [-l loop_count]", NULL},
1061     {"fps", 'p', 0, G_OPTION_ARG_STRING, &measuring_pad,
1062           "Framerate display (specify a measuring point as regular format [-p element:pad])",
1063         NULL},
1064     {NULL}
1065   };
1066
1067 #ifdef USE_AGL
1068
1069   //char *static_options[] = { argv[0], "filesrc", "location=/home/0/3.mp4", "!", "decodebin", "!", "videoconvert", "!", "waylandsink", "sync=false", NULL };
1070   //char **static_argv = static_options;
1071   //int static_argc = 10;
1072   char **static_argv = NULL;
1073   int static_argc = 0;
1074   
1075   // Parse args
1076   int port;
1077   const char *token;
1078
1079   // Get app id
1080   const char *afm_id = getenv("AFM_ID");
1081   if (afm_id == NULL || !afm_id[0]) {
1082     afm_id = argv[0];
1083   }
1084
1085   // Get pipeline information
1086   auto path = std::string(getenv("AFM_APP_INSTALL_DIR"));
1087   path = path + "/pipeline.ini";
1088
1089   FILE *pFile;
1090   long lSize;
1091   size_t res;
1092   char * pipe = NULL;
1093   // Read pipeline from file
1094   pFile = fopen ( path.c_str() , "rb" );
1095   if (pFile==NULL){
1096     fprintf(stderr, "failed to open file\n");
1097     return -1;
1098   }
1099
1100   // obtain file size 
1101   fseek (pFile , 0 , SEEK_END);
1102   lSize = ftell (pFile);
1103   rewind (pFile);
1104
1105   // allocate memory to contain the whole file 
1106   pipe = (char*) malloc (sizeof(char)*lSize);
1107   if (pipe == NULL){
1108     fprintf(stderr,"Cannot allocate memory\n");
1109     return -1;
1110   }
1111
1112   // copy the file into the buffer 
1113   res = fread (pipe,1,lSize,pFile);
1114   if (res != lSize){
1115     fprintf(stderr,"File read error\n");
1116     return -1;
1117   }
1118   //fprintf(stderr,pipe);
1119
1120   /* close file */
1121   fclose (pFile);
1122
1123   char seg[] = " ";
1124   char *charlist[50];
1125   static_argv = charlist;
1126
1127   int memlen = 0;
1128   memlen = strlen(argv[0])+1;
1129   charlist[0] = (char*) malloc (memlen);
1130   memset(charlist[0],0,memlen);
1131   strcpy(charlist[0],argv[0]);
1132
1133   int cnt = 1;
1134   
1135   char *substr= strtok(pipe,seg);
1136   while (substr != NULL) {
1137     memlen = strlen(substr)+1;
1138     charlist[cnt] = (char*) malloc (memlen);
1139     memset(charlist[cnt],0,memlen);
1140     strcpy(charlist[cnt],substr);
1141     cnt++;
1142     substr = strtok(NULL,seg);
1143   } 
1144
1145   if(pipe != NULL)
1146   free(pipe);
1147
1148   port = std::stol(argv[1]);
1149   token = argv[2];
1150
1151   fprintf(stderr, "port: { %d }, token: { %s}, id: { %s } \n", port, token, afm_id);
1152
1153   static_argc = cnt;
1154   gst_init (&static_argc, &static_argv);
1155
1156   RunXDG runxdg(port, token, afm_id);
1157     
1158   // @tobi websocket
1159   websocket_init();
1160   GST_ERROR("[%s] [%s] end", "WebSocket_Debug", __func__);
1161
1162   runxdg.start();
1163 #else
1164   gst_init (&argc, &argv);
1165 #endif
1166
1167   context = g_option_context_new ("PIPELINE-DESCRIPTION");
1168   g_option_context_add_main_entries (context, options, NULL);
1169   g_option_context_add_group (context, gst_init_get_option_group ());
1170 #ifdef USE_AGL
1171   if (!g_option_context_parse (context, &static_argc, &static_argv, &error)) {
1172 #else
1173   if (!g_option_context_parse (context, &argc, &argv, &error)) {
1174 #endif
1175     g_printerr ("option parsing failed: %s\n",
1176         (error) ? error->message : "Unknown error");
1177     return EXIT_FAILURE;
1178   }
1179   g_option_context_free (context);
1180
1181   priv = g_slice_new0 (GstWlDemo);
1182
1183   priv->fullscreen = fullscreen;
1184   priv->nloop = nloop;
1185   priv->min_refresh = G_MAXINT;
1186
1187   priv->loop = g_main_loop_new (NULL, FALSE);
1188
1189   /* Construct a pipeline from the result of parsing argv
1190      similarly to gst-launch. */
1191 #ifdef USE_AGL
1192   argvn = g_new0 (char *, static_argc);
1193   memcpy (argvn, static_argv + 1, sizeof (char *) * (static_argc - 1));
1194 #else
1195   argvn = g_new0 (char *, argc);
1196   memcpy (argvn, argv + 1, sizeof (char *) * (argc - 1));
1197 #endif
1198   error = NULL;
1199   priv->pipeline = gst_parse_launchv ((const gchar **) argvn, &error);
1200   g_free (argvn);
1201
1202   if (!priv->pipeline) {
1203     g_printerr ("pipeline could not be constructed: %s\n",
1204         (error) ? error->message : "Unknown error");
1205     return EXIT_FAILURE;
1206   }
1207
1208   priv->signal_watch_id =
1209       g_unix_signal_add (SIGINT, (GSourceFunc) sigint_handler, priv);
1210
1211   bus = gst_pipeline_get_bus (GST_PIPELINE (priv->pipeline));
1212   gst_bus_set_sync_handler (bus, bus_sync_handler, priv, NULL);
1213   bus_watch_id = gst_bus_add_watch (bus, bus_async_handler, priv);
1214   gst_object_unref (bus);
1215
1216   priv->display = wl_display_connect (NULL);
1217   if (!priv->display) {
1218     g_printerr ("display connection failed\n");
1219     goto leave;
1220   }
1221
1222   priv->queue = wl_display_create_queue (priv->display);
1223
1224   priv->registry = wl_display_get_registry (priv->display);
1225   wl_proxy_set_queue ((struct wl_proxy *) priv->registry, priv->queue);
1226   wl_registry_add_listener (priv->registry, &registry_listener, priv);
1227
1228   /* Need 2 roundtrips to do all the global objects processing. */
1229   for (i = 0; i < 2; i++)
1230     wl_display_roundtrip_queue (priv->display, priv->queue);
1231
1232   priv->source = g_source_new (&GstWaylandEventSourceFuncs,
1233       sizeof (GstWaylandEventSource));
1234   wl_source = (GstWaylandEventSource *) priv->source;
1235
1236   wl_source->pfd.fd = wl_display_get_fd (priv->display);
1237   wl_source->pfd.events = G_IO_IN | G_IO_ERR | G_IO_HUP;
1238   g_source_add_poll (priv->source, &wl_source->pfd);
1239
1240   wl_source->display = priv->display;
1241   wl_source->queue = priv->queue;
1242   wl_source->reading = FALSE;
1243   g_source_attach (priv->source, NULL);
1244   g_source_unref (priv->source);
1245
1246   /* Setup the framerate adjustment by videorate. */
1247   it = gst_bin_iterate_elements (GST_BIN (priv->pipeline));
1248   gst_iterator_foreach (it, setup_framerate_adjustment, priv);
1249   gst_iterator_free (it);
1250
1251   if (measuring_pad) {
1252     elem_name = strtok (measuring_pad, ":");
1253     pad_name = strtok (NULL, ":");
1254     if (!elem_name || !pad_name) {
1255       g_printerr ("tokens extraction failed\n");
1256       goto leave;
1257     }
1258
1259     elem = gst_bin_get_by_name (GST_BIN (priv->pipeline), elem_name);
1260     if (!elem) {
1261       g_printerr ("failed to get the element by name\n");
1262       goto leave;
1263     }
1264
1265     pad = gst_element_get_static_pad (elem, pad_name);
1266     if (!pad) {
1267       g_printerr ("failed to get the static pad by name\n");
1268       gst_object_unref (elem);
1269       goto leave;
1270     }
1271
1272     gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_BUFFER,
1273         (GstPadProbeCallback) cb_have_data, priv, NULL);
1274
1275     gst_object_unref (pad);
1276     gst_object_unref (elem);
1277
1278     /* To calculate the average framerate throughout the playback. */
1279     timer = g_timer_new ();
1280   }
1281
1282   state_ret = gst_element_set_state (priv->pipeline, GST_STATE_PAUSED);
1283   while (state_ret == GST_STATE_CHANGE_ASYNC) {
1284     state_ret = gst_element_get_state (priv->pipeline, NULL, NULL,
1285         GST_CLOCK_TIME_NONE);
1286   }
1287
1288   if (timer)
1289     g_timer_start (timer);
1290
1291   gst_element_set_state (priv->pipeline, GST_STATE_PLAYING);
1292
1293   g_main_loop_run (priv->loop);
1294
1295   if (timer) {
1296     g_timer_stop (timer);
1297     elapsed = g_timer_elapsed (timer, NULL);
1298     g_timer_destroy (timer);
1299     g_print ("Avg. FPS: %.2lf\n", priv->frame_cnt / elapsed);
1300   }
1301
1302   gst_element_set_state (priv->pipeline, GST_STATE_NULL);
1303
1304   ret = 0;
1305
1306 leave:
1307   GST_ERROR ("log: gst_wl_display_finalize");
1308
1309   if (priv->source)
1310     g_source_destroy (priv->source);
1311
1312   gst_object_unref (priv->pipeline);
1313
1314   if (priv->shell_surfaces) {
1315     g_list_foreach (priv->shell_surfaces, (GFunc) shell_surface_destroy, NULL);
1316     g_list_free (priv->shell_surfaces);
1317   }
1318
1319   if (priv->surfaces) {
1320     g_list_foreach (priv->surfaces, (GFunc) surface_destroy, NULL);
1321     g_list_free (priv->surfaces);
1322   }
1323
1324   if (priv->outputs) {
1325     g_list_foreach (priv->outputs, (GFunc) output_destroy, NULL);
1326     g_list_free (priv->outputs);
1327   }
1328
1329   if (priv->shm)
1330     wl_shm_destroy (priv->shm);
1331   if (priv->shell)
1332     wl_shell_destroy (priv->shell);
1333   if (priv->registry)
1334     wl_registry_destroy (priv->registry);
1335   if (priv->compositor)
1336     wl_compositor_destroy (priv->compositor);
1337   if (priv->queue)
1338     wl_event_queue_destroy (priv->queue);
1339   if (priv->display)
1340     wl_display_disconnect (priv->display);
1341
1342   g_source_remove (bus_watch_id);
1343   if (priv->signal_watch_id > 0)
1344     g_source_remove (priv->signal_watch_id);
1345   g_main_loop_unref (priv->loop);
1346   g_slice_free (GstWlDemo, priv);
1347
1348   if (measuring_pad)
1349     g_free (measuring_pad);
1350
1351 #ifdef USE_AGL
1352   for(int i=0;i<cnt;i++)
1353   {
1354     if(charlist[i]!=NULL)
1355     free(charlist[i]);
1356   }
1357 #endif
1358
1359   return ret;
1360 }