Mercurial > pidgin.yaz
comparison libpurple/media.c @ 28191:c8ff0a9cf8cc
Unlink the local audio volume and mute between sessions.
author | Mike Ruprecht <maiku@soc.pidgin.im> |
---|---|
date | Fri, 07 Aug 2009 08:23:12 +0000 |
parents | 584fa66dfb31 |
children | c1687897825f |
comparison
equal
deleted
inserted
replaced
28190:9824572dbb49 | 28191:c8ff0a9cf8cc |
---|---|
92 PurpleMediaSession *session; | 92 PurpleMediaSession *session; |
93 gchar *participant; | 93 gchar *participant; |
94 FsStream *stream; | 94 FsStream *stream; |
95 GstElement *src; | 95 GstElement *src; |
96 GstElement *tee; | 96 GstElement *tee; |
97 GstElement *volume; | |
98 GstElement *level; | |
97 | 99 |
98 GList *local_candidates; | 100 GList *local_candidates; |
99 GList *remote_candidates; | 101 GList *remote_candidates; |
100 | 102 |
101 gboolean initiator; | 103 gboolean initiator; |
157 | 159 |
158 enum { | 160 enum { |
159 S_ERROR, | 161 S_ERROR, |
160 CANDIDATES_PREPARED, | 162 CANDIDATES_PREPARED, |
161 CODECS_CHANGED, | 163 CODECS_CHANGED, |
164 LEVEL, | |
162 NEW_CANDIDATE, | 165 NEW_CANDIDATE, |
163 STATE_CHANGED, | 166 STATE_CHANGED, |
164 STREAM_INFO, | 167 STREAM_INFO, |
165 LAST_SIGNAL | 168 LAST_SIGNAL |
166 }; | 169 }; |
338 G_TYPE_STRING); | 341 G_TYPE_STRING); |
339 purple_media_signals[CODECS_CHANGED] = g_signal_new("codecs-changed", G_TYPE_FROM_CLASS(klass), | 342 purple_media_signals[CODECS_CHANGED] = g_signal_new("codecs-changed", G_TYPE_FROM_CLASS(klass), |
340 G_SIGNAL_RUN_LAST, 0, NULL, NULL, | 343 G_SIGNAL_RUN_LAST, 0, NULL, NULL, |
341 g_cclosure_marshal_VOID__STRING, | 344 g_cclosure_marshal_VOID__STRING, |
342 G_TYPE_NONE, 1, G_TYPE_STRING); | 345 G_TYPE_NONE, 1, G_TYPE_STRING); |
346 purple_media_signals[LEVEL] = g_signal_new("level", G_TYPE_FROM_CLASS(klass), | |
347 G_SIGNAL_RUN_LAST, 0, NULL, NULL, | |
348 purple_smarshal_VOID__STRING_STRING_DOUBLE, | |
349 G_TYPE_NONE, 3, G_TYPE_STRING, | |
350 G_TYPE_STRING, G_TYPE_DOUBLE); | |
343 purple_media_signals[NEW_CANDIDATE] = g_signal_new("new-candidate", G_TYPE_FROM_CLASS(klass), | 351 purple_media_signals[NEW_CANDIDATE] = g_signal_new("new-candidate", G_TYPE_FROM_CLASS(klass), |
344 G_SIGNAL_RUN_LAST, 0, NULL, NULL, | 352 G_SIGNAL_RUN_LAST, 0, NULL, NULL, |
345 purple_smarshal_VOID__POINTER_POINTER_OBJECT, | 353 purple_smarshal_VOID__POINTER_POINTER_OBJECT, |
346 G_TYPE_NONE, 3, G_TYPE_POINTER, | 354 G_TYPE_NONE, 3, G_TYPE_POINTER, |
347 G_TYPE_POINTER, PURPLE_TYPE_MEDIA_CANDIDATE); | 355 G_TYPE_POINTER, PURPLE_TYPE_MEDIA_CANDIDATE); |
1896 | 1904 |
1897 gst_element_link(session->src, session->media->priv->confbin); | 1905 gst_element_link(session->src, session->media->priv->confbin); |
1898 gst_element_set_state(session->tee, GST_STATE_PLAYING); | 1906 gst_element_set_state(session->tee, GST_STATE_PLAYING); |
1899 | 1907 |
1900 g_object_get(session->session, "sink-pad", &sinkpad, NULL); | 1908 g_object_get(session->session, "sink-pad", &sinkpad, NULL); |
1901 srcpad = gst_element_get_request_pad(session->tee, "src%d"); | 1909 if (session->type & PURPLE_MEDIA_SEND_AUDIO) { |
1910 gchar *name = g_strdup_printf("volume_%s", session->id); | |
1911 GstElement *level; | |
1912 GstElement *volume = gst_element_factory_make("volume", name); | |
1913 double input_volume = purple_prefs_get_int( | |
1914 "/purple/media/audio/volume/input")/10.0; | |
1915 g_free(name); | |
1916 name = g_strdup_printf("sendlevel_%s", session->id); | |
1917 level = gst_element_factory_make("level", name); | |
1918 g_free(name); | |
1919 gst_bin_add(GST_BIN(session->media->priv->confbin), volume); | |
1920 gst_bin_add(GST_BIN(session->media->priv->confbin), level); | |
1921 gst_element_link(session->tee, volume); | |
1922 gst_element_link(volume, level); | |
1923 gst_element_set_state(level, GST_STATE_PLAYING); | |
1924 gst_element_set_state(volume, GST_STATE_PLAYING); | |
1925 srcpad = gst_element_get_static_pad(level, "src"); | |
1926 g_object_set(volume, "volume", input_volume, NULL); | |
1927 } else { | |
1928 srcpad = gst_element_get_request_pad(session->tee, "src%d"); | |
1929 } | |
1902 purple_debug_info("media", "connecting pad: %s\n", | 1930 purple_debug_info("media", "connecting pad: %s\n", |
1903 gst_pad_link(srcpad, sinkpad) == GST_PAD_LINK_OK | 1931 gst_pad_link(srcpad, sinkpad) == GST_PAD_LINK_OK |
1904 ? "success" : "failure"); | 1932 ? "success" : "failure"); |
1905 gst_element_set_locked_state(session->src, FALSE); | 1933 gst_element_set_locked_state(session->src, FALSE); |
1906 gst_object_unref(session->src); | 1934 gst_object_unref(session->src); |
1953 static gboolean | 1981 static gboolean |
1954 media_bus_call(GstBus *bus, GstMessage *msg, PurpleMedia *media) | 1982 media_bus_call(GstBus *bus, GstMessage *msg, PurpleMedia *media) |
1955 { | 1983 { |
1956 switch(GST_MESSAGE_TYPE(msg)) { | 1984 switch(GST_MESSAGE_TYPE(msg)) { |
1957 case GST_MESSAGE_ELEMENT: { | 1985 case GST_MESSAGE_ELEMENT: { |
1986 if (g_signal_has_handler_pending(media, | |
1987 purple_media_signals[LEVEL], 0, FALSE) | |
1988 && gst_structure_has_name( | |
1989 gst_message_get_structure(msg), "level")) { | |
1990 GstElement *src = GST_ELEMENT(GST_MESSAGE_SRC(msg)); | |
1991 gchar *name; | |
1992 gchar *participant = NULL; | |
1993 PurpleMediaSession *session = NULL; | |
1994 gdouble rms_db; | |
1995 gdouble percent; | |
1996 const GValue *list; | |
1997 const GValue *value; | |
1998 | |
1999 if (!PURPLE_IS_MEDIA(media) || | |
2000 GST_ELEMENT_PARENT(src) != | |
2001 media->priv->confbin) | |
2002 break; | |
2003 | |
2004 name = gst_element_get_name(src); | |
2005 if (!strncmp(name, "sendlevel_", 10)) { | |
2006 session = purple_media_get_session( | |
2007 media, name+10); | |
2008 } else { | |
2009 GList *iter = media->priv->streams; | |
2010 for (; iter; iter = g_list_next(iter)) { | |
2011 PurpleMediaStream *stream = iter->data; | |
2012 if (stream->level == src) { | |
2013 session = stream->session; | |
2014 participant = stream->participant; | |
2015 break; | |
2016 } | |
2017 } | |
2018 } | |
2019 g_free(name); | |
2020 if (!session) | |
2021 break; | |
2022 | |
2023 list = gst_structure_get_value( | |
2024 gst_message_get_structure(msg), "rms"); | |
2025 value = gst_value_list_get_value(list, 0); | |
2026 rms_db = g_value_get_double(value); | |
2027 percent = pow(10, rms_db / 20) * 5; | |
2028 if(percent > 1.0) | |
2029 percent = 1.0; | |
2030 | |
2031 g_signal_emit(media, purple_media_signals[LEVEL], | |
2032 0, session->id, participant, percent); | |
2033 break; | |
2034 } | |
1958 if (!FS_IS_CONFERENCE(GST_MESSAGE_SRC(msg)) || | 2035 if (!FS_IS_CONFERENCE(GST_MESSAGE_SRC(msg)) || |
1959 !PURPLE_IS_MEDIA(media) || | 2036 !PURPLE_IS_MEDIA(media) || |
1960 media->priv->conference != | 2037 media->priv->conference != |
1961 FS_CONFERENCE(GST_MESSAGE_SRC(msg))) | 2038 FS_CONFERENCE(GST_MESSAGE_SRC(msg))) |
1962 break; | 2039 break; |
2170 | 2247 |
2171 for (; sessions; sessions = g_list_delete_link( | 2248 for (; sessions; sessions = g_list_delete_link( |
2172 sessions, sessions)) { | 2249 sessions, sessions)) { |
2173 PurpleMediaSession *session = sessions->data; | 2250 PurpleMediaSession *session = sessions->data; |
2174 if (session->type & PURPLE_MEDIA_SEND_AUDIO) { | 2251 if (session->type & PURPLE_MEDIA_SEND_AUDIO) { |
2252 gchar *name = g_strdup_printf("volume_%s", | |
2253 session->id); | |
2175 GstElement *volume = gst_bin_get_by_name( | 2254 GstElement *volume = gst_bin_get_by_name( |
2176 GST_BIN(session->src), | 2255 GST_BIN(session->media-> |
2177 "purpleaudioinputvolume"); | 2256 priv->confbin), name); |
2257 g_free(name); | |
2178 g_object_set(volume, "mute", active, NULL); | 2258 g_object_set(volume, "mute", active, NULL); |
2179 } | 2259 } |
2180 } | 2260 } |
2181 } | 2261 } |
2182 | 2262 |
2336 | 2416 |
2337 if (stream->src == NULL) { | 2417 if (stream->src == NULL) { |
2338 GstElement *sink = NULL; | 2418 GstElement *sink = NULL; |
2339 | 2419 |
2340 if (codec->media_type == FS_MEDIA_TYPE_AUDIO) { | 2420 if (codec->media_type == FS_MEDIA_TYPE_AUDIO) { |
2421 GstElement *queue = NULL; | |
2422 double output_volume = purple_prefs_get_int( | |
2423 "/purple/media/audio/volume/output")/10.0; | |
2341 /* | 2424 /* |
2342 * Should this instead be: | 2425 * Should this instead be: |
2343 * audioconvert ! audioresample ! liveadder ! | 2426 * audioconvert ! audioresample ! liveadder ! |
2344 * audioresample ! audioconvert ! realsink | 2427 * audioresample ! audioconvert ! realsink |
2345 */ | 2428 */ |
2429 queue = gst_element_factory_make("queue", NULL); | |
2430 stream->volume = gst_element_factory_make( | |
2431 "volume", NULL); | |
2432 g_object_set(stream->volume, "volume", | |
2433 output_volume, NULL); | |
2434 stream->level = gst_element_factory_make( | |
2435 "level", NULL); | |
2346 stream->src = gst_element_factory_make( | 2436 stream->src = gst_element_factory_make( |
2347 "liveadder", NULL); | 2437 "liveadder", NULL); |
2348 sink = purple_media_manager_get_element(priv->manager, | 2438 sink = purple_media_manager_get_element(priv->manager, |
2349 PURPLE_MEDIA_RECV_AUDIO, | 2439 PURPLE_MEDIA_RECV_AUDIO, |
2350 stream->session->media, | 2440 stream->session->media, |
2351 stream->session->id, | 2441 stream->session->id, |
2352 stream->participant); | 2442 stream->participant); |
2443 gst_bin_add(GST_BIN(priv->confbin), queue); | |
2444 gst_bin_add(GST_BIN(priv->confbin), stream->volume); | |
2445 gst_bin_add(GST_BIN(priv->confbin), stream->level); | |
2446 gst_bin_add(GST_BIN(priv->confbin), sink); | |
2447 gst_element_link(stream->level, sink); | |
2448 gst_element_link(stream->volume, stream->level); | |
2449 gst_element_link(queue, stream->volume); | |
2450 gst_element_sync_state_with_parent(sink); | |
2451 gst_element_sync_state_with_parent(stream->level); | |
2452 gst_element_sync_state_with_parent(stream->volume); | |
2453 sink = queue; | |
2353 } else if (codec->media_type == FS_MEDIA_TYPE_VIDEO) { | 2454 } else if (codec->media_type == FS_MEDIA_TYPE_VIDEO) { |
2354 stream->src = gst_element_factory_make( | 2455 stream->src = gst_element_factory_make( |
2355 "fsfunnel", NULL); | 2456 "fsfunnel", NULL); |
2356 sink = gst_element_factory_make( | 2457 sink = gst_element_factory_make( |
2357 "fakesink", NULL); | 2458 "fakesink", NULL); |
2358 g_object_set(G_OBJECT(sink), "async", FALSE, NULL); | 2459 g_object_set(G_OBJECT(sink), "async", FALSE, NULL); |
2460 gst_bin_add(GST_BIN(priv->confbin), sink); | |
2359 } | 2461 } |
2360 stream->tee = gst_element_factory_make("tee", NULL); | 2462 stream->tee = gst_element_factory_make("tee", NULL); |
2361 gst_bin_add_many(GST_BIN(priv->confbin), | 2463 gst_bin_add_many(GST_BIN(priv->confbin), |
2362 stream->src, stream->tee, sink, NULL); | 2464 stream->src, stream->tee, NULL); |
2363 gst_element_sync_state_with_parent(sink); | 2465 gst_element_sync_state_with_parent(sink); |
2364 gst_element_sync_state_with_parent(stream->tee); | 2466 gst_element_sync_state_with_parent(stream->tee); |
2365 gst_element_sync_state_with_parent(stream->src); | 2467 gst_element_sync_state_with_parent(stream->src); |
2366 gst_element_link_many(stream->src, stream->tee, sink, NULL); | 2468 gst_element_link_many(stream->src, stream->tee, sink, NULL); |
2367 } | 2469 } |
2973 #ifdef USE_VV | 3075 #ifdef USE_VV |
2974 GList *sessions; | 3076 GList *sessions; |
2975 | 3077 |
2976 g_return_if_fail(PURPLE_IS_MEDIA(media)); | 3078 g_return_if_fail(PURPLE_IS_MEDIA(media)); |
2977 | 3079 |
3080 purple_prefs_set_int("/purple/media/audio/volume/input", level); | |
3081 | |
2978 if (session_id == NULL) | 3082 if (session_id == NULL) |
2979 sessions = g_hash_table_get_values(media->priv->sessions); | 3083 sessions = g_hash_table_get_values(media->priv->sessions); |
2980 else | 3084 else |
2981 sessions = g_list_append(NULL, | 3085 sessions = g_list_append(NULL, |
2982 purple_media_get_session(media, session_id)); | 3086 purple_media_get_session(media, session_id)); |
2983 | 3087 |
2984 for (; sessions; sessions = g_list_delete_link(sessions, sessions)) { | 3088 for (; sessions; sessions = g_list_delete_link(sessions, sessions)) { |
2985 PurpleMediaSession *session = sessions->data; | 3089 PurpleMediaSession *session = sessions->data; |
2986 | 3090 |
2987 if (session->type & PURPLE_MEDIA_SEND_AUDIO) { | 3091 if (session->type & PURPLE_MEDIA_SEND_AUDIO) { |
3092 gchar *name = g_strdup_printf("volume_%s", | |
3093 session->id); | |
2988 GstElement *volume = gst_bin_get_by_name( | 3094 GstElement *volume = gst_bin_get_by_name( |
2989 GST_BIN(session->src), | 3095 GST_BIN(session->media->priv->confbin), |
2990 "purpleaudioinputvolume"); | 3096 name); |
2991 g_object_set(volume, "volume", level, NULL); | 3097 g_free(name); |
3098 g_object_set(volume, "volume", level/10.0, NULL); | |
2992 } | 3099 } |
2993 } | 3100 } |
2994 #endif | 3101 #endif |
2995 } | 3102 } |
2996 | 3103 |
3001 #ifdef USE_VV | 3108 #ifdef USE_VV |
3002 GList *streams; | 3109 GList *streams; |
3003 | 3110 |
3004 g_return_if_fail(PURPLE_IS_MEDIA(media)); | 3111 g_return_if_fail(PURPLE_IS_MEDIA(media)); |
3005 | 3112 |
3113 purple_prefs_set_int("/purple/media/audio/volume/output", level); | |
3114 | |
3006 streams = purple_media_get_streams(media, | 3115 streams = purple_media_get_streams(media, |
3007 session_id, participant); | 3116 session_id, participant); |
3008 | 3117 |
3009 for (; streams; streams = g_list_delete_link(streams, streams)) { | 3118 for (; streams; streams = g_list_delete_link(streams, streams)) { |
3010 PurpleMediaStream *stream = streams->data; | 3119 PurpleMediaStream *stream = streams->data; |
3011 | 3120 |
3012 if (stream->session->type & PURPLE_MEDIA_RECV_AUDIO) { | 3121 if (stream->session->type & PURPLE_MEDIA_RECV_AUDIO |
3013 GstElement *tee = stream->tee; | 3122 && GST_IS_ELEMENT(stream->volume)) { |
3014 GstIterator *iter = gst_element_iterate_src_pads(tee); | 3123 g_object_set(stream->volume, "volume", level/10.0, NULL); |
3015 GstPad *sinkpad; | |
3016 while (gst_iterator_next(iter, (gpointer)&sinkpad) | |
3017 == GST_ITERATOR_OK) { | |
3018 GstPad *peer = gst_pad_get_peer(sinkpad); | |
3019 GstElement *volume; | |
3020 | |
3021 if (peer == NULL) { | |
3022 gst_object_unref(sinkpad); | |
3023 continue; | |
3024 } | |
3025 | |
3026 volume = gst_bin_get_by_name(GST_BIN( | |
3027 GST_OBJECT_PARENT(peer)), | |
3028 "purpleaudiooutputvolume"); | |
3029 g_object_set(volume, "volume", level, NULL); | |
3030 gst_object_unref(peer); | |
3031 gst_object_unref(sinkpad); | |
3032 } | |
3033 gst_iterator_free(iter); | |
3034 } | 3124 } |
3035 } | 3125 } |
3036 #endif | 3126 #endif |
3037 } | 3127 } |
3038 | 3128 |