pidgin/gtkmedia.c

branch
cpw.qulogic.gtk3
changeset 32433
f539a2c083b2
parent 32424
be4a642b2d45
parent 31966
82265c009a63
child 32438
dc8991868906
child 33120
f6f1a27ade72
equal deleted inserted replaced
32432:47b61b9e08e6 32433:f539a2c083b2
91 GtkWidget *hold; 91 GtkWidget *hold;
92 GtkWidget *mute; 92 GtkWidget *mute;
93 GtkWidget *pause; 93 GtkWidget *pause;
94 94
95 GtkWidget *send_progress; 95 GtkWidget *send_progress;
96 GtkWidget *recv_progress; 96 GHashTable *recv_progressbars;
97 97
98 PidginMediaState state; 98 PidginMediaState state;
99 99
100 GtkWidget *display; 100 GtkWidget *display;
101 GtkWidget *send_widget; 101 GtkWidget *send_widget;
102 GtkWidget *recv_widget; 102 GtkWidget *recv_widget;
103 GtkWidget *button_widget; 103 GtkWidget *button_widget;
104 GtkWidget *local_video; 104 GtkWidget *local_video;
105 GtkWidget *remote_video; 105 GHashTable *remote_videos;
106 106
107 guint timeout_id; 107 guint timeout_id;
108 PurpleMediaSessionType request_type; 108 PurpleMediaSessionType request_type;
109 }; 109 };
110 110
350 TRUE, TRUE, PIDGIN_HIG_BOX_SPACE); 350 TRUE, TRUE, PIDGIN_HIG_BOX_SPACE);
351 gtk_widget_show(vbox); 351 gtk_widget_show(vbox);
352 352
353 g_signal_connect(G_OBJECT(media), "delete-event", 353 g_signal_connect(G_OBJECT(media), "delete-event",
354 G_CALLBACK(pidgin_media_delete_event_cb), media); 354 G_CALLBACK(pidgin_media_delete_event_cb), media);
355
356 media->priv->recv_progressbars =
357 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
358 media->priv->remote_videos =
359 g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
360 }
361
362 static gchar *
363 create_key(const gchar *session_id, const gchar *participant)
364 {
365 return g_strdup_printf("%s_%s", session_id, participant);
366 }
367
368 static void
369 pidgin_media_insert_widget(PidginMedia *gtkmedia, GtkWidget *widget,
370 const gchar *session_id, const gchar *participant)
371 {
372 gchar *key = create_key(session_id, participant);
373 PurpleMediaSessionType type =
374 purple_media_get_session_type(gtkmedia->priv->media, session_id);
375
376 if (type & PURPLE_MEDIA_AUDIO)
377 g_hash_table_insert(gtkmedia->priv->recv_progressbars, key, widget);
378 else if (type & PURPLE_MEDIA_VIDEO)
379 g_hash_table_insert(gtkmedia->priv->remote_videos, key, widget);
380 }
381
382 static GtkWidget *
383 pidgin_media_get_widget(PidginMedia *gtkmedia,
384 const gchar *session_id, const gchar *participant)
385 {
386 GtkWidget *widget = NULL;
387 gchar *key = create_key(session_id, participant);
388 PurpleMediaSessionType type =
389 purple_media_get_session_type(gtkmedia->priv->media, session_id);
390
391 if (type & PURPLE_MEDIA_AUDIO)
392 widget = g_hash_table_lookup(gtkmedia->priv->recv_progressbars, key);
393 else if (type & PURPLE_MEDIA_VIDEO)
394 widget = g_hash_table_lookup(gtkmedia->priv->remote_videos, key);
395
396 g_free(key);
397 return widget;
398 }
399
400 static void
401 pidgin_media_remove_widget(PidginMedia *gtkmedia,
402 const gchar *session_id, const gchar *participant)
403 {
404 GtkWidget *widget = pidgin_media_get_widget(gtkmedia, session_id, participant);
405
406 if (widget) {
407 PurpleMediaSessionType type =
408 purple_media_get_session_type(gtkmedia->priv->media, session_id);
409 gchar *key = create_key(session_id, participant);
410 GtkRequisition req;
411
412 if (type & PURPLE_MEDIA_AUDIO) {
413 g_hash_table_remove(gtkmedia->priv->recv_progressbars, key);
414
415 if (g_hash_table_size(gtkmedia->priv->recv_progressbars) == 0 &&
416 gtkmedia->priv->send_progress) {
417
418 gtk_widget_destroy(gtkmedia->priv->send_progress);
419 gtkmedia->priv->send_progress = NULL;
420
421 gtk_widget_destroy(gtkmedia->priv->mute);
422 gtkmedia->priv->mute = NULL;
423 }
424 } else if (type & PURPLE_MEDIA_VIDEO) {
425 g_hash_table_remove(gtkmedia->priv->remote_videos, key);
426
427 if (g_hash_table_size(gtkmedia->priv->remote_videos) == 0 &&
428 gtkmedia->priv->local_video) {
429
430 gtk_widget_destroy(gtkmedia->priv->local_video);
431 gtkmedia->priv->local_video = NULL;
432
433 gtk_widget_destroy(gtkmedia->priv->pause);
434 gtkmedia->priv->pause = NULL;
435 }
436 }
437
438 g_free(key);
439
440 gtk_widget_destroy(widget);
441
442 gtk_widget_size_request(GTK_WIDGET(gtkmedia), &req);
443 gtk_window_resize(GTK_WINDOW(gtkmedia), req.width, req.height);
444 }
355 } 445 }
356 446
357 static void 447 static void
358 level_message_cb(PurpleMedia *media, gchar *session_id, gchar *participant, 448 level_message_cb(PurpleMedia *media, gchar *session_id, gchar *participant,
359 double level, PidginMedia *gtkmedia) 449 double level, PidginMedia *gtkmedia)
360 { 450 {
361 GtkWidget *progress; 451 GtkWidget *progress = NULL;
362 if (participant == NULL) 452 if (participant == NULL)
363 progress = gtkmedia->priv->send_progress; 453 progress = gtkmedia->priv->send_progress;
364 else 454 else
365 progress = gtkmedia->priv->recv_progress; 455 progress = pidgin_media_get_widget(gtkmedia, session_id, participant);
366 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), level * 5); 456
457 if (progress)
458 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progress), level * 5);
367 } 459 }
368 460
369 461
370 static void 462 static void
371 pidgin_media_disconnect_levels(PurpleMedia *media, PidginMedia *gtkmedia) 463 pidgin_media_disconnect_levels(PurpleMedia *media, PidginMedia *gtkmedia)
400 } 492 }
401 493
402 if (gtkmedia->priv->timeout_id != 0) 494 if (gtkmedia->priv->timeout_id != 0)
403 g_source_remove(gtkmedia->priv->timeout_id); 495 g_source_remove(gtkmedia->priv->timeout_id);
404 496
497 if (gtkmedia->priv->recv_progressbars) {
498 g_hash_table_destroy(gtkmedia->priv->recv_progressbars);
499 g_hash_table_destroy(gtkmedia->priv->remote_videos);
500 gtkmedia->priv->recv_progressbars = NULL;
501 gtkmedia->priv->remote_videos = NULL;
502 }
503
405 G_OBJECT_CLASS(parent_class)->dispose(media); 504 G_OBJECT_CLASS(parent_class)->dispose(media);
406 } 505 }
407 506
408 static void 507 static void
409 pidgin_media_finalize(GObject *media) 508 pidgin_media_finalize(GObject *media)
434 533
435 static gboolean 534 static gboolean
436 realize_cb_cb(PidginMediaRealizeData *data) 535 realize_cb_cb(PidginMediaRealizeData *data)
437 { 536 {
438 PidginMediaPrivate *priv = data->gtkmedia->priv; 537 PidginMediaPrivate *priv = data->gtkmedia->priv;
439 gulong window_id; 538 GdkWindow *window = NULL;
440 539
540 if (data->participant == NULL)
541 #if GTK_CHECK_VERSION(2, 14, 0)
542 window = gtk_widget_get_window(priv->local_video);
543 #else
544 window = (priv->local_video)->window;
545 #endif
546 else {
547 GtkWidget *widget = pidgin_media_get_widget(data->gtkmedia,
548 data->session_id, data->participant);
549 if (widget)
550 #if GTK_CHECK_VERSION(2, 14, 0)
551 window = gtk_widget_get_window(widget);
552 #else
553 window = widget->window;
554 #endif
555 }
556
557 if (window) {
558 gulong window_id;
441 #ifdef _WIN32 559 #ifdef _WIN32
442 if (data->participant == NULL) 560 window_id = GDK_WINDOW_HWND(window);
443 window_id = GDK_WINDOW_HWND(priv->local_video->window);
444 else
445 window_id = GDK_WINDOW_HWND(priv->remote_video->window);
446 #elif defined(HAVE_X11) 561 #elif defined(HAVE_X11)
447 if (data->participant == NULL) 562 window_id = gdk_x11_window_get_xid(window);
448 window_id = gdk_x11_window_get_xid(gtk_widget_get_window(priv->local_video));
449 else
450 window_id = gdk_x11_window_get_xid(gtk_widget_get_window(priv->remote_video));
451 #else 563 #else
452 # error "Unsupported windowing system" 564 # error "Unsupported windowing system"
453 #endif 565 #endif
454 566
455 purple_media_set_output_window(priv->media, data->session_id, 567 purple_media_set_output_window(priv->media, data->session_id,
456 data->participant, window_id); 568 data->participant, window_id);
569 }
457 570
458 g_free(data->session_id); 571 g_free(data->session_id);
459 g_free(data->participant); 572 g_free(data->participant);
460 g_free(data); 573 g_free(data);
461 return FALSE; 574 return FALSE;
488 } 601 }
489 602
490 static void 603 static void
491 pidgin_media_reject_cb(PurpleMedia *media, int index) 604 pidgin_media_reject_cb(PurpleMedia *media, int index)
492 { 605 {
493 purple_media_stream_info(media, PURPLE_MEDIA_INFO_REJECT, 606 GList *iter = purple_media_get_session_ids(media);
494 NULL, NULL, TRUE); 607 for (; iter; iter = g_list_delete_link(iter, iter)) {
608 const gchar *sessionid = iter->data;
609 if (!purple_media_accepted(media, sessionid, NULL))
610 purple_media_stream_info(media, PURPLE_MEDIA_INFO_REJECT,
611 sessionid, NULL, TRUE);
612 }
495 } 613 }
496 614
497 static gboolean 615 static gboolean
498 pidgin_request_timeout_cb(PidginMedia *gtkmedia) 616 pidgin_request_timeout_cb(PidginMedia *gtkmedia)
499 { 617 {
561 double val = (double)gtk_range_get_value(GTK_RANGE(range)); 679 double val = (double)gtk_range_get_value(GTK_RANGE(range));
562 #endif 680 #endif
563 purple_media_set_output_volume(media, NULL, NULL, val); 681 purple_media_set_output_volume(media, NULL, NULL, val);
564 } 682 }
565 683
684 static void
685 destroy_parent_widget_cb(GtkWidget *widget, GtkWidget *parent)
686 {
687 g_return_if_fail(GTK_IS_WIDGET(parent));
688
689 gtk_widget_destroy(parent);
690 }
691
566 static GtkWidget * 692 static GtkWidget *
567 pidgin_media_add_audio_widget(PidginMedia *gtkmedia, 693 pidgin_media_add_audio_widget(PidginMedia *gtkmedia,
568 PurpleMediaSessionType type) 694 PurpleMediaSessionType type, const gchar *sid)
569 { 695 {
570 GtkWidget *volume_widget, *progress_parent, *volume, *progress; 696 GtkWidget *volume_widget, *progress_parent, *volume, *progress;
571 double value; 697 double value;
572 698
573 if (type & PURPLE_MEDIA_SEND_AUDIO) { 699 if (type & PURPLE_MEDIA_SEND_AUDIO) {
617 gtkmedia->priv->send_progress = progress; 743 gtkmedia->priv->send_progress = progress;
618 } else if (type & PURPLE_MEDIA_RECV_AUDIO) { 744 } else if (type & PURPLE_MEDIA_RECV_AUDIO) {
619 g_signal_connect (G_OBJECT(volume), "value-changed", 745 g_signal_connect (G_OBJECT(volume), "value-changed",
620 G_CALLBACK(pidgin_media_output_volume_changed), 746 G_CALLBACK(pidgin_media_output_volume_changed),
621 gtkmedia->priv->media); 747 gtkmedia->priv->media);
622 gtkmedia->priv->recv_progress = progress; 748
623 } 749 pidgin_media_insert_widget(gtkmedia, progress, sid, gtkmedia->priv->screenname);
750 }
751
752 g_signal_connect(G_OBJECT(progress), "destroy",
753 G_CALLBACK(destroy_parent_widget_cb),
754 volume_widget);
624 755
625 gtk_widget_show_all(volume_widget); 756 gtk_widget_show_all(volume_widget);
626 757
627 return volume_widget; 758 return volume_widget;
628 } 759 }
689 gtk_widget_modify_bg(remote_video, GTK_STATE_NORMAL, &color); 820 gtk_widget_modify_bg(remote_video, GTK_STATE_NORMAL, &color);
690 g_signal_connect(G_OBJECT(remote_video), "realize", 821 g_signal_connect(G_OBJECT(remote_video), "realize",
691 G_CALLBACK(realize_cb), data); 822 G_CALLBACK(realize_cb), data);
692 gtk_container_add(GTK_CONTAINER(aspect), remote_video); 823 gtk_container_add(GTK_CONTAINER(aspect), remote_video);
693 gtk_widget_set_size_request (GTK_WIDGET(remote_video), 320, 240); 824 gtk_widget_set_size_request (GTK_WIDGET(remote_video), 320, 240);
825 g_signal_connect(G_OBJECT(remote_video), "destroy",
826 G_CALLBACK(destroy_parent_widget_cb), aspect);
827
694 gtk_widget_show(remote_video); 828 gtk_widget_show(remote_video);
695 gtk_widget_show(aspect); 829 gtk_widget_show(aspect);
696 830
697 gtkmedia->priv->remote_video = remote_video; 831 pidgin_media_insert_widget(gtkmedia, remote_video,
698 } 832 data->session_id, data->participant);
699 833 }
700 if (type & PURPLE_MEDIA_SEND_VIDEO) { 834
835 if (type & PURPLE_MEDIA_SEND_VIDEO && !gtkmedia->priv->local_video) {
701 PidginMediaRealizeData *data; 836 PidginMediaRealizeData *data;
702 GtkWidget *aspect; 837 GtkWidget *aspect;
703 GtkWidget *local_video; 838 GtkWidget *local_video;
704 GdkColor color = {0, 0, 0, 0}; 839 GdkColor color = {0, 0, 0, 0};
705 840
716 gtk_widget_modify_bg(local_video, GTK_STATE_NORMAL, &color); 851 gtk_widget_modify_bg(local_video, GTK_STATE_NORMAL, &color);
717 g_signal_connect(G_OBJECT(local_video), "realize", 852 g_signal_connect(G_OBJECT(local_video), "realize",
718 G_CALLBACK(realize_cb), data); 853 G_CALLBACK(realize_cb), data);
719 gtk_container_add(GTK_CONTAINER(aspect), local_video); 854 gtk_container_add(GTK_CONTAINER(aspect), local_video);
720 gtk_widget_set_size_request (GTK_WIDGET(local_video), 80, 60); 855 gtk_widget_set_size_request (GTK_WIDGET(local_video), 80, 60);
856 g_signal_connect(G_OBJECT(local_video), "destroy",
857 G_CALLBACK(destroy_parent_widget_cb), aspect);
721 858
722 gtk_widget_show(local_video); 859 gtk_widget_show(local_video);
723 gtk_widget_show(aspect); 860 gtk_widget_show(aspect);
724 861
725 gtkmedia->priv->pause = 862 gtkmedia->priv->pause =
734 gtkmedia->priv->local_video = local_video; 871 gtkmedia->priv->local_video = local_video;
735 } 872 }
736 if (type & PURPLE_MEDIA_RECV_AUDIO) { 873 if (type & PURPLE_MEDIA_RECV_AUDIO) {
737 gtk_box_pack_end(GTK_BOX(recv_widget), 874 gtk_box_pack_end(GTK_BOX(recv_widget),
738 pidgin_media_add_audio_widget(gtkmedia, 875 pidgin_media_add_audio_widget(gtkmedia,
739 PURPLE_MEDIA_RECV_AUDIO), FALSE, FALSE, 0); 876 PURPLE_MEDIA_RECV_AUDIO, sid), FALSE, FALSE, 0);
740 } 877 }
741 878
742 if (type & PURPLE_MEDIA_SEND_AUDIO) { 879 if (type & PURPLE_MEDIA_SEND_AUDIO) {
743 gtkmedia->priv->mute = 880 gtkmedia->priv->mute =
744 gtk_toggle_button_new_with_mnemonic("_Mute"); 881 gtk_toggle_button_new_with_mnemonic("_Mute");
749 G_CALLBACK(pidgin_media_mute_toggled), 886 G_CALLBACK(pidgin_media_mute_toggled),
750 gtkmedia); 887 gtkmedia);
751 888
752 gtk_box_pack_end(GTK_BOX(recv_widget), 889 gtk_box_pack_end(GTK_BOX(recv_widget),
753 pidgin_media_add_audio_widget(gtkmedia, 890 pidgin_media_add_audio_widget(gtkmedia,
754 PURPLE_MEDIA_SEND_AUDIO), FALSE, FALSE, 0); 891 PURPLE_MEDIA_SEND_AUDIO, NULL), FALSE, FALSE, 0);
755 } 892 }
756 893
757 if (type & PURPLE_MEDIA_AUDIO && 894 if (type & PURPLE_MEDIA_AUDIO &&
758 gtkmedia->priv->level_handler_id == 0) { 895 gtkmedia->priv->level_handler_id == 0) {
759 gtkmedia->priv->level_handler_id = g_signal_connect( 896 gtkmedia->priv->level_handler_id = g_signal_connect(
802 pidgin_media_state_changed_cb(PurpleMedia *media, PurpleMediaState state, 939 pidgin_media_state_changed_cb(PurpleMedia *media, PurpleMediaState state,
803 gchar *sid, gchar *name, PidginMedia *gtkmedia) 940 gchar *sid, gchar *name, PidginMedia *gtkmedia)
804 { 941 {
805 purple_debug_info("gtkmedia", "state: %d sid: %s name: %s\n", 942 purple_debug_info("gtkmedia", "state: %d sid: %s name: %s\n",
806 state, sid ? sid : "(null)", name ? name : "(null)"); 943 state, sid ? sid : "(null)", name ? name : "(null)");
807 if (sid == NULL && name == NULL) { 944 if (state == PURPLE_MEDIA_STATE_END) {
808 if (state == PURPLE_MEDIA_STATE_END) { 945 if (sid != NULL && name != NULL) {
946 pidgin_media_remove_widget(gtkmedia, sid, name);
947 } else if (sid == NULL && name == NULL) {
809 pidgin_media_emit_message(gtkmedia, 948 pidgin_media_emit_message(gtkmedia,
810 _("The call has been terminated.")); 949 _("The call has been terminated."));
811 gtk_widget_destroy(GTK_WIDGET(gtkmedia)); 950 gtk_widget_destroy(GTK_WIDGET(gtkmedia));
812 } 951 }
813 } else if (state == PURPLE_MEDIA_STATE_NEW && 952 } else if (state == PURPLE_MEDIA_STATE_NEW &&

mercurial