aboutsummaryrefslogblamecommitdiffstats
path: root/src/bin/e_fileman_mime.c
blob: ff4606df011ec7610d88b172e1e08d249df37ba5 (plain) (tree)





















































                                                                                              



                                                                                      






                                                                          
                                                                          

   







                                                                                               




              



                                                                                                  
                                                                                                   


                                                                                             

                                                                                   

                                                                                                                                                                     
 










                                                     
                           




                            














                                                                             
   















                                                                   









                                              






                                               



















                                               

                                                   














                                             


                                                          








                                                 
                                                           








                                                       
                                                           








                                                       
                                                  







































                                                        

                                                         













                        
 
                                                       


                                                                   
                                         
 
                   


                          


                      
                                   
                      
                                        


                             
                                    

                                             














                                           
        
                                                                             






                                                        
                                                  
                
                                                           














                                                    

                       












                                            
      
 


                                                                    
 





                                                                        




                                      
      
                                                                                                   




                                                 


                                                




                                                                                   

                      

            

 
         























                                                  








                                                                                     


                         










































                                                           
            
                                                                           









                                       
                         










                                      
                            







                                                             

                                                       

                     



                                             






















                                             


















                                                                       












                                                                        



                                                       





                                                                       













                                     





















                                                                                                









                                                              
 












                                                                                                                                                                    
/*
 * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
 */

/* e_fileman_mime.c
 * ================
 * will provide basic function for mime types, mime handlers
 * and operations with them, also a small app to actually 
 * edit the mime database
 *
 *
 * abstract types 
 * ==============================
 * the abstract types will be in a hierarchy way, all the leafs will heritate the parents
 * info (actions: run,open,edit,whatever) 
 *
 * properties:
 * mime: each leaf might have a mime type associated to it ? it wouldnt be neccesary for now, 
 * efm will handle only file names, in the future might visulize other file types?
 * 
 *
 * file 
 * +---- data
 *       +---- image
 *             +---- jpg
 *                   :mime image/jpeg
 *             +---- png
 *       +---- audio
 *             +---- mp3
 *             +---- ogg
 *             +---- wav
 * +---- directory
 * +---- special
 * +---- executable
 *       +---- a.out
 *       +---- java class
 *       +---- scripts
 *
 *
 *
 * file recognition for above types
 * ================================
 * 1. by regex 
 * 2. by suffix
 * 3. by type (directory,hidden,etc)
 * 4. properties (fifo,socket,executables,etc)
 *
 * icons visuals
 * =============
 * 1. by properties (read,write,execute)
 * 2. user defined (video directory, audo directory)
 * 3. by file contents (if a dir is full of mp3, might be an audio dir)
 *
 *
 * previews and thumbnails
 * =======================
 * a thumbnail can be done for example on images,videos,or any graphical file
 * but a preview is for example that when you are over an audio file it starts playing
 *
 * actions
 * =======
 * each mime entry will have a list of possible actions to be taken for it
 * to define the command to execute there are several tokens like:
 *
 * %f => file input
 * %h => hover file (might be the current directory, other file, whatever)
 * 
 *
 * FUTURE
 * ======
 * a new approach can be made, but is too expensive for what e17 currently needs.
 * the mime subsystem can be in fact independent from e_fileman_smart (the function calls 
 * are very simple to change, just pass always an Evas_List of files, and the E_Fm_File hover, 
 * instead of the E_Fileman_Smart). What is complicated is how to pass the data to the internal
 * actions, and if we should define the internal actions here or in the component that will
 * use the mime subsytem.
 *
 */

#include "e.h"

static E_Fm_Mime_Entry  *_e_fm_mime_common(E_Fm_Mime_Entry *e1, E_Fm_Mime_Entry *e2);
static char             *_e_fm_mime_suffix_get(char *filename);
static void              _e_fm_mime_action_append(E_Fm_Mime_Entry *entry, char *action_name);
static void              _e_fm_mime_action_default_set(E_Fm_Mime_Entry *entry, char *action_name);
static char             *_e_fm_mime_string_tokenizer(Evas_List *files, E_Fm_File *dir, char *istr);
/* definitions of the internal actions */
static void              _e_fm_mime_action_internal_folder_open(E_Fm_Smart_Data *data);
static void              _e_fm_mime_action_internal_folder_open_other(E_Fm_Smart_Data *data);
static void              _e_fm_mime_action_internal_copy_to(E_Fm_Smart_Data *data);
static void              _e_fm_mime_action_internal_move_to(E_Fm_Smart_Data *data);
/* definitions of thumbnail functions */
Evas_Object * _e_fm_mime_thumbnail_evas(char *path, Evas_Coord w, Evas_Coord h, Evas *evas, Evas_Object **tmp, void (*cb)(Evas_Object *obj, void *data), void *data);


static int init_count = 0;
static Evas_List *entries = NULL;
static Evas_List *actions = NULL;

/* returns the saved mime tree or a default one */   
int
e_fm_mime_init(void)
{
   E_Fm_Mime_Entry *root;
   E_Fm_Mime_Entry *entry;
   E_Fm_Mime_Entry *l1,*l2;
   E_Fm_Mime_Action *action;

   if(init_count)
     return 1;
   
   /* internal actions */
   /********************/
   action = E_NEW(E_Fm_Mime_Action,1);
   action->name = strdup("_folder_open");
   action->label = strdup("Open the Folder");
   action->is_internal = 1;
   action->internal.function = &_e_fm_mime_action_internal_folder_open;
   actions = evas_list_append(actions,action);

   action = E_NEW(E_Fm_Mime_Action,1);
   action->name = strdup("_folder_open_other");
   action->label = strdup("Open the Folder in other Window");
   action->is_internal = 1;
   action->internal.function = &_e_fm_mime_action_internal_folder_open_other;
   actions = evas_list_append(actions,action);
   
   action = E_NEW(E_Fm_Mime_Action,1);
   action->name = strdup("_copy_to");
   action->label = strdup("Copy to %h");
   action->relative = 1;
   action->is_internal = 1;
   action->internal.function = &_e_fm_mime_action_internal_copy_to;
   actions = evas_list_append(actions,action);
   
   action = E_NEW(E_Fm_Mime_Action,1);
   action->name = strdup("_move_to");
   action->label = strdup("Move to %h");
   action->relative = 1;
   action->is_internal = 1;
   action->internal.function = &_e_fm_mime_action_internal_move_to;
   actions = evas_list_append(actions,action);
   
   /* actions */
   /***********/
   action = E_NEW(E_Fm_Mime_Action,1);
   action->name = strdup("gimp_edit");
   action->label = strdup("Edit with Gimp");
   action->cmd = strdup("gimp %f");
   action->multiple = 1;
   actions = evas_list_append(actions,action);

   action = E_NEW(E_Fm_Mime_Action,1);
   action->name = strdup("exhibit_view");
   action->label = strdup("View with Exhibit");
   action->cmd = strdup("exhibit %f");
   action->multiple = 0;
   actions = evas_list_append(actions,action);
   
   action = E_NEW(E_Fm_Mime_Action,1);
   action->name = strdup("xmms_enqueue");
   action->label = strdup("Add to XMMS Queue");
   action->cmd = strdup("xmms -e %f");
   action->multiple = 1;
   actions = evas_list_append(actions,action);
   
   action = E_NEW(E_Fm_Mime_Action,1);
   action->name = strdup("xmms_play");
   action->label = strdup("Play with XMMS");
   action->cmd = strdup("xmms %f");
   action->multiple = 0;
   actions = evas_list_append(actions,action);
   
   /* entries */
   /***********/
   root = E_NEW(E_Fm_Mime_Entry,1);
   root->name = strdup("file");
   root->label = strdup("Unkown File");
   root->level = 0;
   entries = evas_list_append(entries,root);
   _e_fm_mime_action_default_set(root, "_copy_to");
   _e_fm_mime_action_append(root, "_move_to");
   /* data */
   entry = E_NEW(E_Fm_Mime_Entry,1);
   entry->name = strdup("data");
   entry->label = strdup("Data File");
   entry->parent = root;
   entry->level = 1;
   entries = evas_list_append(entries,entry);
   l1 = entry;
     {
	/* image */
	entry = E_NEW(E_Fm_Mime_Entry,1);
	entry->name = strdup("image");
	entry->label = strdup("Image File");
	entry->parent = l1;
	entry->level = 2;
	entries = evas_list_append(entries,entry);
	_e_fm_mime_action_default_set(entry, "gimp_edit");
	_e_fm_mime_action_append(entry, "exhibit_view");
	l2 = entry;
	  {
	     /* jpg */
	     entry = E_NEW(E_Fm_Mime_Entry, 1);
	     entry->name = strdup("jpg");
	     entry->label = strdup("JPEG Image");
	     entry->parent = l2;
	     entry->level = 3;
	     entry->suffix = strdup("jpg");
	     entry->thumbnail = &_e_fm_mime_thumbnail_evas;
	     entries = evas_list_append(entries,entry);
	     
	     /* png */
	     entry = E_NEW(E_Fm_Mime_Entry, 1);
	     entry->name = strdup("png");
	     entry->label = strdup("PNG Image");
	     entry->parent = l2;
	     entry->level = 3;
	     entry->suffix = strdup("png");
	     entry->thumbnail = &_e_fm_mime_thumbnail_evas;
	     entries = evas_list_append(entries,entry);

	  }
	/* audio */
	entry = E_NEW(E_Fm_Mime_Entry,1);
	entry->name = strdup("audio");
	entry->label = strdup("Audio File");
	entry->parent = l1;
	entry->level = 2;
	entries = evas_list_append(entries,entry);
	_e_fm_mime_action_append(entry, "xmms_play");
	_e_fm_mime_action_append(entry, "xmms_enqueue");
	l2 = entry;
	  {
	     /* mp3 */
	     entry = E_NEW(E_Fm_Mime_Entry, 1);
	     entry->name = strdup("mp3");
	     entry->label = strdup("MP3 Audio");
	     entry->parent = l2;
	     entry->level = 3;
	     entry->suffix = strdup("mp3");
	     entries = evas_list_append(entries,entry);
	     
	     /* ogg */
	     entry = E_NEW(E_Fm_Mime_Entry, 1);
	     entry->name = strdup("ogg");
	     entry->label = strdup("OGG Audio");
	     entry->parent = l2;
	     entry->level = 3;
	     entry->suffix = strdup("ogg");
	     entries = evas_list_append(entries,entry);

	     /* wav */
	     entry = E_NEW(E_Fm_Mime_Entry, 1);
	     entry->name = strdup("wav");
	     entry->label = strdup("WAV Audio");
	     entry->parent = l2;
	     entry->level = 3;
	     entry->suffix = strdup("wav");
	     entries = evas_list_append(entries,entry);
	  }
     }
   /* directory */
   entry = E_NEW(E_Fm_Mime_Entry,1);
   entry->name = strdup("folder");
   entry->label = strdup("Folder");
   entry->type = E_FM_FILE_TYPE_DIRECTORY;
   entry->parent = root;
   entry->level = 1;
   entries = evas_list_append(entries,entry);
   _e_fm_mime_action_default_set(entry, "_folder_open");
   _e_fm_mime_action_append(entry, "_folder_open_other");
   l1 = entry;


   
   init_count++;
   return 1;
}

void
e_fm_mime_shutdwon(void)
{
   init_count--;
}


/* returns the shortest root mime for a list of @files 
 * FIXME can be implemented faster? delete the list while iterating
 */
E_Fm_Mime_Entry *
e_fm_mime_get_from_list(Evas_List *files)
{
   E_Fm_File *file;
   E_Fm_Mime_Entry *entry;
   Evas_List *l;

   if (files == NULL) 
     return NULL;
   
   file = (E_Fm_File *)files->data;
   entry = file->mime;
   for (l = files->next; l; l = l->next)
     {
	E_Fm_Mime_Entry *eme;

	file = (E_Fm_File *)l->data;
	eme = file->mime;
	entry = _e_fm_mime_common(entry,eme);
     }
   return entry;
}


/* returns the mime entry for a file */
void 
e_fm_mime_set(E_Fm_File *file)
{
   Evas_List *l;
   for(l = entries; l; l = l->next)
     {
	E_Fm_Mime_Entry *entry;
	
	entry = (E_Fm_Mime_Entry *)l->data;
	
	/* FIXME add all the possible comparision, suffix,regexp,flags,etc */
	if(entry->suffix)
	  {
	     char *suffix;

	     suffix = _e_fm_mime_suffix_get(file->name);
	     if(!suffix)
	       continue;
	     if(!strcasecmp(suffix,entry->suffix))
	       {
		  //printf("found by suffix %s\n", suffix);
		  file->mime = entry;
	       }
	     free(suffix);
	  }
	if(entry->type)
	  {
	     if(entry->type == file->type)
	       file->mime = entry;
	  }
     }
   /* if it doesnt match anything set to the root */
   if(!file->mime)
     file->mime = (E_Fm_Mime_Entry*)entries->data;
}

#if 0
EAPI E_Fm_Mime_Action *
e_fm_mime_action_get_by_label(char *label)
{
   Evas_List *l;
   E_Fm_Mime_Action *action = NULL;
   
   for(l = actions; l; l = l->next)
     {
	action = (E_Fm_Mime_Action*)l->data;
	if(!strcmp(label,action->label))
	  break;
     }
   return action;
}
#endif

/* will call the command of an @action for the fileman_smart @sd */
EAPI int
e_fm_mime_action_call(E_Fm_Smart_Data *sd, E_Fm_Mime_Action *action)
{
   Ecore_Exe *exe;
   char *command;

   /* FIXME: use the e app execution mechanisms where possible so we can
    * collect error output
    */
   if(action->is_internal)
     {
	action->internal.function(sd);
     }
   else
     {
	command = _e_fm_mime_string_tokenizer(sd->operation.files,sd->operation.hover,action->cmd);
	printf("going to execute %s\n", command);
	exe = ecore_exe_run(command, NULL);

   
	if (!exe)
	  {
	
	     e_error_dialog_show(_("Run Error"),
			    _("Enlightenment was unable to fork a child process:\n"
			      "\n"
			      "%s\n"
			      "\n"),
			    command);
	     return 0;
	  }
     }
   return 1;
}

EAPI void
e_fm_mime_action_default_call(E_Fm_Smart_Data *sd)
{
   E_Fm_Mime_Entry  *mime;
   E_Fm_Mime_Action *action;

   mime = sd->operation.mime;
   do
     {
	action = mime->action_default;
	     
	if(!action)
	  {
	     mime = mime->parent;
	     continue;
	  }
	/* if we reach here we have an action */
	break;
     } while(mime);
   if(!action)
     return;
   
   e_fm_mime_action_call(sd, action);
}

EAPI char *
e_fm_mime_translate(E_Fm_Smart_Data *sd, char *istr)
{
   char *ostr;

   ostr = _e_fm_mime_string_tokenizer(sd->operation.files,sd->operation.hover, istr);

   return ostr;
}

/* subsystem functions */
/***********************/

/* returns the shortest root for both entries @e1 and @e2 
 * FIXME can be implemented faster?
 */

static E_Fm_Mime_Entry *
_e_fm_mime_common(E_Fm_Mime_Entry *e1, E_Fm_Mime_Entry *e2)
{

   E_Fm_Mime_Entry *tmp;
   int i;
   int count;
   
   /* take the lowest on the tree */
   /* set the e1 upper, e2 lower  */
   if(e1->level > e2->level)
     {
	count = e1->level - e2->level;
	tmp = e1;
	e1 = e2;
	e2 = tmp;
     }
   else
	count = e2->level - e1-> level;
	   
   /* first equal levels */
   for(i = 0; i < count; i++)
     {
	e2 = e2->parent;
     }
   /* get up on the tree until we find the same parent */
   for(i = e1->level; i >= 0; i--)
     {
	if(!strcmp(e1->name,e2->name))
	  return e1;
	e1 = e1->parent;
	e2 = e2->parent;
     }
   /* this should never happen */
   return NULL;
}

/* will translate %f,%d to file,dir respective */
static char*
_e_fm_mime_string_tokenizer(Evas_List *files, E_Fm_File *hover, char *istr)
{
   char *buf;
   char *c;
   int i, bsize,trans;
   Evas_List *l;

   buf = calloc(PATH_MAX,sizeof(char));
   bsize = PATH_MAX;
   i = 0;
   trans = 0;
   for(c = istr; *c; c++)
     {
	if( i > bsize - 1)
	  {
	     bsize += PATH_MAX;
	     buf = realloc(buf,bsize);
	  }
	if(trans)
	  {
	     char *astr = NULL;
	     if(*c == 'f')
	       {
		  int j = 2;

		  astr = calloc(PATH_MAX,sizeof(char));
		  for(l = files; l; l = l->next)
		    {
		       E_Fm_File *file;
		       
		       file = (E_Fm_File *)l->data;
		       sprintf(astr,"%s %s",astr,file->path);
		       astr = realloc(astr,PATH_MAX*j);
		       j++;
		    }
	       }
	     if(*c == 'h')
	       {
		  astr = strdup(hover->path);
	       }
	     if(!astr)
	       continue;
	     if(bsize < i + strlen(astr))
	       {
		  bsize += strlen(astr) + 1;
		  buf = realloc(buf,bsize);
	       }
	     buf[i-1] = '\0';
	     sprintf(buf, "%s%s", buf, astr);
	     i += strlen(astr) - 1;
	     trans = 0;
	     free(astr);
	     continue;
	  }
	if(*c == '%')
	     trans = 1;
	else
	     buf[i] = *c;
	i++;
     }
   return buf;
}


static void
_e_fm_mime_action_append(E_Fm_Mime_Entry *entry, char *action_name)
{
   Evas_List *l;

   for(l = actions; l; l = l->next)
     {
	E_Fm_Mime_Action *action;

	action = (E_Fm_Mime_Action *)l->data;
	if(!strcmp(action->name, action_name))
	  {
	     entry->actions = evas_list_append(entry->actions, action);
	     break;
	  }
     }
}

static void
_e_fm_mime_action_default_set(E_Fm_Mime_Entry *entry, char *action_name)
{
   Evas_List *l;

   for(l = actions; l; l = l->next)
     {
	E_Fm_Mime_Action *action;

	action = (E_Fm_Mime_Action *)l->data;
	if(!strcmp(action->name, action_name))
	  {
	     /* overwrite the old default action */
	     if(action->relative)
	       entry->action_default_relative = action;
	     else
	       entry->action_default = action;
	     entry->actions = evas_list_append(entry->actions, action);
	     break;
	  }
     }
}

static char *
_e_fm_mime_suffix_get(char *filename)
{
   char *suf;

   suf = strrchr(filename, '.');
   if (suf)
     {
	suf++;
	suf = strdup(suf);
	return suf;
     }
   return NULL;
}


static void 
_e_fm_mime_action_internal_folder_open(E_Fm_Smart_Data *sd)
{
   E_Fm_File *file;

   file = sd->operation.files->data;
   e_fm_dir_set(sd->object, file->path);

}

static void 
_e_fm_mime_action_internal_folder_open_other(E_Fm_Smart_Data *sd)
{
   E_Fileman *fileman;
   E_Fm_File *file;

   file = sd->operation.files->data;
   fileman = e_fileman_new_to_dir(e_container_current_get(e_manager_current_get()), file->path);
   e_fileman_show(fileman);
}
static void 
_e_fm_mime_action_internal_copy_to(E_Fm_Smart_Data *sd)
{
   printf("going to copy to %s\n", sd->operation.hover->path);
}
static void 
_e_fm_mime_action_internal_move_to(E_Fm_Smart_Data *sd)
{
   printf("going to move to %s\n", sd->operation.hover->path);
}

/* thumbnail functions */
/***********************/
Evas_Object * _e_fm_mime_thumbnail_evas(char *path, Evas_Coord w, Evas_Coord h, Evas *evas, Evas_Object **tmp, void (*cb)(Evas_Object *obj, void *data), void *data)
{
   Evas_Object *r;

   r = e_thumb_generate_begin(path, w,
         h, evas, tmp, cb,
         data);

   return r;
}