From 09c9b73913574a6862135bbcb9d7c2da1f3eea23 Mon Sep 17 00:00:00 2001 From: Michal Ratajsky Date: Thu, 23 Oct 2014 22:02:39 +0200 Subject: Fix memory management problems --- backends/pulse/pulse-backend.c | 47 ++++++++++++++----------- backends/pulse/pulse-device-switch.c | 14 +++++--- backends/pulse/pulse-device.c | 31 +++++++---------- backends/pulse/pulse-port-switch.c | 16 +++++++++ backends/pulse/pulse-sink.c | 67 ++++++++++++++++++++++++++---------- backends/pulse/pulse-sink.h | 2 +- backends/pulse/pulse-source.c | 65 +++++++++++++++++++++++++--------- backends/pulse/pulse-source.h | 2 +- 8 files changed, 163 insertions(+), 81 deletions(-) diff --git a/backends/pulse/pulse-backend.c b/backends/pulse/pulse-backend.c index 4c0697a..56e218e 100644 --- a/backends/pulse/pulse-backend.c +++ b/backends/pulse/pulse-backend.c @@ -462,10 +462,16 @@ pulse_backend_close (MateMixerBackend *backend) g_clear_object (&pulse->priv->connection); } + free_list_devices (pulse); + free_list_streams (pulse); + free_list_ext_streams (pulse); + g_hash_table_remove_all (pulse->priv->devices); g_hash_table_remove_all (pulse->priv->sinks); g_hash_table_remove_all (pulse->priv->sources); g_hash_table_remove_all (pulse->priv->ext_streams); + g_hash_table_remove_all (pulse->priv->sink_inputs); + g_hash_table_remove_all (pulse->priv->source_outputs); pulse->priv->connected_once = FALSE; @@ -761,7 +767,7 @@ on_connection_card_info (PulseConnection *connection, g_hash_table_insert (pulse->priv->devices, GUINT_TO_POINTER (info->index), - g_object_ref (device)); + device); free_list_devices (pulse); g_signal_emit_by_name (G_OBJECT (pulse), @@ -810,10 +816,11 @@ on_connection_sink_info (PulseConnection *connection, if (stream == NULL) { stream = PULSE_STREAM (pulse_sink_new (connection, info, device)); - free_list_streams (pulse); g_hash_table_insert (pulse->priv->sinks, GUINT_TO_POINTER (info->index), - g_object_ref (stream)); + stream); + + free_list_streams (pulse); if (device != NULL) { pulse_device_add_stream (device, stream); @@ -847,8 +854,8 @@ on_connection_sink_removed (PulseConnection *connection, g_object_ref (stream); - free_list_streams (pulse); g_hash_table_remove (pulse->priv->sinks, GUINT_TO_POINTER (idx)); + free_list_streams (pulse); device = pulse_stream_get_device (stream); if (device != NULL) { @@ -887,11 +894,10 @@ on_connection_sink_input_info (PulseConnection *connection, if G_UNLIKELY (sink == NULL) return; - pulse_sink_add_input (sink, info); - - g_hash_table_insert (pulse->priv->sink_inputs, - GUINT_TO_POINTER (info->index), - g_object_ref (sink)); + if (pulse_sink_add_input (sink, info) == TRUE) + g_hash_table_insert (pulse->priv->sink_inputs, + GUINT_TO_POINTER (info->index), + g_object_ref (sink)); } static void @@ -928,10 +934,11 @@ on_connection_source_info (PulseConnection *connection, if (stream == NULL) { stream = PULSE_STREAM (pulse_source_new (connection, info, device)); - free_list_streams (pulse); g_hash_table_insert (pulse->priv->sources, GUINT_TO_POINTER (info->index), - g_object_ref (stream)); + stream); + + free_list_streams (pulse); if (device != NULL) { pulse_device_add_stream (device, stream); @@ -965,8 +972,8 @@ on_connection_source_removed (PulseConnection *connection, g_object_ref (stream); - free_list_streams (pulse); g_hash_table_remove (pulse->priv->sources, GUINT_TO_POINTER (idx)); + free_list_streams (pulse); device = pulse_stream_get_device (stream); if (device != NULL) { @@ -1005,11 +1012,10 @@ on_connection_source_output_info (PulseConnection *connection, if G_UNLIKELY (source == NULL) return; - pulse_source_add_output (source, info); - - g_hash_table_insert (pulse->priv->source_outputs, - GUINT_TO_POINTER (info->index), - g_object_ref (source)); + if (pulse_source_add_output (source, info) == TRUE) + g_hash_table_insert (pulse->priv->source_outputs, + GUINT_TO_POINTER (info->index), + g_object_ref (source)); } static void @@ -1047,10 +1053,11 @@ on_connection_ext_stream_info (PulseConnection *connection, if (ext == NULL) { ext = pulse_ext_stream_new (connection, info, parent); - free_list_ext_streams (pulse); g_hash_table_insert (pulse->priv->ext_streams, g_strdup (info->name), - g_object_ref (ext)); + ext); + + free_list_ext_streams (pulse); g_signal_emit_by_name (G_OBJECT (pulse), "stored-control-added", @@ -1089,8 +1096,8 @@ on_connection_ext_stream_loaded (PulseConnection *connection, PulseBackend *puls if (PULSE_GET_HANGING (ext) == FALSE) continue; - free_list_ext_streams (pulse); g_hash_table_iter_remove (&iter); + free_list_ext_streams (pulse); g_signal_emit_by_name (G_OBJECT (pulse), "stored-control-removed", diff --git a/backends/pulse/pulse-device-switch.c b/backends/pulse/pulse-device-switch.c index 7a43d0a..bc2490d 100644 --- a/backends/pulse/pulse-device-switch.c +++ b/backends/pulse/pulse-device-switch.c @@ -129,7 +129,11 @@ pulse_device_switch_set_property (GObject *object, switch (param_id) { case PROP_DEVICE: /* Construct-only object */ - swtch->priv->device = g_value_dup_object (value); + swtch->priv->device = g_value_get_object (value); + + if (swtch->priv->device != NULL) + g_object_add_weak_pointer (G_OBJECT (swtch->priv->device), + (gpointer *) &swtch->priv->device); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); @@ -152,8 +156,10 @@ pulse_device_switch_dispose (GObject *object) swtch = PULSE_DEVICE_SWITCH (object); - g_clear_object (&swtch->priv->device); - + if (swtch->priv->profiles != NULL) { + g_list_free_full (swtch->priv->profiles, g_object_unref); + swtch->priv->profiles = NULL; + } G_OBJECT_CLASS (pulse_device_switch_parent_class)->dispose (object); } @@ -183,7 +189,7 @@ pulse_device_switch_add_profile (PulseDeviceSwitch *swtch, PulseDeviceProfile *p g_return_if_fail (PULSE_IS_DEVICE_PROFILE (profile)); swtch->priv->profiles = g_list_insert_sorted (swtch->priv->profiles, - profile, + g_object_ref (profile), compare_profiles); } diff --git a/backends/pulse/pulse-device.c b/backends/pulse/pulse-device.c index 9f33132..71040cc 100644 --- a/backends/pulse/pulse-device.c +++ b/backends/pulse/pulse-device.c @@ -38,9 +38,9 @@ struct _PulseDevicePrivate GHashTable *ports; GHashTable *streams; GList *streams_list; - GList *switches_list; PulseConnection *connection; PulseDeviceSwitch *pswitch; + GList *pswitch_list; }; enum { @@ -79,7 +79,6 @@ static void pulse_device_load (PulseDevice *device, const pa_card_info *info); static void free_list_streams (PulseDevice *device); -static void free_list_switches (PulseDevice *device); static void pulse_device_class_init (PulseDeviceClass *klass) @@ -201,8 +200,11 @@ pulse_device_dispose (GObject *object) g_clear_object (&device->priv->pswitch); free_list_streams (device); - free_list_switches (device); + if (device->priv->pswitch_list != NULL) { + g_list_free (device->priv->pswitch_list); + device->priv->pswitch_list = NULL; + } G_OBJECT_CLASS (pulse_device_parent_class)->dispose (object); } @@ -279,12 +281,12 @@ pulse_device_add_stream (PulseDevice *device, PulseStream *stream) name = mate_mixer_stream_get_name (MATE_MIXER_STREAM (stream)); - free_list_streams (device); - g_hash_table_insert (device->priv->streams, g_strdup (name), g_object_ref (stream)); + free_list_streams (device); + g_signal_emit_by_name (G_OBJECT (device), "stream-added", name); @@ -363,7 +365,7 @@ pulse_device_list_switches (MateMixerDevice *mmd) { g_return_val_if_fail (PULSE_IS_DEVICE (mmd), NULL); - return PULSE_DEVICE (mmd)->priv->switches_list; + return PULSE_DEVICE (mmd)->priv->pswitch_list; } static void @@ -387,7 +389,7 @@ pulse_device_load (PulseDevice *device, const pa_card_info *info) g_hash_table_insert (device->priv->ports, g_strdup (name), - g_object_ref (port)); + port); } #endif @@ -397,7 +399,7 @@ pulse_device_load (PulseDevice *device, const pa_card_info *info) _("Profile"), device); - device->priv->switches_list = g_list_prepend (NULL, g_object_ref (device->priv->pswitch)); + device->priv->pswitch_list = g_list_prepend (NULL, device->priv->pswitch); } for (i = 0; i < info->n_profiles; i++) { @@ -421,6 +423,8 @@ pulse_device_load (PulseDevice *device, const pa_card_info *info) p_info->priority); pulse_device_switch_add_profile (device->priv->pswitch, profile); + + g_object_unref (profile); } } @@ -434,14 +438,3 @@ free_list_streams (PulseDevice *device) device->priv->streams_list = NULL; } - -static void -free_list_switches (PulseDevice *device) -{ - if (device->priv->switches_list == NULL) - return; - - g_list_free_full (device->priv->switches_list, g_object_unref); - - device->priv->switches_list = NULL; -} diff --git a/backends/pulse/pulse-port-switch.c b/backends/pulse/pulse-port-switch.c index db06a7c..71e0709 100644 --- a/backends/pulse/pulse-port-switch.c +++ b/backends/pulse/pulse-port-switch.c @@ -53,6 +53,7 @@ static void pulse_port_switch_set_property (GObject *object, GParamSpec *pspec); static void pulse_port_switch_init (PulsePortSwitch *swtch); +static void pulse_port_switch_dispose (GObject *object); G_DEFINE_ABSTRACT_TYPE (PulsePortSwitch, pulse_port_switch, MATE_MIXER_TYPE_SWITCH) @@ -73,6 +74,7 @@ pulse_port_switch_class_init (PulsePortSwitchClass *klass) MateMixerSwitchClass *switch_class; object_class = G_OBJECT_CLASS (klass); + object_class->dispose = pulse_port_switch_dispose; object_class->get_property = pulse_port_switch_get_property; object_class->set_property = pulse_port_switch_set_property; @@ -147,6 +149,20 @@ pulse_port_switch_init (PulsePortSwitch *swtch) PulsePortSwitchPrivate); } +static void +pulse_port_switch_dispose (GObject *object) +{ + PulsePortSwitch *swtch; + + swtch = PULSE_PORT_SWITCH (object); + + if (swtch->priv->ports != NULL) { + g_list_free_full (swtch->priv->ports, g_object_unref); + swtch->priv->ports = NULL; + } + G_OBJECT_CLASS (pulse_port_switch_parent_class)->dispose (object); +} + PulseStream * pulse_port_switch_get_stream (PulsePortSwitch *swtch) { diff --git a/backends/pulse/pulse-sink.c b/backends/pulse/pulse-sink.c index d71ac47..14be2e8 100644 --- a/backends/pulse/pulse-sink.c +++ b/backends/pulse/pulse-sink.c @@ -38,9 +38,9 @@ struct _PulseSinkPrivate { guint32 monitor; GHashTable *inputs; + GList *inputs_list; PulsePortSwitch *pswitch; - GList *streams_list; - GList *switches_list; + GList *pswitch_list; PulseSinkControl *control; }; @@ -54,6 +54,8 @@ G_DEFINE_TYPE (PulseSink, pulse_sink, PULSE_TYPE_STREAM); static const GList *pulse_sink_list_controls (MateMixerStream *mms); static const GList *pulse_sink_list_switches (MateMixerStream *mms); +static void free_list_controls (PulseSink *sink); + static void pulse_sink_class_init (PulseSinkClass *klass) { @@ -93,11 +95,17 @@ pulse_sink_dispose (GObject *object) sink = PULSE_SINK (object); + g_hash_table_remove_all (sink->priv->inputs); + g_clear_object (&sink->priv->control); g_clear_object (&sink->priv->pswitch); - g_hash_table_remove_all (sink->priv->inputs); + free_list_controls (sink); + if (sink->priv->pswitch_list != NULL) { + g_list_free (sink->priv->pswitch_list); + sink->priv->pswitch_list = NULL; + } G_OBJECT_CLASS (pulse_sink_parent_class)->dispose (object); } @@ -164,6 +172,7 @@ pulse_sink_new (PulseConnection *connection, if (p == info->active_port) pulse_port_switch_set_active_port (sink->priv->pswitch, port); } + sink->priv->pswitch_list = g_list_prepend (NULL, sink->priv->pswitch); g_debug ("Created port list for sink %s", info->name); } @@ -175,7 +184,7 @@ pulse_sink_new (PulseConnection *connection, return sink; } -void +gboolean pulse_sink_add_input (PulseSink *sink, const pa_sink_input_info *info) { PulseSinkInput *input; @@ -188,32 +197,40 @@ pulse_sink_add_input (PulseSink *sink, const pa_sink_input_info *info) input = pulse_sink_input_new (sink, info); g_hash_table_insert (sink->priv->inputs, GINT_TO_POINTER (info->index), - g_object_ref (input)); + input); + + free_list_controls (sink); name = mate_mixer_stream_control_get_name (MATE_MIXER_STREAM_CONTROL (input)); g_signal_emit_by_name (G_OBJECT (sink), "control-added", name); - } else - pulse_sink_input_update (input, info); + return TRUE; + } + + pulse_sink_input_update (input, info); + return FALSE; } void pulse_sink_remove_input (PulseSink *sink, guint32 index) { PulseSinkInput *input; - const gchar *name; + gchar *name; input = g_hash_table_lookup (sink->priv->inputs, GINT_TO_POINTER (index)); if G_UNLIKELY (input == NULL) return; - name = mate_mixer_stream_control_get_name (MATE_MIXER_STREAM_CONTROL (input)); + name = g_strdup (mate_mixer_stream_control_get_name (MATE_MIXER_STREAM_CONTROL (input))); g_hash_table_remove (sink->priv->inputs, GINT_TO_POINTER (index)); + + free_list_controls (sink); g_signal_emit_by_name (G_OBJECT (sink), "control-removed", name); + g_free (name); } void @@ -244,16 +261,21 @@ pulse_sink_get_index_monitor (PulseSink *sink) static const GList * pulse_sink_list_controls (MateMixerStream *mms) { - GList *list; + PulseSink *sink; g_return_val_if_fail (PULSE_IS_SINK (mms), NULL); - // XXX - list = g_hash_table_get_values (PULSE_SINK (mms)->priv->inputs); - if (list != NULL) - g_list_foreach (list, (GFunc) g_object_ref, NULL); + sink = PULSE_SINK (mms); + + if (sink->priv->inputs_list == NULL) { + sink->priv->inputs_list = g_hash_table_get_values (sink->priv->inputs); + if (sink->priv->inputs_list != NULL) + g_list_foreach (sink->priv->inputs_list, (GFunc) g_object_ref, NULL); - return g_list_prepend (list, g_object_ref (PULSE_SINK (mms)->priv->control)); + sink->priv->inputs_list = g_list_prepend (sink->priv->inputs_list, + g_object_ref (sink->priv->control)); + } + return sink->priv->inputs_list; } static const GList * @@ -261,9 +283,16 @@ pulse_sink_list_switches (MateMixerStream *mms) { g_return_val_if_fail (PULSE_IS_SINK (mms), NULL); - // XXX - if (PULSE_SINK (mms)->priv->pswitch != NULL) - return g_list_prepend (NULL, PULSE_SINK (mms)->priv->pswitch); + return PULSE_SINK (mms)->priv->pswitch_list; +} + +static void +free_list_controls (PulseSink *sink) +{ + if (sink->priv->inputs_list == NULL) + return; + + g_list_free_full (sink->priv->inputs_list, g_object_unref); - return NULL; + sink->priv->inputs_list = NULL; } diff --git a/backends/pulse/pulse-sink.h b/backends/pulse/pulse-sink.h index 5eaeaa0..355eaf1 100644 --- a/backends/pulse/pulse-sink.h +++ b/backends/pulse/pulse-sink.h @@ -63,7 +63,7 @@ PulseSink *pulse_sink_new (PulseConnection *connection, const pa_sink_info *info, PulseDevice *device); -void pulse_sink_add_input (PulseSink *sink, +gboolean pulse_sink_add_input (PulseSink *sink, const pa_sink_input_info *info); void pulse_sink_remove_input (PulseSink *sink, guint32 index); diff --git a/backends/pulse/pulse-source.c b/backends/pulse/pulse-source.c index 39ec9b7..61526f5 100644 --- a/backends/pulse/pulse-source.c +++ b/backends/pulse/pulse-source.c @@ -37,7 +37,9 @@ struct _PulseSourcePrivate { GHashTable *outputs; + GList *outputs_list; PulsePortSwitch *pswitch; + GList *pswitch_list; PulseSourceControl *control; }; @@ -51,6 +53,8 @@ G_DEFINE_TYPE (PulseSource, pulse_source, PULSE_TYPE_STREAM); static const GList *pulse_source_list_controls (MateMixerStream *mms); static const GList *pulse_source_list_switches (MateMixerStream *mms); +static void free_list_controls (PulseSource *source); + static void pulse_source_class_init (PulseSourceClass *klass) { @@ -88,11 +92,17 @@ pulse_source_dispose (GObject *object) source = PULSE_SOURCE (object); + g_hash_table_remove_all (source->priv->outputs); + g_clear_object (&source->priv->control); g_clear_object (&source->priv->pswitch); - g_hash_table_remove_all (source->priv->outputs); + free_list_controls (source); + if (source->priv->pswitch_list != NULL) { + g_list_free (source->priv->pswitch_list); + source->priv->pswitch_list = NULL; + } G_OBJECT_CLASS (pulse_source_parent_class)->dispose (object); } @@ -159,6 +169,7 @@ pulse_source_new (PulseConnection *connection, if (p == info->active_port) pulse_port_switch_set_active_port (source->priv->pswitch, port); } + source->priv->pswitch_list = g_list_prepend (NULL, source->priv->pswitch); g_debug ("Created port list for source %s", info->name); } @@ -170,7 +181,7 @@ pulse_source_new (PulseConnection *connection, return source; } -void +gboolean pulse_source_add_output (PulseSource *source, const pa_source_output_info *info) { PulseSourceOutput *output; @@ -183,32 +194,40 @@ pulse_source_add_output (PulseSource *source, const pa_source_output_info *info) output = pulse_source_output_new (source, info); g_hash_table_insert (source->priv->outputs, GINT_TO_POINTER (info->index), - g_object_ref (output)); + output); + + free_list_controls (source); name = mate_mixer_stream_control_get_name (MATE_MIXER_STREAM_CONTROL (output)); g_signal_emit_by_name (G_OBJECT (source), "control-added", name); - } else - pulse_source_output_update (output, info); + return TRUE; + } + + pulse_source_output_update (output, info); + return FALSE; } void pulse_source_remove_output (PulseSource *source, guint32 index) { PulseSourceOutput *output; - const gchar *name; + gchar *name; output = g_hash_table_lookup (source->priv->outputs, GINT_TO_POINTER (index)); if G_UNLIKELY (output == NULL) return; - name = mate_mixer_stream_control_get_name (MATE_MIXER_STREAM_CONTROL (output)); + name = g_strdup (mate_mixer_stream_control_get_name (MATE_MIXER_STREAM_CONTROL (output))); g_hash_table_remove (source->priv->outputs, GINT_TO_POINTER (index)); + + free_list_controls (source); g_signal_emit_by_name (G_OBJECT (source), "control-removed", name); + g_free (name); } void @@ -230,16 +249,21 @@ pulse_source_update (PulseSource *source, static const GList * pulse_source_list_controls (MateMixerStream *mms) { - GList *list; + PulseSource *source; g_return_val_if_fail (PULSE_IS_SOURCE (mms), NULL); - // XXX - list = g_hash_table_get_values (PULSE_SOURCE (mms)->priv->outputs); - if (list != NULL) - g_list_foreach (list, (GFunc) g_object_ref, NULL); + source = PULSE_SOURCE (mms); + + if (source->priv->outputs_list == NULL) { + source->priv->outputs_list = g_hash_table_get_values (source->priv->outputs); + if (source->priv->outputs_list != NULL) + g_list_foreach (source->priv->outputs_list, (GFunc) g_object_ref, NULL); - return g_list_prepend (list, g_object_ref (PULSE_SOURCE (mms)->priv->control)); + source->priv->outputs_list = g_list_prepend (source->priv->outputs_list, + g_object_ref (source->priv->control)); + } + return source->priv->outputs_list; } static const GList * @@ -247,9 +271,16 @@ pulse_source_list_switches (MateMixerStream *mms) { g_return_val_if_fail (PULSE_IS_SOURCE (mms), NULL); - // XXX - if (PULSE_SOURCE (mms)->priv->pswitch != NULL) - return g_list_prepend (NULL, PULSE_SOURCE (mms)->priv->pswitch); + return PULSE_SOURCE (mms)->priv->pswitch_list; +} + +static void +free_list_controls (PulseSource *source) +{ + if (source->priv->outputs_list == NULL) + return; + + g_list_free_full (source->priv->outputs_list, g_object_unref); - return NULL; + source->priv->outputs_list = NULL; } diff --git a/backends/pulse/pulse-source.h b/backends/pulse/pulse-source.h index fdc3d5e..5f82aae 100644 --- a/backends/pulse/pulse-source.h +++ b/backends/pulse/pulse-source.h @@ -63,7 +63,7 @@ PulseSource *pulse_source_new (PulseConnection *connection const pa_source_info *info, PulseDevice *device); -void pulse_source_add_output (PulseSource *source, +gboolean pulse_source_add_output (PulseSource *source, const pa_source_output_info *info); void pulse_source_remove_output (PulseSource *source, -- cgit v1.2.1