comparison pidgin/gtkmedia.c @ 25686:3bf9748fdef0

Preliminary video embedded in the conversation window. It's still kind of buggy.
author Mike Ruprecht <maiku@soc.pidgin.im>
date Tue, 10 Jun 2008 05:18:29 +0000
parents 54adcf17d271
children ddbea813862e
comparison
equal deleted inserted replaced
25685:c2231cf3be71 25686:3bf9748fdef0
26 #include <string.h> 26 #include <string.h>
27 #include "debug.h" 27 #include "debug.h"
28 #include "internal.h" 28 #include "internal.h"
29 #include "connection.h" 29 #include "connection.h"
30 #include "media.h" 30 #include "media.h"
31 #include "pidgin.h"
31 32
32 #include "gtkmedia.h" 33 #include "gtkmedia.h"
33 34
34 #ifdef USE_VV 35 #ifdef USE_VV
36
37 #include <gst/interfaces/xoverlay.h>
35 38
36 typedef enum 39 typedef enum
37 { 40 {
38 /* Waiting for response */ 41 /* Waiting for response */
39 PIDGIN_MEDIA_WAITING = 1, 42 PIDGIN_MEDIA_WAITING = 1,
58 61
59 GtkWidget *send_progress; 62 GtkWidget *send_progress;
60 GtkWidget *recv_progress; 63 GtkWidget *recv_progress;
61 64
62 PidginMediaState state; 65 PidginMediaState state;
66
67 GtkWidget *display;
68 GtkWidget *local_video;
69 GtkWidget *remote_video;
63 }; 70 };
64 71
65 #define PIDGIN_MEDIA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PIDGIN_TYPE_MEDIA, PidginMediaPrivate)) 72 #define PIDGIN_MEDIA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), PIDGIN_TYPE_MEDIA, PidginMediaPrivate))
66 73
67 static void pidgin_media_class_init (PidginMediaClass *klass); 74 static void pidgin_media_class_init (PidginMediaClass *klass);
176 gtk_widget_show(media->priv->send_progress); 183 gtk_widget_show(media->priv->send_progress);
177 gtk_widget_show(media->priv->recv_progress); 184 gtk_widget_show(media->priv->recv_progress);
178 185
179 gtk_widget_show_all(media->priv->accept); 186 gtk_widget_show_all(media->priv->accept);
180 gtk_widget_show_all(media->priv->reject); 187 gtk_widget_show_all(media->priv->reject);
188
189 media->priv->display = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
181 } 190 }
182 191
183 static gboolean 192 static gboolean
184 level_message_cb(GstBus *bus, GstMessage *message, PidginMedia *gtkmedia) 193 level_message_cb(GstBus *bus, GstMessage *message, PidginMedia *gtkmedia)
185 { 194 {
244 } 253 }
245 if (gtkmedia->priv->send_level) 254 if (gtkmedia->priv->send_level)
246 gst_object_unref(gtkmedia->priv->send_level); 255 gst_object_unref(gtkmedia->priv->send_level);
247 if (gtkmedia->priv->recv_level) 256 if (gtkmedia->priv->recv_level)
248 gst_object_unref(gtkmedia->priv->recv_level); 257 gst_object_unref(gtkmedia->priv->recv_level);
258 if (gtkmedia->priv->display)
259 gtk_widget_destroy(gtkmedia->priv->display);
249 } 260 }
250 261
251 static void 262 static void
252 pidgin_media_emit_message(PidginMedia *gtkmedia, const char *msg) 263 pidgin_media_emit_message(PidginMedia *gtkmedia, const char *msg)
253 { 264 {
254 g_signal_emit(gtkmedia, pidgin_media_signals[MESSAGE], 0, msg); 265 g_signal_emit(gtkmedia, pidgin_media_signals[MESSAGE], 0, msg);
266 }
267
268 GtkWidget *
269 pidgin_media_get_display_widget(GtkWidget *gtkmedia)
270 {
271 return PIDGIN_MEDIA_GET_PRIVATE(gtkmedia)->display;
255 } 272 }
256 273
257 static gboolean 274 static gboolean
258 media_bus_call(GstBus *bus, GstMessage *msg, gpointer gtkmedia) 275 media_bus_call(GstBus *bus, GstMessage *msg, gpointer gtkmedia)
259 { 276 {
282 } 299 }
283 300
284 return TRUE; 301 return TRUE;
285 } 302 }
286 303
304 static gboolean
305 create_window (GstBus *bus, GstMessage *message, PidginMedia *gtkmedia)
306 {
307 char *name;
308
309 if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_ELEMENT)
310 return TRUE;
311
312 if (!gst_structure_has_name(message->structure, "prepare-xwindow-id"))
313 return TRUE;
314
315 name = gst_object_get_name(GST_MESSAGE_SRC (message));
316 purple_debug_info("gtkmedia", "prepare-xwindow-id object name: %s\n", name);
317
318 /* The XOverlay's name is the sink's name with a suffix */
319 if (!strncmp(name, "purplevideosink", strlen("purplevideosink")))
320 gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(message)),
321 GDK_WINDOW_XWINDOW(gtkmedia->priv->remote_video->window));
322 else if (!strncmp(name, "purplelocalvideosink", strlen("purplelocalvideosink")))
323 gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(GST_MESSAGE_SRC(message)),
324 GDK_WINDOW_XWINDOW(gtkmedia->priv->local_video->window));
325 g_free(name);
326 return TRUE;
327 }
328
287 static void 329 static void
288 pidgin_media_ready_cb(PurpleMedia *media, PidginMedia *gtkmedia) 330 pidgin_media_ready_cb(PurpleMedia *media, PidginMedia *gtkmedia)
289 { 331 {
290 GstElement *element = purple_media_get_pipeline(media); 332 GstElement *element = purple_media_get_pipeline(media);
291 333
292 GstElement *audiosendbin, *audiosendlevel; 334 GstElement *audiosendbin = NULL, *audiosendlevel = NULL;
293 GstElement *audiorecvbin, *audiorecvlevel; 335 GstElement *audiorecvbin = NULL, *audiorecvlevel = NULL;
294 GstElement *videosendbin; 336 GstElement *videosendbin = NULL;
295 GstElement *videorecvbin; 337 GstElement *videorecvbin = NULL;
296 338
297 GList *sessions = purple_media_get_session_names(media); 339 GList *sessions = purple_media_get_session_names(media);
298 GstBus *bus; 340 GstBus *bus;
299 341
300 purple_media_audio_init_src(&audiosendbin, &audiosendlevel);
301 purple_media_audio_init_recv(&audiorecvbin, &audiorecvlevel);
302
303 purple_media_video_init_src(&videosendbin);
304 purple_media_video_init_recv(&videorecvbin);
305
306 for (; sessions; sessions = sessions->next) { 342 for (; sessions; sessions = sessions->next) {
307 if (purple_media_get_session_type(media, sessions->data) & PURPLE_MEDIA_AUDIO) { 343 if (purple_media_get_session_type(media, sessions->data) & PURPLE_MEDIA_AUDIO) {
344 if (!audiosendbin)
345 purple_media_audio_init_src(&audiosendbin, &audiosendlevel);
346 if (!audiorecvbin)
347 purple_media_audio_init_recv(&audiorecvbin, &audiorecvlevel);
308 purple_media_set_src(media, sessions->data, audiosendbin); 348 purple_media_set_src(media, sessions->data, audiosendbin);
309 purple_media_set_sink(media, sessions->data, audiorecvbin); 349 purple_media_set_sink(media, sessions->data, audiorecvbin);
310 } else if (purple_media_get_session_type(media, sessions->data) & PURPLE_MEDIA_VIDEO) { 350 } else if (purple_media_get_session_type(media, sessions->data) & PURPLE_MEDIA_VIDEO) {
351 if (!videosendbin)
352 purple_media_video_init_src(&videosendbin);
353 if (!videorecvbin)
354 purple_media_video_init_recv(&videorecvbin);
311 purple_media_set_src(media, sessions->data, videosendbin); 355 purple_media_set_src(media, sessions->data, videosendbin);
312 purple_media_set_sink(media, sessions->data, videorecvbin); 356 purple_media_set_sink(media, sessions->data, videorecvbin);
313 } 357 }
314 } 358 }
315 g_list_free(sessions); 359 g_list_free(sessions);
318 g_object_set(gtkmedia, "send-level", audiosendlevel, 362 g_object_set(gtkmedia, "send-level", audiosendlevel,
319 "recv-level", audiorecvlevel, 363 "recv-level", audiorecvlevel,
320 NULL); 364 NULL);
321 } 365 }
322 366
367 if (videorecvbin || videosendbin) {
368 GtkWidget *aspect;
369 GtkWidget *remote_video;
370 GtkWidget *local_video;
371
372 gtk_widget_show(gtkmedia->priv->display);
373
374 aspect = gtk_aspect_frame_new(NULL, 0.5, 0.5, 4.0/3.0, FALSE);
375 gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_IN);
376 gtk_box_pack_start(GTK_BOX(gtkmedia->priv->display), aspect, TRUE, TRUE, 0);
377
378 remote_video = gtk_drawing_area_new();
379 gtk_container_add(GTK_CONTAINER(aspect), remote_video);
380 gtk_widget_set_size_request (GTK_WIDGET(remote_video), 100, -1);
381 gtk_widget_show(remote_video);
382 gtk_widget_show(aspect);
383
384 aspect = gtk_aspect_frame_new(NULL, 0.5, 0.5, 4.0/3.0, FALSE);
385 gtk_frame_set_shadow_type(GTK_FRAME(aspect), GTK_SHADOW_IN);
386 gtk_box_pack_start(GTK_BOX(gtkmedia->priv->display), aspect, TRUE, TRUE, 0);
387
388 local_video = gtk_drawing_area_new();
389 gtk_container_add(GTK_CONTAINER(aspect), local_video);
390 gtk_widget_show(local_video);
391 gtk_widget_show(aspect);
392
393 gtkmedia->priv->local_video = local_video;
394 gtkmedia->priv->remote_video = remote_video;
395 }
396
323 bus = gst_pipeline_get_bus(GST_PIPELINE(element)); 397 bus = gst_pipeline_get_bus(GST_PIPELINE(element));
324 gst_bus_add_signal_watch(GST_BUS(bus)); 398 gst_bus_add_signal_watch(GST_BUS(bus));
325 g_signal_connect(G_OBJECT(gst_pipeline_get_bus(GST_PIPELINE(element))), "message", G_CALLBACK(level_message_cb), gtkmedia); 399 g_signal_connect(G_OBJECT(gst_pipeline_get_bus(GST_PIPELINE(element))),
400 "message", G_CALLBACK(level_message_cb), gtkmedia);
401 if (videorecvbin || videosendbin)
402 gst_bus_set_sync_handler(bus, (GstBusSyncHandler)create_window, gtkmedia);
326 gst_bus_add_watch(bus, media_bus_call, gtkmedia); 403 gst_bus_add_watch(bus, media_bus_call, gtkmedia);
327 gst_object_unref(bus); 404 gst_object_unref(bus);
328 } 405 }
329 406
330 static void 407 static void