4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
8 * Jaewon Lim <jaewon81.lim@samsung.com>
9 * Woojin Jung <woojin2.jung@samsung.com>
10 * Juyoung Kim <j0.kim@samsung.com>
11 * Anastasia Lyupa <a.lyupa@samsung.com>
13 * This library is free software; you can redistribute it and/or modify it under
14 * the terms of the GNU Lesser General Public License as published by the
15 * Free Software Foundation; either version 2.1 of the License, or (at your option)
18 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
19 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
21 * License for more details.
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with this library; if not, write to the Free Software Foundation, Inc., 51
25 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 * - Samsung RnD Institute Russia
33 * We refer to the Evas example source code with BSD
34 * (Evas/src/examples/evas-buffer-simple.c)
38 #include <stdlib.h> // for system
39 #include <sys/types.h> // for stat, getpid
40 #include <sys/stat.h> // fot stat, chmod
41 #include <unistd.h> // fot stat, getpid
42 #include <sys/shm.h> // for shmget, shmat
43 #include <pthread.h> // for mutex
46 #include <X11/Xutil.h>
47 #include <X11/extensions/XShm.h>
51 #include <Evas_Engine_Buffer.h>
53 #include "real_functions.h"
59 #define MAX_HEIGHT 720
60 #define CAPTURE_TIMEOUT 2.0
62 typedef struct _screenshot_data
66 XShmSegmentInfo x_shm_info;
70 int convert_image( void* srcbuf, void* dstbuf,
71 pixman_format_code_t src_format,
72 pixman_format_code_t dst_format,
73 int src_width, int src_height,
74 int dst_width, int dst_height,
77 pixman_image_t * src_img;
78 pixman_image_t * dst_img;
79 pixman_transform_t transform;
81 int src_stride, dst_stride;
88 return_val_if_fail (srcbuf != NULL, False);
89 return_val_if_fail (dstbuf != NULL, False);
90 return_val_if_fail (rotate <= 360 && rotate >= -360, False);
94 src_bpp = PIXMAN_FORMAT_BPP (src_format) / 8;
95 return_val_if_fail (src_bpp > 0, False);
97 dst_bpp = PIXMAN_FORMAT_BPP (dst_format) / 8;
98 return_val_if_fail (dst_bpp > 0, False);
100 rotate_step = (rotate + 360) / 90 % 4;
102 src_stride = src_width * src_bpp;
103 dst_stride = dst_width * dst_bpp;
105 src_img = pixman_image_create_bits (src_format, src_width, src_height, srcbuf, src_stride);
106 dst_img = pixman_image_create_bits (dst_format, dst_width, dst_height, dstbuf, dst_stride);
108 goto_if_fail (src_img != NULL, CANT_CONVERT);
109 goto_if_fail (dst_img != NULL, CANT_CONVERT);
111 pixman_transform_init_identity (&transform);
115 int c, s, tx = 0, ty = 0;
122 ty = pixman_int_to_fixed (dst_width);
128 tx = pixman_int_to_fixed (dst_width);
129 ty = pixman_int_to_fixed (dst_height);
135 tx = pixman_int_to_fixed (dst_height);
143 pixman_transform_rotate (&transform, NULL, c, s);
144 pixman_transform_translate (&transform, NULL, tx, ty);
147 pixman_image_set_transform (src_img, &transform);
149 pixman_image_composite (op, src_img, NULL, dst_img,
150 0, 0, 0, 0, 0, 0, dst_width, dst_height);
156 pixman_image_unref (src_img);
158 pixman_image_unref (dst_img);
164 static char* captureScreenShotX(int* pwidth, int* pheight, screenshot_data* sdata)
167 // Atom atom_rotation;
169 sdata->dpy = XOpenDisplay(NULL);
170 if(unlikely(sdata->dpy == NULL))
172 // XOpenDisplay failed!
176 *pwidth = DisplayWidth(sdata->dpy, DefaultScreen(sdata->dpy));
177 *pheight = DisplayHeight(sdata->dpy, DefaultScreen(sdata->dpy));
179 root = RootWindow(sdata->dpy, DefaultScreen(sdata->dpy));
181 sdata->ximage = XShmCreateImage(sdata->dpy, DefaultVisualOfScreen (DefaultScreenOfDisplay (sdata->dpy)), 24,
182 ZPixmap, NULL, &sdata->x_shm_info, (unsigned int)*pwidth, (unsigned int)*pheight);
184 if(sdata->ximage != NULL)
186 sdata->x_shm_info.shmid = shmget(IPC_PRIVATE, sdata->ximage->bytes_per_line * sdata->ximage->height, IPC_CREAT | 0777);
187 sdata->x_shm_info.shmaddr = sdata->ximage->data = shmat(sdata->x_shm_info.shmid, 0, 0);
188 sdata->x_shm_info.readOnly = False;
190 if(XShmAttach(sdata->dpy, &sdata->x_shm_info))
192 if(XShmGetImage(sdata->dpy, root, sdata->ximage, 0, 0, AllPlanes))
194 XSync (sdata->dpy, False);
195 return sdata->ximage->data;
199 ; // XShmGetImage failed !
202 XShmDetach (sdata->dpy, &sdata->x_shm_info);
206 ; // XShmAttach failed !
209 shmdt (sdata->x_shm_info.shmaddr);
210 shmctl (sdata->x_shm_info.shmid, IPC_RMID, NULL);
211 XDestroyImage(sdata->ximage);
212 sdata->ximage = NULL;
216 ; // XShmCreateImage failed!
222 static void releaseScreenShotX(screenshot_data* sdata)
226 XShmDetach (sdata->dpy, &sdata->x_shm_info);
227 shmdt (sdata->x_shm_info.shmaddr);
228 shmctl (sdata->x_shm_info.shmid, IPC_RMID, NULL);
229 XDestroyImage(sdata->ximage);
235 XCloseDisplay(sdata->dpy);
239 static Evas* create_canvas(int width, int height)
242 Evas_Engine_Info_Buffer *einfo;
246 method = evas_render_method_lookup("buffer");
247 if (unlikely(method <= 0))
249 //fputs("ERROR: evas was not compiled with 'buffer' engine!\n", stderr);
254 if (unlikely(canvas == NULL))
256 //fputs("ERROR: could not instantiate new evas canvas.\n", stderr);
260 evas_output_method_set(canvas, method);
261 evas_output_size_set(canvas, width, height);
262 evas_output_viewport_set(canvas, 0, 0, width, height);
264 einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(canvas);
265 if (unlikely(einfo == NULL))
267 //fputs("ERROR: could not get evas engine info!\n", stderr);
272 // ARGB32 is sizeof(int), that is 4 bytes, per pixel
273 pixels = real_malloc(width * height * sizeof(int));
274 if (unlikely(pixels == NULL)) {
275 //fputs("ERROR: could not allocate canvas pixels!\n", stderr);
280 einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32;
281 einfo->info.dest_buffer = pixels;
282 einfo->info.dest_buffer_row_bytes = width * sizeof(int);
283 einfo->info.use_color_key = 0;
284 einfo->info.alpha_threshold = 0;
285 einfo->info.func.new_update_region = NULL;
286 einfo->info.func.free_update_region = NULL;
288 if (unlikely(evas_engine_info_set(canvas,(Evas_Engine_Info*)einfo) == EINA_FALSE)) {
289 PRINTMSG("ERROR: could not set evas engine info!\n");
297 static void destroy_canvas(Evas* canvas)
299 Evas_Engine_Info_Buffer *einfo;
301 einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(canvas);
302 if (unlikely(einfo == NULL))
304 //fputs("ERROR: could not get evas engine info!\n", stderr);
309 free(einfo->info.dest_buffer);
315 char dstpath[MAX_PATH_LENGTH];
320 screenshot_data sdata;
321 probeInfo_t probeInfo;
323 static pthread_mutex_t captureScreenLock = PTHREAD_MUTEX_INITIALIZER;
325 pthread_mutex_lock(&captureScreenLock);
329 setProbePoint(&probeInfo);
331 scrimage = captureScreenShotX(&width, &height, &sdata);
334 ev = create_canvas(width, height);
335 if(likely(ev != NULL))
337 snprintf(dstpath, sizeof(dstpath),
338 SCREENSHOT_DIRECTORY "/%d_%d.png", getpid(),
339 probeInfo.eventIndex);
342 if((img = evas_object_image_add(ev)) != NULL)
345 evas_object_image_data_set(img, NULL);
346 evas_object_image_size_set(img, width, height);
347 evas_object_image_data_set(img, scrimage);
350 if(height > MAX_HEIGHT)
352 width = width * MAX_HEIGHT / height;
354 evas_object_resize(img, width, height);
355 evas_object_image_fill_set(img, 0, 0, width, height);
357 evas_object_image_data_update_add(img, 0, 0, width, height);
360 if(evas_object_image_save(img, dstpath, NULL, "compress=5") != 0)
362 chmod(dstpath, 0777);
364 /* welcome to the hell */
366 PREPARE_LOCAL_BUF_THOUGH((char *)&log);
369 LOCAL_BUF += offsetof(log_t, data);
370 /* pack screenshot name */
371 BUF_PTR = pack_string(LOCAL_BUF, dstpath); /* file name */
375 PACK_COMMON_BEGIN(MSG_PROBE_SCREENSHOT, API_ID_captureScreen, "", 0);
376 PACK_COMMON_END('d', 0, 0, 0);
377 PACK_SCREENSHOT(dstpath, getOrientation());
379 log.length = GET_MSG_LEN() + MSG_LEN_OFFSET + strlen(dstpath) + 1;
381 /* send all message */
382 printLog(&log, MSG_IMAGE);
386 // captureScreen : evas_object_image_save failed
392 // captureScreen : evas_object_image_add failed
398 // captureScreen : create canvas failed
404 // captureScreen : captureScreenShotX failed
409 releaseScreenShotX(&sdata);
415 pthread_mutex_unlock(&captureScreenLock);
419 int initialize_screencapture()
421 // remove all previous screenshot in dir
422 // remove_indir(SCREENSHOT_DIRECTORY);
424 // make screenshot directory
425 // mkdir(SCREENSHOT_DIRECTORY, 0777);
430 int finalize_screencapture()
435 // =======================================================================
436 // screen shot manipulation functions
437 // =======================================================================
439 static Eina_Bool _captureTimer(void __unused * data)
442 SCREENSHOT_TIMEOUT();
445 return ECORE_CALLBACK_CANCEL;
448 int activateCaptureTimer()
450 ecore_timer_add(CAPTURE_TIMEOUT, _captureTimer, NULL);
454 void _cb_render_post(void __unused * data, Evas __unused * e,
455 void __unused * eventinfo)