summaryrefslogblamecommitdiff
path: root/src/bin/ethumb_client/ethumbd_slave.c
blob: d7b7ff6680fd0f9a41d73f06d6c83bc02f7e24df (plain) (tree)
1
2
3
4
5
6
7
8
9




                                                   



                                                                     
  



                                                                    
  


                                                                   



                                                        


                    
 
                   
                  




                   
                 

                   


                            



                                                            


                    

                            

                     
              
                                



                                   
                             


  

                                                    

                

                    





                   








                                                          
      


            

                                                           

                
                          





                   






                                                         





            
                                                                    


            
                                 
 
                                                 











                    
                                       




                    
                 




                      
                              
             


                                                      








                                   

              
                                               



                                                  













                                      
           
 
                                               


              
                                       
 
                                   






                                     
           
 
                                               


              
                                       
 

                                 



            
                                                                         
 
                                      
                                     
 
                                         
                                                     
 












                                                               

                                                       
 

                                                         
 


                                                       




                                          
           


                                             
                                               







                                    



                   

                                          




                   

                                         





                         
 

                                                                  
 
                                       
      
                                                             


       
                                                                         
      









                    
                                                             



             
                                                   


                                  
                          




            
                                                              




            
                                           

              
                                                 

              
                                           


                                  
                             




            
                                                                



             
                                                   


                                     
                             




            
                                                                



             
                                                   


                                     
                             




            
                                                                     



             
                                                   








                                          
                                                              




              
                                           

              
                                                 

              
                                           


                                        
                             




            
                                                                 



             
                                                   


                                      
                              




            
                                                                  



             
                                                   


                                       
                               




            








                                                   
                                                 
          



                         

                                     



                         
                                                 
          




                         

                                       




                         
                                                       

















                                                       
                                    














                                                      
                                  





                  
                                                                    



               
                                                   


                                   
                                 




            
                                                                     



               
                                                   


                                    
                                  




            
                                                                        



               
                                                   


                                       
                                     




            
                                                                      



             
                                                   


                                     
                                   




            
                                                                   



             
                                                   


                                  
                                




            
                                                                       



             
                                                   


                                      
                                    




            
                                                               


             
                        














                               


                                    


                             





                                 











                                   











                                       



                                      
                            






                                       
           

            
                                               


              
                                                 



                                         
                                         
                                                      






                   
              
                
                                                        



                                                                       




                                    
              

                                                                    
                                                 



                               
      
 
                                                   

          
                                                




                               
                                 
 














                                 
                                             




               
                                                









                                    
              
                                              
                                                   
                                      




                                                 

 
   
                                                          




                             











                                                                            
                  


                 
                         
                           
                           


                




                                                
                     

            
 
/**
 * @file
 *
 * Copyright (C) 2009 by ProFUSION embedded systems
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library;
 * if not, see <http://www.gnu.org/licenses/>.
 *
 * @author Rafael Antognolli <antognolli@profusion.mobi>
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <errno.h>

#include <Eina.h>
#include <Ecore.h>
#include <Ethumb.h>

#include "ethumbd_private.h"

#define DBG(...) EINA_LOG_DOM_DBG(_log_domain, __VA_ARGS__)
#define INF(...) EINA_LOG_DOM_INFO(_log_domain, __VA_ARGS__)
#define WRN(...) EINA_LOG_DOM_WARN(_log_domain, __VA_ARGS__)
#define ERR(...) EINA_LOG_DOM_ERR(_log_domain, __VA_ARGS__)

#define NETHUMBS 100

static int _log_domain = -1;

struct _Ethumbd_Child
{
#ifndef _WIN32
   Ecore_Fd_Handler *fd_handler;
#else
   Ecore_Win32_Handler *fd_handler;
#endif

   Ethumb *ethumbt[NETHUMBS];
};


static int
_ec_read_safe(FILE* stream, void *buf, ssize_t size)
{
   ssize_t todo;
   unsigned char *p;
   int c;

   todo = size;
   p = buf;

   while (todo > 0)
     {
        c = getc(stream);
        if (c == EOF)
          {
             ERR("could not read from stream %p", stream);
             return 0;
          }
        *p = c;
        ++p;
        --todo;
     }
   return 1;
}

static int
_ec_write_safe(FILE *stream, const void *buf, ssize_t size)
{
   ssize_t todo;
   const unsigned char *p;

   todo = size;
   p = buf;

   while (todo > 0)
     {
        if (putc(*p, stream) == EOF)
          {
             ERR("could not write to stream %p", stream);
             return 0;
          }
        ++p;
        --todo;
     }

   return 1;
}

static int
_ec_pipe_str_read(struct _Ethumbd_Child *ec EINA_UNUSED, char **str)
{
   int size;
   int r;
   char buf[PATH_MAX] = { '\0' };

   r = _ec_read_safe(stdin, &size, sizeof(size));
   if (!r)
     {
	*str = NULL;
	return 0;
     }

   if (!size)
     {
	*str = NULL;
	return 1;
     }

   r = _ec_read_safe(stdin, buf, size);
   if (!r)
     {
	*str = NULL;
	return 0;
     }
   buf[size] = 0;

   *str = strdup(buf);
   return 1;
}

static struct _Ethumbd_Child *
_ec_new(void)
{
   struct _Ethumbd_Child *ec = calloc(1, sizeof(*ec));

   return ec;
}

static void
_ec_free(struct _Ethumbd_Child *ec)
{
   int i;

   if (ec->fd_handler)
     {
#ifndef _WIN32
     ecore_main_fd_handler_del(ec->fd_handler);
#else
     ecore_main_win32_handler_del(ec->fd_handler);
#endif
     }

   for (i = 0; i < NETHUMBS; i++)
     {
	if (ec->ethumbt[i])
	  ethumb_free(ec->ethumbt[i]);
     }

   free(ec);
}

static int
_ec_op_new(struct _Ethumbd_Child *ec)
{
   int r;
   int idx;

   r = _ec_read_safe(stdin, &idx, sizeof(idx));
   if (!r)
     return 0;

   DBG("ethumbd new(). idx = %d", idx);

   ec->ethumbt[idx] = ethumb_new();
   return 1;
}

static int
_ec_op_del(struct _Ethumbd_Child *ec)
{
   int r;
   int idx;

   r = _ec_read_safe(stdin, &idx, sizeof(idx));
   if (!r)
     return 0;

   DBG("ethumbd del(). idx = %d", idx);

   ethumb_free(ec->ethumbt[idx]);
   ec->ethumbt[idx] = NULL;
   return 1;
}

static void
_ec_op_generated_cb(void *data EINA_UNUSED, Ethumb *e, Eina_Bool success)
{
   const char *thumb_path, *thumb_key;
   int size_path, size_key, size_cmd;

   DBG("thumb generated (%i)!", success);
   ethumb_thumb_path_get(e, &thumb_path, &thumb_key);

   if (!thumb_path)
     size_path = 0;
   else
     size_path = strlen(thumb_path) + 1;

   if (!thumb_key)
     size_key = 0;
   else
     size_key = strlen(thumb_key) + 1;

   size_cmd = sizeof(success) + sizeof(size_path) + size_path +
      sizeof(size_key) + size_key;

   _ec_write_safe(stdout, &size_cmd, sizeof(size_cmd));
   _ec_write_safe(stdout, &success, sizeof(success));

   _ec_write_safe(stdout, &size_path, sizeof(size_path));
   _ec_write_safe(stdout, thumb_path, size_path);

   _ec_write_safe(stdout, &size_key, sizeof(size_key));
   _ec_write_safe(stdout, thumb_key, size_key);
   fflush(stdout);
}

static int
_ec_op_generate(struct _Ethumbd_Child *ec)
{
   int idx;
   char *path, *key, *thumb_path, *thumb_key;
   int r;

   r = _ec_read_safe(stdin, &idx, sizeof(idx));
   if (!r)
     return 0;

   r = _ec_pipe_str_read(ec, &path);
   if (!r)
     return 0;
   r = _ec_pipe_str_read(ec, &key);
   if (!r)
     {
        free(path);
        return 0;
     }
   r = _ec_pipe_str_read(ec, &thumb_path);
   if (!r)
     {
        free(path);
        free(key);
        return 0;
     }
   r = _ec_pipe_str_read(ec, &thumb_key);
   if (!r)
     {
        free(path);
        free(key);
        free(thumb_path);
        return 0;
     }

   ethumb_file_set(ec->ethumbt[idx], path, key);
   ethumb_thumb_path_set(ec->ethumbt[idx], thumb_path, thumb_key);

   if (ethumb_exists(ec->ethumbt[idx]))
     {
        _ec_op_generated_cb(ec, ec->ethumbt[idx], EINA_TRUE);
     }
   else
     {
        ethumb_generate(ec->ethumbt[idx], _ec_op_generated_cb, ec, NULL);
     }

   free(path);
   free(key);
   free(thumb_path);
   free(thumb_key);

   return 1;
}

static int
_ec_fdo_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
{
   int r;
   int value;

   r = _ec_read_safe(stdin, &value, sizeof(value));
   if (!r)
     return 0;
   ethumb_thumb_fdo_set(e, value);
   DBG("fdo = %d", value);

   return 1;
}

static int
_ec_size_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
{
   int r;
   int w, h;
   int type;

   r = _ec_read_safe(stdin, &w, sizeof(w));
   if (!r)
     return 0;
   r = _ec_read_safe(stdin, &type, sizeof(type));
   if (!r)
     return 0;
   r = _ec_read_safe(stdin, &h, sizeof(h));
   if (!r)
     return 0;
   ethumb_thumb_size_set(e, w, h);
   DBG("size = %dx%d", w, h);

   return 1;
}

static int
_ec_format_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
{
   int r;
   int value;

   r = _ec_read_safe(stdin, &value, sizeof(value));
   if (!r)
     return 0;
   ethumb_thumb_format_set(e, value);
   DBG("format = %d", value);

   return 1;
}

static int
_ec_aspect_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
{
   int r;
   int value;

   r = _ec_read_safe(stdin, &value, sizeof(value));
   if (!r)
     return 0;
   ethumb_thumb_aspect_set(e, value);
   DBG("aspect = %d", value);

   return 1;
}

static int
_ec_orientation_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
{
   int r;
   int value;

   r = _ec_read_safe(stdin, &value, sizeof(value));
   if (!r)
     return 0;
   ethumb_thumb_orientation_set(e, value);
   DBG("orientation = %d", value);

   return 1;
}

static int
_ec_crop_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
{
   int r;
   float x, y;
   int type;

   r = _ec_read_safe(stdin, &x, sizeof(x));
   if (!r)
     return 0;
   r = _ec_read_safe(stdin, &type, sizeof(type));
   if (!r)
     return 0;
   r = _ec_read_safe(stdin, &y, sizeof(y));
   if (!r)
     return 0;
   ethumb_thumb_crop_align_set(e, x, y);
   DBG("crop = %fx%f", x, y);

   return 1;
}

static int
_ec_quality_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
{
   int r;
   int value;

   r = _ec_read_safe(stdin, &value, sizeof(value));
   if (!r)
     return 0;
   ethumb_thumb_quality_set(e, value);
   DBG("quality = %d", value);

   return 1;
}

static int
_ec_compress_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
{
   int r;
   int value;

   r = _ec_read_safe(stdin, &value, sizeof(value));
   if (!r)
     return 0;
   ethumb_thumb_compress_set(e, value);
   DBG("compress = %d", value);

   return 1;
}

static int
_ec_frame_set(struct _Ethumbd_Child *ec, Ethumb *e)
{
   int r;
   int type;
   char *theme_file, *group, *swallow;

   r = _ec_pipe_str_read(ec, &theme_file);
   if (!r)
     return 0;
   r = _ec_read_safe(stdin, &type, sizeof(type));
   if (!r)
     {
        free(theme_file);
        return 0;
     }
   r = _ec_pipe_str_read(ec, &group);
   if (!r)
     {
        free(theme_file);
        return 0;
     }
   r = _ec_read_safe(stdin, &type, sizeof(type));
   if (!r)
     {
        free(theme_file);
        free(group);
        return 0;
     }
   r = _ec_pipe_str_read(ec, &swallow);
   if (!r)
     {
        free(theme_file);
        free(group);
        return 0;
     }
   DBG("frame = %s:%s:%s", theme_file, group, swallow);
   ethumb_frame_set(e, theme_file, group, swallow);
   free(theme_file);
   free(group);
   free(swallow);

   return 1;
}

static int
_ec_directory_set(struct _Ethumbd_Child *ec, Ethumb *e)
{
   int r;
   char *directory;

   r = _ec_pipe_str_read(ec, &directory);
   if (!r)
     return 0;
   ethumb_thumb_dir_path_set(e, directory);
   DBG("directory = %s", directory);
   free(directory);

   return 1;
}

static int
_ec_category_set(struct _Ethumbd_Child *ec, Ethumb *e)
{
   int r;
   char *category;

   r = _ec_pipe_str_read(ec, &category);
   if (!r)
     return 0;
   ethumb_thumb_category_set(e, category);
   DBG("category = %s", category);
   free(category);

   return 1;
}

static int
_ec_video_time_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
{
   int r;
   float value;

   r = _ec_read_safe(stdin, &value, sizeof(value));
   if (!r)
     return 0;
   ethumb_video_time_set(e, value);
   DBG("video_time = %f", value);

   return 1;
}

static int
_ec_video_start_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
{
   int r;
   float value;

   r = _ec_read_safe(stdin, &value, sizeof(value));
   if (!r)
     return 0;
   ethumb_video_start_set(e, value);
   DBG("video_start = %f", value);

   return 1;
}

static int
_ec_video_interval_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
{
   int r;
   float value;

   r = _ec_read_safe(stdin, &value, sizeof(value));
   if (!r)
     return 0;
   ethumb_video_interval_set(e, value);
   DBG("video_interval = %f", value);

   return 1;
}

static int
_ec_video_ntimes_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
{
   int r;
   int value;

   r = _ec_read_safe(stdin, &value, sizeof(value));
   if (!r)
     return 0;
   ethumb_video_ntimes_set(e, value);
   DBG("video_ntimes = %d", value);

   return 1;
}

static int
_ec_video_fps_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
{
   int r;
   int value;

   r = _ec_read_safe(stdin, &value, sizeof(value));
   if (!r)
     return 0;
   ethumb_video_fps_set(e, value);
   DBG("video_fps = %d", value);

   return 1;
}

static int
_ec_document_page_set(struct _Ethumbd_Child *ec EINA_UNUSED, Ethumb *e)
{
   int r;
   int value;

   r = _ec_read_safe(stdin, &value, sizeof(value));
   if (!r)
     return 0;
   ethumb_document_page_set(e, value);
   DBG("document_page = %d", value);

   return 1;
}

static void
_ec_setup_process(struct _Ethumbd_Child *ec, int idx, int type)
{
   Ethumb *e;

   e = ec->ethumbt[idx];

   switch (type)
     {
      case ETHUMBD_FDO:
	 _ec_fdo_set(ec, e);
	 break;
      case ETHUMBD_SIZE_W:
	 _ec_size_set(ec, e);
	 break;
      case ETHUMBD_FORMAT:
	 _ec_format_set(ec, e);
	 break;
      case ETHUMBD_ASPECT:
	 _ec_aspect_set(ec, e);
	 break;
      case ETHUMBD_ORIENTATION:
	 _ec_orientation_set(ec, e);
	 break;
      case ETHUMBD_CROP_X:
	 _ec_crop_set(ec, e);
	 break;
      case ETHUMBD_QUALITY:
	 _ec_quality_set(ec, e);
	 break;
      case ETHUMBD_COMPRESS:
	 _ec_compress_set(ec, e);
	 break;
      case ETHUMBD_FRAME_FILE:
	 _ec_frame_set(ec, e);
	 break;
      case ETHUMBD_DIRECTORY:
	 _ec_directory_set(ec, e);
	 break;
      case ETHUMBD_CATEGORY:
	 _ec_category_set(ec, e);
	 break;
      case ETHUMBD_VIDEO_TIME:
	 _ec_video_time_set(ec, e);
	 break;
      case ETHUMBD_VIDEO_START:
	 _ec_video_start_set(ec, e);
	 break;
      case ETHUMBD_VIDEO_INTERVAL:
	 _ec_video_interval_set(ec, e);
	 break;
      case ETHUMBD_VIDEO_NTIMES:
	 _ec_video_ntimes_set(ec, e);
	 break;
      case ETHUMBD_VIDEO_FPS:
	 _ec_video_fps_set(ec, e);
	 break;
      case ETHUMBD_DOCUMENT_PAGE:
	 _ec_document_page_set(ec, e);
	 break;
      default:
	 ERR("wrong type!");
     }
}

static int
_ec_op_setup(struct _Ethumbd_Child *ec)
{
   int r;
   int idx;
   int type;

   r = _ec_read_safe(stdin, &idx, sizeof(idx));
   if (!r)
     return 0;

   r = _ec_read_safe(stdin, &type, sizeof(type));
   if (!r)
     return 0;
   while (type != ETHUMBD_SETUP_FINISHED)
     {
	_ec_setup_process(ec, idx, type);
	r = _ec_read_safe(stdin, &type, sizeof(type));
	if (!r)
	  return 0;
     }

   return 1;
}

#ifndef _WIN32
static Eina_Bool
_ec_fd_handler(void *data, Ecore_Fd_Handler *fd_handler)
#else
static Eina_Bool
_ec_fd_handler(void *data, Ecore_Win32_Handler *fd_handler EINA_UNUSED)
#endif
{
   struct _Ethumbd_Child *ec = data;
   int op_id;
   int r;

#ifndef _WIN32
   if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_ERROR))
     {
	ERR("error on pipein! child exiting...");
	ec->fd_handler = NULL;
	ecore_main_loop_quit();
	return 0;
     }
#endif

   r = _ec_read_safe(stdin, &op_id, sizeof(op_id));
   if (!r)
     {
	DBG("ethumbd exited! child exiting...");
	ec->fd_handler = NULL;
	ecore_main_loop_quit();
	return 0;
     }

   DBG("received op: %d", op_id);

   switch (op_id)
     {
      case ETHUMBD_OP_NEW:
	 r = _ec_op_new(ec);
	 break;
      case ETHUMBD_OP_GENERATE:
	 r = _ec_op_generate(ec);
	 break;
      case ETHUMBD_OP_SETUP:
	 r = _ec_op_setup(ec);
	 break;
      case ETHUMBD_OP_DEL:
	 r = _ec_op_del(ec);
	 break;
      default:
	 ERR("invalid operation: %d", op_id);
	 r = 0;
     }

   if (!r)
     {
	ERR("ethumbd exited! child exiting...");
	ec->fd_handler = NULL;
	ecore_main_loop_quit();
     }

   return r;
}

static void
_ec_setup(struct _Ethumbd_Child *ec)
{
#ifndef _WIN32
   ec->fd_handler = ecore_main_fd_handler_add(
      STDIN_FILENO, ECORE_FD_READ | ECORE_FD_ERROR,
      _ec_fd_handler, ec, NULL, NULL);
#else
   ec->fd_handler = ecore_main_win32_handler_add(
      GetStdHandle(STD_INPUT_HANDLE),
      _ec_fd_handler, ec);
#endif
}

int
main(int argc EINA_UNUSED, const char *argv[] EINA_UNUSED)
{
   struct _Ethumbd_Child *ec;

   ethumb_init();

   if (_log_domain < 0)
     {
	_log_domain = eina_log_domain_register("ethumbd_child", NULL);

	if (_log_domain < 0)
	  {
	     EINA_LOG_CRIT("could not register log domain 'ethumbd_child'");
	     ethumb_shutdown();
	     return 1;
	  }
     }

   ec = _ec_new();

   _ec_setup(ec);

   DBG("child started!");
   ecore_main_loop_begin();
   DBG("child finishing.");

   _ec_free(ec);

   if (_log_domain >= 0)
     {
	eina_log_domain_unregister(_log_domain);
	_log_domain = -1;
     }
   ethumb_shutdown();

   return 0;
}