3 #include "xcnphandler.h"
4 #include "scrcapture.h"
5 #include "clipdrawer.h"
12 #include <Ecore_Input.h>
15 #define IMAGE_SAVE_DIR "/opt/media/Images and videos/My photo clips"
16 #define IMAGE_SAVE_FILE_TYPE ".png"
17 #define CAPTURE_SOUND_FILE "/usr/share/cbhm/sounds/14_screen_capture.wav"
18 #define CAPTURE_SOUND_TIMEOUT_SEC 2
20 #include <mmf/mm_sound_private.h>
25 static pthread_mutex_t g_sound_lock = PTHREAD_MUTEX_INITIALIZER;
26 static pthread_cond_t g_sound_cond = PTHREAD_COND_INITIALIZER;
27 static Eina_Bool g_shot = EINA_FALSE;
29 typedef struct tag_captureimginfo
36 static Eina_Bool get_image_filename_with_date(char *dstr)
38 time_t tim = time(NULL);
39 struct tm *now = localtime(&tim);
41 gettimeofday(&tv, NULL);
42 sprintf(dstr, "%s/screen-%d%02d%02d%02d%02d%02d%0ld%s",
44 now->tm_year+1900, now->tm_mon+1, now->tm_mday,
45 now->tm_hour, now->tm_min,
46 now->tm_sec, tv.tv_usec,
47 IMAGE_SAVE_FILE_TYPE);
51 static void _sound_callback(void *data)
53 DTRACE("_sound_callback\n");
54 pthread_cond_broadcast(&g_sound_cond);
58 static void _play_capture_sound()
60 int ret, step, handle;
61 MMSoundParamType pparam = {0,};
62 Eina_Bool sync = EINA_FALSE;
63 struct timespec timeout;
65 ret = mm_sound_set_path(MM_SOUND_GAIN_CAMERA, MM_SOUND_PATH_SPK, MM_SOUND_PATH_NONE, MM_SOUND_PATH_OPTION_NONE);
66 if (ret != MM_ERROR_NONE)
68 DTRACE("mm_sound_set_path is failed\n");
71 ret = mm_sound_volume_get_step(VOLUME_TYPE_FIXED, &step);
72 if (ret != MM_ERROR_NONE)
74 DTRACE("mm_sound_volume_get_step is failed\n");
77 if (pthread_mutex_trylock(&g_sound_lock) == EBUSY)
79 DTRACE("trylock is fail - g_sound_lock\n");
82 pparam.filename = CAPTURE_SOUND_FILE;
84 pparam.volume = step-1;
85 pparam.callback = _sound_callback;
87 if (mm_sound_play_loud_solo_sound(CAPTURE_SOUND_FILE,
88 VOLUME_TYPE_FIXED, _sound_callback,
94 gettimeofday(&tv, NULL);
95 timeout.tv_sec = tv.tv_sec + CAPTURE_SOUND_TIMEOUT_SEC;
96 timeout.tv_nsec = tv.tv_usec;
97 if(ETIMEDOUT == pthread_cond_timedwait(&g_sound_cond, &g_sound_lock, &timeout))
100 mm_sound_stop_sound(handle);
106 DTRACE("effect sound play failed\n");
107 pthread_mutex_unlock(&g_sound_lock);
110 pthread_mutex_unlock(&g_sound_lock);
111 DTRACE("sound play success\n");
114 static Eina_Bool _scrcapture_capture_postprocess(void* data)
116 captureimginfo_t *capimginfo = data;
118 DTIME("start capture postprocess - %s\n", capimginfo->filename);
120 if (!evas_object_image_save(capimginfo->eo, capimginfo->filename, NULL, "compress=1"))
122 DTRACE("screen capture save fail\n");
127 DTIME("end capture postprocess - %s\n", capimginfo->filename);
129 char *imgpath = NULL;
130 imgpath = malloc(strlen(capimginfo->filename)+strlen("file://")+2);
131 snprintf(imgpath, strlen(capimginfo->filename)+strlen("file://")+1,
132 "%s%s", "file://", capimginfo->filename);
133 DTRACE("add to image history = %s\n", imgpath+strlen("file://"));
134 clipdrawer_add_item(imgpath+strlen("file://"), GI_IMAGE);
137 evas_object_del(capimginfo->eo);
138 free(capimginfo->imgdata);
141 DTIME("end current capture\n");
143 _play_capture_sound();
150 Eina_Bool capture_current_screen(void *data)
152 struct appdata *ad = data;
156 DTRACE("too early to capture current screen\n");
161 DTIME("start current capture\n");
163 captureimginfo_t *capimginfo = NULL;
164 capimginfo = malloc(sizeof(captureimginfo_t) * 1);
165 get_image_filename_with_date(capimginfo->filename);
166 DTRACE("capture current screen\n");
171 capimginfo->imgdata = malloc(sizeof(char) * (width*height*4) + 1);
172 capimginfo->eo = evas_object_image_add(ad->evas);
174 char *scrimage = NULL;
175 scrimage = scrcapture_capture_screen_by_xv_ext(width, height);
177 memcpy(capimginfo->imgdata, scrimage, width*height*4);
178 scrcapture_release_screen_by_xv_ext(scrimage);
180 if (scrimage == NULL || capimginfo->eo == NULL || capimginfo->imgdata == NULL)
182 DTRACE("screen capture fail\n");
183 free(capimginfo->imgdata);
185 evas_object_del(capimginfo->eo);
191 DTRACE("screen capture prepared\n");
193 evas_object_image_data_set(capimginfo->eo, NULL);
194 evas_object_image_size_set(capimginfo->eo, width, height);
195 evas_object_image_data_set(capimginfo->eo, capimginfo->imgdata);
196 evas_object_image_data_update_add(capimginfo->eo, 0, 0, width, height);
197 evas_object_resize(capimginfo->eo, width, height);
199 ecore_idler_add(_scrcapture_capture_postprocess, capimginfo);
204 static Eina_Bool scrcapture_keydown_cb(void *data, int type, void *event)
206 struct appdata *ad = data;
207 Ecore_Event_Key *ev = event;
209 if (!strcmp(ev->keyname, KEY_END))
210 clipdrawer_lower_view(ad);
212 return ECORE_CALLBACK_PASS_ON;
215 int init_scrcapture(void *data)
217 struct appdata *ad = data;
222 Ecore_X_Display *xdisp = ecore_x_display_get();
223 Ecore_X_Window xwin = (Ecore_X_Window)ecore_evas_window_get(ecore_evas_ecore_evas_get(ad->evas));
225 ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, scrcapture_keydown_cb, ad);
227 pthread_mutex_init(&g_sound_lock, NULL);
228 pthread_cond_init(&g_sound_cond, NULL);
233 void close_scrcapture(void *data)
235 struct appdata *ad = data;
237 Ecore_X_Display *xdisp = ecore_x_display_get();
238 Ecore_X_Window xwin = (Ecore_X_Window)ecore_evas_window_get(ecore_evas_ecore_evas_get(ad->evas));
240 pthread_mutex_destroy(&g_sound_lock);
241 pthread_cond_destroy(&g_sound_cond);
245 inline static Ecore_X_Display *get_display(void)
247 return ecore_x_display_get();
250 static int get_window_attribute(Window id, int *depth, Visual **visual, int *width, int *height)
253 XWindowAttributes attr;
255 DTRACE("XGetWindowAttributes\n");
256 if (!XGetWindowAttributes(get_display(), id, &attr))
261 if (attr.map_state == IsViewable && attr.class == InputOutput)
265 *height= attr.height;
266 *visual= attr.visual;
272 static Window _get_parent_window( Window id )
279 DTRACE("XQeuryTree\n");
281 if (!XQueryTree(get_display(), id, &root, &parent, &children, &num))
295 static Window find_capture_available_window( Window id, Visual** visual, int* depth, int* width, int* height)
297 XWindowAttributes attr;
309 DTRACE("find_capture - XGetWindowAttributes\n");
311 if (!XGetWindowAttributes(get_display(), id, &attr))
316 parent = _get_parent_window( id );
318 if (attr.map_state == IsViewable
319 && attr.override_redirect == True
320 && attr.class == InputOutput && parent == attr.root )
324 *height = attr.height;
325 *visual = attr.visual;
328 } while( parent != attr.root && parent != 0 ); //Failed finding a redirected window
331 DTRACE( "find_capture - cannot find id\n");
332 XGetWindowAttributes (get_display(), orig_id, &attr);
335 *height = attr.height;
336 *visual = attr.visual;
342 char *scrcapture_screen_capture(Window oid, int *size)
351 char *captured_image;
354 id = find_capture_available_window(ecore_x_window_focus_get(), &visual, &depth, &width, &height);
356 if (id == 0 || id == -1 || id == oid)
358 DTRACE("Window : 0x%lX\n", id);
359 if (get_window_attribute(id, &depth, &visual, &width, &height) < 0)
361 DTRACE("Failed to get the attributes from 0x%x\n", (unsigned int)id);
366 DTRACE("WxH : %dx%d\n", width, height);
367 DTRACE("Depth : %d\n", depth >> 3);
369 // NOTE: just add one more depth....
370 si.shmid = shmget(IPC_PRIVATE, width * height * ((depth >> 3)+1), IPC_CREAT | 0666);
373 DTRACE("error at shmget\n");
377 si.shmaddr = shmat(si.shmid, NULL, 0);
378 if (si.shmaddr == (char*)-1)
381 shmctl(si.shmid, IPC_RMID, 0);
382 DTRACE("can't get shmat\n");
387 if (!need_redirecting)
390 if (get_border_window(id, &border) < 0)
392 need_redirecting = 1;
393 printf("Failed to find a border, forcely do redirecting\n");
398 printf("Border window is found, use it : 0x%X\n", (unsigned int)id);
402 if (need_redirecting)
404 printf("XCompositeRedirectWindow");
405 XCompositeRedirectWindow(get_display(), id, CompositeRedirectManual);
410 DTRACE("XShmCreateImage\n");
411 xim = XShmCreateImage(get_display(), visual, depth, ZPixmap, NULL, &si, width, height);
415 shmctl(si.shmid, IPC_RMID, 0);
418 if (need_redirecting)
420 printf("XCompositeUnredirectWindow");
421 XCompositeUnredirectWindow(get_display(), id, CompositeRedirectManual);
427 *size = xim->bytes_per_line * xim->height;
428 xim->data = si.shmaddr;
430 DTRACE("XCompositeNameWindowPixmap\n");
431 pix = XCompositeNameWindowPixmap(get_display(), id);
433 DTRACE("XShmAttach\n");
434 XShmAttach(get_display(), &si);
436 DTRACE("XShmGetImage\n");
437 XShmGetImage(get_display(), pix, xim, 0, 0, 0xFFFFFFFF);
439 //XUnmapWindow(disp, id);
440 //XMapWindow(disp, id);
442 XSync(get_display(), False);
445 // We can optimize this!
446 captured_image = calloc(1, *size);
449 memcpy(captured_image, xim->data, *size);
453 DTRACE("calloc error");
456 DTRACE("XShmDetach");
457 XShmDetach(get_display(), &si);
458 DTRACE("XFreePixmap\n");
459 XFreePixmap(get_display(), pix);
460 DTRACE("XDestroyImage\n");
464 if (need_redirecting) {
465 printf("XCompositeUnredirectWindow");
466 XCompositeUnredirectWindow(get_display(), id, CompositeRedirectManual);
471 shmctl(si.shmid, IPC_RMID, 0);
472 return captured_image;
475 char *scrcapture_capture_screen_by_x11(Window xid, int *size)
482 char *captured_image;
485 DTRACE("Window : 0x%lX\n", xid);
486 if (get_window_attribute(xid, &depth, &visual, &width, &height) < 0)
488 DTRACE("Failed to get the attributes from 0x%x\n", (unsigned int)xid);
492 DTRACE("WxH : %dx%d\n", width, height);
493 DTRACE("Depth : %d\n", depth >> 3);
495 xim = XGetImage(get_display(), xid, 0, 0,
496 width, height, AllPlanes, ZPixmap);
498 *size = xim->bytes_per_line * xim->height;
500 captured_image = calloc(1, *size);
503 memcpy(captured_image, xim->data, *size);
507 DTRACE("calloc error");
510 return captured_image;
513 char *scrcapture_capture_screen_by_xv_ext(int w, int h)
515 return createScreenShot(w, h);
518 void scrcapture_release_screen_by_xv_ext(const char *s)
520 releaseScreenShot(s);