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