--- a/libpurple/media.c Thu Aug 11 21:56:21 2022 -0500
+++ b/libpurple/media.c Fri Aug 12 01:29:41 2022 -0500
@@ -234,22 +234,20 @@
purple_media_stream_free(PurpleMediaStream *stream)
g_free(stream->participant);
- if (stream->local_candidates)
- purple_media_candidate_list_free(stream->local_candidates);
- if (stream->remote_candidates)
- purple_media_candidate_list_free(stream->remote_candidates);
- if (stream->active_local_candidates)
- purple_media_candidate_list_free(
- stream->active_local_candidates);
- if (stream->active_remote_candidates)
- purple_media_candidate_list_free(
- stream->active_remote_candidates);
+ g_clear_pointer(&stream->local_candidates, + purple_media_candidate_list_free); + g_clear_pointer(&stream->remote_candidates, + purple_media_candidate_list_free); + g_clear_pointer(&stream->active_local_candidates, + purple_media_candidate_list_free); + g_clear_pointer(&stream->active_remote_candidates, + purple_media_candidate_list_free); @@ -257,8 +255,9 @@
purple_media_session_free(PurpleMediaSession *session)
@@ -274,20 +273,9 @@
purple_media_manager_remove_media(priv->manager, PURPLE_MEDIA(media));
- g_object_unref(priv->backend);
- g_object_unref(priv->manager);
- if (priv->conference_type) {
- g_free(priv->conference_type);
- priv->conference_type = NULL;
+ g_clear_object(&priv->backend); + g_clear_object(&priv->manager); + g_clear_pointer(&priv->conference_type, g_free); G_OBJECT_CLASS(purple_media_parent_class)->dispose(media);
@@ -327,34 +315,27 @@
media->priv->account = g_value_get_object(value);
case PROP_CONFERENCE_TYPE:
- media->priv->conference_type =
- g_value_dup_string(value);
+ media->priv->conference_type = g_value_dup_string(value); media->priv->backend = g_object_new(
- purple_media_manager_get_backend_type(
- purple_media_manager_get()),
- media->priv->conference_type,
+ purple_media_manager_get_backend_type(purple_media_manager_get()), + "conference-type", media->priv->conference_type, g_signal_connect(media->priv->backend,
- purple_media_candidate_pair_established_cb),
+ G_CALLBACK(purple_media_candidate_pair_established_cb), g_signal_connect(media->priv->backend,
- purple_media_candidates_prepared_cb),
+ G_CALLBACK(purple_media_candidates_prepared_cb), g_signal_connect(media->priv->backend,
- purple_media_codecs_changed_cb),
+ G_CALLBACK(purple_media_codecs_changed_cb), g_signal_connect(media->priv->backend,
- purple_media_new_local_candidate_cb),
+ G_CALLBACK(purple_media_new_local_candidate_cb), @@ -388,8 +369,7 @@
g_value_set_object(value, media->priv->account);
case PROP_CONFERENCE_TYPE:
- g_value_set_string(value,
- media->priv->conference_type);
+ g_value_set_string(value, media->priv->conference_type); g_value_set_boolean(value, media->priv->initiator);
@@ -425,7 +405,9 @@
PurpleMediaStream *stream = streams->data;
if (purple_strequal(stream->session->id, session) &&
purple_strequal(stream->participant, participant))
@@ -448,7 +430,9 @@
purple_strequal(stream->session->id, session)) &&
purple_strequal(stream->participant, participant)))
ret = g_list_append(ret, stream);
@@ -599,13 +583,16 @@
g_list_remove(media->priv->streams, stream);
- if (g_list_find(sessions, stream->session) == NULL)
+ if (g_list_find(sessions, stream->session) == NULL) { sessions = g_list_prepend(sessions, stream->session);
if (g_list_find_custom(participants, stream->participant,
(GCompareFunc)strcmp) == NULL)
participants = g_list_prepend(participants,
g_strdup(stream->participant));
purple_media_stream_free(stream);
@@ -692,12 +679,10 @@
g_return_if_fail(PURPLE_IS_MEDIA(media));
- streams = purple_media_get_streams(media,
- session_id, participant);
+ streams = purple_media_get_streams(media, session_id, participant); /* Emit stream acceptance */
- for (; streams; streams =
- g_list_delete_link(streams, streams)) {
+ for (; streams; streams = g_list_delete_link(streams, streams)) { PurpleMediaStream *stream = streams->data;
@@ -707,15 +692,16 @@
0, type, stream->session->id,
stream->participant, local);
- if (g_list_find(sessions, stream->session) == NULL)
- sessions = g_list_prepend(sessions,
+ if (g_list_find(sessions, stream->session) == NULL) { + sessions = g_list_prepend(sessions, stream->session); if (g_list_find_custom(participants,
- (GCompareFunc)strcmp) == NULL)
+ (GCompareFunc)strcmp) == NULL) { participants = g_list_prepend(participants,
g_strdup(stream->participant));
/* Emit session acceptance */
@@ -723,11 +709,12 @@
g_list_delete_link(sessions, sessions)) {
PurpleMediaSession *session = sessions->data;
- if (purple_media_accepted(media, session->id, NULL))
+ if (purple_media_accepted(media, session->id, NULL)) { g_signal_emit(media, purple_media_signals[
PURPLE_MEDIA_INFO_ACCEPT,
session->id, NULL, local);
/* Emit participant acceptance */
@@ -735,21 +722,23 @@
participants, participants)) {
gchar *participant = participants->data;
- if (purple_media_accepted(media, NULL, participant))
+ if (purple_media_accepted(media, NULL, participant)) { g_signal_emit(media, purple_media_signals[
PURPLE_MEDIA_INFO_ACCEPT,
NULL, participant, local);
/* Emit conference acceptance */
- if (purple_media_accepted(media, NULL, NULL))
+ if (purple_media_accepted(media, NULL, NULL)) { purple_media_signals[STREAM_INFO],
0, PURPLE_MEDIA_INFO_ACCEPT,
} else if (type == PURPLE_MEDIA_INFO_HANGUP ||
@@ -758,12 +747,10 @@
g_return_if_fail(PURPLE_IS_MEDIA(media));
- streams = purple_media_get_streams(media,
- session_id, participant);
+ streams = purple_media_get_streams(media, session_id, participant); - for (; streams; streams =
- g_list_delete_link(streams, streams)) {
+ for (; streams; streams = g_list_delete_link(streams, streams)) { PurpleMediaStream *stream = streams->data;
@@ -779,9 +766,10 @@
GList *participants = media->priv->participants;
- if (media->priv->sessions != NULL)
+ if (media->priv->sessions != NULL) { sessions = g_hash_table_get_values(
for (; sessions; sessions = g_list_delete_link(
@@ -878,9 +866,11 @@
g_return_val_if_fail(param != NULL, FALSE);
params = purple_media_backend_get_available_params(media->priv->backend);
- for (; *params != NULL; ++params)
- if (purple_strequal(*params, param))
+ for (; *params != NULL; ++params) { + if (purple_strequal(*params, param)) { @@ -1306,10 +1296,8 @@
} else if (sess_id != NULL && participant == NULL) {
- GList *streams = purple_media_get_streams(
- for (; streams; streams =
- g_list_delete_link(streams, streams)) {
+ GList *streams = purple_media_get_streams(media, sess_id, NULL); + for (; streams; streams = g_list_delete_link(streams, streams)) { PurpleMediaStream *stream = streams->data;
if (stream->accepted == FALSE) {
@@ -1320,8 +1308,9 @@
} else if (sess_id != NULL && participant != NULL) {
PurpleMediaStream *stream = purple_media_get_stream(
media, sess_id, participant);
- if (stream == NULL || stream->accepted == FALSE)
+ if (stream == NULL || stream->accepted == FALSE) { @@ -1401,19 +1390,19 @@
PurpleMediaBackendInterface *backend_iface = NULL;
backend_iface = PURPLE_MEDIA_BACKEND_GET_INTERFACE(media->priv->backend);
+ } else if (dtmf == 'b') {
+ } else if (dtmf == 'c') {
+ } else if (dtmf == 'd') { g_return_val_if_fail(strchr("0123456789ABCD#*", dtmf), FALSE);
--- a/libpurple/mediamanager.c Thu Aug 11 21:56:21 2022 -0500
+++ b/libpurple/mediamanager.c Fri Aug 12 01:29:41 2022 -0500
@@ -224,12 +224,12 @@
g_list_free_full(priv->medias, g_object_unref);
g_list_free_full(priv->private_medias, g_object_unref);
g_list_free_full(priv->elements, g_object_unref);
- gst_caps_unref(priv->video_caps);
+ g_clear_pointer(&priv->video_caps, gst_caps_unref); #ifdef HAVE_MEDIA_APPLICATION
- if (priv->appdata_info)
- g_list_free_full (priv->appdata_info,
- (GDestroyNotify) free_appdata_info_locked);
+ if (priv->appdata_info) { + g_list_free_full(priv->appdata_info, + (GDestroyNotify)free_appdata_info_locked); g_mutex_clear (&priv->appdata_mutex);
if (priv->device_monitor) {
@@ -247,8 +247,10 @@
static PurpleMediaManager *manager = NULL;
manager = PURPLE_MEDIA_MANAGER(g_object_new(purple_media_manager_get_type(), NULL));
@@ -261,7 +263,7 @@
switch(GST_MESSAGE_TYPE(msg)) {
- purple_debug_info("mediamanager", "End of Stream\n");
+ purple_debug_info("mediamanager", "End of Stream"); case GST_MESSAGE_ERROR: {
@@ -269,15 +271,13 @@
gst_message_parse_error(msg, &err, &debug);
- purple_debug_error("mediamanager",
- "gst pipeline error: %s\n",
+ purple_debug_error("mediamanager", "gst pipeline error: %s", - purple_debug_error("mediamanager",
- "Debug details: %s\n", debug);
+ purple_debug_error("mediamanager", "Debug details: %s", debug); @@ -348,11 +348,13 @@
manager->priv->private_medias = g_list_append(
manager->priv->private_medias, media);
manager->priv->medias = g_list_append(manager->priv->medias, media);
@@ -363,10 +365,11 @@
get_media(PurpleMediaManager *manager, gboolean private)
return manager->priv->private_medias;
return manager->priv->medias;
@@ -383,10 +386,11 @@
g_return_val_if_fail(PURPLE_IS_MEDIA_MANAGER(manager), NULL);
iter = manager->priv->private_medias;
iter = manager->priv->medias;
for (; iter; iter = g_list_next(iter)) {
media_account = purple_media_get_account(iter->data);
if (media_account == account) {
@@ -495,8 +499,9 @@
GstAppSrcCallbacks null_src_cb = { NULL, NULL, NULL, { NULL } };
GstAppSinkCallbacks null_sink_cb = { NULL, NULL, NULL , { NULL } };
- info->notify (info->user_data);
+ info->notify(info->user_data); @@ -529,9 +534,7 @@
info->writable_timer_id = 0;
- if (info->current_sample)
- gst_sample_unref (info->current_sample);
- info->current_sample = NULL;
+ g_clear_pointer(&info->current_sample, gst_sample_unref); /* Unblock any reading thread before destroying the GCond */
g_cond_broadcast (&info->readable_cond);
@@ -632,8 +635,7 @@
purple_media_manager_set_video_caps(PurpleMediaManager *manager, GstCaps *caps)
- if (manager->priv->video_caps)
- gst_caps_unref(manager->priv->video_caps);
+ g_clear_pointer(&manager->priv->video_caps, gst_caps_unref); manager->priv->video_caps = caps;
@@ -657,9 +659,11 @@
purple_media_manager_get_video_caps(PurpleMediaManager *manager)
- if (manager->priv->video_caps == NULL)
+ if (manager->priv->video_caps == NULL) { manager->priv->video_caps = gst_caps_from_string("video/x-raw,"
"width=[250,352], height=[200,288], framerate=[1/1,20/1]");
return manager->priv->video_caps;
@@ -714,9 +718,10 @@
g_mutex_unlock (&manager->priv->appdata_mutex);
- if (writable_cb && media)
+ if (writable_cb && media) { writable_cb (manager, media, session_id, participant, writable,
@@ -741,8 +746,9 @@
PurpleMediaManager *manager = purple_media_manager_get ();
/* We already have a writable callback scheduled, don't create another one */
- if (info->writable_cb_token || info->callbacks.writable == NULL)
+ if (info->writable_cb_token || info->callbacks.writable == NULL) { /* We can't use writable_timer_id as a token, because the timeout is added
* into libpurple's main event loop, which runs in a different thread than
@@ -763,8 +769,9 @@
/* Only signal writable if we also established a connection */
call_appsrc_writable_locked (info);
g_mutex_unlock (&manager->priv->appdata_mutex);
@@ -821,8 +828,9 @@
/* We established the connection, if we were writable, then we need to
call_appsrc_writable_locked (info);
g_mutex_unlock (&manager->priv->appdata_mutex);
@@ -932,8 +940,9 @@
g_cond_broadcast (&info->readable_cond);
/* We already have a writable callback scheduled, don't create another one */
- if (info->readable_cb_token || info->callbacks.readable == NULL)
+ if (info->readable_cb_token || info->callbacks.readable == NULL) { info->readable_cb_token = ++manager->priv->appdata_cb_token;
info->readable_timer_id = g_timeout_add (0, appsink_readable, info);
@@ -1051,21 +1060,23 @@
PurpleMediaElementInfo *info = NULL;
PurpleMediaElementType element_type;
- if (type & PURPLE_MEDIA_SEND_AUDIO)
+ if (type & PURPLE_MEDIA_SEND_AUDIO) { info = manager->priv->audio_src;
- else if (type & PURPLE_MEDIA_RECV_AUDIO)
+ } else if (type & PURPLE_MEDIA_RECV_AUDIO) { info = manager->priv->audio_sink;
- else if (type & PURPLE_MEDIA_SEND_VIDEO)
+ } else if (type & PURPLE_MEDIA_SEND_VIDEO) { info = manager->priv->video_src;
- else if (type & PURPLE_MEDIA_RECV_VIDEO)
+ } else if (type & PURPLE_MEDIA_RECV_VIDEO) { info = manager->priv->video_sink;
- else if (type & PURPLE_MEDIA_SEND_APPLICATION)
+ } else if (type & PURPLE_MEDIA_SEND_APPLICATION) { info = get_send_application_element_info ();
- else if (type & PURPLE_MEDIA_RECV_APPLICATION)
+ } else if (type & PURPLE_MEDIA_RECV_APPLICATION) { info = get_recv_application_element_info ();
element_type = purple_media_element_info_get_element_type(info);
@@ -1100,8 +1111,9 @@
gst_bin_add_many(GST_BIN(bin), videoscale, capsfilter, NULL);
gst_element_link_many(ret, videoscale, capsfilter, tee, NULL);
gst_element_link(ret, tee);
* This shouldn't be necessary, but it stops it from
@@ -1150,8 +1162,9 @@
purple_debug_error("media", "Error creating source or sink\n");
@@ -1168,8 +1181,7 @@
iter = manager->priv->elements;
for (; iter; iter = g_list_next(iter)) {
- purple_media_element_info_get_id(iter->data);
+ gchar *element_id = purple_media_element_info_get_id(iter->data); if (purple_strequal(element_id, id)) {
g_object_ref(iter->data);
@@ -1225,8 +1237,7 @@
- manager->priv->elements =
- g_list_prepend(manager->priv->elements, info);
+ manager->priv->elements = g_list_prepend(manager->priv->elements, info); detail = element_info_to_detail(info);
@@ -1254,14 +1265,18 @@
- if (manager->priv->audio_src == info)
+ if (manager->priv->audio_src == info) { manager->priv->audio_src = NULL;
- if (manager->priv->audio_sink == info)
+ if (manager->priv->audio_sink == info) { manager->priv->audio_sink = NULL;
- if (manager->priv->video_src == info)
+ if (manager->priv->video_src == info) { manager->priv->video_src = NULL;
- if (manager->priv->video_sink == info)
+ if (manager->priv->video_sink == info) { manager->priv->video_sink = NULL;
detail = element_info_to_detail(info);
@@ -1294,10 +1309,11 @@
info2 = purple_media_manager_get_element_info(manager, id);
purple_media_manager_register_element(manager, info);
type = purple_media_element_info_get_element_type(info);
@@ -1332,20 +1348,21 @@
g_return_val_if_fail(PURPLE_IS_MEDIA_MANAGER(manager), NULL);
if (type & PURPLE_MEDIA_ELEMENT_SRC) {
- if (type & PURPLE_MEDIA_ELEMENT_AUDIO)
+ if (type & PURPLE_MEDIA_ELEMENT_AUDIO) { return manager->priv->audio_src;
- else if (type & PURPLE_MEDIA_ELEMENT_VIDEO)
+ } else if (type & PURPLE_MEDIA_ELEMENT_VIDEO) { return manager->priv->video_src;
- else if (type & PURPLE_MEDIA_ELEMENT_APPLICATION)
+ } else if (type & PURPLE_MEDIA_ELEMENT_APPLICATION) { return get_send_application_element_info ();
} else if (type & PURPLE_MEDIA_ELEMENT_SINK) {
- if (type & PURPLE_MEDIA_ELEMENT_AUDIO)
+ if (type & PURPLE_MEDIA_ELEMENT_AUDIO) { return manager->priv->audio_sink;
- else if (type & PURPLE_MEDIA_ELEMENT_VIDEO)
+ } else if (type & PURPLE_MEDIA_ELEMENT_VIDEO) { return manager->priv->video_sink;
- else if (type & PURPLE_MEDIA_ELEMENT_APPLICATION)
+ } else if (type & PURPLE_MEDIA_ELEMENT_APPLICATION) { return get_recv_application_element_info ();
@@ -1373,8 +1390,9 @@
GstElement *tee = purple_media_get_tee(media,
session_id, participant);
queue = gst_element_factory_make("queue", NULL);
convert = gst_element_factory_make("videoconvert", NULL);
@@ -1388,14 +1406,14 @@
/* aka this is a preview sink */
G_OBJECT_GET_CLASS(ow->sink);
- if (g_object_class_find_property(klass,
+ if (g_object_class_find_property(klass, "sync")) { g_object_set(G_OBJECT(ow->sink),
- if (g_object_class_find_property(klass,
+ if (g_object_class_find_property(klass, "async")) { g_object_set(G_OBJECT(ow->sink),
gst_bin_add_many(GST_BIN(GST_ELEMENT_PARENT(tee)),
@@ -1437,9 +1455,10 @@
manager->priv->output_windows = g_list_prepend(
manager->priv->output_windows, output_window);
- if (purple_media_get_tee(media, session_id, participant) != NULL)
+ if (purple_media_get_tee(media, session_id, participant) != NULL) { purple_media_manager_create_output_window(manager,
media, session_id, participant);
return output_window->id;
@@ -1468,8 +1487,9 @@
- if (output_window == NULL)
+ if (output_window == NULL) { if (output_window->sink != NULL) {
GstElement *element = output_window->sink;
@@ -1547,11 +1567,13 @@
PurpleMediaOutputWindow *ow = iter->data;
iter = g_list_next(iter);
- if (media == ow->media &&
- purple_strequal(session_id, ow->session_id) &&
- purple_strequal(participant, ow->participant))
- purple_media_manager_remove_output_window(
+ if (media == ow->media && + purple_strequal(session_id, ow->session_id) && + purple_strequal(participant, ow->participant)) + purple_media_manager_remove_output_window( @@ -1568,10 +1590,11 @@
oldcaps = manager->priv->ui_caps;
manager->priv->ui_caps = caps;
purple_media_manager_signals[UI_CAPS_CHANGED],
@@ -1621,8 +1644,9 @@
PurpleMediaAppDataInfo * info = ensure_app_data_info_and_lock (manager,
media, session_id, participant);
info->notify (info->user_data);
if (info->readable_cb_token) {
g_source_remove (info->readable_timer_id);
@@ -1644,8 +1668,9 @@
call_appsrc_writable_locked (info);
- if (info->num_samples > 0 || info->current_sample != NULL)
+ if (info->num_samples > 0 || info->current_sample != NULL) { call_appsink_readable_locked (info);
g_mutex_unlock (&manager->priv->appdata_mutex);
@@ -1711,8 +1736,9 @@
if (!info->current_sample && info->appsink && info->num_samples > 0) {
info->current_sample = gst_app_sink_pull_sample (info->appsink);
- if (info->current_sample)
+ if (info->current_sample) { if (info->current_sample) {
@@ -1726,9 +1752,8 @@
gst_buffer_map (gstbuffer, &mapinfo, GST_MAP_READ);
/* We must copy only the data remaining in the buffer without
* overflowing the buffer */
- bytes_to_copy = max_size - bytes_read;
- if (bytes_to_copy > mapinfo.size - info->sample_offset)
- bytes_to_copy = mapinfo.size - info->sample_offset;
+ bytes_to_copy = MIN(max_size - bytes_read, + mapinfo.size - info->sample_offset); memcpy ((guint8 *)buffer + bytes_read,
mapinfo.data + info->sample_offset, bytes_to_copy);
@@ -1766,8 +1791,7 @@
- } while (bytes_read < max_size &&
- (blocking || info->num_samples > 0));
+ } while (bytes_read < max_size && (blocking || info->num_samples > 0)); g_mutex_unlock (&manager->priv->appdata_mutex);
@@ -2351,8 +2375,7 @@
priv->create = g_value_get_pointer(value);
- G_OBJECT_WARN_INVALID_PROPERTY_ID(
- object, prop_id, pspec);
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -2381,8 +2404,7 @@
g_value_set_pointer(value, priv->create);
- G_OBJECT_WARN_INVALID_PROPERTY_ID(
- object, prop_id, pspec);
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); @@ -2466,8 +2488,9 @@
PurpleMediaElementCreateCallback create;
g_return_val_if_fail(PURPLE_IS_MEDIA_ELEMENT_INFO(info), NULL);
g_object_get(info, "create-cb", &create, NULL);
return create(info, media, session_id, participant);