Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYves 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)
commit33cfc959568035ec0cfd0088821cc99ad8ef64a9 (patch)
tree8af55f9cf78b20e0fd8bb99ccd0ad8a5737ebf4b
parent8cfbdf6b59db699ea36efbd4cb902113c796d1f3 (diff)
Added sound policy
-rw-r--r--ChangeLog11
-rw-r--r--src/gc_sound/ChangeLog10
-rw-r--r--src/gc_sound/src/gc-sound-channel.gob190
-rw-r--r--src/gc_sound/src/gc-sound-item.gob115
-rw-r--r--src/gc_sound/src/gc-sound-mixer.gob6
-rw-r--r--src/gc_sound/src/test_gc_sound.c28
6 files changed, 258 insertions, 102 deletions
diff --git a/ChangeLog b/ChangeLog
index 7d2a98c..6e8e082 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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));