Commit 0c5b0799 authored by Guido Günther's avatar Guido Günther
Browse files

Initial commit

Based on calls-call-display and bits from libhandy.
parents
Pipeline #294028 passed with stage
in 2 minutes and 20 seconds
include:
- 'https://source.puri.sm/Librem5/librem5-ci/raw/master/librem5-pipeline-definitions.yml'
stages:
- build
variables:
DIST: bullseye
DEPS: ccache build-essential libgtk-3-dev libcallaudio-dev libhandy-1-dev meson
EXP_DEPS: libhandy-1-dev/experimental libhandy-1-0/experimental gir1.2-handy-1/experimental libgladeui-common/experimental
before_script:
- echo "man-db man-db/auto-update boolean false" | debconf-set-selections
- export DEBIAN_FRONTEND=noninteractive
- echo "deb http://deb.debian.org/debian/ experimental main" > /etc/apt/sources.list.d/exp.list
- apt-get -y update
- apt-get -y install eatmydata
- eatmydata apt-get -y install $DEPS
- eatmydata apt-get -y install $EXP_DEPS
.build: &build_steps
echo "BUILD_OPTS=${BUILD_OPTS}" &&
export LC_ALL=C.UTF-8 &&
meson ${BUILD_OPTS} . _build &&
ninja -C _build
build-debian-gcc:
image: debian:bullseye
stage: build
variables:
BUILD_OPTS: --werror
script:
- *build_steps
artifacts:
when: always
paths:
- _build
Adrien Plazas <kekun.plazas@laposte.net>
Alexander Mikhaylenko <alexm@gnome.org>
Arnaud Ferraris <arnaud.ferraris@gmail.com>
Bob Ham <bob.ham@puri.sm>
Evangelos Ribeiro Tzaras <evangelos.tzaras@puri.sm>
Guido Günther <agx@sigxcpu.org>
Julian Sparber <julian@sparber.net>
Mohammed Sadiq <sadiq@sadiqpk.org>
This diff is collapsed.
# libcall-ui
Libcall-ui carries common user interface parts for call handling. It is meant
to be used as a git submodule.
## License
libcall-ui is licensed under the LGPLv2.1-or-later.
## Getting the source
```sh
git clone https://gitlab.gnome.org/guido/libcall-ui.git
cd libcall-ui
```
The main branch has the current development version.
## Dependencies
See `meson.build` for required dependencies.
## Building
We use the meson (and thereby Ninja) build system for phosh. The quickest
way to get going is to do the following:
meson . _build
ninja -C _build
ninja -C _build install
## Running the demo
You can run the contained demo via:
_build/examples/call-ui-demo
# Getting in Touch
* Issue tracker: https://gitlab.gnome.org/guidog/libcall-ui/issues
* Matrix: https://im.puri.sm/#/room/#calls:talk.puri.sm
/*
* Autogenerated by the Meson build system.
* Do not edit, your changes will be lost.
*/
#pragma once
#mesondefine GETTEXT_PACKAGE
#mesondefine LOCALEDIR
#include <gtk/gtk.h>
#include <call-ui.h>
#include "cui-demo-window.h"
static void
startup (GtkApplication *app)
{
GtkCssProvider *css_provider = gtk_css_provider_new ();
hdy_init ();
cui_init (FALSE);
gtk_css_provider_load_from_resource (css_provider, "/org/gnome/CallUI/Demo/ui/style.css");
gtk_style_context_add_provider_for_screen (gdk_screen_get_default (),
GTK_STYLE_PROVIDER (css_provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
g_object_unref (css_provider);
}
static void
show_window (GtkApplication *app)
{
CuiDemoWindow *window;
window = cui_demo_window_new (app);
gtk_window_present (GTK_WINDOW (window));
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gnome.CallUI.Demo", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "startup", G_CALLBACK (startup), NULL);
g_signal_connect (app, "activate", G_CALLBACK (show_window), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/CallUI/Demo">
<file preprocess="xml-stripblanks">icons/scalable/actions/call-ui-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/scalable/actions/call-arrow-incoming-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/scalable/status/dark-mode-symbolic.svg</file>
<file preprocess="xml-stripblanks">icons/scalable/status/light-mode-symbolic.svg</file>
</gresource>
<gresource prefix="/org/gnome/CallUI/Demo/ui">
<file preprocess="xml-stripblanks">cui-demo-window.ui</file>
<file compressed="true">style.css</file>
</gresource>
</gresources>
/*
* Copyright (C) 2021 Purism SPC
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Author: Guido Günther <agx@sigxcpu.org>
*/
#include "cui-demo-call.h"
#include <glib/gi18n.h>
enum {
PROP_0,
PROP_DISPLAY_NAME,
PROP_ID,
PROP_STATE,
PROP_ENCRYPED,
PROP_LAST_PROP,
};
struct _CuiDemoCall
{
GObject parent_instance;
gchar *id;
gchar *display_name;
CuiCallState state;
gboolean encrypted;
};
static void cui_demo_cui_call_interface_init (CuiCallInterface *iface);
G_DEFINE_TYPE_WITH_CODE (CuiDemoCall, cui_demo_call, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (CUI_TYPE_CALL,
cui_demo_cui_call_interface_init))
static void
cui_demo_call_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
CuiDemoCall *self = CUI_DEMO_CALL (object);
switch (prop_id) {
case PROP_ID:
g_value_set_string (value, self->id);
break;
case PROP_DISPLAY_NAME:
g_value_set_string (value, self->display_name);
break;
case PROP_STATE:
g_value_set_enum (value, self->state);
break;
case PROP_ENCRYPED:
g_value_set_boolean (value, self->encrypted);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
cui_demo_call_class_init (CuiDemoCallClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = cui_demo_call_get_property;
g_object_class_override_property (object_class,
PROP_DISPLAY_NAME,
"id");
g_object_class_override_property (object_class,
PROP_ID,
"display-name");
g_object_class_override_property (object_class,
PROP_STATE,
"state");
g_object_class_override_property (object_class,
PROP_ENCRYPED,
"encrypted");
}
static const char *
cui_demo_call_get_id (CuiCall *call)
{
g_return_val_if_fail (CUI_IS_DEMO_CALL (call), NULL);
return CUI_DEMO_CALL (call)->id;
}
static const char *
cui_demo_call_get_display_name (CuiCall *call)
{
g_return_val_if_fail (CUI_IS_DEMO_CALL (call), NULL);
return CUI_DEMO_CALL (call)->display_name;
}
static CuiCallState
cui_demo_call_get_state (CuiCall *call)
{
g_return_val_if_fail (CUI_IS_DEMO_CALL (call), CUI_CALL_STATE_UNKNOWN);
return CUI_DEMO_CALL (call)->state;
}
static gboolean
cui_demo_call_get_encrypted (CuiCall *call)
{
g_return_val_if_fail (CUI_IS_DEMO_CALL (call), CUI_CALL_STATE_UNKNOWN);
return CUI_DEMO_CALL (call)->encrypted;
}
static gboolean
on_accept_timeout (gpointer data)
{
CuiDemoCall *self = CUI_DEMO_CALL (data);
self->state = CUI_CALL_STATE_ACTIVE;
g_object_notify (G_OBJECT (self), "state");
return G_SOURCE_REMOVE;
}
static gboolean
on_hang_up_timeout (gpointer data)
{
CuiDemoCall *self = CUI_DEMO_CALL (data);
self->state = CUI_CALL_STATE_DISCONNECTED;
g_object_notify (G_OBJECT (self), "state");
return G_SOURCE_REMOVE;
}
static void
cui_demo_call_accept (CuiCall *call)
{
g_return_if_fail (CUI_IS_DEMO_CALL (call));
g_timeout_add_seconds (1, on_accept_timeout, call);
}
static void
cui_demo_call_hang_up (CuiCall *call)
{
g_return_if_fail (CUI_IS_DEMO_CALL (call));
g_timeout_add (250, on_hang_up_timeout, call);
}
static void
cui_demo_cui_call_interface_init (CuiCallInterface *iface)
{
iface->get_id = cui_demo_call_get_id;
iface->get_display_name = cui_demo_call_get_display_name;
iface->get_state = cui_demo_call_get_state;
iface->get_encrypted = cui_demo_call_get_encrypted;
iface->accept = cui_demo_call_accept;
iface->hang_up = cui_demo_call_hang_up;
}
static void
cui_demo_call_init (CuiDemoCall *self)
{
self->display_name = g_strdup ("John Doe");
self->id = "0800 1234";
self->state = CUI_CALL_STATE_INCOMING;
}
CuiDemoCall *
cui_demo_call_new (void)
{
return g_object_new (CUI_TYPE_DEMO_CALL, NULL);
}
#pragma once
#include <cui-call.h>
G_BEGIN_DECLS
#define CUI_TYPE_DEMO_CALL (cui_demo_call_get_type())
G_DECLARE_FINAL_TYPE (CuiDemoCall, cui_demo_call, CUI, DEMO_CALL, GObject)
CuiDemoCall *cui_demo_call_new (void);
G_END_DECLS
/*
* Copyright (C) 2021 Purism SPC
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Author: Guido Günther <agx@sigxcpu.org>
*/
#include "cui-demo-call.h"
#include "cui-demo-window.h"
#include <glib/gi18n.h>
struct _CuiDemoWindow
{
HdyApplicationWindow parent_instance;
GtkImage *theme_variant_image;
HdyLeaflet *content_box;
CuiCallDisplay *call_display;
CuiDemoCall *call1;
};
G_DEFINE_TYPE (CuiDemoWindow, cui_demo_window, HDY_TYPE_APPLICATION_WINDOW)
static void
theme_variant_button_clicked_cb (CuiDemoWindow *self)
{
GtkSettings *settings = gtk_settings_get_default ();
gboolean prefer_dark_theme;
g_object_get (settings, "gtk-application-prefer-dark-theme", &prefer_dark_theme, NULL);
g_object_set (settings, "gtk-application-prefer-dark-theme", !prefer_dark_theme, NULL);
}
static gboolean
prefer_dark_theme_to_icon_name_cb (GBinding *binding,
const GValue *from_value,
GValue *to_value,
gpointer user_data)
{
g_value_set_string (to_value,
g_value_get_boolean (from_value) ? "light-mode-symbolic" :
"dark-mode-symbolic");
return TRUE;
}
static void
back_clicked_cb (GtkWidget *sender,
CuiDemoWindow *self)
{
hdy_leaflet_navigate (self->content_box, HDY_NAVIGATION_DIRECTION_BACK);
}
static void
on_incoming_call_clicked (GtkWidget *sender,
CuiDemoWindow *self)
{
if (!self->call1) {
self->call1 = cui_demo_call_new ();
cui_call_display_set_call (self->call_display, CUI_CALL (self->call1));
}
}
static gboolean
key_pressed_cb (GtkWidget *sender,
GdkEvent *event,
CuiDemoWindow *self)
{
GdkModifierType default_modifiers = gtk_accelerator_get_default_mod_mask ();
guint keyval;
GdkModifierType state;
GdkKeymap *keymap;
GdkEventKey *key_event = (GdkEventKey *) event;
gdk_event_get_state (event, &state);
keymap = gdk_keymap_get_for_display (gtk_widget_get_display (sender));
gdk_keymap_translate_keyboard_state (keymap,
key_event->hardware_keycode,
state,
key_event->group,
&keyval, NULL, NULL, NULL);
if ((keyval == GDK_KEY_q || keyval == GDK_KEY_Q) &&
(state & default_modifiers) == GDK_CONTROL_MASK) {
gtk_widget_destroy (GTK_WIDGET (self));
return TRUE;
}
return FALSE;
}
static void
cui_demo_window_class_init (CuiDemoWindowClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/CallUI/Demo/ui/cui-demo-window.ui");
gtk_widget_class_bind_template_child (widget_class, CuiDemoWindow, call_display);
gtk_widget_class_bind_template_child (widget_class, CuiDemoWindow, content_box);
gtk_widget_class_bind_template_child (widget_class, CuiDemoWindow, theme_variant_image);
gtk_widget_class_bind_template_callback (widget_class, back_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, key_pressed_cb);
gtk_widget_class_bind_template_callback (widget_class, theme_variant_button_clicked_cb);
gtk_widget_class_bind_template_callback (widget_class, on_incoming_call_clicked);
}
static void
cui_demo_window_init (CuiDemoWindow *self)
{
GtkSettings *settings = gtk_settings_get_default ();
gtk_widget_init_template (GTK_WIDGET (self));
g_object_bind_property_full (settings, "gtk-application-prefer-dark-theme",
self->theme_variant_image, "icon-name",
G_BINDING_SYNC_CREATE,
prefer_dark_theme_to_icon_name_cb,
NULL,
NULL,
NULL);
}
CuiDemoWindow *
cui_demo_window_new (GtkApplication *application)
{
return g_object_new (CUI_TYPE_DEMO_WINDOW, "application", application, NULL);
}
#pragma once
#include <call-ui.h>
#include <handy.h>
G_BEGIN_DECLS
#define CUI_TYPE_DEMO_WINDOW (cui_demo_window_get_type())
G_DECLARE_FINAL_TYPE (CuiDemoWindow, cui_demo_window, CUI, DEMO_WINDOW, HdyApplicationWindow)
CuiDemoWindow *cui_demo_window_new (GtkApplication *application);
G_END_DECLS
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<requires lib="gtk+" version="3.24"/>
<requires lib="libhandy" version="1.0"/>
<template class="CuiDemoWindow" parent="HdyApplicationWindow">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Call-UI Demo</property>
<property name="default_width">800</property>
<property name="default_height">576</property>
<signal name="key-press-event" handler="key_pressed_cb" after="yes" swapped="no"/>
<child>
<object class="HdyLeaflet" id="content_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="can-swipe-back">True</property>
<property name="width-request">360</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkRevealer" id="header_revealer">
<property name="visible">True</property>
<property name="transition-type">slide-down</property>
<property name="reveal-child">True</property>
<child>
<object class="HdyHeaderBar" id="header_bar">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">Call-UI Demo</property>
<property name="show_close_button">True</property>
<child>
<object class="GtkButton">
<property name="visible">True</property>
<property name="can_focus">True</property>
<signal name="clicked" handler="theme_variant_button_clicked_cb" swapped="yes"/>
<child>
<object class="GtkImage" id="theme_variant_image">
<property name="visible">True</property>
<property name="can_focus">False</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkStackSidebar" id="sidebar">
<property name="width_request">270</property>
<property name="visible">True</property>
<property name="vexpand">True</property>
<property name="can_focus">False</property>
<property name="stack">stack</property>
</object>
</child>
</object>
<packing>
<property name="name">sidebar</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkRevealer">
<property name="visible">True</property>
<property name="transition-type" bind-source="header_revealer" bind-property="transition-type" bind-flags="bidirectional|sync-create"/>
<property name="reveal-child" bind-source="header_revealer" bind-property="reveal-child" bind-flags="bidirectional|sync-create"/>
<child>
<object class="HdyWindowHandle" id="header_separator">
<property name="visible">True</property>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<style>
<class name="sidebar"/>
</style>
</object>
</child>
</object>
</child>
</object>
</child>
<child>
<object class="GtkSeparator">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="vexpand">True</property>