4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
25 @defgroup SLP_PG_APPCORE Application Model and Appcore
28 <h1 class="pg">Introduction</h1>
30 <h2 class="pg">Purpose of this document</h2>
31 This document demonstrates the basic steps needed to develop application(EFL or GTK) using appcore module in the SLP(Samsung Linux Platform). The document provides a brief introduction to the appcore architecture and explains application life-cycle of appcore. Programmers should develop their applications(EFL or GTK) based on the appcore module. The sample applications can be studied and can be used to develop other applications.
33 <h2 class="pg">Features</h2>
34 - Support EFL and GTK(including STK) application's basic function
35 - Support internalization
36 - Support rotation function
37 - Support power state function
41 <h1 class="pg">Components of Appcore</h3>
42 @image html SLP_Appcore_PG_overview.png
44 - Appcore EFL(libappcore-efl.so)
45 - It provides appcore_efl_main() which includes elm_init(), elm_run(), and other initializations for EFL application
46 - Refer to appcore-efl.h
47 - Appcore common(libappcore-common.so)
48 - It provides useful rotation function to control sensor’s rotation operation in application
49 - It provides useful function to process internalization based on GNU gettext
50 - It provides useful function to control power-state in application
51 - Refer to appcore-common.h
52 - Libraries used by Appcore
53 - EFL and GTK(STK) is a graphic widget library
54 - Sensor for supporting rotation
55 - AUL for application's life-cycle
56 - RUA for task manager
57 - Vconf for system events (such as low battery, low memory).
59 @defgroup SLP_PG_APPCORE1 1.Application's life-cycle
60 @ingroup SLP_PG_APPCORE
63 <h1 class="pg">Application's life-cycle</h2>
64 Appcore provides basic life-cycle like the following to manage application in SLP
67 <td> @image html SLP_Appcore_PG_lifecycle.png </td>
76 <td>Called once before the main loop. Initialize the application such as window creation, data structure allocation, and etc.</td>
80 <td>Called at the first idler and every "relaunch" message. Reset the application states and data structures.</td>
84 <td>Called when the entire window in this application are invisible. Recommend to suspend the actions related to the visibility.</td>
88 <td>Called when one of the windows in this application is visible. Resume the paused actions.</td>
92 <td>Called once after the main loop. Release the resources.</td>
98 Call the main function (appcore_efl_main() with struct appcore_ops filled with the proper function pointers. The functions are called by Appcore at the proper situation.
101 void *data; // Callback data
102 int (*create)(void *); // Called before main loop
103 int (*terminate)(void *); // Called after main loop
104 int (*pause)(void *); // Called when every window goes back
105 int (*resume)(void *); // Called when any window comes on top
106 int (*reset)(bundle *, void *); // Called at the first idler and every relaunching
111 @defgroup SLP_PG_APPCORE2 2.Appcore event handling
112 @ingroup SLP_PG_APPCORE
115 <h1 class="pg">Appcore event handling</h2>
116 An Application should perform an action when a system change occurs, such as the battery level goes low. Appcore provides APIs to handle the system changes notified by other frameworks and managers. The following figure shows the relationship between events and callback functions.
118 @image html SLP_Appcore_PG_events.png
120 Appcore provides appcore_set_event_callback() to handle events from the system. If you set the callback function, it will be called when the event received. Otherwise, Appcore does default behavior which is defined as following.
125 <th>Default behavior</th>
128 <td>APPCORE_EVENT_LOW_MEMORY</td>
129 <td>A system memory goes low</td>
130 <td>call malloc_trim() to enforce giving back the freed memory</td>
133 <td>APPCORE_EVENT_LOW_BATTERY</td>
134 <td>A system is out of battery</td>
135 <td>Quit the main loop</td>
138 <td>APPCORE_EVENT_LANG_CHANGE</td>
139 <td>A system's language setting is changed</td>
140 <td>Reset the environment variable "LANG". This has influence on the function related to internationalization</td>
146 @defgroup SLP_PG_APPCORE3 3.Internationalization
147 @ingroup SLP_PG_APPCORE
150 <h1 class="pg">Internationalization</h3>
151 SLP platform uses GNU gettext for Internationalization.
152 The process of using gettext is as follows:
153 -# Marking any phrases to be translated using gettext(“phrase”) or gettext_noop(“phrase”)
154 -# Generating a <I>po</I> file by extracting marked phrases using a <I>xgettext</I> command.
155 -# Modifying the <I>po</I> file and entering a translated phrase for the corresponding phrase.
156 -# Compiling a <I>po</I> file into a <I>mo</I> file using a <I>msgfmt</I> command.
157 -# Installing <I>mo</I> files into proper locale directories.
158 -# gettext() returns a properly translated phrase while an application is running.
160 For example, we have the following source code
162 printf(“%s\n”, gettext(“Hello”));
165 Then, as you can see, we can have the following po file using xgettext,
172 And we can enter a translated phrase as the following,
176 msgstr "안녕하세요" // Hello in Korean
179 Finally we generate and install a mo file. In doing so, an application will print out "안녕하세요" instead of "Hello", if the applied language is Korean.
181 appcore_set_i18n() has been introduced to achieve an internationalization which requires information on a mo file's name and its installed directory.
183 int appcore_set_i18n(const char *domainname, const char *dirname)
186 The first parameter, <I>domainname</I>, a mo file’s name and the second one, <I>dirname</I>, is the directory.<br>
187 In general, a mo file will be installed in the following fashion, <I>dirname/locale/category/domainname.mo</I>. <I>locale</I> is a locale’s name, such as ‘ko’ and ‘ja’, and category is LC_MESSAGES. For instance, a mo file has been installed in /usr/share/locale/ko/LC_MESSAGES/example.mo, and then <I>dirname</I> becomes /usr/share/locale.<br>
188 Typically, mo files will be installed in ${prefix}/share/locale.
190 Generally the following macros are defined for easy to use gettext()
192 #define _(str) gettext(str)
193 #define gettext_noop(str) (str)
194 #define N_(str) gettext_noop(str)
197 N_() macro only extracts any marked phrases using xgettext command, it will not do anything in the action. This macro is used to handle an array of phrases. Since gettext() cannot be called in declaration of an array, we let N_() macro extract phrases and then call gettext(). Let’s look at the following example.
200 static const char *messages[] = {
205 printf(“Message: %s\n”, _(messages[0]);
209 In doing so, we now can handle phrases in an array as same as we do for the following.
212 printf(“Message: %s\n”, _(“Hello”);
215 For more details, refer to GNU gettext manual (http://www.gnu.org/software/gettext/manual/gettext.html)
218 @defgroup SLP_PG_APPCORE4 4.Rotation
219 @ingroup SLP_PG_APPCORE
222 <h1 class="pg">Rotation</h3>
223 An Application can display its UI in either landscape or portrait mode. The application registers to receive rotation events from the system with the appcore_set_rotation_cb() API. The system automatically calls the registered user's callback whenever the sensor framework detects that the current rotation status has changed. This continues until appcore_unset_rotation_cb() is called.
228 APPCORE_RM_PORTRAIT_NORMAL , // Portrait mode
229 APPCORE_RM_PORTRAIT_REVERSE , // Portrait upside down mode
230 APPCORE_RM_LANDSCAPE_NORMAL , // Left handed landscape mode
231 APPCORE_RM_LANDSCAPE_REVERSE , // Right handed landscape mode
234 int appcore_set_rotation_cb(int (*cb)(enum appcore_rm, void *), void *data);
235 int appcore_unset_rotation_cb(void);
236 int appcore_get_rotation_state(enum appcore_rm *curr);
239 <I>enum appcore_rm</I> has portrait, portrait upside down, left handed landscape, and right handed landscape mode. The following is an each mode.
240 @image html SLP_Appcore_PG_rotation.png
242 When the registered callback is called, it receives the current mode state as the first argument. According to the received mode state, the application should rotate the window, resize window to changed screen size and composite the screen.
245 @defgroup SLP_PG_APPCORE5 5.Using code template
246 @ingroup SLP_PG_APPCORE
249 <h1 class="pg">Using code template</h1>
250 We provide a code template for reference and convenience. You can generate a code template using the script "app-gen.sh" which is included in the <I>app-template</I> package.
255 Usage) app-gen.sh dest app_name [EFL|GTK]
256 app_name does not support _ string because of debian usage."
260 # app-gen.sh ~/efl_app MyApp
263 # app-gen.sh /home/app/gtk_app TestApp GTK
267 Let's make a simple application using template
268 -# Install <I>app-template</I> package
270 # apt-get install app-template
272 -# Generate a code template
274 # app-gen.sh ~/apps/simple simple EFL
279 # dpkg-buildpackage -sa -rfakeroot
282 @defgroup SLP_PG_APPCORE6 6.Example: EFL Apps
283 @ingroup SLP_PG_APPCORE
286 <h1 class="pg">Example: EFL application</h1>
290 12 #ifndef __APP_COMMON_H__
291 13 #define __APP_COMMON_H__
293 15 #include <Elementary.h>
295 17 #if !defined(PACKAGE)
296 18 # define PACKAGE "example" // for appcore_set_i18n()
299 21 #if !defined(LOCALEDIR)
300 22 # define LOCALEDIR "/opt/apps/com.slp.example/share/locale" // for appcore_set_i18n()
303 25 #if !defined(EDJDIR)
304 26 # define EDJDIR "/opt/apps/com.slp.example/share/edje"
307 29 #define EDJ_FILE EDJDIR "/" PACKAGE ".edj"
308 30 #define GRP_MAIN "main"
313 35 Evas_Object *ly_main;
315 37 // add more variables here
318 40 #endif // __APP_COMMON_H__
323 12 #include <stdio.h>
324 13 #include <appcore-efl.h>
325 14 #include <Ecore_X.h>
327 16 #include "example.h"
329 18 struct text_part { // this for internationalization
334 23 static struct text_part main_txt[] = {
335 24 { "txt_title", N_("Application template"), },
336 25 { "txt_mesg", N_("Click to exit"), }, // N_() is do nothing. Only for extracting the string
340 29 static void win_del(void *data, Evas_Object *obj, void *event)
345 34 static void main_quit_cb(void *data, Evas_Object *obj,
346 35 const char *emission, const char *source)
351 40 static void update_ts(Evas_Object *eo, struct text_part *tp, int size)
355 44 if (eo == NULL || tp == NULL || size < 0)
358 47 for (i = 0; i < size; i++) {
359 48 if (tp[i].part && tp[i].msgid)
360 49 edje_object_part_text_set(eo,
361 50 tp[i].part, _(tp[i].msgid)); // _() return translated string
365 54 static int lang_changed(void *data) // language changed callback
367 56 struct appdata *ad = data;
369 58 if (ad->ly_main == NULL)
372 61 update_ts(elm_layout_edje_get(ad->ly_main), main_txt,
373 62 sizeof(main_txt)/sizeof(main_txt[0]));
378 67 static int rotate(enum appcore_rm m, void *data) // rotation callback
380 69 struct appdata *ad = data;
383 72 if (ad == NULL || ad->win == NULL)
387 76 case APPCORE_RM_PORTRAIT_NORMAL:
390 79 case APPCORE_RM_PORTRAIT_REVERSE:
393 82 case APPCORE_RM_LANDSCAPE_NORMAL:
396 85 case APPCORE_RM_LANDSCAPE_REVERSE:
404 93 if (r >= 0) // Using this API, you can implement the rotation mode easily
405 94 elm_win_rotation_with_resize_set(ad->win, r);
410 99 static Evas_Object* create_win(const char *name)
415 104 eo = elm_win_add(NULL, name, ELM_WIN_BASIC);
417 106 elm_win_title_set(eo, name);
418 107 elm_win_borderless_set(eo, EINA_TRUE);
419 108 evas_object_smart_callback_add(eo, "delete,request",
421 110 ecore_x_window_size_get(ecore_x_window_root_first_get(), // get root window(screen) size
423 112 evas_object_resize(eo, w, h);
429 118 static Evas_Object* load_edj(Evas_Object *parent, const char *file,
430 119 const char *group)
435 124 eo = elm_layout_add(parent);
437 126 r = elm_layout_file_set(eo, file, group);
439 128 evas_object_del(eo);
443 132 evas_object_size_hint_weight_set(eo,
444 133 EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
450 139 static int app_create(void *data)
452 141 struct appdata *ad = data;
453 142 Evas_Object *win;
458 147 win = create_win(PACKAGE);
464 153 ly = load_edj(win, EDJ_FILE, GRP_MAIN);
467 156 elm_win_resize_object_add(win, ly); // This can make the EDJE object fitted in window size
468 157 edje_object_signal_callback_add(elm_layout_edje_get(ly),
469 158 "EXIT", "*", main_quit_cb, NULL);
470 159 ad->ly_main = ly;
471 160 evas_object_show(ly);
473 166 lang_changed(ad); // call the language changed callback to update strings
475 168 evas_object_show(win);
477 170 // add system event callback
478 171 appcore_set_event_callback(APPCORE_EVENT_LANG_CHANGE,
479 172 lang_changed, ad);
481 174 appcore_set_rotation_cb(rotate, ad); // set rotation callback
483 176 // appcore measure time example
484 177 printf("from AUL to %s(): %d msec\n", __func__,
485 178 appcore_measure_time_from("APP_START_TIME"));
487 180 appcore_measure_start();
491 184 static int app_terminate(void *data) // terminate callback
493 186 struct appdata *ad = data;
496 189 evas_object_del(ad->ly_main);
499 192 evas_object_del(ad->win);
504 197 static int app_pause(void *data) // pause callback
506 199 struct appdata *ad = data;
511 204 static int app_resume(void *data) // resume callback
513 206 struct appdata *ad = data;
518 211 static int app_reset(bundle *b, void *data) // reset callback
520 213 struct appdata *ad = data;
522 215 // appcore measure time example
523 216 printf("from AUL to %s(): %d msec\n", __func__,
524 217 appcore_measure_time_from("APP_START_TIME"));
525 218 printf("from create to %s(): %d msec\n", __func__,
526 219 appcore_measure_time());
529 222 elm_win_activate(ad->win); // You should make one of the window on top
534 227 int main(int argc, char *argv[])
536 229 struct appdata ad;
537 230 struct appcore_ops ops = { // fill the appcore_ops with callback functions
538 231 .create = app_create,
539 232 .terminate = app_terminate,
540 233 .pause = app_pause,
541 234 .resume = app_resume,
542 235 .reset = app_reset,
545 238 // appcore measure time example
546 239 printf("from AUL to %s(): %d msec\n", __func__,
547 240 appcore_measure_time_from("APP_START_TIME"));
549 242 memset(&ad, 0x0, sizeof(struct appdata));
552 245 return appcore_efl_main(PACKAGE, &argc, &argv, &ops); // start mainloop