summaryrefslogblamecommitdiff
path: root/src/lib/edje/edje_multisense.c
blob: ce4bd12e870d98fe033702e2786e7ff2fd866b5c (plain) (tree)
1
2
3
4
5
6
7
8
9
                         

                        
                        
 
                      
                    
                                      
 
           
                                                              
 
                            
 
 
           
                                                         

                       
                            
              

 
                                
 


                                  
                       

  
          
                                                           
 
                                               

                     
 
          
                                                                             
 
                                               
 
                  
      

                            

              


                             
 

                                         




              
                     

 
          
                                                                              
 
                                               
 





                                                
 
          
                                                     
 
                                               
 
                     

 

                 
 
                                                     
 
                                             
                                                           
                         

              
 



















                                                                      
                                     

                                        

                 
      





                                                 
                                                

                                        
                 
                    

      
 
         
                                                                                                               
 
                        
          
                             
                        
         
                              
 
                                                     
 
                                  
 




                                           

                                                      
                       
 
                                                                
      









































                                                                                    
                                                                                                                                                                                                                                                                                                                      

                      
 
              
                                                                                                                                                                       

                   
                                                                                                                                                                     

        



                                  












                                                                             
                                

                                    
                                                             

                      






                                                           
                                


                                    
      
                    
     
                 



                     
                     
      


         
                                                                                                              
 
                        

                         
                              
 
          

                  
                                       

                          
 

                                                     
                                  
 

                                                      
 
                                                         



                                              
                                                               
                                      
                                                                            
                                                         
                                                                                               

                      
                
              
                                                                                                                                                                       

                   
                                                                                                                                                                     

        

                                  
 
                                                             


                                                
                                

                                    


                    
     
                 



                   
                     
      

 



                                                                                                                                  

                                                                                  
     

                



                     



                           
                      






                               






                                                               
                         


                   
                          

      
 
#include "edje_private.h"

#ifdef ENABLE_MULTISENSE
#include "Ecore_Audio.h"

static Eo *out = NULL;
static int outs = 0;
static Eina_Bool outfail = EINA_FALSE;

static void
_play_finished(void *data EINA_UNUSED, const Efl_Event *event)
{
   efl_unref(event->object);
}

static void
_out_fail(void *data EINA_UNUSED, const Efl_Event *event)
{
   outfail = EINA_TRUE;
   efl_unref(event->object);
   out = NULL;
}

struct _edje_multisense_eet_data
{
   unsigned int    offset, length;
   Eet_File       *ef;
   const char     *data;
   Ecore_Audio_Vio vio;
};

static int
eet_snd_file_get_length(void *data, Eo *eo_obj EINA_UNUSED)
{
   struct _edje_multisense_eet_data *vf = data;
   return vf->length;
}

static int
eet_snd_file_seek(void *data, Eo *eo_obj EINA_UNUSED, int offset, int whence)
{
   struct _edje_multisense_eet_data *vf = data;

   switch (whence)
     {
      case SEEK_SET:
        vf->offset = offset;
        break;

      case SEEK_CUR:
        vf->offset += offset;
        break;

      case SEEK_END:
        vf->offset = vf->length + offset;
        break;

      default:
        break;
     }
   return vf->offset;
}

static int
eet_snd_file_read(void *data, Eo *eo_obj EINA_UNUSED, void *buffer, int count)
{
   struct _edje_multisense_eet_data *vf = data;

   if ((vf->offset + count) > vf->length)
     count = vf->length - vf->offset;
   memcpy(buffer, vf->data + vf->offset, count);
   vf->offset += count;
   return count;
}

static int
eet_snd_file_tell(void *data, Eo *eo_obj EINA_UNUSED)
{
   struct _edje_multisense_eet_data *vf = data;

   return vf->offset;
}

static void
_free(void *data)
{
   struct _edje_multisense_eet_data *eet_data = data;

   if (eet_data->ef) eet_close(eet_data->ef);
// don't free if eet_data->data  comes from eet_read_direct
//  free(eet_data->data);
   free(data);
   outs--;
}

static Eina_Bool _channel_mute_states[8] = { 0 };

static Eina_Bool
_channel_mute(Edje *ed EINA_UNUSED, int channel)
{
   // ed lets use set mute per object... but for now no api's for this
   // if all are muted ... then all!
   if (_channel_mute_states[7]) return EINA_TRUE;
   if ((channel < 0) || (channel > 7)) return EINA_FALSE;
   return _channel_mute_states[channel];
   return EINA_FALSE;
}

#endif

EAPI void
edje_audio_channel_mute_set(Edje_Channel channel, Eina_Bool mute)
{
#ifdef ENABLE_MULTISENSE
   if ((unsigned)channel > 7) return;
   _channel_mute_states[channel] = mute;
#else
   (void)channel;
   (void)mute;
#endif
}

EAPI Eina_Bool
edje_audio_channel_mute_get(Edje_Channel channel)
{
#ifdef ENABLE_MULTISENSE
   if ((unsigned)channel > 7) return EINA_FALSE;
   return _channel_mute_states[channel];
#else
   (void)channel;
   return EINA_TRUE;
#endif
}

Eina_Bool
_edje_multisense_internal_sound_sample_play(Edje *ed, const char *sample_name, const double speed, int channel)
{
#ifdef ENABLE_MULTISENSE
   Eo *in;
   Edje_Sound_Sample *sample;
   char snd_id_str[255];
   int i;
   Eina_Bool ret = EINA_FALSE;

   if (_channel_mute(ed, channel)) return EINA_FALSE;

   if (outfail) return EINA_FALSE;

   if (!sample_name)
     {
        ERR("Given Sample Name is NULL\n");
        return EINA_FALSE;
     }

   if ((!ed) || (!ed->file) || (!ed->file->sound_dir))
     return EINA_FALSE;

   for (i = 0; i < (int)ed->file->sound_dir->samples_count; i++)
     {
        sample = &ed->file->sound_dir->samples[i];
        if (!strcmp(sample->name, sample_name))
          {
             struct _edje_multisense_eet_data *eet_data;
             int len;

             snprintf(snd_id_str, sizeof(snd_id_str), "edje/sounds/%i", sample->id);

             eet_data = calloc(1, sizeof(struct _edje_multisense_eet_data));
             if (!eet_data)
               {
                  ERR("Out of memory in allocating multisense sample info");
                  return EINA_FALSE;
               }
             // open eet file again to esnure we have  reference because we
             // use eet_read_direct to avoid duplicating/copying into memory
             // by relying on a direct mmap, but this means we need to close
             // the eet file handle instead of freeing data
             eet_data->ef = eet_mmap(ed->file->f);
             if (!eet_data->ef)
               {
                  ERR("Cannot open edje file '%s' for samples", ed->path);
                  free(eet_data);
                  return EINA_FALSE;
               }
             eet_data->data = eet_read_direct(eet_data->ef, snd_id_str, &len);
             if (len <= 0)
               {
                  ERR("Sample form edj file '%s' is 0 length", ed->path);
                  eet_close(eet_data->ef);
                  free(eet_data);
                  return EINA_FALSE;
               }
             eet_data->length = len;
             /* action->speed */

             eet_data->vio.get_length = eet_snd_file_get_length;
             eet_data->vio.seek = eet_snd_file_seek;
             eet_data->vio.read = eet_snd_file_read;
             eet_data->vio.tell = eet_snd_file_tell;
             eet_data->offset = 0;

             in = efl_add_ref(ECORE_AUDIO_IN_SNDFILE_CLASS, NULL, efl_name_set(efl_added, snd_id_str), ecore_audio_obj_in_speed_set(efl_added, speed), ecore_audio_obj_vio_set(efl_added, &eet_data->vio, eet_data, _free), efl_event_callback_add(efl_added, ECORE_AUDIO_IN_EVENT_IN_STOPPED, _play_finished, NULL));
             if (!out)
               {

# ifdef _WIN32
                  out = efl_add_ref(ECORE_AUDIO_OUT_WASAPI_CLASS, NULL, efl_event_callback_add(efl_added, ECORE_AUDIO_OUT_WASAPI_EVENT_CONTEXT_FAIL, _out_fail, NULL));
# else
#  ifdef HAVE_PULSE
                  out = efl_add_ref(ECORE_AUDIO_OUT_PULSE_CLASS, NULL, efl_event_callback_add(efl_added, ECORE_AUDIO_OUT_PULSE_EVENT_CONTEXT_FAIL, _out_fail, NULL));
#  endif
# endif
                  if (out) outs++;
               }
             if (!out)
               {
                  static Eina_Bool complained = EINA_FALSE;

                  if (!complained)
                    {
                       complained = EINA_TRUE;
# ifdef _WIN32
                       ERR("Could not create multisense audio out (wasapi)");
# else
#  ifdef HAVE_PULSE
                       ERR("Could not create multisense audio out (pulse)");
#  endif
# endif
                    }
                  efl_unref(in);
                  return EINA_FALSE;
               }
             ret = ecore_audio_obj_out_input_attach(out, in);
             if (!ret)
               {
                  static Eina_Bool complained = EINA_FALSE;

                  if (!complained)
                    {
                       complained = EINA_TRUE;
                       ERR("Could not attach input");
                    }
                  efl_unref(in);
                  return EINA_FALSE;
               }
          }
     }
   return EINA_TRUE;
#else
   // warning shh
   (void)ed;
   (void)sample_name;
   (void)speed;
   (void)channel;
   return EINA_FALSE;
#endif
}

Eina_Bool
_edje_multisense_internal_sound_tone_play(Edje *ed, const char *tone_name, const double duration, int channel)
{
#ifdef ENABLE_MULTISENSE
   unsigned int i;
   Edje_Sound_Tone *tone;
   Eina_Bool ret = EINA_FALSE;

   Eo *in;
   if (!tone_name)
     {
        ERR("Given Tone Name is NULL");
        return EINA_FALSE;
     }

   if (_channel_mute(ed, channel)) return EINA_FALSE;

   if (outfail) return EINA_FALSE;

   if ((!ed) || (!ed->file) || (!ed->file->sound_dir))
     return EINA_FALSE;

   for (i = 0; i < ed->file->sound_dir->tones_count; i++)
     {
        tone = &ed->file->sound_dir->tones[i];
        if (!strcmp(tone->name, tone_name))
          {
             in = efl_add_ref(ECORE_AUDIO_IN_TONE_CLASS, NULL);
             efl_name_set(in, "tone");
             efl_key_data_set(in, ECORE_AUDIO_ATTR_TONE_FREQ, &tone->value);
             ecore_audio_obj_in_length_set(in, duration);
             efl_event_callback_add(in, ECORE_AUDIO_IN_EVENT_IN_STOPPED, _play_finished, NULL);

             if (!out)
               {
# ifdef _WIN32
                  out = efl_add_ref(ECORE_AUDIO_OUT_WASAPI_CLASS, NULL, efl_event_callback_add(efl_added, ECORE_AUDIO_OUT_WASAPI_EVENT_CONTEXT_FAIL, _out_fail, NULL));
# else
#  ifdef HAVE_PULSE
                  out = efl_add_ref(ECORE_AUDIO_OUT_PULSE_CLASS, NULL, efl_event_callback_add(efl_added, ECORE_AUDIO_OUT_PULSE_EVENT_CONTEXT_FAIL, _out_fail, NULL));
#  endif
# endif
                  if (out) outs++;
               }

             ret = ecore_audio_obj_out_input_attach(out, in);
             if (!ret)
               {
                  ERR("Could not attach input");
                  efl_unref(in);
                  return EINA_FALSE;
               }
          }
     }
   return EINA_TRUE;
#else
   // warning shh
   (void)ed;
   (void)duration;
   (void)tone_name;
   (void)channel;
   return EINA_FALSE;
#endif
}

Eina_Bool
_edje_multisense_internal_vibration_sample_play(Edje *ed EINA_UNUSED, const char *sample_name EINA_UNUSED, int repeat EINA_UNUSED)
{
#ifdef ENABLE_MULTISENSE
   ERR("Vibration is not supported yet, name:%s, repeat:%d", sample_name, repeat);
   return EINA_FALSE;
#else
   (void)ed;
   (void)repeat;
   return EINA_FALSE;
#endif
}

void
_edje_multisense_init(void)
{
#ifdef ENABLE_MULTISENSE
   ecore_audio_init();
#endif
}

void
_edje_multisense_shutdown(void)
{
#ifdef ENABLE_MULTISENSE
   if (outs > 0)
     {
        WRN("Shutting down audio while samples still playing");
     }
   if (out)
     {
        // XXX: this causes an abort inside of pa!!!!!
        //efl_unref(out);
        out = NULL;
        outs = 0;
     }
   ecore_audio_shutdown();
#endif
}