4 * Copyright 2013 Samsung Electronics Co., Ltd
6 * Licensed under the Flora License, Version 1.1 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://floralicense.org/license/
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
22 #include <page_preview.h>
24 #include <preview_coords.h>
25 #include <previewgen.h>
27 #include "pts_debug.h"
29 #include "preview_task_model.h"
32 #define PREVIEWGEN_EXECUTABLE BINDIR "/previewgen-tool"
33 #define SHADOW_SIZE_PX_X 10
34 #define SHADOW_SIZE_PX_Y 10
36 #define CMD_STR_MAX_LEN 1024
38 #define SINGLE_PAGE_PREVIEWGEN
41 /* TODO: task model destruction */
42 enum preview_task_type {
43 PREVIEW_TASK_EMPTY_PAGE,
49 struct preview_task_data {
51 enum preview_task_type task_type;
52 struct preview_conf conf;
53 char out_pic_fname[sizeof(PREVIEW_TEMP_DIR "/mobileprint_xxxx.ppm ")];
57 struct preview_model *pmodel;
58 struct preview_task_model *task_model;
59 char *previewgen_exe_cmd;
63 int init_preview_task_model(struct preview_task_model *model,
64 struct preview_engine *engine)
67 PTS_RETV_IF(model == NULL || engine == NULL, -1 , "Invalid argument");
69 /*model->task_count = MAX_PREVIEW_TASK_COUNT;
70 model->tasks = malloc(sizeof(struct preview_task) * model->task_count);
71 if (NULL == model->tasks) {
72 model->task_count = 0;
75 model->task_list = NULL;
76 model->previewgen_handle = NULL;
77 model->event_handler = NULL;
78 model->is_stop_processing = 0;
79 model->engine = engine;
81 //model->pdata = pdata;
87 int clear_preview_task_queue(struct preview_task_model *task_model)
90 PTS_RETV_IF(task_model == NULL , -1 , "Invalid argument");
92 struct preview_task_data *ptd;
95 if (task_model->task_list != NULL) {
97 EINA_LIST_FOREACH(task_model->task_list, cur, ptd) {
100 eina_list_free(task_model->task_list);
102 task_model->task_list = NULL;
108 int parse_previewgen_output(Ecore_Exe_Event_Data *data_from_process,
109 enum file_type ftype, int *pages_count)
112 PTS_RETV_IF(NULL == pages_count || NULL == data_from_process
113 || data_from_process->size <= 0,
114 -1, "Invalid argument");
115 PTS_DEBUG("data_from_process->size : %d\n", data_from_process->size);
116 char *msg = calloc(1, data_from_process->size + 1);
117 PTS_RETV_IF(NULL == msg, -1, "Memory allocation error");
119 strncpy(msg, data_from_process->data, data_from_process->size);
120 msg[data_from_process->size] = '\0';
123 PTS_DEBUG("msg: %s", msg);
126 case FILE_TYPE_IMAGE:
127 sscanf(msg, "init img: pages count: %d", pages_count);
130 sscanf(msg, "init pdf: pages count: %d", pages_count);
132 case FILE_TYPE_INCORRECT:
136 PTS_IF_FREE_MEM(msg);
138 PTS_RETV_IF (*pages_count <= 0, -1, "Error");
143 static Eina_Bool preview_handler_end_cb(void *d, int type, void *event)
147 PTS_RETV_IF(d == NULL, ECORE_CALLBACK_DONE, "Invalid argument");
149 struct preview_task_data *ptd = (struct preview_task_data *)d;
150 struct preview_task_data *next_ptd;
151 struct preview_task_model *task_model = ptd->task_model;
152 int is_init_engine = 1;
155 /* TODO: check for next initialization in queue */
157 switch (ptd->task_type) {
158 case PREVIEW_TASK_EMPTY_PAGE:
159 preview_model_page_available(ptd->pmodel,
160 PREVIEW_ENGINE_EVENT_EMPTY_PAGE_READY,
163 case PREVIEW_TASK_GENERIC:
164 /* TODO: check does task OK (parse output) */
165 //if (ptd->is_task_ok) {
166 preview_model_page_available(ptd->pmodel,
167 PREVIEW_ENGINE_EVENT_PAGE_READY,
170 preview_model_page_available(ptd->pmodel,
171 PREVIEW_ENGINE_EVENT_PAGE_ERROR,
175 case PREVIEW_TASK_INITIAL:
176 if (task_model->task_list != NULL) {
177 next_ptd = (struct preview_task_data *)
178 eina_list_data_get(task_model->task_list);
179 if (PREVIEW_TASK_INITIAL == next_ptd->task_type) {
183 if (is_init_engine) {
184 res = parse_previewgen_output(
185 (Ecore_Exe_Event_Data *)event,
187 &(ptd->conf.pages_count));
189 preview_engine_init_done(task_model->engine,
191 /* TODO: ERROR condition in case of res < 0 */
193 PTS_DEBUG("releasing memory");
194 destroy_preview_conf(&(ptd->conf));
195 PTS_DEBUG("memory released");
199 task_model->previewgen_handle = NULL;
200 ecore_event_handler_del(task_model->event_handler);
201 task_model->event_handler = NULL;
202 PTS_DEBUG("Freeing memory");
203 PTS_IF_FREE_MEM(ptd->previewgen_exe_cmd);
204 PTS_IF_FREE_MEM(ptd);
206 /* manage tasks queue */
207 if (task_model->task_list != NULL) {
208 ptd = (struct preview_task_data *)
209 eina_list_data_get(task_model->task_list);
210 task_model->task_list = eina_list_remove_list(
211 task_model->task_list, task_model->task_list);
212 task_model->previewgen_handle =
213 ecore_exe_pipe_run(ptd->previewgen_exe_cmd,
214 ECORE_EXE_PIPE_READ_LINE_BUFFERED
215 | ECORE_EXE_PIPE_READ, NULL);
216 if (NULL == task_model->previewgen_handle) {
217 PTS_DEBUG("ecore_exe_pipe_run error (%s)",
218 ptd->previewgen_exe_cmd);
219 PTS_IF_FREE_MEM(ptd->previewgen_exe_cmd);
220 PTS_IF_FREE_MEM(ptd);
222 return ECORE_CALLBACK_DONE;
224 task_model->event_handler = ecore_event_handler_add(
225 ECORE_EXE_EVENT_DATA,
226 preview_handler_end_cb, ptd);
230 return ECORE_CALLBACK_DONE;
234 int add_preview_task_initial(struct preview_task_model *model,
235 const struct preview_conf *conf)
238 PTS_RETV_IF(model == NULL || conf == NULL, -1, "Invalid argument");
241 struct preview_task_data *ptd;
245 /* fill the preview_task_data structure */
246 ptd = malloc(sizeof(struct preview_task_data));
247 PTS_RETV_IF(ptd == NULL, -1, "malloc failed");
249 memset(ptd, 0, sizeof(struct preview_task_data));
250 ptd->task_type = PREVIEW_TASK_INITIAL;
252 ptd->task_model = model;
253 /* fill cmd with arguments from ptd depending on file type*/
254 /* TODO: check for each file */
255 ptd->ftype = get_file_type(ptd->conf.initial_fnames[0]);
257 ptd->previewgen_exe_cmd = NULL;
259 enum page_scale_type scale_type = ptd->conf.scale.type;
260 switch (ptd->ftype) {
261 case FILE_TYPE_IMAGE:
262 /* calculate correct string length to support
265 for (i = 0; i < conf->files_count; ++i)
266 fnames_strlen += strlen(ptd->conf.initial_fnames[i])
268 fnames_str = (char*)malloc(sizeof(char) * (fnames_strlen + 1));
269 if (NULL == fnames_str) {
270 PTS_IF_FREE_MEM(ptd);
271 PTS_RETV_IF(ptd == NULL, -1, "malloc failed");
273 /* generate fnames list string */
274 fnames_str[0] = '\0';
275 for (i = 0; i < conf->files_count; ++i) {
276 strncat(fnames_str, ptd->conf.initial_fnames[i],
278 strncat(fnames_str, " ", fnames_strlen);
280 fnames_str[fnames_strlen] = '\0';
281 /* generate command string */
282 ptd->previewgen_exe_cmd = (char*)malloc(sizeof(char)
283 * (CMD_STR_MAX_LEN + fnames_strlen + 1));
284 if (NULL == ptd->previewgen_exe_cmd) {
285 PTS_IF_FREE_MEM(ptd);
286 PTS_IF_FREE_MEM(fnames_str);
287 PTS_RETV_IF(ptd == NULL, -1, "malloc failed");
289 PTS_DEBUG("processing image");
290 snprintf(ptd->previewgen_exe_cmd, CMD_STR_MAX_LEN,
291 PREVIEWGEN_EXECUTABLE " init img "
292 "%s%s %s %s %lf %lf %d %d %s %d %s %d %lf %lf %d",
293 fnames_str, ptd->conf.fname,
294 ptd->conf.ppd, ptd->conf.paper_size.name,
295 ptd->conf.paper_size.s.x, ptd->conf.paper_size.s.y,
296 ptd->conf.settings_req.available_size_px.x,
297 ptd->conf.settings_req.available_size_px.y,
298 (PAGE_ORIENTATION_LANDSCAPE == ptd->conf.orientation)
300 (PAGE_ORIENTATION_PORTRAIT == ptd->conf.orientation)
303 (SCALE_FIT_TO_PAPER == scale_type) ? "fit_to_paper" :
304 (SCALE_CUSTOM == scale_type) ? "custom" :
305 (SCALE_RELATIVE == scale_type) ? "relative" :
306 (SCALE_ORIGINAL == scale_type) ? "original" : "",
307 ptd->conf.scale.zoom, ptd->conf.scale.w, ptd->conf.scale.h,
308 ptd->conf.settings_req.is_grayscale);
309 PTS_IF_FREE_MEM(fnames_str);
310 PTS_DEBUG("cmd: %s", ptd->previewgen_exe_cmd);
313 PTS_DEBUG("processing PDF");
314 ptd->previewgen_exe_cmd = malloc(sizeof(char)
315 * (CMD_STR_MAX_LEN + 1));
316 snprintf(ptd->previewgen_exe_cmd, CMD_STR_MAX_LEN,
317 PREVIEWGEN_EXECUTABLE " init pdf "
318 "%s %s %s %s %lf %lf %s %d %s %d %lf %lf %d",
319 ptd->conf.initial_fnames[0], ptd->conf.fname,
320 ptd->conf.ppd, ptd->conf.paper_size.name,
321 ptd->conf.paper_size.s.x, ptd->conf.paper_size.s.y,
322 (PAGE_ORIENTATION_LANDSCAPE == ptd->conf.orientation) ? "landscape" :
323 (PAGE_ORIENTATION_PORTRAIT == ptd->conf.orientation) ? "portrait" : "",
325 (SCALE_FIT_TO_PAPER == scale_type) ? "fit_to_paper" :
326 (SCALE_CUSTOM == scale_type) ? "custom" :
327 (SCALE_RELATIVE == scale_type) ? "relative" :
328 (SCALE_ORIGINAL == scale_type) ? "original" : "",
329 ptd->conf.scale.zoom, ptd->conf.scale.w, ptd->conf.scale.h,
330 ptd->conf.settings_req.is_grayscale);
331 PTS_DEBUG("cmd: %s", ptd->previewgen_exe_cmd);
333 case FILE_TYPE_INCORRECT:
334 PTS_DEBUG("Incorrect file type");
335 PTS_IF_FREE_MEM(ptd->previewgen_exe_cmd);
336 PTS_IF_FREE_MEM(ptd);
341 /* TODO: clear task queue, disable generic tasks */
342 clear_preview_task_queue(model);
344 /* manage task queue */
345 if (NULL != model->previewgen_handle) {
346 /* plan task for calculation in future */
347 /* TODO: check, does we have current tasks in task model */
348 model->task_list = eina_list_append(model->task_list, ptd);
349 /* TODO: leave only 4 last page requests in queue */
351 /* this task is a top task - just process */
352 model->previewgen_handle = ecore_exe_pipe_run(
353 ptd->previewgen_exe_cmd,
354 ECORE_EXE_PIPE_READ, NULL);
355 if (NULL == model->previewgen_handle) {
356 PTS_DEBUG("ecore_exe_pipe_run error (%s)",
357 ptd->previewgen_exe_cmd);
358 PTS_IF_FREE_MEM(ptd->previewgen_exe_cmd);
359 destroy_preview_conf(&(ptd->conf));
360 PTS_IF_FREE_MEM(ptd);
364 model->event_handler = ecore_event_handler_add(
365 ECORE_EXE_EVENT_DATA,
366 preview_handler_end_cb, ptd);
374 int process_preview_task_ptd(struct preview_task_model *model,
375 struct preview_task_data *ptd)
377 struct preview_task_data *next_ptd;
380 PTS_RETV_IF(model == NULL || NULL == ptd,
381 -1, "Argument error");
383 if (NULL != model->previewgen_handle) {
384 if (NULL != model->task_list) {
385 next_ptd = (struct preview_task_data *)
386 eina_list_data_get(model->task_list);
387 if (next_ptd == NULL || PREVIEW_TASK_INITIAL
388 == next_ptd->task_type) {
389 /* incorret list content or initialization
391 PTS_IF_FREE_MEM(ptd->previewgen_exe_cmd);
392 PTS_IF_FREE_MEM(ptd);
396 /* plan task for calculation in future */
397 model->task_list = eina_list_append(
398 model->task_list, ptd);
399 } else { /* NULL == model->task_list */
400 model->task_list = eina_list_append(
401 model->task_list, ptd);
403 /* TODO: leave only 4 last page requests in queue */
405 /* this task is a top task - just process */
406 model->previewgen_handle = ecore_exe_pipe_run(
407 ptd->previewgen_exe_cmd,
408 ECORE_EXE_PIPE_READ_LINE_BUFFERED
409 | ECORE_EXE_PIPE_READ, NULL);
410 if (NULL == model->previewgen_handle) {
411 PTS_DEBUG("ecore_exe_pipe_run error (%s)",
412 ptd->previewgen_exe_cmd);
413 PTS_IF_FREE_MEM(ptd->previewgen_exe_cmd);
414 PTS_IF_FREE_MEM(ptd);
418 model->event_handler = ecore_event_handler_add(
419 ECORE_EXE_EVENT_DATA,
420 preview_handler_end_cb, ptd);
428 int add_preview_task_empty_page(struct preview_task_model *model,
429 struct preview_model *pmodel)
432 PTS_RETV_IF(model == NULL || pmodel == NULL, -1, "Invalid argument");
433 PTS_RETV_IF(model->is_stop_processing, -1, "is_stop_processing is %d",
434 model->is_stop_processing);
437 struct preview_task_data *ptd;
438 struct preview_task_data *next_ptd;
440 /* fill the preview_task_data structure */
441 ptd = malloc(sizeof(struct preview_task_data));
442 PTS_RETV_IF(ptd == NULL, -1, "malloc failed");
445 ptd->task_type = PREVIEW_TASK_EMPTY_PAGE;
446 strncpy(ptd->out_pic_fname, PREVIEW_TEMP_DIR "/empty_page.ppm", sizeof(ptd->out_pic_fname) - 1);
448 ptd->conf = pmodel->conf;
449 ptd->pmodel = pmodel;
450 ptd->task_model = model;
452 ptd->previewgen_exe_cmd = malloc(sizeof(char) * (CMD_STR_MAX_LEN + 1));
453 if (NULL == ptd->previewgen_exe_cmd) {
454 PTS_IF_FREE_MEM(ptd);
455 PTS_RETV_IF(ptd == NULL, -1, "malloc failed");
458 int to_be_previewed_as_landscape =
459 (PAGE_ORIENTATION_LANDSCAPE == ptd->conf.orientation);
460 /* for number_up 2 page should be rotated to be viewed correctly */
461 if (2 == ptd->conf.n_up) {
462 switch_size_pts_coords(&(ptd->conf.paper_size.s));
463 //switch_size_px_coords(&(ptd->conf.settings_req.available_size_px));
466 /* fill cmd with arguments from ptd */
467 snprintf(ptd->previewgen_exe_cmd, CMD_STR_MAX_LEN,
468 PREVIEWGEN_EXECUTABLE " empty_gen "
469 "%s %lf %lf %d %d %d %d %d",
471 ptd->conf.paper_size.s.x, ptd->conf.paper_size.s.y,
472 ptd->conf.settings_req.available_size_px.x,
473 ptd->conf.settings_req.available_size_px.y,
474 ptd->conf.settings_req.shadow_offset.x,
475 ptd->conf.settings_req.shadow_offset.y,
476 to_be_previewed_as_landscape);
477 PTS_DEBUG("cmd: %s", ptd->previewgen_exe_cmd);
479 res = process_preview_task_ptd(model, ptd);
486 int add_preview_task(struct preview_task_model *model, int page,
487 struct preview_model *pmodel)
490 PTS_RETV_IF(model == NULL || pmodel == NULL , -1, "Invalid argument");
491 PTS_RETV_IF(model->is_stop_processing, -1, "is_stop_processing is %d", model->is_stop_processing);
494 struct preview_task_data *ptd;
495 struct preview_task_data *next_ptd;
497 /* fill the preview_task_data structure */
498 ptd = malloc(sizeof(struct preview_task_data));
499 PTS_RETV_IF(ptd == NULL, -1, "malloc failed");
502 ptd->task_type = PREVIEW_TASK_GENERIC;
503 snprintf(ptd->out_pic_fname, sizeof(ptd->out_pic_fname),
504 "/tmp/mobileprint/mobileprint_%04d.ppm", page);
506 ptd->conf = pmodel->conf;
507 ptd->pmodel = pmodel;
508 ptd->task_model = model;
510 ptd->previewgen_exe_cmd = malloc(sizeof(char) * (CMD_STR_MAX_LEN + 1));
511 if (NULL == ptd->previewgen_exe_cmd) {
512 PTS_IF_FREE_MEM(ptd);
513 PTS_RETV_IF(ptd == NULL, -1, "malloc failed");
516 int to_be_previewed_as_landscape = (PAGE_ORIENTATION_LANDSCAPE == ptd->conf.orientation);
517 /* for number_up 2 page should be rotated to be viewed correctly */
518 if (2 == ptd->conf.n_up) {
519 switch_size_pts_coords(&(ptd->conf.paper_size.s));
520 //switch_size_px_coords(&(ptd->conf.settings_req.available_size_px));
523 /* fill cmd with arguments from ptd */
524 snprintf(ptd->previewgen_exe_cmd, CMD_STR_MAX_LEN,
525 PREVIEWGEN_EXECUTABLE " pagegen "
526 "%s %d %s %lf %lf %d %d %d %d %d %d",
527 ptd->conf.fname, page, ptd->out_pic_fname,
528 ptd->conf.paper_size.s.x, ptd->conf.paper_size.s.y,
529 ptd->conf.settings_req.available_size_px.x,
530 ptd->conf.settings_req.available_size_px.y,
531 ptd->conf.settings_req.shadow_offset.x,
532 ptd->conf.settings_req.shadow_offset.y,
533 to_be_previewed_as_landscape,
534 ptd->conf.settings_req.is_grayscale);
535 PTS_DEBUG("cmd: %s", ptd->previewgen_exe_cmd);
537 res = process_preview_task_ptd(model, ptd);
544 int debug_print_preview_task_list(struct preview_task_model *model)
546 /*struct preview_task_data *ptd;
549 PTS_DEBUG("task_list size: %d", eina_list_count(model->task_list));