X-Git-Url: https://git.0d.be/?p=empathy.git;a=blobdiff_plain;f=libempathy%2Fempathy-tp-call.c;h=a5c0003c56741182ad665d9292d61a811899fd9e;hp=e1bb6f4a7504b98c4704db8c951c712f57c7ca6b;hb=9b9fcd3ce3b9c7fdc62836821d83377bec58d0a5;hpb=fb2ea59a07e6ecc6be24c6e84612353754aa7dd2 diff --git a/libempathy/empathy-tp-call.c b/libempathy/empathy-tp-call.c index e1bb6f4a..a5c0003c 100644 --- a/libempathy/empathy-tp-call.c +++ b/libempathy/empathy-tp-call.c @@ -1,4 +1,3 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * Copyright (C) 2007 Elliot Fairweather * Copyright (C) 2007-2008 Collabora Ltd. @@ -27,30 +26,21 @@ #include #include -#include - #include "empathy-tp-call.h" -#include "empathy-contact-factory.h" -#include "empathy-tp-group.h" +#include "empathy-tp-contact-factory.h" #include "empathy-utils.h" #define DEBUG_FLAG EMPATHY_DEBUG_TP #include "empathy-debug.h" -#define STREAM_ENGINE_BUS_NAME "org.freedesktop.Telepathy.StreamEngine" -#define STREAM_ENGINE_OBJECT_PATH "/org/freedesktop/Telepathy/StreamEngine" - #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyTpCall) typedef struct { + gboolean dispose_has_run; TpChannel *channel; - TpProxy *stream_engine; - TpDBusDaemon *dbus_daemon; - EmpathyTpGroup *group; EmpathyContact *contact; gboolean is_incoming; guint status; - gboolean stream_engine_running; EmpathyTpCallStream *audio; EmpathyTpCallStream *video; @@ -264,64 +254,82 @@ tp_call_request_streams_for_capabilities (EmpathyTpCall *call, } static void -tp_call_member_added_cb (EmpathyTpGroup *group, - EmpathyContact *contact, - EmpathyContact *actor, - guint reason, - const gchar *message, - EmpathyTpCall *call) +tp_call_got_contact_cb (EmpathyTpContactFactory *factory, + EmpathyContact *contact, + const GError *error, + gpointer user_data, + GObject *call) { EmpathyTpCallPriv *priv = GET_PRIV (call); - g_object_ref (call); - if (!priv->contact && !empathy_contact_is_user (contact)) + if (error) { - priv->contact = g_object_ref (contact); - priv->is_incoming = TRUE; - priv->status = EMPATHY_TP_CALL_STATUS_PENDING; - g_object_notify (G_OBJECT (call), "is-incoming"); - g_object_notify (G_OBJECT (call), "contact"); - g_object_notify (G_OBJECT (call), "status"); - tp_call_request_streams_for_capabilities (call, - EMPATHY_CAPABILITIES_AUDIO); - + DEBUG ("Error: %s", error->message); + return; } - if (priv->status == EMPATHY_TP_CALL_STATUS_PENDING && - ((priv->is_incoming && contact != priv->contact) || - (!priv->is_incoming && contact == priv->contact))) - { - priv->status = EMPATHY_TP_CALL_STATUS_ACCEPTED; - g_object_notify (G_OBJECT (call), "status"); - } - g_object_unref (call); + priv->contact = g_object_ref (contact); + priv->is_incoming = TRUE; + priv->status = EMPATHY_TP_CALL_STATUS_PENDING; + g_object_notify (G_OBJECT (call), "is-incoming"); + g_object_notify (G_OBJECT (call), "contact"); + g_object_notify (G_OBJECT (call), "status"); } static void -tp_call_remote_pending_cb (EmpathyTpGroup *group, - EmpathyContact *contact, - EmpathyContact *actor, - guint reason, - const gchar *message, - EmpathyTpCall *call) +tp_call_update_status (EmpathyTpCall *call) { EmpathyTpCallPriv *priv = GET_PRIV (call); + TpHandle self_handle; + const TpIntSet *set; + TpIntSetIter iter; g_object_ref (call); - if (!priv->contact && !empathy_contact_is_user (contact)) + + self_handle = tp_channel_group_get_self_handle (priv->channel); + set = tp_channel_group_get_members (priv->channel); + tp_intset_iter_init (&iter, set); + while (tp_intset_iter_next (&iter)) { - priv->contact = g_object_ref (contact); - priv->is_incoming = FALSE; - priv->status = EMPATHY_TP_CALL_STATUS_PENDING; - g_object_notify (G_OBJECT (call), "is-incoming"); - g_object_notify (G_OBJECT (call), "contact"); - g_object_notify (G_OBJECT (call), "status"); - tp_call_request_streams_for_capabilities (call, - EMPATHY_CAPABILITIES_AUDIO); + if (priv->contact == NULL && iter.element != self_handle) + { + EmpathyTpContactFactory *factory; + TpConnection *connection; + + /* We found the remote contact */ + connection = tp_channel_borrow_connection (priv->channel); + factory = empathy_tp_contact_factory_dup_singleton (connection); + empathy_tp_contact_factory_get_from_handle (factory, iter.element, + tp_call_got_contact_cb, NULL, NULL, G_OBJECT (call)); + g_object_unref (factory); + } + + if (priv->status == EMPATHY_TP_CALL_STATUS_PENDING && + ((priv->is_incoming && iter.element == self_handle) || + (!priv->is_incoming && iter.element != self_handle))) + { + priv->status = EMPATHY_TP_CALL_STATUS_ACCEPTED; + g_object_notify (G_OBJECT (call), "status"); + } } + g_object_unref (call); } +void +empathy_tp_call_to (EmpathyTpCall *call, EmpathyContact *contact) +{ + EmpathyTpCallPriv *priv = GET_PRIV (call); + + priv->contact = g_object_ref (contact); + priv->is_incoming = FALSE; + priv->status = EMPATHY_TP_CALL_STATUS_PENDING; + g_object_notify (G_OBJECT (call), "is-incoming"); + g_object_notify (G_OBJECT (call), "contact"); + g_object_notify (G_OBJECT (call), "status"); + tp_call_request_streams_for_capabilities (call, EMPATHY_CAPABILITIES_AUDIO); +} + static void tp_call_channel_invalidated_cb (TpChannel *channel, GQuark domain, @@ -346,110 +354,6 @@ tp_call_async_cb (TpProxy *proxy, DEBUG ("Error %s: %s", (gchar*) user_data, error->message); } -static void -tp_call_close_channel (EmpathyTpCall *call) -{ - EmpathyTpCallPriv *priv = GET_PRIV (call); - - if (priv->status == EMPATHY_TP_CALL_STATUS_CLOSED) - return; - - DEBUG ("Closing channel"); - - tp_cli_channel_call_close (priv->channel, -1, - NULL, NULL, NULL, NULL); - - priv->status = EMPATHY_TP_CALL_STATUS_CLOSED; - g_object_notify (G_OBJECT (call), "status"); -} - -static void -tp_call_stream_engine_invalidated_cb (TpProxy *stream_engine, - GQuark domain, - gint code, - gchar *message, - EmpathyTpCall *call) -{ - DEBUG ("Stream engine proxy invalidated: %s", message); - tp_call_close_channel (call); -} - -static void -tp_call_stream_engine_watch_name_owner_cb (TpDBusDaemon *daemon, - const gchar *name, - const gchar *new_owner, - gpointer call) -{ - EmpathyTpCallPriv *priv = GET_PRIV (call); - - /* G_STR_EMPTY(new_owner) means either stream-engine has not started yet or - * has crashed. We want to close the channel if stream-engine has crashed. - * */ - DEBUG ("Watch SE: name='%s' SE running='%s' new_owner='%s'", - name, priv->stream_engine_running ? "yes" : "no", - new_owner ? new_owner : "none"); - if (priv->stream_engine_running && G_STR_EMPTY (new_owner)) - { - DEBUG ("Stream engine falled off the bus"); - tp_call_close_channel (call); - return; - } - - priv->stream_engine_running = !G_STR_EMPTY (new_owner); -} - -static void -tp_call_stream_engine_handle_channel (EmpathyTpCall *call) -{ - EmpathyTpCallPriv *priv = GET_PRIV (call); - gchar *channel_type; - gchar *object_path; - guint handle_type; - guint handle; - TpProxy *connection; - - DEBUG ("Revving up the stream engine"); - - priv->stream_engine = g_object_new (TP_TYPE_PROXY, - "bus-name", STREAM_ENGINE_BUS_NAME, - "dbus-connection", tp_get_bus (), - "object-path", STREAM_ENGINE_OBJECT_PATH, - NULL); - tp_proxy_add_interface_by_id (priv->stream_engine, - EMP_IFACE_QUARK_STREAM_ENGINE); - tp_proxy_add_interface_by_id (priv->stream_engine, - EMP_IFACE_QUARK_CHANNEL_HANDLER); - - g_signal_connect (priv->stream_engine, "invalidated", - G_CALLBACK (tp_call_stream_engine_invalidated_cb), - call); - - /* FIXME: dbus daemon should be unique */ - priv->dbus_daemon = tp_dbus_daemon_new (tp_get_bus ()); - tp_dbus_daemon_watch_name_owner (priv->dbus_daemon, STREAM_ENGINE_BUS_NAME, - tp_call_stream_engine_watch_name_owner_cb, - call, NULL); - - g_object_get (priv->channel, - "connection", &connection, - "channel-type", &channel_type, - "object-path", &object_path, - "handle_type", &handle_type, - "handle", &handle, - NULL); - - emp_cli_channel_handler_call_handle_channel (priv->stream_engine, -1, - connection->bus_name, - connection->object_path, - channel_type, object_path, handle_type, handle, - tp_call_async_cb, "calling handle channel", NULL, - G_OBJECT (call)); - - g_object_unref (connection); - g_free (channel_type); - g_free (object_path); -} - static GObject * tp_call_constructor (GType type, guint n_construct_params, @@ -479,62 +383,55 @@ tp_call_constructor (GType type, tp_cli_channel_type_streamed_media_call_list_streams (priv->channel, -1, tp_call_request_streams_cb, NULL, NULL, G_OBJECT (call)); - /* Setup group interface */ - priv->group = empathy_tp_group_new (priv->channel); - - g_signal_connect (priv->group, "member-added", - G_CALLBACK (tp_call_member_added_cb), call); - g_signal_connect (priv->group, "remote-pending", - G_CALLBACK (tp_call_remote_pending_cb), call); - - /* Start stream engine */ - tp_call_stream_engine_handle_channel (call); + /* Update status when members changes */ + tp_call_update_status (call); + g_signal_connect_swapped (priv->channel, "group-members-changed", + G_CALLBACK (tp_call_update_status), call); return object; } - -static void -tp_call_finalize (GObject *object) +static void +tp_call_dispose (GObject *object) { EmpathyTpCallPriv *priv = GET_PRIV (object); - DEBUG ("Finalizing: %p", object); + DEBUG ("Disposing: %p, %d", object, priv->dispose_has_run); - g_slice_free (EmpathyTpCallStream, priv->audio); - g_slice_free (EmpathyTpCallStream, priv->video); - g_object_unref (priv->group); + if (priv->dispose_has_run) + return; + + priv->dispose_has_run = TRUE; if (priv->channel != NULL) { g_signal_handlers_disconnect_by_func (priv->channel, - tp_call_channel_invalidated_cb, object); - tp_call_close_channel (EMPATHY_TP_CALL (object)); - g_object_unref (priv->channel); - } + tp_call_channel_invalidated_cb, object); - if (priv->stream_engine != NULL) - { - g_signal_handlers_disconnect_by_func (priv->stream_engine, - tp_call_stream_engine_invalidated_cb, object); - g_object_unref (priv->stream_engine); + g_object_unref (priv->channel); + priv->channel = NULL; } if (priv->contact != NULL) g_object_unref (priv->contact); - if (priv->dbus_daemon != NULL) - { - tp_dbus_daemon_cancel_name_owner_watch (priv->dbus_daemon, - STREAM_ENGINE_BUS_NAME, - tp_call_stream_engine_watch_name_owner_cb, - object); - g_object_unref (priv->dbus_daemon); - } + if (G_OBJECT_CLASS (empathy_tp_call_parent_class)->dispose) + G_OBJECT_CLASS (empathy_tp_call_parent_class)->dispose (object); +} + +static void +tp_call_finalize (GObject *object) +{ + EmpathyTpCallPriv *priv = GET_PRIV (object); + + DEBUG ("Finalizing: %p", object); + + g_slice_free (EmpathyTpCallStream, priv->audio); + g_slice_free (EmpathyTpCallStream, priv->video); (G_OBJECT_CLASS (empathy_tp_call_parent_class)->finalize) (object); } -static void +static void tp_call_set_property (GObject *object, guint prop_id, const GValue *value, @@ -592,9 +489,8 @@ empathy_tp_call_class_init (EmpathyTpCallClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - emp_cli_init (); - object_class->constructor = tp_call_constructor; + object_class->dispose = tp_call_dispose; object_class->finalize = tp_call_finalize; object_class->set_property = tp_call_set_property; object_class->get_property = tp_call_get_property; @@ -632,12 +528,11 @@ static void empathy_tp_call_init (EmpathyTpCall *call) { EmpathyTpCallPriv *priv = G_TYPE_INSTANCE_GET_PRIVATE (call, - EMPATHY_TYPE_TP_CALL, EmpathyTpCallPriv); + EMPATHY_TYPE_TP_CALL, EmpathyTpCallPriv); call->priv = priv; priv->status = EMPATHY_TP_CALL_STATUS_READYING; priv->contact = NULL; - priv->stream_engine_running = FALSE; priv->audio = g_slice_new0 (EmpathyTpCallStream); priv->video = g_slice_new0 (EmpathyTpCallStream); priv->audio->exists = FALSE; @@ -658,16 +553,37 @@ void empathy_tp_call_accept_incoming_call (EmpathyTpCall *call) { EmpathyTpCallPriv *priv = GET_PRIV (call); - EmpathyContact *self_contact; + TpHandle self_handle; + GArray handles = {(gchar *) &self_handle, 1}; g_return_if_fail (EMPATHY_IS_TP_CALL (call)); g_return_if_fail (priv->status == EMPATHY_TP_CALL_STATUS_PENDING); + g_return_if_fail (priv->is_incoming); DEBUG ("Accepting incoming call"); - self_contact = empathy_tp_group_get_self_contact (priv->group); - empathy_tp_group_add_member (priv->group, self_contact, NULL); - g_object_unref (self_contact); + self_handle = tp_channel_group_get_self_handle (priv->channel); + tp_cli_channel_interface_group_call_add_members (priv->channel, -1, + &handles, NULL, NULL, NULL, NULL, NULL); +} + +void +empathy_tp_call_close (EmpathyTpCall *call) +{ + EmpathyTpCallPriv *priv = GET_PRIV (call); + + g_return_if_fail (EMPATHY_IS_TP_CALL (call)); + + if (priv->status == EMPATHY_TP_CALL_STATUS_CLOSED) + return; + + DEBUG ("Closing channel"); + + tp_cli_channel_call_close (priv->channel, -1, + NULL, NULL, NULL, NULL); + + priv->status = EMPATHY_TP_CALL_STATUS_CLOSED; + g_object_notify (G_OBJECT (call), "status"); } void @@ -701,113 +617,6 @@ empathy_tp_call_request_video_stream_direction (EmpathyTpCall *call, tp_call_async_cb, NULL, NULL, G_OBJECT (call)); } -void -empathy_tp_call_add_preview_video (EmpathyTpCall *call, - guint preview_video_socket_id) -{ - EmpathyTpCallPriv *priv = GET_PRIV (call); - - g_return_if_fail (EMPATHY_IS_TP_CALL (call)); - - DEBUG ("Adding preview video"); - - emp_cli_stream_engine_call_add_preview_window (priv->stream_engine, -1, - preview_video_socket_id, - tp_call_async_cb, - "adding preview window", NULL, - G_OBJECT (call)); -} - -void -empathy_tp_call_remove_preview_video (EmpathyTpCall *call, - guint preview_video_socket_id) -{ - EmpathyTpCallPriv *priv = GET_PRIV (call); - - g_return_if_fail (EMPATHY_IS_TP_CALL (call)); - - DEBUG ("Removing preview video"); - - emp_cli_stream_engine_call_remove_preview_window (priv->stream_engine, -1, - preview_video_socket_id, - tp_call_async_cb, - "removing preview window", NULL, - G_OBJECT (call)); -} - -void -empathy_tp_call_add_output_video (EmpathyTpCall *call, - guint output_video_socket_id) -{ - EmpathyTpCallPriv *priv = GET_PRIV (call); - - g_return_if_fail (EMPATHY_IS_TP_CALL (call)); - - DEBUG ("Adding output video - socket: %d", output_video_socket_id); - - emp_cli_stream_engine_call_set_output_window (priv->stream_engine, -1, - TP_PROXY (priv->channel)->object_path, - priv->video->id, output_video_socket_id, - tp_call_async_cb, - "setting output window", NULL, - G_OBJECT (call)); -} - -void -empathy_tp_call_set_output_volume (EmpathyTpCall *call, - guint volume) -{ - EmpathyTpCallPriv *priv = GET_PRIV (call); - - g_return_if_fail (EMPATHY_IS_TP_CALL (call)); - g_return_if_fail (priv->status != EMPATHY_TP_CALL_STATUS_CLOSED); - - DEBUG ("Setting output volume: %d", volume); - - emp_cli_stream_engine_call_set_output_volume (priv->stream_engine, -1, - TP_PROXY (priv->channel)->object_path, - priv->audio->id, volume, - tp_call_async_cb, - "setting output volume", NULL, - G_OBJECT (call)); -} - -void -empathy_tp_call_mute_output (EmpathyTpCall *call, - gboolean is_muted) -{ - EmpathyTpCallPriv *priv = GET_PRIV (call); - - g_return_if_fail (EMPATHY_IS_TP_CALL (call)); - - DEBUG ("Setting output mute: %d", is_muted); - - emp_cli_stream_engine_call_mute_output (priv->stream_engine, -1, - TP_PROXY (priv->channel)->object_path, - priv->audio->id, is_muted, - tp_call_async_cb, - "muting output", NULL, - G_OBJECT (call)); -} - -void -empathy_tp_call_mute_input (EmpathyTpCall *call, - gboolean is_muted) -{ - EmpathyTpCallPriv *priv = GET_PRIV (call); - - g_return_if_fail (EMPATHY_IS_TP_CALL (call)); - - DEBUG ("Setting input mute: %d", is_muted); - - emp_cli_stream_engine_call_mute_input (priv->stream_engine, -1, - TP_PROXY (priv->channel)->object_path, - priv->audio->id, is_muted, - tp_call_async_cb, - "muting input", NULL, - G_OBJECT (call)); -} - void empathy_tp_call_start_tone (EmpathyTpCall *call, TpDTMFEvent event) {