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-12-08 12:17:50 (GMT)
committer Yves Combe <ycombe@src.gnome.org>2006-12-08 12:17:50 (GMT)
commit59a68ac4a498251f80b4cce4306078492c37f781 (patch)
tree6e200a7b2fc816bd308e567d394b3525255d594a
parent3029281726ef0767af37b5e4922a8edb54013d14 (diff)
gc_sound: Work on destroy recursive on mixer-SDL/channel/item
-rw-r--r--ChangeLog46
-rw-r--r--src/gc_sound/ChangeLog43
-rw-r--r--src/gc_sound/src/gc-sound-channel.c93
-rw-r--r--src/gc_sound/src/gc-sound-channel.h6
-rw-r--r--src/gc_sound/src/gc-sound-item.c50
-rw-r--r--src/gc_sound/src/gc-sound-item.h3
-rw-r--r--src/gc_sound/src/gc-sound-mixer-SDL.c148
-rw-r--r--src/gc_sound/src/gc-sound-mixer-SDL.h8
-rw-r--r--src/gc_sound/src/gc-sound-object.c42
-rw-r--r--src/gc_sound/src/gc-sound-object.h9
-rw-r--r--src/gc_sound/src/test_gc_sound.c92
11 files changed, 335 insertions, 205 deletions
diff --git a/ChangeLog b/ChangeLog
index 1e175f7..087ec0f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,49 @@
+2006-12-08 Yves Combe <yves@ycombe.net>
+
+ GC_SOUND
+ Work on destroy recursive on mixer-SDL/channel/item
+ TODO:
+ - fix if channel is destroyed before mixer,
+ an error occurs when mixer is destroyed?
+ - python bindings
+
+ * src/gc_sound/ChangeLog:
+ * src/gc_sound/src/gc-sound-channel.c:
+ (gc_sound_channel_play_item), (gc_sound_channel_pause),
+ (gc_sound_channel_resume), (gc_sound_channel_halt),
+ (gc_sound_channel_play), (root_destroyed),
+ (gc_sound_channel_destroy), (gc_sound_channel_init),
+ (gc_sound_channel_get_property), (gc_sound_channel_set_property),
+ (gc_sound_channel_signal_chunk_end), (gc_sound_channel_signal_run),
+ (gc_sound_channel_class_init):
+ * src/gc_sound/src/gc-sound-channel.h:
+ * src/gc_sound/src/gc-sound-item.c: (gc_sound_item_run_next),
+ (gc_sound_item_child_destroyed), (gc_sound_item_append_child),
+ (gc_sound_item_signal_real_play), (gc_sound_item_signal_play_end),
+ (gc_sound_item_signal_play_start),
+ (gc_sound_item_signal_chunk_end),
+ (gc_sound_item_signal_chunk_start), (gc_sound_item_init),
+ (gc_sound_item_get_property), (gc_sound_item_set_property),
+ (gc_sound_item_class_init):
+ * src/gc_sound/src/gc-sound-item.h:
+ * src/gc_sound/src/gc-sound-mixer-SDL.c:
+ (gc_sound_mixer_SDL_open_audio), (reset_channel_number),
+ (channel_destroyed), (gc_sound_mixer_SDL_new_channel),
+ (gc_sound_mixer_SDL_pause_channel),
+ (gc_sound_mixer_SDL_resume_channel),
+ (gc_sound_mixer_SDL_halt_channel), (gc_sound_mixer_SDL_play_item),
+ (channel_finished_cb), (gc_sound_mixer_SDL_channel_finished),
+ (gc_sound_mixer_SDL_init), (gc_sound_mixer_SDL_finalize),
+ (gc_sound_mixer_SDL_destroy), (gc_sound_mixer_SDL_class_init),
+ (gc_init_sound_mixer):
+ * src/gc_sound/src/gc-sound-mixer-SDL.h:
+ * src/gc_sound/src/gc-sound-object.c: (gc_sound_object_class_init),
+ (gc_sound_object_init), (gc_sound_object_destroy),
+ (parent_destroyed), (gc_sound_object_set_property),
+ (gc_sound_object_get_property):
+ * src/gc_sound/src/gc-sound-object.h:
+ * src/gc_sound/src/test_gc_sound.c: (finish), (start), (main):
+
2006-12-01 Yves Combe <yves@ycombe.net>
GCSound:
diff --git a/src/gc_sound/ChangeLog b/src/gc_sound/ChangeLog
index f6b9f90..3389b8a 100644
--- a/src/gc_sound/ChangeLog
+++ b/src/gc_sound/ChangeLog
@@ -1,3 +1,46 @@
+2006-12-08 Yves Combe <yves@ycombe.net>
+
+ Work on destroy recursive on mixer-SDL/channel/item
+ TODO:
+ - fix if channel is destroyed before mixer,
+ an error occurs when mixer is destroyed?
+ - python bindings
+
+ * src/gc-sound-channel.c: (gc_sound_channel_play_item),
+ (gc_sound_channel_pause), (gc_sound_channel_resume),
+ (gc_sound_channel_halt), (gc_sound_channel_play), (root_destroyed),
+ (gc_sound_channel_destroy), (gc_sound_channel_init),
+ (gc_sound_channel_get_property), (gc_sound_channel_set_property),
+ (gc_sound_channel_signal_chunk_end), (gc_sound_channel_signal_run),
+ (gc_sound_channel_class_init):
+ * src/gc-sound-channel.h:
+ * src/gc-sound-item.c: (gc_sound_item_run_next),
+ (gc_sound_item_child_destroyed), (gc_sound_item_append_child),
+ (gc_sound_item_signal_real_play), (gc_sound_item_signal_play_end),
+ (gc_sound_item_signal_play_start),
+ (gc_sound_item_signal_chunk_end),
+ (gc_sound_item_signal_chunk_start), (gc_sound_item_init),
+ (gc_sound_item_get_property), (gc_sound_item_set_property),
+ (gc_sound_item_class_init):
+ * src/gc-sound-item.h:
+ * src/gc-sound-mixer-SDL.c: (gc_sound_mixer_SDL_open_audio),
+ (reset_channel_number), (channel_destroyed),
+ (gc_sound_mixer_SDL_new_channel),
+ (gc_sound_mixer_SDL_pause_channel),
+ (gc_sound_mixer_SDL_resume_channel),
+ (gc_sound_mixer_SDL_halt_channel), (gc_sound_mixer_SDL_play_item),
+ (channel_finished_cb), (gc_sound_mixer_SDL_channel_finished),
+ (gc_sound_mixer_SDL_init), (gc_sound_mixer_SDL_finalize),
+ (gc_sound_mixer_SDL_destroy), (gc_sound_mixer_SDL_class_init),
+ (gc_init_sound_mixer):
+ * src/gc-sound-mixer-SDL.h:
+ * src/gc-sound-object.c: (gc_sound_object_class_init),
+ (gc_sound_object_init), (gc_sound_object_destroy),
+ (parent_destroyed), (gc_sound_object_set_property),
+ (gc_sound_object_get_property):
+ * src/gc-sound-object.h:
+ * src/test_gc_sound.c: (finish), (start), (main):
+
2006-12-01 Yves Combe <yves@ycombe.net>
Add GCSoundObject to have a base class with destroy signal/functions.
diff --git a/src/gc_sound/src/gc-sound-channel.c b/src/gc_sound/src/gc-sound-channel.c
index 15592a8..8f03d3e 100644
--- a/src/gc_sound/src/gc-sound-channel.c
+++ b/src/gc_sound/src/gc-sound-channel.c
@@ -38,12 +38,10 @@ guint gc_sound_channel_signals[N_SIGNALS] = {0};
gboolean gc_sound_channel_play_item (GCSoundChannel * self, GCSoundItem *item)
{
- g_warning("gc_sound_channel_play_item %s %s", self->nick, item->nick);
-
self->running_sample = item;
self->stopped = FALSE;
- return gc_sound_mixer_play_item (self->mixer, self, item);
+ return gc_sound_mixer_play_item (GC_SOUND_MIXER(GC_SOUND_OBJECT(self)->parent), self, item);
}
GCSoundItem * gc_sound_channel_get_root (GCSoundChannel * self)
@@ -53,17 +51,17 @@ GCSoundItem * gc_sound_channel_get_root (GCSoundChannel * self)
gboolean gc_sound_channel_pause (GCSoundChannel * self)
{
- return gc_sound_mixer_pause_channel( self->mixer, self);
+ return gc_sound_mixer_pause_channel( GC_SOUND_MIXER(GC_SOUND_OBJECT(self)->parent), self);
}
gboolean gc_sound_channel_resume (GCSoundChannel * self)
{
- return gc_sound_mixer_resume_channel( self->mixer, self);
+ return gc_sound_mixer_resume_channel( GC_SOUND_MIXER(GC_SOUND_OBJECT(self)->parent), self);
}
gboolean gc_sound_channel_halt (GCSoundChannel * self)
{
- return gc_sound_mixer_halt_channel( self->mixer, self);
+ return gc_sound_mixer_halt_channel(GC_SOUND_MIXER(GC_SOUND_OBJECT(self)->parent), self);
}
GCSoundPolicy gc_sound_channel_get_policy (GCSoundChannel * self)
@@ -88,8 +86,6 @@ gboolean gc_sound_channel_play (GCSoundChannel *self,
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->running_sample || g_list_length (self->playlist)>0)
@@ -99,26 +95,22 @@ gboolean gc_sound_channel_play (GCSoundChannel *self,
g_signal_emit(self, gc_sound_channel_signals[RUN], 0);
break;
- case GC_SOUND_INTERRUPT_AND_PLAY:
- g_list_free (self->playlist);
- self->playlist = NULL;
- self->playlist = g_list_append (self->playlist, item);
- if (self->running_sample){
- self->stopped = TRUE;
- //g_warning("halting channel %d %d", self->_priv->channel, g_list_length(self->_priv->play_list));
- // send a signal to halt.
- gc_sound_channel_halt(self);
- }
- // TODO send a signal to run !!!
+ case GC_SOUND_INTERRUPT_AND_PLAY:
+ g_list_free (self->playlist);
+ self->playlist = NULL;
+ self->playlist = g_list_append (self->playlist, item);
+ if (self->running_sample){
+ self->stopped = TRUE;
+ gc_sound_channel_halt(self);
+ }
+ g_signal_emit(self, gc_sound_channel_signals[RUN], 0);
+ break;
+
+ default:
+ self->playlist = g_list_append (self->playlist, item);
+ if (!self->running_sample)
g_signal_emit(self, gc_sound_channel_signals[RUN], 0);
- break;
-
- default:
- self->playlist = g_list_append (self->playlist, item);
- if (!self->running_sample)
- // TODO send a signal to run !!!
- g_signal_emit(self, gc_sound_channel_signals[RUN], 0);
- break;
+ break;
}
}
@@ -131,7 +123,23 @@ enum {
/* GType */
-G_DEFINE_TYPE(GCSoundChannel, gc_sound_channel, G_TYPE_OBJECT);
+G_DEFINE_TYPE(GCSoundChannel, gc_sound_channel, GC_TYPE_SOUND_OBJECT);
+
+static void root_destroyed (GCSoundObject *root, gpointer data)
+{
+ // direct call claas destroy because root is already destroyed.
+
+ GC_SOUND_OBJECT_GET_CLASS(data)->destroy (GC_SOUND_OBJECT(data));
+}
+
+static void
+gc_sound_channel_destroy (GCSoundChannel *self){
+ g_signal_handlers_disconnect_by_func(self->root, root_destroyed, self);
+ gc_sound_object_destroy(GC_SOUND_OBJECT(self->root));
+ g_object_unref(self->root);
+
+ GC_SOUND_OBJECT_GET_CLASS(self)->destroy (GC_SOUND_OBJECT(self));
+}
static void
gc_sound_channel_init(GCSoundChannel* self)
@@ -144,9 +152,13 @@ gc_sound_channel_init(GCSoundChannel* self)
self->stopped = FALSE;
- self->mixer = NULL;
+ GC_SOUND_OBJECT(self)->parent = NULL;
self->root = GC_SOUND_ITEM(g_object_new(GC_TYPE_SOUND_ITEM, "channel", self, NULL));
+ g_object_ref_sink(G_OBJECT(self->root));
+
+ g_signal_connect(G_OBJECT(self->root), "destroy", (GCallback) root_destroyed, self);
+
self->playlist = NULL;
//this one is the item with the file
@@ -154,9 +166,6 @@ gc_sound_channel_init(GCSoundChannel* self)
// this one is the group playing
self->running_root = NULL;
- //debug. will be removed.
- gchar *nick;
-
}
static void
@@ -164,9 +173,6 @@ gc_sound_channel_get_property(GObject* object, guint prop_id, GValue* value, GPa
{
GCSoundChannel *self = GC_SOUND_CHANNEL(object);
switch(prop_id) {
- case PROP_MIXER:
- g_value_set_object(value, self->mixer);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@@ -179,9 +185,6 @@ gc_sound_channel_set_property(GObject* object, guint prop_id, GValue const* valu
GCSoundChannel *self = GC_SOUND_CHANNEL(object);
switch(prop_id) {
- case PROP_MIXER:
- self->mixer = g_value_get_object(value);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
@@ -198,8 +201,6 @@ gc_sound_channel_signal_chunk_end (GCSoundChannel *self)
g_return_if_fail(GC_IS_SOUND_ITEM(chunk));
- g_warning ("%s received chunk_end self->stopped %s", self->nick, self->stopped ? "TRUE" : "FALSE");
-
g_signal_emit_by_name (chunk, "chunk_end", 0, self->stopped);
}
@@ -209,8 +210,6 @@ gc_sound_channel_signal_run (GCSoundChannel *self)
GList *item_root;
gboolean ret;
- g_warning("Channel %s received run !", self->nick);
-
while (g_list_length(self->playlist)>0)
{
self->running_root = g_list_first (self->playlist);
@@ -236,15 +235,6 @@ gc_sound_channel_class_init(GCSoundChannelClass* self_class)
go_class->get_property = gc_sound_channel_get_property;
go_class->set_property = gc_sound_channel_set_property;
- g_object_class_install_property(go_class,
- PROP_MIXER,
- g_param_spec_object ("mixer",
- "GCompris mixer",
- "The mixer where this channel stand",
- GC_TYPE_SOUND_MIXER,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
-
/* signals */
/* enum { */
/* RUN, /\* internal: launch recursive playing of playlist *\/ */
@@ -261,6 +251,7 @@ gc_sound_channel_class_init(GCSoundChannelClass* self_class)
self_class->run = gc_sound_channel_signal_run;
self_class->chunk_end = gc_sound_channel_signal_chunk_end;
+ self_class->destroy = gc_sound_channel_destroy;
gc_sound_channel_signals[RUN] =
g_signal_new("run", /* name */
diff --git a/src/gc_sound/src/gc-sound-channel.h b/src/gc_sound/src/gc-sound-channel.h
index 855d5b4..ab6b487 100644
--- a/src/gc_sound/src/gc-sound-channel.h
+++ b/src/gc_sound/src/gc-sound-channel.h
@@ -71,17 +71,15 @@ struct _GCSoundChannel {
GList* running_root;
gint channel_number;
-
- //debug. will be removed.
- gchar *nick;
};
struct _GCSoundChannelClass {
GCSoundObjectClass __parentClass__;
/* signal handlers */
- void (* run) (GCSoundChannel * self);
+ void (* run) (GCSoundChannel * self);
void (* chunk_end) (GCSoundChannel * self);
+ void (* destroy) (GCSoundChannel *self);
};
GCSoundItem * gc_sound_channel_get_root (GCSoundChannel * self);
diff --git a/src/gc_sound/src/gc-sound-item.c b/src/gc_sound/src/gc-sound-item.c
index 9820be5..c6b0e15 100644
--- a/src/gc_sound/src/gc-sound-item.c
+++ b/src/gc_sound/src/gc-sound-item.c
@@ -45,8 +45,6 @@ gboolean gc_sound_item_run_next (GCSoundItem *self,
{
gboolean ret;
- g_warning("run_next %s %d", self->nick, stopped);
-
/* if we are stopped, we don't continue */
if (stopped) {
g_signal_emit(self, gc_sound_item_signals[PLAY_END], 0, stopped);
@@ -69,7 +67,6 @@ gboolean gc_sound_item_run_next (GCSoundItem *self,
self->playing = g_list_next (self->playing );
if ((self->playing == NULL) && (self->loop)) {
- g_warning ("looping on %s", self->nick);
self->playing = g_list_first (self->children );
}
@@ -133,20 +130,32 @@ void gc_sound_item_child_end( GCSoundItem *child, gboolean stopped, gpointer dat
gc_sound_item_run_next(self, stopped);
}
+void gc_sound_item_child_destroyed( GCSoundItem *child, gpointer data)
+{
+ GCSoundItem *self = GC_SOUND_ITEM(data);
+
+ self->children = g_list_remove ( self->children, child);
+ g_object_unref (G_OBJECT(child));
+}
+
GCSoundItem * gc_sound_item_append_child (GCSoundItem *self)
{
GCSoundItem *child;
- child = GC_SOUND_ITEM(g_object_new(gc_sound_item_get_type(), "parent", self, "channel", self->channel, NULL));
+ child = GC_SOUND_ITEM(g_object_new(GC_TYPE_SOUND_ITEM,
+ "parent", self,
+ "channel", self->channel,
+ NULL));
/* Child is added to our lists */
self->children = g_list_append (self->children, child);
/* we get a ref */
- g_object_ref (G_OBJECT(child));
+ g_object_ref_sink (G_OBJECT(child));
g_signal_connect( child, "play-end", (GCallback) gc_sound_item_child_end, self);
g_signal_connect( child, "play-start", (GCallback) gc_sound_item_child_start, self);
+ g_signal_connect( child, "destroy", (GCallback) gc_sound_item_child_destroyed, self);
return child;
}
@@ -177,8 +186,6 @@ gchar * gc_sound_item_get_filename (GCSoundItem *self)
static void
gc_sound_item_signal_real_play (GCSoundItem *self)
{
- g_warning("item %s received real_play", self->nick);
-
g_signal_emit(self, gc_sound_item_signals[CHUNK_START], 0);
gc_sound_channel_play_item (self->channel, self);
}
@@ -186,8 +193,6 @@ gc_sound_item_signal_real_play (GCSoundItem *self)
static void
gc_sound_item_signal_play_end (GCSoundItem *self, gboolean stopped)
{
- g_warning("item %s received play_end", self->nick);
-
if (self->has_played || stopped) {
self->started = FALSE;
self->has_played = FALSE;
@@ -198,16 +203,12 @@ gc_sound_item_signal_play_end (GCSoundItem *self, gboolean stopped)
static void
gc_sound_item_signal_play_start (GCSoundItem *self)
{
- g_warning("item %s received play_start", self->nick);
-
self->started = TRUE;
}
static void
gc_sound_item_signal_chunk_end (GCSoundItem *self, gboolean stopped)
{
- g_warning("item %s received chunk_end", self->nick);
-
/*
We receive this signal from channel when play of chunk if finished.
We have to continue play in our group.
@@ -219,8 +220,6 @@ gc_sound_item_signal_chunk_end (GCSoundItem *self, gboolean stopped)
static void
gc_sound_item_signal_chunk_start (GCSoundItem *self)
{
- g_warning("item %s received chunk_start", self->nick);
-
self->started = TRUE;
}
@@ -228,19 +227,16 @@ gc_sound_item_signal_chunk_start (GCSoundItem *self)
enum {
PROP_0,
PROP_CHANNEL,
- PROP_PARENT,
PROP_FILENAME
};
/* GType */
-G_DEFINE_TYPE(GCSoundItem, gc_sound_item, G_TYPE_OBJECT);
+G_DEFINE_TYPE(GCSoundItem, gc_sound_item, GC_TYPE_SOUND_OBJECT);
static void
gc_sound_item_init(GCSoundItem* self)
{
// initialisation des variables.
- g_warning("gc_sound_item_init");
-
self->volume = -1.0;
self->mute = FALSE;
@@ -276,9 +272,6 @@ gc_sound_item_get_property(GObject* object, guint prop_id, GValue* value, GParam
case PROP_CHANNEL:
g_value_set_object(value, self->channel);
break;
- case PROP_PARENT:
- g_value_set_object(value, self->parent);
- break;
case PROP_FILENAME:
g_value_set_string(value, self->filename);
break;
@@ -297,9 +290,6 @@ gc_sound_item_set_property(GObject* object, guint prop_id, GValue const* value,
case PROP_CHANNEL:
self->channel = g_value_get_object(value);
break;
- case PROP_PARENT:
- self->parent = g_value_get_object(value);
- break;
case PROP_FILENAME:
gc_sound_item_set_filename( self, (gchar *)g_value_get_string(value));
break;
@@ -314,8 +304,6 @@ static void
gc_sound_item_class_init(GCSoundItemClass* self_class)
{
// c'est ici qu'il faut passer les properties et les signals.
- g_warning("gc_sound_item_class_init");
-
GObjectClass* go_class;
/* GObjectClass */
@@ -332,14 +320,6 @@ gc_sound_item_class_init(GCSoundItemClass* self_class)
GC_TYPE_SOUND_CHANNEL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
- g_object_class_install_property(go_class,
- PROP_PARENT,
- g_param_spec_object ("parent",
- "GCompris parent",
- "The parent where this channel stand",
- GC_TYPE_SOUND_ITEM,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
-
/* signals */
/* enum { */
/* RUN, /\* internal: launch recursive playing of playlist *\/ */
diff --git a/src/gc_sound/src/gc-sound-item.h b/src/gc_sound/src/gc-sound-item.h
index ee1d037..967eb77 100644
--- a/src/gc_sound/src/gc-sound-item.h
+++ b/src/gc_sound/src/gc-sound-item.h
@@ -60,9 +60,6 @@ struct _GCSoundItem {
GCSoundItem* parent;
GList* children;
- //debug. will be removed
- gchar * nick;
-
//internal use
// TRUE if we are in running play tree.
gboolean has_played;
diff --git a/src/gc_sound/src/gc-sound-mixer-SDL.c b/src/gc_sound/src/gc-sound-mixer-SDL.c
index e800c97..ae1aa17 100644
--- a/src/gc_sound/src/gc-sound-mixer-SDL.c
+++ b/src/gc_sound/src/gc-sound-mixer-SDL.c
@@ -75,13 +75,13 @@ gc_sound_mixer_SDL_open_audio (GCSoundMixer* mixer)
// print out some info on the audio device and stream
Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels);
bits=audio_format&0xFF;
- Mix_AllocateChannels(g_hash_table_size(self->channels_from_pointer));
+ Mix_AllocateChannels(self->channels->len);
g_warning("Opened audio at %d Hz %d bit %s, %d bytes audio buffer number of channels %d",
audio_rate,
bits,
audio_channels>1?"stereo":"mono",
audio_buffers,
- g_hash_table_size(self->channels_from_pointer));
+ self->channels->len);
return TRUE;
}
@@ -105,39 +105,67 @@ gc_sound_mixer_SDL_close_audio (GCSoundMixer * mixer)
return TRUE;
}
+static void reset_channel_number(GCSoundChannel *channel, gboolean stopped, gpointer data)
+{
+ channel->channel_number = GPOINTER_TO_INT(data);
+}
+
+static void channel_destroyed(GCSoundChannel *channel, gpointer data)
+{
+ GCSoundMixerSDL *self = GC_SOUND_MIXER_SDL (data);
+ int i;
+
+ //check if channel is playing
+ if (channel->running_sample) {
+ // Correct. As channel take a ref on itself when it's playing, it will
+ // not be finalized before it get this signal.
+ gc_sound_mixer_halt_channel (GC_SOUND_MIXER(self), channel);
+ }
+
+ g_ptr_array_remove_index (self->channels, channel->channel_number);
+ g_object_unref (channel);
+
+ /* channel reorganisation */
+ for (i = 0; i < self->channels->len; i++) {
+ GCSoundChannel *i_channel = g_ptr_array_index (self->channels, i);
+
+ if (i!=i_channel->channel_number) {
+ if (i_channel->running_sample)
+ g_signal_connect(i_channel, "chunk_end", (GCallback) reset_channel_number, GINT_TO_POINTER(i));
+ else
+ reset_channel_number ( i_channel, FALSE, GINT_TO_POINTER(i));
+ }
+ }
+}
+
static GCSoundChannel *gc_sound_mixer_SDL_new_channel (GCSoundMixer * mixer)
- {
+{
GCSoundMixerSDL* self;
g_return_val_if_fail(GC_IS_SOUND_MIXER_SDL(mixer), FALSE);
self = GC_SOUND_MIXER_SDL(mixer);
- g_warning ("gc_sound_mixer_SDL_new_channel");
-
GCSoundChannel *channel = GC_SOUND_CHANNEL(g_object_new(GC_TYPE_SOUND_CHANNEL,
- "mixer", self, NULL));
+ "parent", self, NULL));
g_assert (channel != 0);
- channel->channel_number = g_hash_table_size(self->channels_from_pointer);
-
- g_warning ("inserting channel %d into tables", channel->channel_number);
- g_hash_table_insert (self->channels_from_pointer,
- channel,
- GINT_TO_POINTER(channel->channel_number));
+ channel->channel_number = self->channels->len;
- g_hash_table_insert (self->channels_to_pointer,
- &(channel->channel_number),
- channel);
+ g_ptr_array_add (self->channels,
+ channel);
Mix_AllocateChannels(channel->channel_number + 1);
- g_warning ("Numbers of channels allocated %d", Mix_AllocateChannels(-1));
+ g_warning ("Numbers of channels allocated is now %d", Mix_AllocateChannels(-1));
- return channel;
- }
+ g_object_ref_sink(G_OBJECT(channel));
+
+ g_signal_connect(G_OBJECT(channel), "destroy", (GCallback) channel_destroyed, self);
+ return channel;
+}
gboolean gc_sound_mixer_SDL_pause (GCSoundMixer * mixer)
{
@@ -193,11 +221,7 @@ gc_sound_mixer_SDL_pause_channel (GCSoundMixer * mixer, GCSoundChannel * cha
g_return_val_if_fail(GC_IS_SOUND_MIXER_SDL(mixer), FALSE);
g_return_val_if_fail(GC_IS_SOUND_CHANNEL(channel), FALSE);
- self = GC_SOUND_MIXER_SDL(mixer);
- int channel_number = (int) g_hash_table_lookup (self->channels_from_pointer,
- channel);
-
- Mix_Pause (channel_number);
+ Mix_Pause (channel->channel_number);
}
gboolean
@@ -208,12 +232,7 @@ gc_sound_mixer_SDL_resume_channel (GCSoundMixer * mixer, GCSoundChannel * cha
g_return_val_if_fail(GC_IS_SOUND_MIXER_SDL(mixer), FALSE);
g_return_val_if_fail(GC_IS_SOUND_CHANNEL(channel), FALSE);
- self = GC_SOUND_MIXER_SDL(mixer);
-
- int channel_number = (int) g_hash_table_lookup (self->channels_from_pointer,
- channel);
-
- Mix_Resume (channel_number);
+ Mix_Resume (channel->channel_number);
return TRUE;
}
@@ -226,12 +245,7 @@ gc_sound_mixer_SDL_halt_channel (GCSoundMixer * mixer, GCSoundChannel * cha
g_return_val_if_fail(GC_IS_SOUND_MIXER_SDL(mixer), FALSE);
g_return_val_if_fail(GC_IS_SOUND_CHANNEL(channel), FALSE);
- self = GC_SOUND_MIXER_SDL(mixer);
-
- int channel_number = (int) g_hash_table_lookup (self->channels_from_pointer,
- channel);
-
- Mix_HaltChannel (channel_number);
+ Mix_HaltChannel (channel->channel_number);
return TRUE;
}
@@ -249,10 +263,7 @@ gc_sound_mixer_SDL_play_item (GCSoundMixer * mixer, GCSoundChannel * channel, G
self = GC_SOUND_MIXER_SDL(mixer);
- int channel_number = (int) g_hash_table_lookup (self->channels_from_pointer,
- channel);
-
- if (Mix_Playing(channel_number)){
+ if (Mix_Playing(channel->channel_number)){
g_warning("Channel busy ? no play!");
return FALSE;
}
@@ -273,7 +284,7 @@ gc_sound_mixer_SDL_play_item (GCSoundMixer * mixer, GCSoundChannel * channel, G
else
Mix_VolumeChunk(sample, (int) item->volume * MIX_MAX_VOLUME);
- if (Mix_PlayChannel(channel_number, sample, 0)==-1) {
+ if (Mix_PlayChannel(channel->channel_number, sample, 0)==-1) {
g_warning("Channel cannot play music %s", item->filename);
Mix_FreeChunk (sample);
return FALSE;
@@ -281,7 +292,7 @@ gc_sound_mixer_SDL_play_item (GCSoundMixer * mixer, GCSoundChannel * channel, G
g_hash_table_insert( self->samples, channel, sample);
- g_warning("Playing %s on channel #%d", item->filename, channel_number);
+ g_warning("Playing %s on channel #%d", item->filename, channel->channel_number);
return TRUE;
}
@@ -290,14 +301,7 @@ void channel_finished_cb (int channel_number)
{
GCSoundMixerSDL* self = running_mixer;
- g_warning("Channel number %d size %d",
- channel_number,
- g_hash_table_size(self->channels_to_pointer));
-
- int cn = channel_number;
-
- GCSoundChannel *channel = GC_SOUND_CHANNEL(g_hash_table_lookup (self->channels_to_pointer,
- &cn));
+ GCSoundChannel *channel = g_ptr_array_index(self->channels, channel_number);
g_return_if_fail(channel != NULL);
g_return_if_fail(GC_IS_SOUND_MIXER_SDL(self));
@@ -316,6 +320,7 @@ void gc_sound_mixer_SDL_channel_finished (GCSoundMixerSDL* self,
sample = g_hash_table_lookup (self->samples, channel);
Mix_FreeChunk (sample);
+ g_hash_table_remove (self->samples, channel);
g_signal_emit_by_name (channel, "chunk_end", 0, channel->stopped);
}
@@ -328,10 +333,8 @@ gc_sound_mixer_SDL_init (GCSoundMixerSDL* self)
g_error("Sorry, i can't allocate more than one mixer !!!");
running_mixer = self;
- self->channels_from_pointer = g_hash_table_new (g_direct_hash,
- g_direct_equal);
- self->channels_to_pointer = g_hash_table_new (g_int_hash,
- g_int_equal);
+ self->channels = g_ptr_array_new ();
+
self->samples = g_hash_table_new (g_direct_hash,
g_direct_equal);
self->paused = FALSE;
@@ -357,6 +360,7 @@ enum {
PROP_0,
PROP_DEVICE,
};
+static GObjectClass *parent_class;
static void
@@ -366,16 +370,39 @@ gc_sound_mixer_SDL_finalize (GObject* object)
running_mixer = NULL;
- g_hash_table_destroy (self->channels_from_pointer);
- g_hash_table_destroy (self->channels_to_pointer);
+ g_ptr_array_free (self->channels, TRUE);
+
g_hash_table_destroy (self->samples);
if (self->audio_opened)
Mix_CloseAudio();
SDL_Quit();
+
+ parent_class->finalize (object);
}
+static void
+gc_sound_mixer_SDL_destroy (GCSoundMixerSDL *self)
+{
+ gint i;
+
+ if (self->has_user_ref_count)
+ {
+ self->has_user_ref_count = FALSE;
+ g_object_unref (self);
+ }
+
+ for (i = 0; i < self->channels->len; i++)
+ {
+ g_signal_handlers_disconnect_by_func(GC_SOUND_OBJECT(g_ptr_array_index(self->channels,i)), channel_destroyed, self);
+ gc_sound_object_destroy (GC_SOUND_OBJECT(g_ptr_array_index(self->channels,i)));
+ g_object_unref(G_OBJECT(g_ptr_array_index(self->channels,i)));
+ }
+
+ GC_SOUND_OBJECT_GET_CLASS(self)->destroy (GC_SOUND_OBJECT(self));
+
+}
static void
gc_sound_mixer_SDL_get_property() {}
@@ -386,16 +413,17 @@ gc_sound_mixer_SDL_set_property() {}
static void
gc_sound_mixer_SDL_class_init (GCSoundMixerSDLClass* self_class)
{
- g_warning("gc_sound_mixer_SDL_class_init");
-
GObjectClass* go_class;
+ parent_class = g_type_class_peek_parent (G_OBJECT_CLASS(self_class));
+
/* GObjectClass */
go_class = G_OBJECT_CLASS(self_class);
go_class->finalize = gc_sound_mixer_SDL_finalize;
go_class->get_property = gc_sound_mixer_SDL_get_property;
go_class->set_property = gc_sound_mixer_SDL_set_property;
-
+
+ self_class->destroy = gc_sound_mixer_SDL_destroy;
_gc_sound_mixer_install_property( go_class, PROP_DEVICE);
/* signals */
@@ -432,12 +460,12 @@ gc_sound_mixer_SDL_class_init (GCSoundMixerSDLClass* self_class)
static void gc_init_sound_mixer (GCSoundMixerIface* iface);
-G_DEFINE_TYPE_WITH_CODE(GCSoundMixerSDL, gc_sound_mixer_SDL, G_TYPE_OBJECT,
+G_DEFINE_TYPE_WITH_CODE(GCSoundMixerSDL, gc_sound_mixer_SDL, GC_TYPE_SOUND_OBJECT,
G_IMPLEMENT_INTERFACE(GC_TYPE_SOUND_MIXER, gc_init_sound_mixer));
void gc_init_sound_mixer (GCSoundMixerIface* iface)
{
- g_warning("Sound Mixer is initalized from SDL! ");
+ g_warning("Sound Mixer is initalized by SDL mixer! ");
/* vtable */
iface->open_audio = gc_sound_mixer_SDL_open_audio;
diff --git a/src/gc_sound/src/gc-sound-mixer-SDL.h b/src/gc_sound/src/gc-sound-mixer-SDL.h
index 533496e..16bcb2c 100644
--- a/src/gc_sound/src/gc-sound-mixer-SDL.h
+++ b/src/gc_sound/src/gc-sound-mixer-SDL.h
@@ -66,15 +66,11 @@ struct _GCSoundMixerSDL {
gboolean paused;
/* List of channels */
- GHashTable *channels_from_pointer;
- GHashTable *channels_to_pointer;
+ GPtrArray *channels;
GHashTable *samples;
gboolean stopped;
- // debug only. will be removed.
- gchar* nick;
-
gboolean has_user_ref_count;
};
@@ -106,6 +102,8 @@ struct _GCSoundMixerSDLClass {
void (* channel_finished) (GCSoundMixerSDL * self,
GCSoundChannel * channel);
+
+ void (* destroy) (GCSoundMixerSDL *self);
};
G_END_DECLS
diff --git a/src/gc_sound/src/gc-sound-object.c b/src/gc_sound/src/gc-sound-object.c
index 3bc36b8..b217a70 100644
--- a/src/gc_sound/src/gc-sound-object.c
+++ b/src/gc_sound/src/gc-sound-object.c
@@ -43,6 +43,7 @@ enum {
};
enum {
PROP_0,
+ PROP_PARENT,
PROP_USER_DATA
};
@@ -99,6 +100,9 @@ gc_sound_object_class_init (GCSoundObjectClass *class)
parent_class = g_type_class_ref (G_TYPE_OBJECT);
+ gobject_class->get_property = gc_sound_object_get_property;
+ gobject_class->set_property = gc_sound_object_set_property;
+
gobject_class->dispose = gc_sound_object_dispose;
gobject_class->finalize = gc_sound_object_finalize;
@@ -110,6 +114,13 @@ gc_sound_object_class_init (GCSoundObjectClass *class)
"User Data",
"Anonymous User Data Pointer",
G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class,
+ PROP_PARENT,
+ g_param_spec_object ("parent",
+ "Parent Object",
+ "GCSoundObject parent",
+ GC_TYPE_SOUND_OBJECT,
+ G_PARAM_READWRITE));
gc_sound_object_signals[DESTROY] =
g_signal_new ("destroy",
@@ -125,6 +136,8 @@ static void
gc_sound_object_init (GCSoundObject *object,
GCSoundObjectClass *klass)
{
+ // TRUE is default;
+ object->destroy_with_parent = TRUE;
}
/********************************************
@@ -136,9 +149,10 @@ gc_sound_object_destroy (GCSoundObject *object)
{
g_return_if_fail (object != NULL);
g_return_if_fail (GC_IS_SOUND_OBJECT (object));
-
- if (!(GC_SOUND_OBJECT_FLAGS (object) & GC_SOUND_IN_DESTRUCTION))
+
+ if (!(GC_SOUND_OBJECT_FLAGS (object) & GC_SOUND_IN_DESTRUCTION)){
g_object_run_dispose (G_OBJECT (object));
+ }
}
static void
@@ -188,6 +202,15 @@ gc_sound_object_finalize (GObject *gobject)
* comes directly from GtkObject
*
*****************************************/
+static void
+parent_destroyed (GCSoundObject *object, gpointer data)
+{
+ if (GC_SOUND_OBJECT(object)->parent) {
+ g_signal_handlers_disconnect_by_func(GC_SOUND_OBJECT(object)->parent, parent_destroyed, object);
+ g_object_unref (GC_SOUND_OBJECT(object)->parent);
+ }
+ gc_sound_object_destroy(GC_SOUND_OBJECT(data));
+}
static void
gc_sound_object_set_property (GObject *object,
@@ -200,6 +223,18 @@ gc_sound_object_set_property (GObject *object,
case PROP_USER_DATA:
g_object_set_data (G_OBJECT (object), "user_data", g_value_get_pointer (value));
break;
+ case PROP_PARENT:
+ if (GC_SOUND_OBJECT(object)->parent) {
+ g_signal_handlers_disconnect_by_func(GC_SOUND_OBJECT(object)->parent, parent_destroyed, object);
+ g_object_unref (GC_SOUND_OBJECT(object)->parent);
+ }
+ GC_SOUND_OBJECT(object)->parent = g_value_get_object (value);
+ if (GC_SOUND_OBJECT(object)->parent){
+ g_object_ref (GC_SOUND_OBJECT(object)->parent);
+ g_signal_connect ( G_OBJECT(GC_SOUND_OBJECT(object)->parent), "destroy", (GCallback) parent_destroyed, object );
+ }
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@@ -217,6 +252,9 @@ gc_sound_object_get_property (GObject *object,
case PROP_USER_DATA:
g_value_set_pointer (value, g_object_get_data (G_OBJECT (object), "user_data"));
break;
+ case PROP_PARENT:
+ g_value_set_object (value, G_OBJECT (GC_SOUND_OBJECT(object)->parent));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
diff --git a/src/gc_sound/src/gc-sound-object.h b/src/gc_sound/src/gc-sound-object.h
index d3f651c..0b73bbd 100644
--- a/src/gc_sound/src/gc-sound-object.h
+++ b/src/gc_sound/src/gc-sound-object.h
@@ -52,6 +52,13 @@ struct _GCSoundObject {
GInitiallyUnowned __parent__;
guint32 flags;
+
+ // NULL on mixer; mixer on channel,; prent item on item
+ GCSoundObject *parent;
+ gboolean destroy_with_parent;
+
+ //debug
+ gchar *nick;
};
struct _GCSoundObjectClass {
@@ -60,6 +67,8 @@ struct _GCSoundObjectClass {
void (*destroy) (GCSoundObject *object);
};
+void gc_sound_object_destroy (GCSoundObject *object);
+
G_END_DECLS
diff --git a/src/gc_sound/src/test_gc_sound.c b/src/gc_sound/src/test_gc_sound.c
index 6ae45d0..8e8722d 100644
--- a/src/gc_sound/src/test_gc_sound.c
+++ b/src/gc_sound/src/test_gc_sound.c
@@ -4,12 +4,12 @@
void finish(GCSoundItem *item, gboolean stopped, gpointer data)
{
- g_warning("Return of finish callback %s %s", item->nick, stopped ? "STOPPED" : "normal");
+ g_warning("Return of finish callback %s %s", GC_SOUND_OBJECT(item)->nick, stopped ? "STOPPED" : "normal");
}
void start(GCSoundItem *item, gpointer data)
{
- g_warning("Return of start callback %s", item->nick);
+ g_warning("Return of start callback %s", GC_SOUND_OBJECT(item)->nick);
}
main (int argc, char *argv)
@@ -21,71 +21,62 @@ main (int argc, char *argv)
/* Sound mixer opens SDL and audio device */
gcmix = gc_sound_mixer_SDL_new();
- GC_SOUND_MIXER_SDL(gcmix)->nick = "gcmix";
+ GC_SOUND_OBJECT(gcmix)->nick = "gcmix";
/* We open two chans to play simultaneously */
gcchan1 = gc_sound_mixer_new_channel(gcmix);
gcchan2 = gc_sound_mixer_new_channel(gcmix);
- gcchan1->nick = "gcchan1";
- gcchan2->nick = "gcchan2";
-
- //g_warning ("nick of mixer %s %s", GC_SOUND_MIXER_SDL(gcchan1->mixer)->nick,
- // GC_SOUND_MIXER_SDL(gcchan2->mixer)->nick);
+ GC_SOUND_OBJECT(gcchan1)->nick = "gcchan1";
+ GC_SOUND_OBJECT(gcchan2)->nick = "gcchan2";
GCSoundMixer *gcmix2;
- g_object_get(G_OBJECT(gcchan2), "mixer", &gcmix2, NULL);
+ g_object_get(G_OBJECT(gcchan2), "parent", &gcmix2, NULL);
- g_warning ("g_object_get return mixer %s", GC_SOUND_MIXER_SDL(gcmix2)->nick);
/* Each chan has a root item, where we group the sounds to play in that channel*/
root1 = GC_SOUND_ITEM(gc_sound_channel_get_root(gcchan1));
root2 = GC_SOUND_ITEM(gc_sound_channel_get_root(gcchan2));
- root1->nick="root1";
- root2->nick="root2";
+ GC_SOUND_OBJECT(root1)->nick="root1";
+ GC_SOUND_OBJECT(root2)->nick="root2";
/* create new item for our sounds */
- item1 = gc_sound_item_append_child (root1);
- item2 = gc_sound_item_append_child (root2);
- item3 = gc_sound_item_append_child (root2);
- item1_1 = gc_sound_item_append_child (item1);
-
- item1_2 = gc_sound_item_append_child (item1);
-
- GCSoundChannel *gcc2;
- g_object_get(G_OBJECT(item2), "channel", &gcc2, NULL);
-
- g_warning ("g_object_get return channel %s", GC_SOUND_CHANNEL(gcc2)->nick);
-
-
- item1->nick = "item1";
- item2->nick = "item2";
- item3->nick = "item3";
- item1_1->nick = "item1_1";
- item1_2->nick = "item1_2";
+ item1 = gc_sound_item_append_child (root1);
+ item2 = gc_sound_item_append_child (root2);
+ item3 = gc_sound_item_append_child (root2);
+ item1_1 = gc_sound_item_append_child (item1);
+
+ item1_2 = gc_sound_item_append_child (item1);
+
+ GC_SOUND_OBJECT(item1)->nick = "item1";
+ GC_SOUND_OBJECT(item2)->nick = "item2";
+ GC_SOUND_OBJECT(item3)->nick = "item3";
+ GC_SOUND_OBJECT(item1_1)->nick = "item1_1";
+ GC_SOUND_OBJECT(item1_2)->nick = "item1_2";
/* set file sound name */
- 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");
+ gc_sound_item_set_filename(item1_1, "../../../../../gcompris_main/gcompris/boards/sounds/wahoo.ogg");
+ gc_sound_item_set_filename(item1_2, "../../../../../gcompris_main/gcompris/boards/sounds/wahoo.ogg");
+ gc_sound_item_set_filename(item2, "../../../../../gcompris_main/gcompris/boards/music/background/LRLaPause.ogg");
+ gc_sound_item_set_filename(item3, "../../../../../gcompris_main/gcompris/boards/sounds/bonus.ogg");
// test
gc_sound_item_set_filename(item1_1, NULL);
- gc_sound_item_set_filename(item1_1, "../../../boards/sounds/train.ogg");
+ gc_sound_item_set_filename(item1_1, "../../../../../gcompris_main/gcompris/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(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);
- g_signal_connect( item2, "play_end", finish, NULL);
- g_signal_connect( item2, "play_end", finish, NULL);
- g_signal_connect( item1_1, "play_start", start, NULL);
- g_signal_connect( item1_2, "play_start", start, NULL);
+ //gc_sound_item_connect__play_finished(item2, (GCallback) finish, NULL);
+ //gc_sound_item_connect__play_finished(item3, (GCallback) finish, NULL);
+ //gc_sound_item_connect__play_started(item1_1, (GCallback) start, NULL);
+ //gc_sound_item_connect__play_started(item1_2, (GCallback) start, NULL);
+ g_signal_connect( item2, "play_end", (GCallback) finish, NULL);
+ g_signal_connect( item2, "play_end", (GCallback) finish, NULL);
+ g_signal_connect( item1_1, "play_start", (GCallback) start, NULL);
+ g_signal_connect( item1_2, "play_start", (GCallback) start, NULL);
+ g_signal_connect( item1_2, "play_end", (GCallback) finish, NULL);
/* // test mute */
@@ -108,9 +99,20 @@ main (int argc, char *argv)
g_usleep(3000000);
//this will stop item2 because of policy
- gc_sound_item_play(item3);
+ //gc_sound_item_play(item3);
+ //gc_sound_object_destroy(GC_SOUND_OBJECT(gcchan2));
+ gc_sound_object_destroy(GC_SOUND_OBJECT(item1));
+ g_usleep(3000000);
+ //gc_sound_object_destroy(GC_SOUND_OBJECT(root2));
+
+ g_usleep(3000000);
+
+ gc_sound_object_destroy(GC_SOUND_OBJECT(gcmix));
+ gc_sound_object_destroy(GC_SOUND_OBJECT(gcmix2));
+
+ g_usleep(3000000);
/* infinite loop */
- g_main_loop_run(g_main_loop_new (NULL, FALSE));
+ //g_main_loop_run(g_main_loop_new (NULL, FALSE));
}