* Finch is the legal property of its developers, whose names are too numerous * to list here. Please refer to the COPYRIGHT file distributed with this * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA #include "conversation.h" #include "mediamanager.h" /* An incredibly large part of the following is from gtkmedia.c */ #define FINCH_TYPE_MEDIA (finch_media_get_type()) #define FINCH_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), FINCH_TYPE_MEDIA, FinchMedia)) #define FINCH_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), FINCH_TYPE_MEDIA, FinchMediaClass)) #define FINCH_IS_MEDIA(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), FINCH_TYPE_MEDIA)) #define FINCH_IS_MEDIA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), FINCH_TYPE_MEDIA)) #define FINCH_MEDIA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), FINCH_TYPE_MEDIA, FinchMediaClass)) typedef struct _FinchMedia FinchMedia; typedef struct _FinchMediaClass FinchMediaClass; typedef struct _FinchMediaPrivate FinchMediaPrivate; typedef enum _FinchMediaState FinchMediaState; GntBoxClass parent_class; struct _FinchMediaPrivate PurpleConversation *conv; #define FINCH_MEDIA_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), FINCH_TYPE_MEDIA, FinchMediaPrivate)) static void finch_media_class_init (FinchMediaClass *klass); static void finch_media_init (FinchMedia *media); static void finch_media_finalize (GObject *object); static void finch_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void finch_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); static GntBoxClass *parent_class = NULL; static guint finch_media_signals[LAST_SIGNAL] = {0}; finch_media_get_type(void) static const GTypeInfo info = { (GClassInitFunc) finch_media_class_init, (GInstanceInitFunc) finch_media_init, type = g_type_register_static(GNT_TYPE_BOX, "FinchMedia", &info, 0); finch_media_class_init (FinchMediaClass *klass) GObjectClass *gobject_class = (GObjectClass*)klass; parent_class = g_type_class_peek_parent(klass); gobject_class->finalize = finch_media_finalize; gobject_class->set_property = finch_media_set_property; gobject_class->get_property = finch_media_get_property; g_object_class_install_property(gobject_class, PROP_MEDIA, g_param_spec_object("media", "The PurpleMedia associated with this media.", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); finch_media_signals[MESSAGE] = g_signal_new("message", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); g_type_class_add_private(klass, sizeof(FinchMediaPrivate)); finch_media_init (FinchMedia *media) media->priv = FINCH_MEDIA_GET_PRIVATE(media); media->priv->calling = gnt_label_new(_("Calling...")); media->priv->hangup = gnt_button_new(_("Hangup")); media->priv->accept = gnt_button_new(_("Accept")); media->priv->reject = gnt_button_new(_("Reject")); gnt_box_set_alignment(GNT_BOX(media), GNT_ALIGN_MID); gnt_box_add_widget(GNT_BOX(media), media->priv->accept); gnt_box_add_widget(GNT_BOX(media), media->priv->reject); finch_media_finalize (GObject *media) FinchMedia *gntmedia = FINCH_MEDIA(media); purple_debug_info("gntmedia", "finch_media_finalize\n"); if (gntmedia->priv->media) g_object_unref(gntmedia->priv->media); finch_media_emit_message(FinchMedia *gntmedia, const char *msg) g_signal_emit(gntmedia, finch_media_signals[MESSAGE], 0, msg); finch_media_connected_cb(PurpleMedia *media, FinchMedia *gntmedia) finch_media_emit_message(gntmedia, _("Call in progress.")); gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->accept); gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->reject); gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->hangup); gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->calling); gnt_box_add_widget(GNT_BOX(gntmedia), gntmedia->priv->hangup); gnt_widget_destroy(gntmedia->priv->accept); gnt_widget_destroy(gntmedia->priv->reject); gnt_widget_destroy(gntmedia->priv->calling); gntmedia->priv->accept = NULL; gntmedia->priv->reject = NULL; gntmedia->priv->calling = NULL; parent = GNT_WIDGET(gntmedia); gnt_box_readjust(GNT_BOX(parent)); finch_media_wait_cb(PurpleMedia *media, FinchMedia *gntmedia) gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->accept); gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->reject); gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->hangup); gnt_box_remove(GNT_BOX(gntmedia), gntmedia->priv->calling); gnt_box_add_widget(GNT_BOX(gntmedia), gntmedia->priv->calling); gnt_box_add_widget(GNT_BOX(gntmedia), gntmedia->priv->hangup); parent = GNT_WIDGET(gntmedia); gnt_box_readjust(GNT_BOX(parent)); finch_media_state_changed_cb(PurpleMedia *media, PurpleMediaState state, gchar *sid, gchar *name, FinchMedia *gntmedia) purple_debug_info("gntmedia", "state: %d sid: %s name: %s\n", if (sid == NULL && name == NULL) { if (state == PURPLE_MEDIA_STATE_END) { finch_media_emit_message(gntmedia, _("The call has been terminated.")); finch_conversation_set_info_widget( gntmedia->priv->conv, NULL); gnt_widget_destroy(GNT_WIDGET(gntmedia)); * XXX: This shouldn't have to be here * to free the FinchMedia widget. g_object_unref(gntmedia); } else if (state == PURPLE_MEDIA_STATE_CONNECTED) { finch_media_connected_cb(media, gntmedia); } else if (state == PURPLE_MEDIA_STATE_NEW && sid != NULL && name != NULL && purple_media_is_initiator(media, sid, name) == FALSE) { PurpleMediaSessionType type = purple_media_get_session_type(media, sid); account = purple_media_get_account(gntmedia->priv->media); buddy = purple_blist_find_buddy(account, name); alias = buddy ? purple_buddy_get_contact_alias(buddy) : name; if (type & PURPLE_MEDIA_AUDIO) { message = g_strdup_printf( _("%s wishes to start an audio session with you."), message = g_strdup_printf( _("%s is trying to start an unsupported media session type with you."), finch_media_emit_message(gntmedia, message); finch_media_stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type, gchar *sid, gchar *name, gboolean local, FinchMedia *gntmedia) if (type == PURPLE_MEDIA_INFO_REJECT) { finch_media_emit_message(gntmedia, _("You have rejected the call.")); finch_media_accept_cb(PurpleMedia *media, GntWidget *widget) purple_media_stream_info(media, PURPLE_MEDIA_INFO_ACCEPT, finch_media_hangup_cb(PurpleMedia *media, GntWidget *widget) purple_media_stream_info(media, PURPLE_MEDIA_INFO_HANGUP, finch_media_reject_cb(PurpleMedia *media, GntWidget *widget) purple_media_stream_info(media, PURPLE_MEDIA_INFO_REJECT, finch_media_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) g_return_if_fail(FINCH_IS_MEDIA(object)); media = FINCH_MEDIA(object); g_object_unref(media->priv->media); media->priv->media = g_value_get_object(value); g_object_ref(media->priv->media); g_signal_connect_swapped(G_OBJECT(media->priv->accept), "activate", G_CALLBACK(finch_media_accept_cb), media->priv->media); g_signal_connect_swapped(G_OBJECT(media->priv->reject), "activate", G_CALLBACK(finch_media_reject_cb), media->priv->media); g_signal_connect_swapped(G_OBJECT(media->priv->hangup), "activate", G_CALLBACK(finch_media_hangup_cb), media->priv->media); if (purple_media_is_initiator(media->priv->media, finch_media_wait_cb(media->priv->media, media); g_signal_connect(G_OBJECT(media->priv->media), "state-changed", G_CALLBACK(finch_media_state_changed_cb), media); g_signal_connect(G_OBJECT(media->priv->media), "stream-info", G_CALLBACK(finch_media_stream_info_cb), media); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); finch_media_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) g_return_if_fail(FINCH_IS_MEDIA(object)); media = FINCH_MEDIA(object); g_value_set_object(value, media->priv->media); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); finch_media_new(PurpleMedia *media) return GNT_WIDGET(g_object_new(finch_media_get_type(), gntmedia_message_cb(FinchMedia *gntmedia, const char *msg, PurpleConversation *conv) if (PURPLE_IS_IM_CONVERSATION(conv)) { purple_conversation_write_system_message(conv, msg, 0); finch_new_media(PurpleMediaManager *manager, PurpleMedia *media, PurpleAccount *account, gchar *name, gpointer null) PurpleConversation *conv; conv = PURPLE_CONVERSATION(purple_im_conversation_new(account, name)); gntmedia = finch_media_new(media); g_signal_connect(G_OBJECT(gntmedia), "message", G_CALLBACK(gntmedia_message_cb), conv); FINCH_MEDIA(gntmedia)->priv->conv = conv; finch_conversation_set_info_widget(conv, gntmedia); call_cmd_cb(PurpleConversation *conv, const char *cmd, char **args, char **eror, gpointer data) PurpleAccount *account = purple_conversation_get_account(conv); if (!purple_protocol_initiate_media(account, purple_conversation_get_name(conv), return PURPLE_CMD_RET_FAILED; return PURPLE_CMD_RET_OK; void finch_media_manager_init(void) PurpleMediaManager *manager = purple_media_manager_get(); PurpleMediaElementInfo *audio_src = NULL; PurpleMediaElementInfo *audio_sink = NULL; pref = purple_prefs_get_string( FINCH_PREFS_ROOT "/vvconfig/audio/src/device"); audio_src = purple_media_manager_get_element_info(manager, pref); FINCH_PREFS_ROOT "/vvconfig/audio/src/device", pref); audio_src = purple_media_manager_get_element_info(manager, pref = purple_prefs_get_string( FINCH_PREFS_ROOT "/vvconfig/audio/sink/device"); audio_sink = purple_media_manager_get_element_info(manager, pref); FINCH_PREFS_ROOT "/vvconfig/audio/sink/device", pref); audio_sink = purple_media_manager_get_element_info(manager, g_signal_connect(G_OBJECT(manager), "init-media", G_CALLBACK(finch_new_media), NULL); purple_cmd_register("call", "", PURPLE_CMD_P_DEFAULT, PURPLE_CMD_FLAG_IM, NULL, call_cmd_cb, _("call: Make an audio call."), NULL); purple_media_manager_set_ui_caps(manager, PURPLE_MEDIA_CAPS_AUDIO | PURPLE_MEDIA_CAPS_AUDIO_SINGLE_DIRECTION); purple_debug_info("gntmedia", "Registering media element types\n"); purple_media_manager_set_active_element(manager, audio_src); purple_media_manager_set_active_element(manager, audio_sink); void finch_media_manager_uninit(void) PurpleMediaManager *manager = purple_media_manager_get(); g_signal_handlers_disconnect_by_func(G_OBJECT(manager), G_CALLBACK(finch_new_media), NULL);