#include <telepathy-farsight/channel.h>
#include <telepathy-farsight/stream.h>
+#include <gst/farsight/fs-element-added-notifier.h>
+
#include "empathy-call-handler.h"
#include "empathy-dispatcher.h"
#include "empathy-marshal.h"
enum {
PROP_TP_CALL = 1,
PROP_GST_BUS,
- PROP_CONTACT
+ PROP_CONTACT,
+ PROP_INITIAL_AUDIO,
+ PROP_INITIAL_VIDEO
};
/* private structure */
EmpathyTpCall *call;
EmpathyContact *contact;
TfChannel *tfchannel;
+ gboolean initial_audio;
+ gboolean initial_video;
+ FsElementAddedNotifier *fsnotifier;
} EmpathyCallHandlerPriv;
#define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyCallHandler)
priv->call = NULL;
+ if (priv->fsnotifier != NULL)
+ {
+ g_object_unref (priv->fsnotifier);
+ }
+ priv->fsnotifier = NULL;
+
/* release any references held by the object here */
if (G_OBJECT_CLASS (empathy_call_handler_parent_class)->dispose)
G_OBJECT_CLASS (empathy_call_handler_parent_class)->dispose (object);
obj->priv = priv;
}
+static void
+empathy_call_handler_constructed (GObject *object)
+{
+ EmpathyCallHandlerPriv *priv = GET_PRIV (object);
+
+ if (priv->contact == NULL)
+ {
+ g_object_get (priv->call, "contact", &(priv->contact), NULL);
+ }
+}
+
static void
empathy_call_handler_set_property (GObject *object,
guint property_id, const GValue *value, GParamSpec *pspec)
case PROP_TP_CALL:
priv->call = g_value_dup_object (value);
break;
+ case PROP_INITIAL_AUDIO:
+ priv->initial_audio = g_value_get_boolean (value);
+ break;
+ case PROP_INITIAL_VIDEO:
+ priv->initial_video = g_value_get_boolean (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
case PROP_TP_CALL:
g_value_set_object (value, priv->call);
break;
+ case PROP_INITIAL_AUDIO:
+ g_value_set_boolean (value, priv->initial_audio);
+ break;
+ case PROP_INITIAL_VIDEO:
+ g_value_set_boolean (value, priv->initial_video);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
g_type_class_add_private (klass, sizeof (EmpathyCallHandlerPriv));
+ object_class->constructed = empathy_call_handler_constructed;
object_class->set_property = empathy_call_handler_set_property;
object_class->get_property = empathy_call_handler_get_property;
object_class->dispose = empathy_call_handler_dispose;
param_spec = g_param_spec_object ("contact",
"contact", "The remote contact",
EMPATHY_TYPE_CONTACT,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_CONTACT, param_spec);
param_spec = g_param_spec_object ("tp-call",
"tp-call", "The calls channel wrapper",
EMPATHY_TYPE_TP_CALL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_TP_CALL, param_spec);
+ param_spec = g_param_spec_boolean ("initial-audio",
+ "initial-audio", "Whether the call should start with audio",
+ TRUE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_INITIAL_AUDIO,
+ param_spec);
+
+ param_spec = g_param_spec_boolean ("initial-video",
+ "initial-video", "Whether the call should start with video",
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_INITIAL_VIDEO,
+ param_spec);
+
signals[CONFERENCE_ADDED] =
g_signal_new ("conference-added", G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
0);
}
+/**
+ * empathy_call_handler_new_for_contact:
+ * @contact: an #EmpathyContact
+ *
+ * Creates a new #EmpathyCallHandler with contact @contact.
+ *
+ * Return value: a new #EmpathyCallHandler
+ */
EmpathyCallHandler *
empathy_call_handler_new_for_contact (EmpathyContact *contact)
{
"contact", contact, NULL));
}
+/**
+ * empathy_call_handler_new_for_contact_with_streams:
+ * @contact: an #EmpathyContact
+ * @audio: if %TRUE the call will be started with audio
+ * @video: if %TRUE the call will be started with video
+ *
+ * Creates a new #EmpathyCallHandler with contact @contact.
+ *
+ * Return value: a new #EmpathyCallHandler
+ */
+EmpathyCallHandler *
+empathy_call_handler_new_for_contact_with_streams (EmpathyContact *contact,
+ gboolean audio, gboolean video)
+{
+ return EMPATHY_CALL_HANDLER (g_object_new (EMPATHY_TYPE_CALL_HANDLER,
+ "contact", contact,
+ "initial-audio", audio,
+ "initial-video", video,
+ NULL));
+}
+
EmpathyCallHandler *
empathy_call_handler_new_for_channel (EmpathyTpCall *call)
{
tf_channel_bus_message (priv->tfchannel, message);
}
+static void
+conference_element_added (FsElementAddedNotifier *notifier,
+ GstBin *bin,
+ GstElement *element,
+ gpointer user_data)
+{
+ GstElementFactory *factory;
+ const gchar *name;
+
+ factory = gst_element_get_factory (element);
+ name = gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory));
+
+ if (!tp_strdiff (name, "x264enc"))
+ {
+ /* Ensure that the encoder creates the baseline profile */
+ g_object_set (element,
+ "byte-stream", TRUE,
+ "bframes", 0,
+ "b-adapt", FALSE,
+ "cabac", FALSE,
+ "dct8x8", FALSE,
+ NULL);
+ }
+ else if (!tp_strdiff (name, "gstrtpbin"))
+ {
+ /* Lower the jitterbuffer latency to make it more suitable for video
+ * conferencing */
+ g_object_set (element, "latency", 100, NULL);
+ }
+}
+
static void
empathy_call_handler_tf_channel_session_created_cb (TfChannel *tfchannel,
FsConference *conference, FsParticipant *participant,
EmpathyCallHandler *self)
{
+ EmpathyCallHandlerPriv *priv = GET_PRIV (self);
+
+ priv->fsnotifier = fs_element_added_notifier_new ();
+ fs_element_added_notifier_add (priv->fsnotifier, GST_BIN (conference));
+
+ g_signal_connect (priv->fsnotifier, "element-added",
+ G_CALLBACK (conference_element_added), NULL);
+
g_signal_emit (G_OBJECT (self), signals[CONFERENCE_ADDED], 0,
GST_ELEMENT (conference));
}
empathy_call_handler_start_tpfs (self);
- empathy_tp_call_to (priv->call, priv->contact);
+ empathy_tp_call_to (priv->call, priv->contact,
+ priv->initial_audio, priv->initial_video);
empathy_dispatch_operation_claim (operation);
}
-static void
-empathy_call_handler_contact_ready_cb (EmpathyContact *contact,
- const GError *error, gpointer user_data, GObject *object)
+void
+empathy_call_handler_start_call (EmpathyCallHandler *handler)
{
- EmpathyCallHandler *self = EMPATHY_CALL_HANDLER (object);
- EmpathyCallHandlerPriv *priv = GET_PRIV (self);
+
+ EmpathyCallHandlerPriv *priv = GET_PRIV (handler);
EmpathyDispatcher *dispatcher;
- McAccount *account;
- GStrv allowed;
+ TpConnection *connection;
+ GList *classes;
GValue *value;
- GHashTable *request = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
- (GDestroyNotify) tp_g_value_slice_free);
+ GHashTable *request;
+
+ if (priv->call != NULL)
+ {
+ empathy_call_handler_start_tpfs (handler);
+ empathy_tp_call_accept_incoming_call (priv->call);
+ return;
+ }
g_assert (priv->contact != NULL);
dispatcher = empathy_dispatcher_dup_singleton ();
- account = empathy_contact_get_account (priv->contact);
- allowed = empathy_dispatcher_find_channel_class (dispatcher, account,
- TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA, TP_HANDLE_TYPE_CONTACT);
+ connection = empathy_contact_get_connection (priv->contact);
+ classes = empathy_dispatcher_find_requestable_channel_classes
+ (dispatcher, connection, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA,
+ TP_HANDLE_TYPE_CONTACT, NULL);
+
+ if (classes == NULL)
+ return;
- if (!tp_strv_contains ((const gchar * const *)allowed,
- TP_IFACE_CHANNEL ".TargetHandle"))
- g_assert_not_reached ();
+ g_list_free (classes);
+
+ request = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+ (GDestroyNotify) tp_g_value_slice_free);
/* org.freedesktop.Telepathy.Channel.ChannelType */
value = tp_g_value_slice_new (G_TYPE_STRING);
g_value_set_uint (value, empathy_contact_get_handle (priv->contact));
g_hash_table_insert (request, TP_IFACE_CHANNEL ".TargetHandle", value);
- empathy_dispatcher_create_channel (dispatcher, account,
- request, empathy_call_handler_request_cb, self);
+ empathy_dispatcher_create_channel (dispatcher, connection,
+ request, empathy_call_handler_request_cb, handler);
g_object_unref (dispatcher);
}
-void
-empathy_call_handler_start_call (EmpathyCallHandler *handler)
-{
-
- EmpathyCallHandlerPriv *priv = GET_PRIV (handler);
-
- if (priv->call == NULL)
- {
- empathy_contact_call_when_ready (priv->contact,
- EMPATHY_CONTACT_READY_HANDLE,
- empathy_call_handler_contact_ready_cb, NULL, NULL, G_OBJECT (handler));
- }
- else
- {
- empathy_call_handler_start_tpfs (handler);
- empathy_tp_call_accept_incoming_call (priv->call);
- }
-}