Commit f6f42658 authored by Stepan Salenikovich's avatar Stepan Salenikovich

gnome: add video quality control slider

Refs #77698

Change-Id: I88d5e02d1b6685c0483acd798d44b56028ac9621
parent 8073000a
<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M0 0h24v24H0z" fill="none"/>
<path d="M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 11H9.5v-2h-2v2H6V9h1.5v2.5h2V9H11v6zm7-1c0 .55-.45 1-1 1h-.75v1.5h-1.5V15H14c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v4zm-3.5-.5h2v-3h-2v3z"/>
</svg>
\ No newline at end of file
......@@ -16,5 +16,6 @@
<file alias="mute_video">ic_videocam_off_black_24px.svg</file>
<file alias="pause">ic_pause_black_24px.svg</file>
<file alias="end">ic_clear_black_24px.svg</file>
<file alias="quality">ic_high_quality_black_24px.svg</file>
</gresource>
</gresources>
......@@ -45,6 +45,8 @@
#include "models/gtkqtreemodel.h"
#include "video/videowindow.h"
#include "ringnotify.h"
#include <audio/codecmodel.h>
#include <account.h>
struct _CurrentCallView
{
......@@ -75,6 +77,12 @@ struct _CurrentCallViewPrivate
GtkWidget *fullscreen_window;
GtkWidget *buttonbox_call_controls;
GtkWidget *button_hangup;
GtkWidget *scalebutton_quality;
/* flag used to keep track of the video quality scale pressed state;
* we do not want to update the codec bitrate until the user releases the
* scale button */
gboolean quality_scale_pressed;
Call *call;
......@@ -155,6 +163,83 @@ scroll_to_bottom(GtkAdjustment *adjustment, G_GNUC_UNUSED gpointer user_data)
gtk_adjustment_get_upper(adjustment) - gtk_adjustment_get_page_size(adjustment));
}
/**
* This gets the GtkScaleButtonScale widget (which is a GtkScale) from the
* given GtkScaleButton in order to be able to modify its properties and connect
* to its signals
*/
static GtkScale *
gtk_scale_button_get_scale(GtkScaleButton *button)
{
GtkScale *scale = NULL;
GtkWidget *dock = gtk_scale_button_get_popup(button);
// the dock is a popup window which contains a frame, which contains a box
// which contains the + button, scale, and - button
// we want to get the scale
if (GtkWidget *box = gtk_bin_get_child(GTK_BIN(dock))) {
GList *children = gtk_container_get_children(GTK_CONTAINER(box));
for (GList *c = children; c && !scale; c = c->next) {
if (GTK_IS_SCALE(c->data))
scale = GTK_SCALE(c->data);
}
g_list_free(children);
}
return scale;
}
static void
quality_changed(GtkScaleButton *button, G_GNUC_UNUSED gdouble value, CurrentCallView *self)
{
g_return_if_fail(IS_CURRENT_CALL_VIEW(self));
CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(self);
/* only update if the scale button is released, to reduce the number of updates */
if (priv->quality_scale_pressed) return;
/* we get the value directly from the widget, in case this function is not
* called from the event */
unsigned int bitrate = (unsigned int)gtk_scale_button_get_value(button);
if (const auto& codecModel = priv->call->account()->codecModel()) {
const auto& videoCodecs = codecModel->videoCodecs();
for (int i=0; i < videoCodecs->rowCount();i++) {
const auto& idx = videoCodecs->index(i,0);
g_debug("setting codec bitrate to %u", bitrate);
videoCodecs->setData(idx, QString::number(bitrate), CodecModel::Role::BITRATE);
}
codecModel << CodecModel::EditAction::SAVE;
}
}
static gboolean
quality_button_pressed(G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED GdkEvent *event, CurrentCallView *self)
{
g_debug("button pressed");
g_return_val_if_fail(IS_CURRENT_CALL_VIEW(self), FALSE);
CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(self);
priv->quality_scale_pressed = TRUE;
return FALSE; // propogate the event
}
static gboolean
quality_button_released(G_GNUC_UNUSED GtkWidget *widget, G_GNUC_UNUSED GdkEvent *event, CurrentCallView *self)
{
g_debug("button released");
g_return_val_if_fail(IS_CURRENT_CALL_VIEW(self), FALSE);
CurrentCallViewPrivate *priv = CURRENT_CALL_VIEW_GET_PRIVATE(self);
priv->quality_scale_pressed = FALSE;
/* now make sure the quality gets updated */
quality_changed(GTK_SCALE_BUTTON(priv->scalebutton_quality), 0, self);
return FALSE; // propogate the event
}
static void
current_call_view_init(CurrentCallView *view)
{
......@@ -183,6 +268,13 @@ current_call_view_init(CurrentCallView *view)
gtk_style_context_add_provider_for_screen(screen,
GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
/* customize the quality button scale */
if (GtkScale *scale = gtk_scale_button_get_scale(GTK_SCALE_BUTTON(priv->scalebutton_quality))) {
gtk_scale_set_draw_value(scale, TRUE);
gtk_scale_set_value_pos(scale, GTK_POS_RIGHT);
gtk_scale_set_digits(scale, 0);
}
}
static void
......@@ -206,6 +298,7 @@ current_call_view_class_init(CurrentCallViewClass *klass)
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, scrolledwindow_chat);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, buttonbox_call_controls);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, button_hangup);
gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), CurrentCallView, scalebutton_quality);
}
GtkWidget *
......@@ -475,4 +568,20 @@ current_call_view_set_call_info(CurrentCallView *view, const QModelIndex& idx) {
/* check if there were any chat notifications and open the chat view if so */
if (ring_notify_close_chat_notification(priv->call))
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->togglebutton_chat), TRUE);
/* get the current codec quality and set that as the initial slider value
* for now we assume that all codecs have the same quality */
if (const auto& codecModel = priv->call->account()->codecModel()) {
const auto& videoCodecs = codecModel->videoCodecs();
if (videoCodecs->rowCount() > 0) {
const auto& idx = videoCodecs->index(0,0);
double value = idx.data(static_cast<int>(CodecModel::Role::BITRATE)).toDouble();
gtk_scale_button_set_value(GTK_SCALE_BUTTON(priv->scalebutton_quality), value);
}
}
g_signal_connect(priv->scalebutton_quality, "value-changed", G_CALLBACK(quality_changed), view);
g_signal_connect(gtk_scale_button_get_scale(GTK_SCALE_BUTTON(priv->scalebutton_quality)),
"button-press-event", G_CALLBACK(quality_button_pressed), view);
g_signal_connect(gtk_scale_button_get_scale(GTK_SCALE_BUTTON(priv->scalebutton_quality)),
"button-release-event", G_CALLBACK(quality_button_released), view);
}
......@@ -328,6 +328,27 @@
<property name="fill">True</property>
</packing>
</child>
<child>
<object class="GtkScaleButton" id="scalebutton_quality">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="width-request">42</property>
<property name="height-request">42</property>
<property name="has_tooltip">True</property>
<property name="tooltip-text" translatable="yes">Adjust outgoing video quality (bit/s)</property>
<property name="image">image_quality</property>
<property name="adjustment">adjustment_quality</property>
<child internal-child="accessible">
<object class="AtkObject" id="scalebutton_quality-atkobject">
<property name="AtkObject::accessible-name" translatable="yes">Video quality</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
</packing>
</child>
</object>
<packing>
<property name="expand">True</property>
......@@ -388,4 +409,20 @@
</object>
</child>
</object>
<object class="GtkImage" id="image_quality">
<property name="visible">True</property>
<property name="resource">/cx/ring/RingGnome/quality</property>
<child internal-child="accessible">
<object class="AtkObject" id="image_quality-atkobject">
<property name="AtkObject::accessible-description" translatable="yes">Video quality</property>
</object>
</child>
</object>
<object class="GtkAdjustment" id="adjustment_quality">
<property name="lower">200</property>
<property name="upper">3000</property>
<property name="value">800</property>
<property name="step_increment">10</property>
<property name="page_increment">50</property>
</object>
</interface>
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