/* gcompris - soundutil.c
*
* Copyright (C) 2002 Pascal Georges
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see .
*/
#include "string.h"
#include "gcompris.h"
#include
#include
#include
static GList *pending_queue = NULL;
static int sound_policy;
static GSList *music_list = NULL;
GHashTable *sound_callbacks = NULL;
/* =====================================================================
*
* =====================================================================*/
void
gc_sound_policy_set(int policy)
{
switch (policy)
{
case PLAY_ONLY_IF_IDLE : sound_policy = PLAY_ONLY_IF_IDLE; break;
case PLAY_AFTER_CURRENT : sound_policy = PLAY_AFTER_CURRENT; break;
case PLAY_AND_INTERRUPT : sound_policy = PLAY_AND_INTERRUPT; break;
default : sound_policy = PLAY_AFTER_CURRENT;
}
}
/* =====================================================================
*
* =====================================================================*/
int
gc_sound_policy_get()
{
return sound_policy;
}
void
gc_sound_close()
{
gc_sound_bg_close();
gc_sound_fx_close();
}
void
gc_sound_reopen()
{
gc_sound_bg_reopen();
gc_sound_fx_reopen();
}
GSList *
gc_sound_get_music_list()
{
return music_list;
}
char *gc_sound_get_next_music()
{
static guint bg_music_index = 0;
/* Music wrapping */
if(bg_music_index++ >= g_slist_length(gc_sound_get_music_list()))
bg_music_index = 0;
return gc_file_find_absolute(g_slist_nth_data(gc_sound_get_music_list(),
bg_music_index));
}
void
gc_sound_build_music_list()
{
GcomprisProperties *properties = gc_prop_get();
gchar *str;
gchar *music_dir;
GDir *dir;
const gchar *one_dirent;
/* 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;
}
/* 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);
music_list = g_slist_insert (music_list, str,
RAND(0, g_slist_length(music_list)));
}
}
g_dir_close(dir);
/* No music no play */
if(g_slist_length(music_list)==0)
{
g_free(music_dir);
return;
}
}
/* =====================================================================
* Returns the next sound play, or NULL if there is no
======================================================================*/
char*
get_next_sound_to_play( )
{
char* tmpSound = NULL;
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 );
}
return tmpSound;
}
/* =====================================================================
* Play a OGG sound file.
* gc_sound_play_ogg function to process the sounds.
======================================================================*/
void
gc_sound_play_ogg_cb(const gchar *file, GcomprisSoundCallback cb)
{
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);
}
/* =====================================================================
* Play a list of OGG sound files. The list must be NULL terminated
* This function wraps the var args into a GList and call the
* gc_sound_play_ogg_list function to process the sounds.
======================================================================*/
void
gc_sound_play_ogg(const gchar *sound, ...)
{
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);
}
/* =====================================================================
* Play a list of OGG sound files.
* The given ogg files will be first tested as a locale dependant sound file:
* sounds//
* If it doesn't exists, then the test is done with a music file:
* music/
=====================================================================*/
void
gc_sound_play_ogg_list( GList* files )
{
GList* list;
gchar* 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 ) {
gc_sound_fx_close();
while ( g_list_length(pending_queue) > 0 )
{
tmpSound = g_list_nth_data( pending_queue, 0 );
g_warning("removing queue file (%s)", tmpSound);
pending_queue = g_list_remove( pending_queue, tmpSound );
gc_sound_callback(tmpSound);
}
}
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) ));
g_warning("adding queue file (%s)", (gchar*)(list->data));
}
list = g_list_next(list);
}
fx_play();
}
/** return a string representing a letter or number audio file
* get alphabet sound file name from gunichar
*
* the returned sound has the suffix .ogg
*
* \return a newly allocated string of the form U0033.ogg
*/
gchar *
gc_sound_alphabet(gchar *chars)
{
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;
}
void gc_sound_callback(gchar *file)
{
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);
g_free(file);
}