summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Vasut <marex@denx.de>2022-03-20 22:58:36 +0100
committerTran Ba Khang(MS/EMC31-XC) <Khang.TranBa@vn.bosch.com>2023-03-20 14:23:35 +0700
commit85be38aed104e41311763361052364f02702d8b4 (patch)
tree554d9859d564f6edcadb9d810f339071d8271b12
parentb090cb09fbf7fec9e18fc76c5ba31ac9adc76e74 (diff)
downloadwayland-ivi-extension-85be38aed104e41311763361052364f02702d8b4.tar.gz
ilmControl: Extend screenshot API with callback support
Extend the screenshot API such that it permits user to add their own hooks into screenshot_done and screenshot_err callbacks. This way, the user can obtain the FD with the screenshot and process it instead of having the screenshot written into a file in /tmp directory. Make the filename optional, so the user can provide only the callbacks and skip writing the file into /tmp altogether. The library ABI is unaffected, the new functionality is added via two library functions, ilm_takeScreenshot5() and ilm_takeSurfaceScreenshot5(), which are now internally called by their original counterparts with callback hooks set to NULL. Signed-off-by: Marek Vasut <marex@denx.de> [khangtb: rename the name of functions, ilm_takeAsyncScreenshot() and ilm_takeAsyncSurfaceScreenshot(). Define typedef for notification callbacks. Correct the minor things. remove the filename input from the function, make the non-blocking] Signed-off-by: Tran Ba Khang(MS/EMC31-XC) <Khang.TranBa@vn.bosch.com>
-rw-r--r--ivi-layermanagement-api/ilmCommon/include/ilm_types.h29
-rw-r--r--ivi-layermanagement-api/ilmControl/include/ilm_control.h35
-rw-r--r--ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c145
3 files changed, 180 insertions, 29 deletions
diff --git a/ivi-layermanagement-api/ilmCommon/include/ilm_types.h b/ivi-layermanagement-api/ilmCommon/include/ilm_types.h
index 98a8e62..64e30a7 100644
--- a/ivi-layermanagement-api/ilmCommon/include/ilm_types.h
+++ b/ivi-layermanagement-api/ilmCommon/include/ilm_types.h
@@ -287,4 +287,33 @@ typedef void(*notificationFunc)(ilmObjectType object,
typedef void(*shutdownNotificationFunc)(t_ilm_shutdown_error_type error_type,
int errornum,
void* user_data);
+
+/**
+ * Typedef for notification callback on screenshot send done event
+ * @param user_data the use data, be passed when call the screenshot api
+ * @param fd fd for file containing image data, don't close it in callback,
+ * it will be closed and shouldn't be accessed any longer after the callback execution.
+ * @param width image width in pixels
+ * @param height image height in pixels
+ * @param stride number of bytes per pixel row
+ * @param format image format of type wl_shm.format
+ * @param timestamp timestamp in milliseconds
+ */
+typedef ilmErrorTypes(*screenshotDoneNotificationFunc)(void *user_data,
+ t_ilm_int fd,
+ t_ilm_uint width,
+ t_ilm_uint height,
+ t_ilm_uint stride,
+ t_ilm_uint format,
+ t_ilm_uint timestamp);
+
+/**
+ * Typedef for notification callback on screenshot send error event
+ * @param user_data the use data, be passed when call the screenshot api
+ * @param error error code
+ * @param message error description
+ */
+typedef void(*screenshotErrorNotificationFunc)(void *user_data,
+ t_ilm_uint error,
+ const char *message);
#endif /* _ILM_TYPES_H_*/
diff --git a/ivi-layermanagement-api/ilmControl/include/ilm_control.h b/ivi-layermanagement-api/ilmControl/include/ilm_control.h
index 71e4968..c67152a 100644
--- a/ivi-layermanagement-api/ilmControl/include/ilm_control.h
+++ b/ivi-layermanagement-api/ilmControl/include/ilm_control.h
@@ -366,6 +366,23 @@ ilmErrorTypes ilm_displaySetRenderOrder(t_ilm_display display, t_ilm_layer *pLay
ilmErrorTypes ilm_takeScreenshot(t_ilm_uint screen, t_ilm_const_string filename);
/**
+ * \brief Take a screenshot from the current displayed layer scene with non-blocking.
+ * The function allows to setup callbacks when capturing the display,
+ * It helps to avoid a blocking, user can handle screenshot data or error in
+ * the callbacks.
+ * \param[in] screen Id of screen where screenshot should be taken
+ * \param[in] callback_done callback called when screenshot is acquired
+ * \param[in] callback_error callback called when screenshot acqusition failed
+ * \param[in] user_data callback user data passed in by called
+ * \return ILM_SUCCESS if the method call was successful
+ * \return ILM_FAILED if the client can not call the method on the service.
+ */
+ilmErrorTypes ilm_takeAsyncScreenshot(t_ilm_uint screen,
+ screenshotDoneNotificationFunc callback_done,
+ screenshotErrorNotificationFunc callback_error,
+ void *user_data);
+
+/**
* \brief Take a screenshot of a certain surface
* The screenshot is saved as bmp file with the corresponding filename.
* \ingroup ilmControl
@@ -377,6 +394,24 @@ ilmErrorTypes ilm_takeScreenshot(t_ilm_uint screen, t_ilm_const_string filename)
ilmErrorTypes ilm_takeSurfaceScreenshot(t_ilm_const_string filename, t_ilm_surface surfaceid);
/**
+ * \brief Take a screenshot of a certain surface with non-blocking.
+ * The function allows to setup callbacks when capturing a surface,
+ * It helps to avoid a blocking, user can handle screenshot data or error in
+ * the callbacks.
+ * \ingroup ilmControl
+ * \param[in] surfaceid Identifier of the surface to take the screenshot of
+ * \param[in] callback_done callback called when screenshot is acquired
+ * \param[in] callback_error callback called when screenshot acqusition failed
+ * \param[in] user_data callback user data passed in by called
+ * \return ILM_SUCCESS if the method call was successful
+ * \return ILM_FAILED if the client can not call the method on the service.
+ */
+ilmErrorTypes ilm_takeAsyncSurfaceScreenshot(t_ilm_surface surfaceid,
+ screenshotDoneNotificationFunc callback_done,
+ screenshotErrorNotificationFunc callback_error,
+ void *user_data);
+
+/**
* \brief register for notification on property changes of layer
* \ingroup ilmControl
* \param[in] layer id of layer to register for notification
diff --git a/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c b/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c
index b4fdfbf..97e4e6d 100644
--- a/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c
+++ b/ivi-layermanagement-api/ilmControl/src/ilm_control_wayland_platform.c
@@ -70,6 +70,9 @@ struct screen_context {
struct screenshot_context {
const char *filename;
ilmErrorTypes result;
+ screenshotDoneNotificationFunc callback_done;
+ screenshotErrorNotificationFunc callback_error;
+ void *callback_priv;
};
static inline void lock_context(struct ilm_control_context *ctx)
@@ -2126,9 +2129,17 @@ static void screenshot_done(void *data, struct ivi_screenshot *ivi_screenshot,
ctx_scrshot->filename = NULL;
ivi_screenshot_destroy(ivi_screenshot);
- if (filename == NULL) {
- ctx_scrshot->result = ILM_FAILED;
- fprintf(stderr, "screenshot file name not provided: %m\n");
+ if (ctx_scrshot->callback_done)
+ if (ctx_scrshot->callback_done(ctx_scrshot->callback_priv,
+ fd, width, height, stride, format, timestamp) == ILM_FAILED) {
+ ctx_scrshot->result = ILM_FAILED;
+ close(fd);
+ return;
+ }
+ // if filename is null, free resource and return
+ if (!filename) {
+ close(fd);
+ free(ctx_scrshot);
return;
}
@@ -2170,9 +2181,15 @@ static void screenshot_error(void *data, struct ivi_screenshot *ivi_screenshot,
uint32_t error, const char *message)
{
struct screenshot_context *ctx_scrshot = data;
+ const char *filename = ctx_scrshot->filename;
ctx_scrshot->filename = NULL;
ivi_screenshot_destroy(ivi_screenshot);
+ if (ctx_scrshot->callback_error)
+ ctx_scrshot->callback_error(ctx_scrshot->callback_priv, error, message);
fprintf(stderr, "screenshot failed, error 0x%x: %s\n", error, message);
+ // free resource
+ if (!filename)
+ free(ctx_scrshot);
}
static struct ivi_screenshot_listener screenshot_listener = {
@@ -2180,76 +2197,146 @@ static struct ivi_screenshot_listener screenshot_listener = {
screenshot_error,
};
-ILM_EXPORT ilmErrorTypes
-ilm_takeScreenshot(t_ilm_uint screen, t_ilm_const_string filename)
+static ilmErrorTypes
+ilm_takeShoot(t_ilm_uint screen, t_ilm_const_string filename,
+ screenshotDoneNotificationFunc callback_done,
+ screenshotErrorNotificationFunc callback_error,
+ void *user_data)
{
ilmErrorTypes returnValue = ILM_FAILED;
struct ilm_control_context *const ctx = &ilm_context;
struct screen_context *ctx_scrn = NULL;
+ // if filename, callback_done and callback_error are null, don't do anything, then return success
+ if (!filename && !callback_done && !callback_error) {
+ return ILM_SUCCESS;
+ }
+
lock_context(ctx);
ctx_scrn = get_screen_context_by_id(&ctx->wl, (uint32_t)screen);
if (ctx_scrn != NULL) {
- struct screenshot_context ctx_scrshot = {
- .filename = filename,
- .result = ILM_FAILED,
- };
+ struct screenshot_context *ctx_scrshot = calloc(1, sizeof(struct screenshot_context));
- struct ivi_screenshot *scrshot =
- ivi_wm_screen_screenshot(ctx_scrn->controller);
+ if (!ctx_scrshot) {
+ fprintf(stderr, "Failed to allocate memory for screenshot_context\n");
+ goto exit;
+ }
+ ctx_scrshot->filename = filename;
+ ctx_scrshot->result = ILM_FAILED;
+ ctx_scrshot->callback_done = callback_done;
+ ctx_scrshot->callback_error = callback_error;
+ ctx_scrshot->callback_priv = user_data;
+
+ struct ivi_screenshot *scrshot = ivi_wm_screen_screenshot(ctx_scrn->controller);
if (scrshot) {
- ivi_screenshot_add_listener(scrshot, &screenshot_listener,
- &ctx_scrshot);
+ ivi_screenshot_add_listener(scrshot, &screenshot_listener, ctx_scrshot);
+ // don't need to wait if file name is empty
+ if (!filename) {
+ wl_display_flush(ctx->wl.display);
+ returnValue = ILM_SUCCESS;
+ goto exit;
+ }
// dispatch until filename has been reset in done or error callback
int ret;
do {
ret =
wl_display_dispatch_queue(ctx->wl.display, ctx->wl.queue);
- } while ((ret != -1) && ctx_scrshot.filename);
+ } while ((ret != -1) && ctx_scrshot->filename);
- returnValue = ctx_scrshot.result;
+ returnValue = ctx_scrshot->result;
}
+ free(ctx_scrshot);
}
+exit:
unlock_context(ctx);
-
return returnValue;
}
ILM_EXPORT ilmErrorTypes
-ilm_takeSurfaceScreenshot(t_ilm_const_string filename,
- t_ilm_surface surfaceid)
+ilm_takeAsyncScreenshot(t_ilm_uint screen,
+ screenshotDoneNotificationFunc callback_done,
+ screenshotErrorNotificationFunc callback_error,
+ void *user_data)
+{
+ return ilm_takeShoot(screen, NULL, callback_done, callback_error, user_data);
+}
+
+ILM_EXPORT ilmErrorTypes
+ilm_takeScreenshot(t_ilm_uint screen, t_ilm_const_string filename)
+{
+ return ilm_takeShoot(screen, filename, NULL, NULL, NULL);
+}
+
+static ilmErrorTypes
+ilm_takeSurfaceShoot(t_ilm_surface surfaceid, t_ilm_const_string filename,
+ screenshotDoneNotificationFunc callback_done,
+ screenshotErrorNotificationFunc callback_error,
+ void *user_data)
{
ilmErrorTypes returnValue = ILM_FAILED;
struct ilm_control_context *const ctx = &ilm_context;
+ // if filename, callback_done and callback_error are null, don't do anything, then return success
+ if (!filename && !callback_done && !callback_error) {
+ return ILM_SUCCESS;
+ }
+
lock_context(ctx);
if (ctx->wl.controller) {
- struct screenshot_context ctx_scrshot = {
- .filename = filename,
- .result = ILM_FAILED,
- };
+ struct screenshot_context *ctx_scrshot = calloc(1, sizeof(struct screenshot_context));
- struct ivi_screenshot *scrshot =
- ivi_wm_surface_screenshot(ctx->wl.controller, surfaceid);
+ if (!ctx_scrshot) {
+ fprintf(stderr, "Failed to allocate memory for screenshot_context\n");
+ goto exit;
+ }
+ ctx_scrshot->filename = filename;
+ ctx_scrshot->result = ILM_FAILED;
+ ctx_scrshot->callback_done = callback_done;
+ ctx_scrshot->callback_error = callback_error;
+ ctx_scrshot->callback_priv = user_data;
+
+ struct ivi_screenshot *scrshot = ivi_wm_surface_screenshot(ctx->wl.controller, surfaceid);
if (scrshot) {
- ivi_screenshot_add_listener(scrshot, &screenshot_listener,
- &ctx_scrshot);
+ ivi_screenshot_add_listener(scrshot, &screenshot_listener, ctx_scrshot);
+ // don't need to wait if file name is empty
+ if (!filename) {
+ wl_display_flush(ctx->wl.display);
+ returnValue = ILM_SUCCESS;
+ goto exit;
+ }
// dispatch until filename has been reset in done or error callback
int ret;
do {
ret =
wl_display_dispatch_queue(ctx->wl.display, ctx->wl.queue);
- } while ((ret != -1) && ctx_scrshot.filename);
+ } while ((ret != -1) && ctx_scrshot->filename);
- returnValue = ctx_scrshot.result;
+ returnValue = ctx_scrshot->result;
}
+ free(ctx_scrshot);
}
+exit:
unlock_context(ctx);
-
return returnValue;
}
ILM_EXPORT ilmErrorTypes
+ilm_takeAsyncSurfaceScreenshot(t_ilm_surface surfaceid,
+ screenshotDoneNotificationFunc callback_done,
+ screenshotErrorNotificationFunc callback_error,
+ void *user_data)
+{
+ return ilm_takeSurfaceShoot(surfaceid, NULL, callback_done, callback_error, user_data);
+}
+
+ILM_EXPORT ilmErrorTypes
+ilm_takeSurfaceScreenshot(t_ilm_const_string filename,
+ t_ilm_surface surfaceid)
+{
+ return ilm_takeSurfaceShoot(surfaceid, filename, NULL, NULL, NULL);
+}
+
+ILM_EXPORT ilmErrorTypes
ilm_layerAddNotification(t_ilm_layer layer,
layerNotificationFunc callback)
{