diff options
author | Yves Combe <ycombe@src.gnome.org> | 2006-11-16 15:15:01 (GMT) |
---|---|---|
committer | Yves Combe <ycombe@src.gnome.org> | 2006-11-16 15:15:01 (GMT) |
commit | 33cfc959568035ec0cfd0088821cc99ad8ef64a9 (patch) | |
tree | 8af55f9cf78b20e0fd8bb99ccd0ad8a5737ebf4b | |
parent | 8cfbdf6b59db699ea36efbd4cb902113c796d1f3 (diff) |
Added sound policy
-rw-r--r-- | ChangeLog | 11 | ||||
-rw-r--r-- | src/gc_sound/ChangeLog | 10 | ||||
-rw-r--r-- | src/gc_sound/src/gc-sound-channel.gob | 190 | ||||
-rw-r--r-- | src/gc_sound/src/gc-sound-item.gob | 115 | ||||
-rw-r--r-- | src/gc_sound/src/gc-sound-mixer.gob | 6 | ||||
-rw-r--r-- | src/gc_sound/src/test_gc_sound.c | 28 |
6 files changed, 258 insertions, 102 deletions
@@ -1,3 +1,14 @@ +2006-11-16 Yves Combe <yves@ycombe.net> + + Added sound policy (play only if iddle, after current, or interrupt and play). + Seems works ! + + * src/gc_sound/ChangeLog: + * src/gc_sound/src/gc-sound-channel.gob: + * src/gc_sound/src/gc-sound-item.gob: + * src/gc_sound/src/gc-sound-mixer.gob: + * src/gc_sound/src/test_gc_sound.c: (finish), (main): + 2006-11-15 Yves Combe <yves@ycombe.net> Play loop item/groups. diff --git a/src/gc_sound/ChangeLog b/src/gc_sound/ChangeLog index 5af3391..87a4b27 100644 --- a/src/gc_sound/ChangeLog +++ b/src/gc_sound/ChangeLog @@ -1,3 +1,13 @@ +2006-11-16 Yves Combe <yves@ycombe.net> + + Added sound policy (play only if iddle, after current, or interrupt and play). + Seems works ! + + * src/gc-sound-channel.gob: + * src/gc-sound-item.gob: + * src/gc-sound-mixer.gob: + * src/test_gc_sound.c: (finish), (main): + 2006-11-15 Yves Combe <yves@ycombe.net> Play loop of items/group. diff --git a/src/gc_sound/src/gc-sound-channel.gob b/src/gc_sound/src/gc-sound-channel.gob index 5ccc7db..37bfc08 100644 --- a/src/gc_sound/src/gc-sound-channel.gob +++ b/src/gc_sound/src/gc-sound-channel.gob @@ -37,7 +37,7 @@ requires 2.0.0 #endif #include "gc-sound-channel-private.h" - +#include "gc-sound-item-private.h" %} %h{ @@ -48,8 +48,18 @@ requires 2.0.0 %{ static GHashTable *channels_table = NULL; %} + +enum GC_SOUND { + POLICY_NONE, + PLAY_ONLY_IF_IDLE, + PLAY_AFTER_CURRENT, + INTERRUPT_AND_PLAY +} GC:Sound:Policy; + class GC:Sound:Channel from G:Object { public gchar *nick = {NULL}; + + /* channel is the mixer channel number we use */ private int channel destroy { g_hash_table_remove(channels_table, GINT_TO_POINTER(channel)); @@ -59,11 +69,6 @@ class GC:Sound:Channel from G:Object { channels_table = NULL; } }; - property INT channel - (nick = _("Short nickname"), - blurb = _("Long description"), - minimum = 0, export) - get { g_value_set_int (VAL, self->_priv->channel); }; private gboolean initialised = {FALSE}; @@ -71,16 +76,25 @@ class GC:Sound:Channel from G:Object { private GC:Sound:Item *playing_item = { NULL }; private G:List *playing_root = { NULL }; private G:List *play_list = { NULL }; - private gulong signal_id_child = { 0 }; + /* the default volume for the channel */ private int volume = { MIX_MAX_VOLUME }; - property INT volume ( nick= _("Channel volume"), - blurb= _("Volume max of the channel"), + blurb= _("Default volume of the channel"), export, link); + /* The default policy for the channel */ + private GCSoundPolicy policy = {GC_SOUND_PLAY_AFTER_CURRENT}; + property ENUM policy + ( nick = _("Channel policy"), + blurb = _("Default policy for this channel"), + enum_type = GC:Sound:Policy, + export, link); + + /* the mixer we are attached on */ + /* The mixer initalise SDL and audio */ private GC:Sound:Mixer *mixer = { NULL } destroywith g_object_unref ; @@ -96,6 +110,7 @@ class GC:Sound:Channel from G:Object { Mix_AllocateChannels(self->_priv->mixer->channels ); g_warning("Channel #%d initialised", self->_priv->channel); + Mix_HaltChannel(self->_priv->channel); g_hash_table_insert(channels_table, &(self->_priv->channel), self); @@ -110,15 +125,17 @@ class GC:Sound:Channel from G:Object { private GC:Sound:Item *rootItem = { NULL } destroywith g_object_unref; - property OBJECT rootItem + property OBJECT rootItem (nick = _("GCompris Sound Item root"), blurb = _("GCompris Sound Item root"), object_type=GC:Sound:Item, export, link) ; + private gboolean stopped = { FALSE }; + init (self) { - g_warning("gc channel instance init"); + //g_warning("gc channel instance init"); if (!channels_table) channels_table = g_hash_table_new (g_int_hash, g_int_equal); @@ -126,7 +143,7 @@ class GC:Sound:Channel from G:Object { } class_init (class) { - g_warning("gc channel class init"); + //g_warning("gc channel class init"); } public GC:Sound:Item * @@ -142,6 +159,8 @@ class GC:Sound:Channel from G:Object { /* get self */ GCSoundChannel *self; + //g_warning ("Channel finished %d", channel); + self = GC_SOUND_CHANNEL(g_hash_table_lookup(channels_table, &channel)); if (!self) { @@ -151,55 +170,94 @@ class GC:Sound:Channel from G:Object { self_play_finished (self, self->_priv->playing_item); } - public gboolean - real_play (self, GC:Sound:Item *item (check null type)) + private void real_play ( GC:Sound:Item *item, gpointer data) { - int i=0; - g_warning ("Real play %s", item->nick); + //g_warning ("Real play %s", item->nick); + GCSoundChannel *self = GC_SOUND_CHANNEL(data); + gchar * filename = gc_sound_item_get_filename(item); - if (filename == NULL){ - g_warning("No filename ? no play!"); - return FALSE; - } + if (Mix_Playing(self->_priv->channel)){ + g_warning("Channel busy ? no play!"); + return; + } - self->_priv->sample=Mix_LoadWAV_RW(SDL_RWFromFile(filename, "rb"), 1); - if (!self->_priv->sample) { - g_warning("Sample music %s cannot be load", filename); - return FALSE; - } + if (filename == NULL){ + g_warning("No filename ? no play!"); + return; + } - if ((item->volume == -1) || (item->volume > self->_priv->volume)) - Mix_VolumeChunk(self->_priv->sample, self->_priv->volume); - else - Mix_VolumeChunk(self->_priv->sample, item->volume); + self->_priv->sample=Mix_LoadWAV_RW(SDL_RWFromFile(filename, "rb"), 1); + if (!self->_priv->sample) { + g_warning("Sample music %s cannot be load", filename); + return; + } - if (Mix_PlayChannel(self->_priv->channel, self->_priv->sample, 0)==-1) { - g_warning (" ? %d",i++); - g_warning("Channel cannot play music %s", filename); - return FALSE; - } + if ((item->volume == -1) || (item->volume > self->_priv->volume)) + Mix_VolumeChunk(self->_priv->sample, self->_priv->volume); + else + Mix_VolumeChunk(self->_priv->sample, item->volume); - g_warning("Playing %s on channel %d", filename, self->_priv->channel); + if (Mix_PlayChannel(self->_priv->channel, self->_priv->sample, 0)==-1) { + g_warning("Channel cannot play music %s", filename); + return; + } + + g_warning("Playing %s on channel #%d", filename, self->_priv->channel); + + + self->_priv->playing_item = item; + } - self->_priv->playing_item = item; - return TRUE; - } signal first NONE (POINTER) void play_finished (self, GC:Sound:Item *item (check null type)) { + //g_warning ("Channel finish item %s", item->nick); Mix_FreeChunk(self->_priv->sample); self->_priv->sample = NULL; - gc_sound_item_play_next(item); + gc_sound_item_play_next(item, self->_priv->stopped); } - protected void play_item (self, GC:Sound:Item *item) + /* connected to do_play signal of item */ + protected void do_play (GC:Sound:Item *item, gpointer data) { - self->_priv->play_list = g_list_append (self->_priv->play_list, item); - - self_play_first_item(self); + GCSoundChannel *self = GC_SOUND_CHANNEL(data); + GCSoundPolicy policy; + + /* item policy if it's set */ + if (gc_sound_item_get_policy(item) == GC_SOUND_POLICY_NONE) + policy = self->_priv->policy; + else + policy = gc_sound_item_get_policy(item); + + //g_warning ("play_item %s with policy %d", item->nick, policy); + + switch (policy) { + case GC_SOUND_PLAY_ONLY_IF_IDLE: + if (self->_priv->sample || g_list_length (self->_priv->play_list)>0) + return; + break; + + case GC_SOUND_INTERRUPT_AND_PLAY: + g_list_free (self->_priv->play_list); + self->_priv->play_list = NULL; + self->_priv->play_list = g_list_append (self->_priv->play_list, item); + if (self->_priv->sample){ + self->_priv->stopped = TRUE; + //g_warning("halting channel %d %d", self->_priv->channel, g_list_length(self->_priv->play_list)); + self_halt(self); + } + self_run(self); + break; + + default: + self->_priv->play_list = g_list_append (self->_priv->play_list, item); + if (!self->_priv->sample) + self_run(self); + break; + } } protected void play_first_item(self) @@ -211,23 +269,53 @@ class GC:Sound:Channel from G:Object { self->_priv->playing_root = g_list_first (self->_priv->play_list); self->_priv->play_list = g_list_remove_link (self->_priv->play_list, self->_priv->playing_root); - self->_priv->signal_id_child = gc_sound_item_connect__play_finished (GC_SOUND_ITEM(self->_priv->playing_root->data), self_item_play_finished, self); - ret = gc_sound_item_play_next(GC_SOUND_ITEM(self->_priv->playing_root->data)); + ret = gc_sound_item_play_next (GC_SOUND_ITEM(self->_priv->playing_root->data), FALSE); if (ret) return ; } } - private void item_play_finished (GC:Sound:Item *item, gpointer data) + private void item_play_finished (GC:Sound:Item *item, gboolean stopped, gpointer data) { - if (item != GC_SOUND_ITEM(GC_SOUND_CHANNEL(data)->_priv->playing_root->data)) - return; - g_warning("channel item_play_finished on channel %d %s\n", GC_SOUND_CHANNEL(data)->_priv->channel, item->nick); - self_play_first_item(GC_SOUND_CHANNEL(data)); + //g_warning("channel item_play_finished %s %s", item->nick, stopped ? "STOPPED":"normal"); + + /* if item our our root item playing */ + if (item == GC_SOUND_ITEM(GC_SOUND_CHANNEL(data)->_priv->playing_root->data)) + { + GC_SOUND_CHANNEL(data)->_priv->playing_root = NULL; + /* do not call run if we are stopping */ + if (GC_SOUND_CHANNEL(data)->_priv->stopped) + GC_SOUND_CHANNEL(data)->_priv->stopped = FALSE; + else + self_run(GC_SOUND_CHANNEL(data)); + } } public void connect_me (self, GC:Sound:Item *item ) { gc_sound_item_connect__play_finished(item, self_item_play_finished, self); - } + gc_sound_item_connect__do_play(item, self_do_play, self); + gc_sound_item_connect__real_play(item, self_real_play, self); + + } + + private signal first NONE (NONE) + void run (self) + { + //g_warning("channel run"); + self_play_first_item(self); + } + + public signal first NONE (NONE) + void halt (self) + { + //g_warning("halting channel %d", self->_priv->channel); + Mix_HaltChannel(self->_priv->channel); + } + + private signal first NONE (POINTER) + void halt_and_play (self, GC:Sound:Item *item ) + { + } + } diff --git a/src/gc_sound/src/gc-sound-item.gob b/src/gc_sound/src/gc-sound-item.gob index 570b77e..6f8fa1d 100644 --- a/src/gc_sound/src/gc-sound-item.gob +++ b/src/gc_sound/src/gc-sound-item.gob @@ -42,11 +42,15 @@ typedef struct _GCSoundChannel GCSoundChannel; #define N_(String) gettext_noop (String) #endif + #include "gc-sound-item-private.h" -#include "gc-sound-channel.h" %} +%privateheader{ + /* because of GCSoundPolicy */ + #include "gc-sound-channel.h" +%} class GC:Sound:Item from G:Object { /* debug */ public gchar *nick = {NULL}; @@ -149,6 +153,14 @@ class GC:Sound:Item from G:Object { g_list_free (SoundItems); }; + /* The default policy for the channel */ + private GC:Sound:Policy policy = {GC_SOUND_POLICY_NONE}; + property ENUM policy + ( nick = _("Channel policy"), + blurb = _("Default policy for this channel"), + enum_type = GC:Sound:Policy, + export, link); + /* PlayList */ private GList *PlayList = { NULL } @@ -159,12 +171,12 @@ class GC:Sound:Item from G:Object { /* Objects methods */ init (self) { - g_warning("Item sound instance init"); + //g_warning("Item sound instance init"); /* do nothing. We set up channel when property is set */ } class_init (class) { - g_warning("item sound class init"); + //g_warning("item sound class init"); } @@ -196,17 +208,65 @@ class GC:Sound:Item from G:Object { self->_priv->has_played = TRUE; /* we will be added in play list channel */ - gc_sound_channel_play_item(self->_priv->channel, self); + self_do_play (self); + } + + signal first NONE (NONE) + void do_play (self) + { + //g_warning ("item %s received do_play signal", self->nick); + } + + signal first NONE (NONE) + void real_play (self) + { + //g_warning ("item %s received do_play signal", self->nick); } - /* recursive play in group */ - protected gboolean - play_next (self) + /* play */ + signal first NONE (BOOLEAN) + void play_finished (self, gboolean stopped) + { + //g_warning("item : play_finished %s", self->nick); + if ((!self->_priv->has_played) || (!self->_priv->playing) || stopped) { + self->_priv->started = FALSE; + self->_priv->has_played = FALSE; + } + } + + signal last NONE (NONE) + void play_started (self) + { + self->_priv->started = TRUE; + } + + private void child_play_finished (GC:Sound:Item *item, gboolean stopped, gpointer data) + { + if ( GC_SOUND_ITEM(data)->_priv->has_played ) + self_play_next(GC_SOUND_ITEM(data), stopped); + } + + private void child_play_started (GC:Sound:Item *item, gpointer data) + { + if (! GC_SOUND_ITEM(data)->_priv->started) + self_play_started(GC_SOUND_ITEM(data)); + } + + protected gboolean play_next (self, gboolean stopped) { gboolean ret; + + //g_warning("play_next %s %d", self->nick, stopped); + + if (stopped) { + gc_sound_item_play_finished(self, TRUE); + return TRUE; + } + if (self->mute) return FALSE; + /* mark if we are in play tree */ self->_priv->has_played = TRUE; @@ -219,19 +279,19 @@ class GC:Sound:Item from G:Object { self->_priv->playing = g_list_next (self->_priv->playing ); if ((self->_priv->playing == NULL) && (self->loop)) { - g_warning ("looping on %s", self->nick); + //g_warning ("looping on %s", self->nick); self->_priv->playing = g_list_first (self->_priv->PlayList ); } while (self->_priv->playing) { if ( GC_SOUND_ITEM(self->_priv->playing->data) == self){ if (!self->_priv->started) - self_play_started(self); - gc_sound_channel_real_play(self->_priv->channel, self); + self_play_started(self); + self_real_play(self); return TRUE; } else { - ret= gc_sound_item_play_next ( GC_SOUND_ITEM(self->_priv->playing->data)); + ret= self_play_next ( GC_SOUND_ITEM(self->_priv->playing->data), FALSE); if (ret) return ret; } @@ -240,42 +300,11 @@ class GC:Sound:Item from G:Object { /* if we have play, it's finished */ if (self->_priv->started) { - g_warning("Call play_finished %s %d %d", self->nick, self->_priv->has_played, self->_priv->playing); - - self_play_finished(self); + self_play_finished(self, FALSE); } return FALSE; } - /* play */ - signal first NONE (NONE) - void play_finished (self) - { - g_warning("play_finished %s %d %d", self->nick, self->_priv->has_played, self->_priv->playing); - - if ((!self->_priv->has_played) || (!self->_priv->playing)) { - self->_priv->started = FALSE; - self->_priv->has_played = FALSE; - } - } - signal last NONE (NONE) - void play_started (self) - { - //g_warning("play_started %s", self->nick); - self->_priv->started = TRUE; - } - - private void child_play_finished (GC:Sound:Item *item, gpointer data) - { - if ( GC_SOUND_ITEM(data)->_priv->has_played ) - self_play_next(GC_SOUND_ITEM(data)); - } - - private void child_play_started (GC:Sound:Item *item, gpointer data) - { - if (! GC_SOUND_ITEM(data)->_priv->started) - self_play_started(GC_SOUND_ITEM(data)); - } } diff --git a/src/gc_sound/src/gc-sound-mixer.gob b/src/gc_sound/src/gc-sound-mixer.gob index adb4340..3fca60f 100644 --- a/src/gc_sound/src/gc-sound-mixer.gob +++ b/src/gc_sound/src/gc-sound-mixer.gob @@ -90,7 +90,7 @@ class GC:Sound:Mixer from G:Object { Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels); self->_priv->bits=audio_format&0xFF; Mix_AllocateChannels(self->channels ); - g_warning("Opened audio at %d Hz %d bit %s, %d bytes audio buffer\n Numbers of channels %d", audio_rate, + g_warning("Opened audio at %d Hz %d bit %s, %d bytes audio buffer\n Number of channels %d", audio_rate, self->_priv->bits, audio_channels>1?"stereo":"mono", self->_priv->audio_buffers, self->channels); Mix_AllocateChannels(self->channels ); @@ -108,7 +108,7 @@ class GC:Sound:Mixer from G:Object { private gboolean sdl_ok = { FALSE }; init (self) { - g_warning("gc mixer init"); + //g_warning("gc mixer init"); // initialize SDL for audio if(SDL_Init(SDL_INIT_AUDIO)<0){ @@ -121,7 +121,7 @@ class GC:Sound:Mixer from G:Object { } class_init (class) { - g_warning("gc mixer class init"); + //g_warning("gc mixer class init"); } diff --git a/src/gc_sound/src/test_gc_sound.c b/src/gc_sound/src/test_gc_sound.c index 8ccc96d..8ae03cc 100644 --- a/src/gc_sound/src/test_gc_sound.c +++ b/src/gc_sound/src/test_gc_sound.c @@ -2,9 +2,9 @@ #include <gc-sound.h> #include <stdio.h> -void finish(GCSoundItem *item, gpointer data) +void finish(GCSoundItem *item, gboolean stopped, gpointer data) { - g_warning("Return of finish callback %s", item->nick); + g_warning("Return of finish callback %s %s", item->nick, stopped ? "STOPPED" : "normal"); } void start(GCSoundItem *item, gpointer data) @@ -16,7 +16,7 @@ main (int argc, char *argv) { GCSoundMixer *gcmix; GCSoundChannel* gcchan1, *gcchan2; - GCSoundItem *item1, *item2, *root1, *root2, *item1_1, *item1_2; + GCSoundItem *item1, *item2, *item3, *root1, *root2, *item1_1, *item1_2; g_type_init (); /* Sound mixer opens SDL and audio device */ @@ -39,11 +39,13 @@ main (int argc, char *argv) /* create new item for our sounds */ item1 = gc_sound_item_new (root1); item2 = gc_sound_item_new (root2); + item3 = gc_sound_item_new (root2); item1_1 = gc_sound_item_new (item1); item1_2 = gc_sound_item_new (item1); item1->nick = "item1"; item2->nick = "item2"; + item3->nick = "item3"; item1_1->nick = "item1_1"; item1_2->nick = "item1_2"; @@ -51,14 +53,19 @@ main (int argc, char *argv) gc_sound_item_set_filename(item1_1, "../../../boards/sounds/wahoo.ogg"); gc_sound_item_set_filename(item1_2, "../../../boards/sounds/wahoo.ogg"); gc_sound_item_set_filename(item2, "../../../boards/music/background/LRLaPause.ogg"); + gc_sound_item_set_filename(item3, "../../../boards/sounds/bonus.ogg"); // test gc_sound_item_set_filename(item1_1, NULL); gc_sound_item_set_filename(item1_1, "../../../boards/sounds/train.ogg"); + //policy test: works on channel and on item. + //gc_sound_channel_set_policy(gcchan2, GC_SOUND_INTERRUPT_AND_PLAY); + gc_sound_item_set_policy(item3, GC_SOUND_INTERRUPT_AND_PLAY); + // callback connection - gc_sound_item_connect__play_finished(item1_1, finish, NULL); - gc_sound_item_connect__play_finished(item1_2, finish, NULL); + gc_sound_item_connect__play_finished(item2, finish, NULL); + gc_sound_item_connect__play_finished(item3, finish, NULL); gc_sound_item_connect__play_started(item1_1, start, NULL); gc_sound_item_connect__play_started(item1_2, start, NULL); @@ -70,8 +77,19 @@ main (int argc, char *argv) //play gc_sound_item_play(item2); g_usleep(1000000); + + /* will loop with the two sounds of group */ gc_sound_item_play(item1); + g_usleep(8000000); + + //stopping loop after next + gc_sound_item_set_loop(item1, FALSE); + g_usleep(3000000); + + //this will sop item2 because of policy + gc_sound_item_play(item3); + /* infinite loop */ g_main_loop_run(g_main_loop_new (NULL, FALSE)); |