Notification launch support. (TIVI-2926/1892)
[profile/ivi/ico-uxf-homescreen.git] / lib / system-controller / CicoSCWayland.cpp
1 /*
2  * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
3  *
4  * This program is licensed under the terms and conditions of the
5  * Apache License, version 2.0.  The full text of the Apache License is at
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  */
9
10 //==========================================================================    
11 /**
12  *  @file   CicoSCWayland.cpp
13  *
14  *  @brief  This file implementation of CicoSCWayland class
15  */
16 //==========================================================================    
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <signal.h>
23 #include <errno.h>
24 #include <sys/ioctl.h>
25 #include <Ecore.h>
26
27 #include <map>
28 using namespace std;
29
30 #include <wayland-client.h>
31 #include <ico-uxf-weston-plugin/ico_window_mgr-client-protocol.h>
32 #include <ilm/ilm_control.h>
33
34 #include "CicoSCWayland.h"
35 #include "CicoSCWlWinMgrIF.h"
36 #include "CicoSCWindowController.h"
37 #include "CicoLog.h"
38 #include "ico_syc_error.h"
39
40 //==========================================================================    
41 //  private static variable
42 //==========================================================================    
43 CicoSCWayland* CicoSCWayland::ms_myInstance = NULL;
44
45 //--------------------------------------------------------------------------
46 /**
47  *  @brief  default constructor
48  */
49 //--------------------------------------------------------------------------
50 CicoSCWayland::CicoSCWayland()
51     : m_wlDisplay(NULL),
52       m_wlRegistry(NULL),
53       m_wlFd(-1),
54       m_ecoreFdHandler(NULL)
55 {
56     // wayland callbacks
57     m_wlListener.global        = wlGlobalCB;
58     m_wlListener.global_remove = NULL;
59
60     CicoSCWayland::ms_myInstance = this;
61 }
62
63 //--------------------------------------------------------------------------
64 /**
65  *  @brief  destructor
66  */
67 //--------------------------------------------------------------------------
68 CicoSCWayland::~CicoSCWayland()
69 {
70     CicoSCWayland::ms_myInstance = NULL;
71 }
72
73 //--------------------------------------------------------------------------
74 /**
75  *  @brief  get instance of CicoSCWayland
76  *
77  *  @return instance of CicoSCWayland
78  */
79 //--------------------------------------------------------------------------
80 CicoSCWayland*
81 CicoSCWayland::getInstance(void)
82 {
83     if (NULL == ms_myInstance) {
84         ms_myInstance = new CicoSCWayland();
85     }
86
87     return ms_myInstance;
88 }
89
90 //--------------------------------------------------------------------------
91 /**
92  *  @brief  initialize wayland connection
93  *
94  *  @return ICO_SYC_EOK on success, other on error
95  */
96 //--------------------------------------------------------------------------
97 int
98 CicoSCWayland::initialize(void)
99 {
100     ICO_TRA("CicoSCWayland::initialize Enter");
101
102     for (int i = 0; i < (5000/50); ++i)  {
103         m_wlDisplay = wl_display_connect(NULL);
104         if (NULL != m_wlDisplay) {
105             break;
106         }
107         usleep(50*1000);
108     }
109
110     if (NULL == m_wlDisplay) {
111         ICO_ERR("wl_display_connect failed.");
112         ICO_TRA("CicoSCWayland::initialize Leave(EIO)");
113         return ICO_SYC_EIO;
114     }
115
116     ICO_DBG("called: wl_display_get_registry(wlDisplay=0x%08x)", m_wlDisplay);
117     m_wlRegistry = wl_display_get_registry(m_wlDisplay);
118     if (NULL == m_wlRegistry) {
119         ICO_ERR("wl_display_get_registry failed.");
120         ICO_TRA("CicoSCWayland::initialize Leave(EIO)");
121         return ICO_SYC_EIO;
122     }
123
124     // add wayland global callbacks
125     ICO_DBG("called: wl_registry_add_listener");
126     wl_registry_add_listener(m_wlRegistry, &m_wlListener, this);
127
128     int initCount = 0;
129     int ifcount = m_wlInterfaceList.size();
130     for (int i = 0; i < (500/20); ++i) {
131         initCount = 0;
132         map<string, CicoSCWaylandIF*>::iterator itr;
133         itr = m_wlInterfaceList.begin();
134         for (; itr != m_wlInterfaceList.end(); ++itr) {
135             if(true == itr->second->isInitialized()) {
136                 initCount++;
137             }
138         }
139         if (ifcount == initCount) {
140             break;
141         }
142         ICO_DBG("called: wl_display_dispatch"
143                 "(wlDisplay=0x%08x)", (int)m_wlDisplay);
144         wl_display_dispatch(m_wlDisplay);
145         usleep(20*1000);
146     }
147
148     if (ifcount != initCount) {
149         ICO_ERR("initialize interface time up NG");
150         ICO_TRA("CicoSCWayland::initialize Leave(EIO)");
151         return ICO_SYC_EIO;
152     }
153     else {
154         ICO_DBG("initialize interface all OK");
155     }
156
157     // flush display 
158     ICO_DBG("called: wl_display_flush(wlDisplay=0x%08x)", (int)m_wlDisplay);
159     wl_display_flush(m_wlDisplay);
160
161     // initialize genivi ivi-shell
162     if (ilm_init() != ILM_SUCCESS)  {
163         ICO_ERR("ilm_init failed.");
164         ICO_TRA("CicoSCWayland::initialize Leave(EIO)");
165         return ICO_SYC_EIO;
166     }
167
168     ICO_DBG("called: wl_display_get_fd(wlDisplay=0x%08x)", (int)m_wlDisplay);
169     m_wlFd = wl_display_get_fd(m_wlDisplay);
170     ICO_DBG("CicoSCWayland::initialize: Wayland/Weston fd=%d", m_wlFd);
171
172     ICO_DBG("CicoSCWayland::initialize: Wayland/Weston connect OK");
173
174     // initialize genivi callbacks
175     CicoSCWindowController::getInstance()->initializeGeniviLMS();
176
177     ICO_TRA("CicoSCWayland::initialize: Leave(EOK)");
178     return ICO_SYC_EOK;
179 }
180
181 //--------------------------------------------------------------------------
182 /**
183  *  @brief  flush display
184  */
185 //--------------------------------------------------------------------------
186 void
187 CicoSCWayland::flushDisplay(void)
188 {
189     if (NULL == m_wlDisplay) {
190         ICO_ERR("wlDisplay == NULL");
191         return;
192     }
193 //    ICO_DBG("called: wl_display_flush(0x%08x)", (int)m_wlDisplay);
194     int wlret = wl_display_flush(m_wlDisplay);
195     if (-1 == wlret) {
196         int error = wl_display_get_error(m_wlDisplay);
197         ICO_ERR("wayland error(%d)", error);
198     }
199 }
200
201 //--------------------------------------------------------------------------
202 /**
203  *  @brief  dispatch display
204  */
205 //--------------------------------------------------------------------------
206 void
207 CicoSCWayland::dispatchDisplay(void)
208 {
209     if (NULL == m_wlDisplay) {
210         ICO_ERR("wlDisplay == NULL");
211         return;
212     }
213 //    ICO_DBG("call wl_display_dispatch(0x%08x)", (int)m_wlDisplay);
214     int wlret = wl_display_dispatch(m_wlDisplay);
215     if (-1 == wlret) {
216         int error =  wl_display_get_error(m_wlDisplay);
217         ICO_ERR("wl_display_dispatch failed. error(%d)", error);
218
219         if (error == EINVAL)    {
220             exit(9);
221         }
222     }
223 }
224
225 //--------------------------------------------------------------------------
226 /**
227  *  @brief  get wayland error
228  */
229 //--------------------------------------------------------------------------
230 int
231 CicoSCWayland::getError(void)
232 {
233     if (NULL == m_wlDisplay) {
234         ICO_ERR("wlDisplay == NULL");
235         return -1;
236     }
237
238     ICO_DBG("fd=%d", wl_display_get_fd(m_wlDisplay));
239     return wl_display_get_error(m_wlDisplay);
240 }
241
242 //--------------------------------------------------------------------------
243 /**
244  *  @brief  get wayland file destructor
245  *
246  *  @return wayland file destructor
247  */
248 //--------------------------------------------------------------------------
249 int CicoSCWayland::getWlFd(void)
250 {
251     return m_wlFd;
252 }
253
254 //--------------------------------------------------------------------------
255 /**
256  *  @brief  add wayland file destructor handler to ecore main 
257  *
258  *  @return ICO_SYC_EOK on success, other on error
259  *  @retval ICO_SYC_EIO ecore_main_fd_handler_add failed
260  */
261 //--------------------------------------------------------------------------
262 int
263 CicoSCWayland::addEcoreMainWlFdHandler(void)
264 {
265     ICO_TRA("CicoSCWayland::addEcoreMainWlFdHandler Enter");
266     ICO_DBG("called: ecore_main_fd_handler_add(fd=%d)", m_wlFd);
267     m_ecoreFdHandler = ecore_main_fd_handler_add(m_wlFd, 
268                                                  ECORE_FD_READ,
269                                                  &waylandFdHandler,
270                                                  NULL,
271                                                  NULL,
272                                                  NULL);
273     if (NULL == m_ecoreFdHandler) {
274         ICO_ERR("ecore_main_fd_handler_add failed.");
275         ICO_TRA("CicoSCWayland::addEcoreMainWlFdHandler Leave(EIO)");
276         return ICO_SYC_EIO;
277     }
278     ecore_main_loop_iterate();
279
280     int arg = 0;
281     if (ioctl(m_wlFd, FIONREAD, &arg) < 0) {
282         ICO_WRN("ioclt(FIONREAD) failed. errno=%d:%s", errno, strerror(errno));
283         arg = 0;
284     }
285     if (arg > 0)   {
286         CicoSCWayland::getInstance()->dispatchDisplay();
287     }
288
289     ICO_TRA("CicoSCWayland::addEcoreMainWlFdHandler Leave");
290     return ICO_SYC_EOK;
291 }
292
293 //--------------------------------------------------------------------------
294 /**
295  *  @brief   add wayland interface
296  *
297  *  @param [in] name        interface name
298  *  @param [in] interface   interface instance
299  */
300 //--------------------------------------------------------------------------
301 void
302 CicoSCWayland::addWaylandIF(const char *name, CicoSCWaylandIF* interface)
303 {
304     m_wlInterfaceList[name] = interface;
305 }
306
307 //--------------------------------------------------------------------------
308 /**
309  *  @brief   wayland global callback
310  *
311  *  @param [in] data        user data(unused)
312  *  @param [in] registry    wayland registry
313  *  @param [in] name        wayland display Id(unused)
314  *  @param [in] interface   wayland interface name
315  *  @param [in] version     wayland interface version number(unused)
316  */
317 //--------------------------------------------------------------------------
318 void
319 CicoSCWayland::globalCB(void               *data,
320                         struct wl_registry *registry,
321                         uint32_t           name,
322                         const char         *interface,
323                         uint32_t           version)
324 {
325     map<string, CicoSCWaylandIF*>::iterator itr;
326     itr = m_wlInterfaceList.find(interface);
327
328     if (m_wlInterfaceList.end() == itr) {
329         ICO_DBG("skip interface=%s", interface);
330         return;
331     }
332
333     CicoSCWaylandIF *wlIF = itr->second;
334     wlIF->initInterface(data, registry, name, interface, version);
335
336     // flush display 
337     wl_display_flush(m_wlDisplay);
338 }
339
340 //--------------------------------------------------------------------------
341 /**
342  *  @brief   wayland global callback
343  *
344  *  @param [in] data        user data
345  *  @param [in] registry    wayland registry
346  *  @param [in] name        wayland display Id(unused)
347  *  @param [in] interface   wayland interface name
348  *  @param [in] version     wayland interface version number(unused)
349  */
350 //--------------------------------------------------------------------------
351 void
352 CicoSCWayland::wlGlobalCB(void               *data,
353                           struct wl_registry *registry,
354                           uint32_t           name,
355                           const char         *interface,
356                           uint32_t           version)
357 {
358     if (NULL == data) {
359         ICO_ERR("data == NULL");
360         return;
361     }
362
363     static_cast<CicoSCWayland*>(data)->globalCB(data, registry, name,
364                                                 interface, version);
365 }
366
367 //--------------------------------------------------------------------------
368 /**
369  *  @brief  wayland global callback
370  *
371  *  @param [in] data        user data
372  *  @param [in] handler     ecore file destructor handler
373  *
374  *  @return ECORE_CALLBACK_RENEW on retry , ECORE_CALLBACK_CANCEL on cancel
375  */
376 //--------------------------------------------------------------------------
377 Eina_Bool
378 CicoSCWayland::waylandFdHandler(void *data, Ecore_Fd_Handler *handler)
379 {
380 //    ICO_TRA("waylandFdHandler: Enter");
381
382     CicoSCWayland::getInstance()->flushDisplay();
383
384     int arg = 0;
385     if (ioctl(CicoSCWayland::getInstance()->getWlFd(), FIONREAD, &arg) < 0) {
386         ICO_WRN("ioclt(FIONREAD) failed. errno=%d:%s", errno, strerror(errno));
387         arg = 0;
388     }
389
390 //    ICO_DBG("waylandFdHandler: arg(%d))", arg);
391     if (arg > 0) {
392         CicoSCWayland::getInstance()->dispatchDisplay();
393     }
394
395     if (0 == arg) {
396         ICO_ERR("wayland fd read error.");
397         ICO_DBG("called: ecore_main_loop_quit()");
398         ecore_main_loop_quit();
399         return ECORE_CALLBACK_CANCEL;
400     }
401
402     CicoSCWayland::getInstance()->flushDisplay();
403 //    ICO_TRA("waylandFdHandler: Leave");
404     return ECORE_CALLBACK_RENEW ;
405 }
406 // vim:set expandtab ts=4 sw=4: