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