Commit 66e4df72 authored by Olivier Gregoire's avatar Olivier Gregoire Committed by Stepan Salenikovich

add SmartInfo

Use smartInfoHub API to display relevant advanced information
during a call.

Change-Id: Ia4e19953e69460ee7e006654cba553bfc2d06581
[stepan.salenikovich@savoirfairelinux.com:  got rid of mem leaks; disconnect
 from signal on destructions; improved menu item; perform start/stop action
 in RingClient so that it can be called from anywhere]
Signed-off-by: default avatarStepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
Reviewed-by: default avatarStepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
parent 5fd97bc6
......@@ -42,6 +42,7 @@
#include "chatview.h"
#include <itemdataroles.h>
#include <numbercategory.h>
#include <smartinfohub.h>
static constexpr int CONTROLS_FADE_TIMEOUT = 3000000; /* microseconds */
static constexpr int FADE_DURATION = 500; /* miliseconds */
......@@ -62,11 +63,15 @@ struct _CurrentCallViewPrivate
{
GtkWidget *hbox_call_info;
GtkWidget *hbox_call_controls;
GtkWidget *vbox_call_smartInfo;
GtkWidget *image_peer;
GtkWidget *label_name;
GtkWidget *label_uri;
GtkWidget *label_status;
GtkWidget *label_duration;
GtkWidget *label_smartinfo_description;
GtkWidget *label_smartinfo_value;
GtkWidget *label_smartinfo_general_information;
GtkWidget *paned_call;
GtkWidget *frame_video;
GtkWidget *video_widget;
......@@ -95,6 +100,10 @@ struct _CurrentCallViewPrivate
ClutterTransition *fade_controls;
gint64 time_last_mouse_motion;
guint timer_fade;
// smart info
QMetaObject::Connection smartinfo_refresh_connection;
guint smartinfo_action;
};
G_DEFINE_TYPE_WITH_PRIVATE(CurrentCallView, current_call_view, GTK_TYPE_BOX);
......@@ -121,11 +130,14 @@ current_call_view_dispose(GObject *object)
QObject::disconnect(priv->call_details_connection);
QObject::disconnect(priv->local_renderer_connection);
QObject::disconnect(priv->remote_renderer_connection);
QObject::disconnect(priv->smartinfo_refresh_connection);
g_clear_object(&priv->settings);
g_source_remove(priv->timer_fade);
auto display_smartinfo = g_action_map_lookup_action(G_ACTION_MAP(g_application_get_default()), "display-smartinfo");
g_signal_handler_disconnect(display_smartinfo, priv->smartinfo_action);
G_OBJECT_CLASS(current_call_view_parent_class)->dispose(object);
}
......@@ -410,6 +422,7 @@ current_call_view_init(CurrentCallView *view)
auto stage = gtk_clutter_embed_get_stage(GTK_CLUTTER_EMBED(priv->video_widget));
auto actor_info = gtk_clutter_actor_new_with_contents(priv->hbox_call_info);
auto actor_controls = gtk_clutter_actor_new_with_contents(priv->hbox_call_controls);
auto actor_smartInfo = gtk_clutter_actor_new_with_contents(priv->vbox_call_smartInfo);
clutter_actor_add_child(stage, actor_info);
clutter_actor_set_x_align(actor_info, CLUTTER_ACTOR_ALIGN_FILL);
......@@ -419,6 +432,14 @@ current_call_view_init(CurrentCallView *view)
clutter_actor_set_x_align(actor_controls, CLUTTER_ACTOR_ALIGN_CENTER);
clutter_actor_set_y_align(actor_controls, CLUTTER_ACTOR_ALIGN_END);
clutter_actor_add_child(stage, actor_smartInfo);
clutter_actor_set_x_align(actor_smartInfo, CLUTTER_ACTOR_ALIGN_END);
clutter_actor_set_y_align(actor_smartInfo, CLUTTER_ACTOR_ALIGN_START);
ClutterMargin clutter_margin_smartInfo;
clutter_margin_smartInfo.top = 50;
clutter_margin_smartInfo.right = 10;
clutter_actor_set_margin (actor_smartInfo, &clutter_margin_smartInfo);
/* add fade in and out states to the info and controls */
priv->time_last_mouse_motion = g_get_monotonic_time();
priv->fade_info = create_fade_out_transition();
......@@ -477,11 +498,15 @@ current_call_view_class_init(CurrentCallViewClass *klass)
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, hbox_call_info);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, hbox_call_controls);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, vbox_call_smartInfo);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, image_peer);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, label_name);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, label_uri);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, label_status);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, label_duration);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, label_smartinfo_description);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, label_smartinfo_value);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, label_smartinfo_general_information);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, paned_call);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, frame_video);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, frame_chat);
......@@ -528,6 +553,67 @@ update_details(CurrentCallView *view, Call *call)
gtk_label_set_text(GTK_LABEL(priv->label_duration), ba_length.constData());
}
static void
update_smartInfo(CurrentCallView *view)
{
CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(view);
if (!SmartInfoHub::instance().isConference()) {
gchar* general_information = g_strdup_printf("Call ID: %s", SmartInfoHub::instance().callID().toStdString().c_str());
gtk_label_set_text(GTK_LABEL(priv->label_smartinfo_general_information), general_information);
g_free(general_information);
gchar* description = g_strdup_printf("You\n"
"Framerate:\n"
"Video codec:\n"
"Audio codec:\n"
"Resolution:\n\n"
"Peer\n"
"Framerate:\n"
"Video codec:\n"
"Audio codec:\n"
"Resolution:");
gtk_label_set_text(GTK_LABEL(priv->label_smartinfo_description),description);
g_free(description);
gchar* value = g_strdup_printf("\n%f\n%s\n%s\n%dx%d\n\n\n%f\n%s\n%s\n%dx%d",
(double)SmartInfoHub::instance().localFps(),
SmartInfoHub::instance().localVideoCodec().toStdString().c_str(),
SmartInfoHub::instance().localAudioCodec().toStdString().c_str(),
SmartInfoHub::instance().localWidth(),
SmartInfoHub::instance().localHeight(),
(double)SmartInfoHub::instance().remoteFps(),
SmartInfoHub::instance().remoteVideoCodec().toStdString().c_str(),
SmartInfoHub::instance().remoteAudioCodec().toStdString().c_str(),
SmartInfoHub::instance().remoteWidth(),
SmartInfoHub::instance().remoteHeight());
gtk_label_set_text(GTK_LABEL(priv->label_smartinfo_value),value);
g_free(value);
} else {
gchar* general_information = g_strdup_printf("Conference ID: %s", SmartInfoHub::instance().callID().toStdString().c_str());
gtk_label_set_text(GTK_LABEL(priv->label_smartinfo_general_information), general_information);
g_free(general_information);
gchar* description = g_strdup_printf("You\n"
"Framerate:\n"
"Video codec:\n"
"Audio codec:\n"
"Resolution:");
gtk_label_set_text(GTK_LABEL(priv->label_smartinfo_description),description);
g_free(description);
gchar* value = g_strdup_printf("\n%f\n%s\n%s\n%dx%d",
(double)SmartInfoHub::instance().localFps(),
SmartInfoHub::instance().localVideoCodec().toStdString().c_str(),
SmartInfoHub::instance().localAudioCodec().toStdString().c_str(),
SmartInfoHub::instance().localWidth(),
SmartInfoHub::instance().localHeight());
gtk_label_set_text(GTK_LABEL(priv->label_smartinfo_value),value);
g_free(value);
}
}
static gboolean
on_button_press_in_video_event(GtkWidget *self, GdkEventButton *event, CurrentCallView *view)
{
......@@ -543,6 +629,16 @@ on_button_press_in_video_event(GtkWidget *self, GdkEventButton *event, CurrentCa
return GDK_EVENT_PROPAGATE;
}
static void
toggle_smartinfo(GSimpleAction* action, G_GNUC_UNUSED GVariant* state, GtkWidget* vbox_call_smartInfo)
{
if (g_variant_get_boolean(g_action_get_state(G_ACTION(action)))) {
gtk_widget_show(vbox_call_smartInfo);
} else {
gtk_widget_hide(vbox_call_smartInfo);
}
}
void
current_call_view_set_call_info(CurrentCallView *view, const QModelIndex& idx) {
CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(view);
......@@ -573,6 +669,12 @@ current_call_view_set_call_info(CurrentCallView *view, const QModelIndex& idx) {
update_state(view, priv->call);
update_details(view, priv->call);
priv->smartinfo_refresh_connection = QObject::connect(
&SmartInfoHub::instance(),
&SmartInfoHub::changed,
[view, priv]() { update_smartInfo(view); }
);
priv->state_change_connection = QObject::connect(
priv->call,
&Call::stateChanged,
......@@ -629,6 +731,13 @@ current_call_view_set_call_info(CurrentCallView *view, const QModelIndex& idx) {
G_CALLBACK(on_button_press_in_video_event),
view);
/* handle smartinfo in right click menu */
auto display_smartinfo = g_action_map_lookup_action(G_ACTION_MAP(g_application_get_default()), "display-smartinfo");
priv->smartinfo_action = g_signal_connect(display_smartinfo,
"notify::state",
G_CALLBACK(toggle_smartinfo),
priv->vbox_call_smartInfo);
/* check if auto quality is enabled or not; */
if (const auto& codecModel = priv->call->account()->codecModel()) {
const auto& videoCodecs = codecModel->videoCodecs();
......
......@@ -50,6 +50,7 @@
#include <peerprofilecollection.h>
#include <localprofilecollection.h>
#include <accountmodel.h>
#include <smartinfohub.h>
// Ring client
#include "ring_client_options.h"
......@@ -177,16 +178,28 @@ action_about(G_GNUC_UNUSED GSimpleAction *simple,
ring_about_dialog(priv->win);
}
static void
toggle_smartinfo(GSimpleAction *action, GVariant *parameter, gpointer)
{
g_simple_action_set_state(action, parameter);
if (g_variant_get_boolean(parameter)) {
SmartInfoHub::instance().start();
} else {
SmartInfoHub::instance().stop();
}
}
static const GActionEntry ring_actions[] =
{
{ "accept", NULL, NULL, NULL, NULL, {0} },
{ "hangup", NULL, NULL, NULL, NULL, {0} },
{ "hold", NULL, NULL, "false", NULL, {0} },
{ "quit", action_quit, NULL, NULL, NULL, {0} },
{ "about", action_about, NULL, NULL, NULL, {0} },
{ "mute_audio", NULL, NULL, "false", NULL, {0} },
{ "mute_video", NULL, NULL, "false", NULL, {0} },
{ "record", NULL, NULL, "false", NULL, {0} },
{ "accept", NULL, NULL, NULL, NULL, {0} },
{ "hangup", NULL, NULL, NULL, NULL, {0} },
{ "hold", NULL, NULL, "false", NULL, {0} },
{ "quit", action_quit, NULL, NULL, NULL, {0} },
{ "about", action_about, NULL, NULL, NULL, {0} },
{ "mute_audio", NULL, NULL, "false", NULL, {0} },
{ "mute_video", NULL, NULL, "false", NULL, {0} },
{ "record", NULL, NULL, "false", NULL, {0} },
{ "display-smartinfo", NULL, NULL, "false", toggle_smartinfo, {0} },
/* TODO implement the other actions */
// { "transfer", NULL, NULL, "flase", NULL, {0} },
};
......
......@@ -33,6 +33,7 @@
#include <mutex>
#include <call.h>
#include "xrectsel.h"
#include <smartinfohub.h>
static constexpr int VIDEO_LOCAL_SIZE = 150;
static constexpr int VIDEO_LOCAL_OPACITY_DEFAULT = 255; /* out of 255 */
......@@ -172,7 +173,6 @@ video_widget_finalize(GObject *object)
G_OBJECT_CLASS(video_widget_parent_class)->finalize(object);
}
/*
* video_widget_class_init()
*
......@@ -522,6 +522,15 @@ video_widget_on_button_press_in_screen_event(GtkWidget *parent, GdkEventButton
g_object_set_data(G_OBJECT(item), JOIN_CALL_KEY, call);
g_signal_connect(item, "activate", G_CALLBACK(switch_video_input_file), parent);
/* add separator */
gtk_menu_shell_append(GTK_MENU_SHELL(menu), gtk_separator_menu_item_new());
/* add SmartInfo */
item = gtk_check_menu_item_new_with_mnemonic(_("Show advanced information"));
gtk_actionable_set_action_name(GTK_ACTIONABLE(item), "app.display-smartinfo");
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
gtk_widget_insert_action_group(menu, "app", G_ACTION_GROUP(g_application_get_default()));
/* show menu */
gtk_widget_show_all(menu);
gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event->button, event->time);
......
......@@ -47,6 +47,81 @@
<!-- end of Paned container -->
</template>
<!-- vertical box which contains smartInfo -->
<object class="GtkBox" id="vbox_call_smartInfo">
<property name="visible">True</property>
<property name="spacing">5</property>
<property name="valign">start</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="label_smartinfo_general_information">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="selectable">True</property>
<property name="ellipsize">end</property>
<property name="halign">start</property>
<attributes>
<attribute name="scale" value="1"/>
<attribute name="foreground" value="#8a8ae2e23434"/>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<!-- horizontal box which contains smartInfo -->
<object class="GtkBox" id="hbox_call_smartInfo">
<property name="visible">True</property>
<property name="hexpand">True</property>
<property name="spacing">10</property>
<property name="border-width">10</property>
<child>
<object class="GtkLabel" id="label_smartinfo_description">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="selectable">True</property>
<property name="ellipsize">end</property>
<property name="halign">start</property>
<attributes>
<attribute name="scale" value="1"/>
<attribute name="foreground" value="#8a8ae2e23434"/>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label_smartinfo_value">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="selectable">True</property>
<property name="ellipsize">end</property>
<property name="halign">start</property>
<attributes>
<attribute name="scale" value="1"/>
<attribute name="foreground" value="#8a8ae2e23434"/>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
</object>
</child>
<!-- end of horizontal box which contains smartInfo -->
</object>
<!-- end of the vertical box which contains smartInfo -->
<!-- box which contains peer image and name and call status -->
<object class="GtkBox" id="hbox_call_info">
<property name="visible">True</property>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment