Back to index

gcompris  8.2.2
Classes | Functions | Variables
soundutil.c File Reference
#include "string.h"
#include "gcompris.h"
#include <signal.h>
#include <glib.h>
#include "gcompris-marshal.h"

Go to the source code of this file.

Classes

struct  _GcomprisSoundPrivate

Functions

static void * thread_play_ogg (gchar *file)
static char * get_next_sound_to_play ()
static gpointer scheduler_fx (gpointer user_data)
static gpointer scheduler_music (gpointer user_data)
void gc_sound_callback (GcomprisSound *ctl, gchar *file, gpointer user_data)
void gc_sound_init ()
void gc_sound_close ()
void gc_sound_reopen ()
void gc_sound_pause ()
void gc_sound_resume ()
void gc_sound_policy_set (int policy)
int gc_sound_policy_get ()
void gc_sound_play_ogg_cb (const gchar *file, GcomprisSoundCallback cb)
void gc_sound_play_ogg (const gchar *sound,...)
void free_string (gpointer data, gpointer user_data)
void gc_sound_play_ogg_list (GList *files)
gchar * gc_sound_alphabet (gchar *chars)
 return a string representing a letter or number audio file get alphabet sound file name from gunichar
static void gc_sound_instance_init (GTypeInstance *instance, gpointer g_class)
static void default_sound_played_signal_handler (GcomprisSound *obj, gchar *file, gpointer user_data)
static void gc_sound_class_init (gpointer g_class, gpointer g_class_data)
GType gc_sound_get_type (void)

Variables

static GList * pending_queue = NULL
static int sound_policy
static gboolean music_paused = FALSE
static gboolean sound_closed = FALSE
GMutex * lock = NULL
GMutex * lock_music = NULL
GMutex * lock_fx = NULL
GCond * cond = NULL
static guint sound_init = 0
GThread * thread_scheduler_fx
GThread * thread_scheduler_music
GObject * gc_sound_controller = NULL
GHashTable * sound_callbacks = NULL

Class Documentation

struct _GcomprisSoundPrivate

Definition at line 508 of file soundutil.c.


Function Documentation

static void default_sound_played_signal_handler ( GcomprisSound *  obj,
gchar *  file,
gpointer  user_data 
) [static]

Definition at line 523 of file soundutil.c.

{
        /* Here, we trigger the real file write. */
        g_warning ("sound_played: %s\n", file);
}

Here is the caller graph for this function:

void free_string ( gpointer  data,
gpointer  user_data 
)

Definition at line 397 of file soundutil.c.

{
  g_free(data);
}
gchar* gc_sound_alphabet ( gchar *  chars)

return a string representing a letter or number audio file get alphabet sound file name from gunichar

the returned sound has the suffix .ogg

Returns:
a newly allocated string of the form U0033.ogg

Definition at line 454 of file soundutil.c.

{
  gchar *next, *str, *prev, *result;
  gint i;
  gint length;
  gunichar next_unichar;

  length = g_utf8_strlen(chars, -1);

  next = chars;
  result = NULL;

  for (i=0; i < length; i++) {
    next_unichar = g_utf8_get_char(next);
    str = g_strdup_printf("U%.4X",(gint32) g_unichar_tolower(next_unichar));
    prev = result;
    if (prev)
      result = g_strconcat( prev, str, NULL);
    else
      result = g_strdup(str);

    g_free(str);
    g_free(prev);
    next = g_utf8_next_char(next);
  }

  gchar *result2 = g_strdup_printf("%s.ogg",result);
  g_free(result);

  return result2;
}

Here is the caller graph for this function:

void gc_sound_callback ( GcomprisSound *  ctl,
gchar *  file,
gpointer  user_data 
)

Definition at line 487 of file soundutil.c.

{
  GcomprisSoundCallback cb;

  if (!sound_callbacks)
    return;

  cb = g_hash_table_lookup (sound_callbacks, file);

  if (cb){
    g_warning("calling callback for %s", file);
    cb(file);
  }
  else
    g_warning("%s has no callback", file);
  g_hash_table_remove(sound_callbacks, file);

}

Here is the caller graph for this function:

static void gc_sound_class_init ( gpointer  g_class,
gpointer  g_class_data 
) [static]

Definition at line 530 of file soundutil.c.

{
        GcomprisSoundClass *klass = GCOMPRIS_SOUND_CLASS (g_class);

       klass->sound_played = default_sound_played_signal_handler;

        klass->sound_played_signal_id =
                g_signal_new ("sound-played",
                           G_TYPE_FROM_CLASS (g_class),
                           G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
                           G_STRUCT_OFFSET (GcomprisSoundClass, sound_played),
                           NULL /* accumulator */,
                           NULL /* accu_data */,
                           gnome_canvas_marshal_VOID__POINTER,
                           G_TYPE_NONE /* return_type */,
                           1     /* n_params */,
                           G_TYPE_POINTER  /* param_types */);

}

Here is the call graph for this function:

Here is the caller graph for this function:

void gc_sound_close ( void  )

Definition at line 111 of file soundutil.c.

{
  if ( !sound_closed )
    {
      sdlplayer_halt_music();
      sdlplayer_halt_fx();
      g_mutex_lock(lock_fx);
      g_mutex_lock(lock_music);
      sdlplayer_close();
      sound_closed = TRUE;
      music_paused = FALSE;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

GType gc_sound_get_type ( void  )

Definition at line 551 of file soundutil.c.

{
        static GType type = 0;
        if (type == 0) {
                static const GTypeInfo info = {
                        sizeof (GcomprisSoundClass),
                        NULL,   /* base_init */
                        NULL,   /* base_finalize */
                        gc_sound_class_init,   /* class_init */
                        NULL,   /* class_finalize */
                        NULL,   /* class_data */
                        sizeof (GcomprisSound),
                        0,      /* n_preallocs */
                        gc_sound_instance_init    /* instance_init */
                };
                type = g_type_register_static (G_TYPE_OBJECT,
                                               "GcomprisSoundType",
                                               &info, 0);
        }
        return type;
}

Here is the call graph for this function:

void gc_sound_init ( void  )

Definition at line 61 of file soundutil.c.

{

  /* Check to run the init once only */
  if(sound_init == 1)
    {
      if(sound_closed == TRUE)
       gc_sound_reopen();

         return;
    }
  sound_init = 1;

  gc_sound_controller = g_object_new (GCOMPRIS_SOUND_TYPE, NULL);

  g_signal_connect( gc_sound_controller,
                  "sound-played",
                  (GCallback) gc_sound_callback,
                  NULL);

  g_assert( gc_sound_controller != NULL );

  /* Initialize the thread system */
  if (!g_thread_supported ()) g_thread_init (NULL);

  lock = g_mutex_new ();
  lock_music = g_mutex_new ();
  lock_fx = g_mutex_new ();
  cond = g_cond_new ();

  sound_policy = PLAY_AFTER_CURRENT;

  if(sdlplayer_init()!=0) {
    /* Sound init failed. Desactivate the sound */
    gc_prop_get()->music = 0;
    gc_prop_get()->fx    = 0;
    return;
  }

  thread_scheduler_fx = g_thread_create((GThreadFunc)scheduler_fx, NULL, FALSE, NULL);
  if (thread_scheduler_fx == NULL)
    perror("create failed for fx scheduler");

  thread_scheduler_music = g_thread_create((GThreadFunc)scheduler_music, NULL, FALSE, NULL);
  if (thread_scheduler_music == NULL)
    perror("create failed for music scheduler");

}

Here is the call graph for this function:

Here is the caller graph for this function:

static void gc_sound_instance_init ( GTypeInstance *  instance,
gpointer  g_class 
) [static]

Definition at line 515 of file soundutil.c.

{
        GcomprisSound *self = (GcomprisSound *)instance;
        self->private = g_new (GcomprisSoundPrivate, 1);
}

Here is the caller graph for this function:

void gc_sound_pause ( void  )

Definition at line 139 of file soundutil.c.

Here is the call graph for this function:

Here is the caller graph for this function:

void gc_sound_play_ogg ( const gchar *  sound,
  ... 
)

Definition at line 365 of file soundutil.c.

{
  va_list ap;
  char* tmp = NULL;
  GList* list = NULL;

  if(!sound || !gc_prop_get()->fx)
    return;

  list = g_list_append(list, (gpointer)sound);

  g_warning("Adding %s in the play list queue\n", sound);

  va_start( ap, sound);
  while( (tmp = va_arg (ap, char *)))
    {
      list = g_list_append(list, (gpointer)tmp);
    }
  va_end(ap);

  gc_sound_play_ogg_list( list );

  g_list_free(list);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void gc_sound_play_ogg_cb ( const gchar *  file,
GcomprisSoundCallback  cb 
)

Definition at line 338 of file soundutil.c.

{

  g_assert ( cb != NULL);

  /* g_intern_string is in 2.10 */
  const gchar *intern_file = g_quark_to_string( g_quark_from_string(file));

  if (!sound_callbacks)
    sound_callbacks = g_hash_table_new_full (g_str_hash,
                                       g_str_equal,
                                       NULL,
                                       NULL);

  /* i suppose there will not be two call of that function with same sound file before sound is played */
  g_hash_table_replace (sound_callbacks,
                     (gpointer)intern_file,
                     cb);
  gc_sound_play_ogg(intern_file, NULL);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void gc_sound_play_ogg_list ( GList *  files)

Definition at line 402 of file soundutil.c.

{
  GList* list;
  char* tmpSound = NULL;

  if ( !gc_prop_get()->fx )
    return;

  if (        sound_policy == PLAY_ONLY_IF_IDLE &&
        g_list_length( pending_queue ) > 0 )
    return;

  if ( sound_policy == PLAY_AND_INTERRUPT ) {
    g_warning("halt music");
    while ( g_list_length(pending_queue) > 0 )
    {
      tmpSound = g_list_nth_data( pending_queue, 0 );
      pending_queue = g_list_remove( pending_queue, tmpSound );
      g_free(tmpSound);
    }
    sdlplayer_halt_fx();
  }

  g_mutex_lock (lock);

  list = g_list_first( files );
  while( list!=NULL )
    {
      if (g_list_length(pending_queue) < MAX_QUEUE_LENGTH)
       {
         pending_queue = g_list_append(pending_queue, g_strdup( (gchar*)(list->data) ));
       }
      list = g_list_next(list);
    }

  g_mutex_unlock (lock);

  // Tell the scheduler to check for new sounds to play
  g_warning("Tell the scheduler to check for new sounds to play\n");
  g_cond_signal (cond);

}

Here is the call graph for this function:

Here is the caller graph for this function:

int gc_sound_policy_get ( void  )

Definition at line 170 of file soundutil.c.

{
  return sound_policy;
}

Here is the caller graph for this function:

void gc_sound_policy_set ( int  policy)

Definition at line 156 of file soundutil.c.

Here is the caller graph for this function:

void gc_sound_reopen ( void  )

Definition at line 126 of file soundutil.c.

{
  if (sound_closed)
    {
      sdlplayer_reopen();
      g_mutex_unlock(lock_fx);
      g_mutex_unlock(lock_music);
      sound_closed = FALSE;
      music_paused = FALSE;
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void gc_sound_resume ( void  )

Definition at line 146 of file soundutil.c.

Here is the call graph for this function:

Here is the caller graph for this function:

static char * get_next_sound_to_play ( ) [static]

Definition at line 315 of file soundutil.c.

{
  char* tmpSound = NULL;

  g_mutex_lock (lock);

  if ( g_list_length(pending_queue) > 0 )
    {
      tmpSound = g_list_nth_data( pending_queue, 0 );
      pending_queue = g_list_remove( pending_queue, tmpSound );
      g_warning( "... get_next_sound_to_play : %s\n", tmpSound );
    }

  g_mutex_unlock (lock);

  return tmpSound;
}

Here is the caller graph for this function:

static gpointer scheduler_fx ( gpointer  user_data) [static]

Definition at line 261 of file soundutil.c.

{
  char *sound = NULL;

  while (TRUE)
    {
      if ( ( sound = get_next_sound_to_play( ) ) != NULL )
       {
         thread_play_ogg(sound);
         g_free(sound);
       }
      else
       {
         g_mutex_lock (lock);
         g_cond_wait (cond, lock);
         g_mutex_unlock (lock);
       }
    }
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gpointer scheduler_music ( gpointer  user_data) [static]

Definition at line 181 of file soundutil.c.

{
  GcomprisProperties *properties = gc_prop_get();
  gint i;
  gchar *str;
  gchar *music_dir;
  GSList *musiclist = NULL;
  GDir *dir;
  const gchar *one_dirent;

  /* Sleep to let gcompris intialisation and intro music to complete */
  g_usleep(25000000);

  /* Load the Music directory file names */
  music_dir = g_strconcat(properties->package_data_dir, "/music/background", NULL);

  dir = g_dir_open(music_dir, 0, NULL);

  if (!dir) {
    g_warning ("Couldn't open music dir: %s", music_dir);
    g_free(music_dir);
    return NULL;
  }

  /* Fill up the music list */
  while((one_dirent = g_dir_read_name(dir)) != NULL)
    {
      if (g_str_has_suffix(one_dirent, ".ogg"))
       {
         str = g_strdup_printf("%s/%s", music_dir, one_dirent);
         musiclist = g_slist_insert (musiclist, str, RAND(0, g_slist_length(musiclist)));
       }
    }
  g_dir_close(dir);

  /* No music no play */
  if(g_slist_length(musiclist)==0)
    {
      g_free(music_dir);
      return NULL;
    }

  /* Now loop over all our music files */
  while (TRUE)
    {
      for(i=0; i<g_slist_length(musiclist); i++)
       {
         /* Music can be disabled at any time */
         while(!gc_prop_get()->music || music_paused)
           g_usleep(1000000);

         /* WARNING Displaying stuff in a thread seems to make gcompris unstable */
         /*     display_ogg_file_credits((char *)g_list_nth_data(musiclist, i)); */
         //     if(decode_ogg_file((char *)g_list_nth_data(musiclist, i))!=0)
         g_mutex_lock(lock_music);
         if(sdlplayer_music((char *)g_slist_nth_data(musiclist, i), 128)!=0){
           g_warning("sdlplayer_music failed, try again in 5 seconds");
           g_usleep(5000000);
         }
         g_mutex_unlock(lock_music);

       }
    }

  /* Never happen */
  g_slist_free(musiclist);
  g_warning( "The background thread music is stopped now. "\
            "The files in %s are not ogg vorbis OR the sound output failed",
            music_dir);
  g_free(music_dir);
  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void * thread_play_ogg ( gchar *  file) [static]

Definition at line 285 of file soundutil.c.

{
  gchar *absolute_file;

  g_warning("  Thread_play_ogg %s", file);

  absolute_file = gc_file_find_absolute(file);

  if (!absolute_file)
    return NULL;

  g_warning("   Calling gcompris internal sdlplayer_file (%s)", absolute_file);
  g_mutex_lock(lock_fx);
  sdlplayer_fx(absolute_file, 128);
  g_mutex_unlock(lock_fx);
  g_signal_emit (gc_sound_controller,
               GCOMPRIS_SOUND_GET_CLASS (gc_sound_controller)->sound_played_signal_id,
               0 /* details */,
               g_strdup(file));
  g_warning("  sdlplayer_fx(%s) ended.", absolute_file);

  g_free(absolute_file);

  return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

GCond* cond = NULL

Definition at line 38 of file soundutil.c.

GObject* gc_sound_controller = NULL

Definition at line 53 of file soundutil.c.

GMutex* lock = NULL

Definition at line 35 of file soundutil.c.

GMutex* lock_fx = NULL

Definition at line 37 of file soundutil.c.

GMutex* lock_music = NULL

Definition at line 36 of file soundutil.c.

gboolean music_paused = FALSE [static]

Definition at line 31 of file soundutil.c.

GList* pending_queue = NULL [static]

Definition at line 29 of file soundutil.c.

GHashTable* sound_callbacks = NULL

Definition at line 55 of file soundutil.c.

gboolean sound_closed = FALSE [static]

Definition at line 32 of file soundutil.c.

guint sound_init = 0 [static]

Definition at line 41 of file soundutil.c.

int sound_policy [static]

Definition at line 30 of file soundutil.c.

Definition at line 44 of file soundutil.c.

Definition at line 44 of file soundutil.c.