Commit 48dff5da authored by Arnaud Ferraris's avatar Arnaud Ferraris
Browse files

New upstream version 0.0.0+git20200707

parents 43168c17 68a1e3cd
......@@ -62,6 +62,7 @@ applications which will use the Feedback Theme Specification.
- message-new-email: The event used when a new email is received.
- message-missed-email: The event used when an email was received but not seen by the user.
- message-missed-instant: The event used when a instant message was received but not seen by the user.
- message-missed-notification: The event used when a notification was shown but not seen by the user.
- message-missed-sms: The event used when a sms message was received but not seen by the user.
- phone-incoming-call: This Event is used when a phone/voip call is coming in.
- phone-missed-call: This Event is used when a phone/voip call is was incoming but not answered.
......@@ -84,7 +85,8 @@ applications which will use the Feedback Theme Specification.
### Input Event
- button-pressed: The Event used when a button is pressed.
- button-pressed: The event used when a button is pressed.
- button-released: The event used when a button is released.
- window-close: The sound used when an existing window is closed.
[Sound naming spec]: http://0pointer.de/public/sound-naming-spec.html
......@@ -80,6 +80,7 @@ available feedback types are:
- Sound (an audible sound from the sound naming spec)
- VibraRumble: haptic motor rumbling
- VibraPeriodic: periodic feedback from the haptic motor
- Led: Feedback via blinking LEDs
You can check the feedback theme and the classes (prefixed with Fbd)
for available properties. Note that the feedback theme API (including
......@@ -89,7 +90,7 @@ daemon.
## Profiles
The profile determines which parts of the theme are in use:
- `full`: Use configured events form the `full`, `quiet` and `silent` parts of
- `full`: Use configured events from the `full`, `quiet` and `silent` parts of
the feedback them.
- `quiet`: Use `quiet` and `silent` part from of the feedback theme. This usually
means no audio feedback.
......@@ -101,9 +102,9 @@ It can be set via a GSetting
```sh
gsettings set org.sigxcpu.feedbackd profile full
```
## fbdcli
## fbcli
`fbdcli` can be used to trigger feedback for different events. Here are some examples:
`fbcli` can be used to trigger feedback for different events. Here are some examples:
### Phone call
Run feedbacks for event `phone-incoming-call` until explicitly stopped:
......@@ -127,7 +128,7 @@ _build/cli/fbcli -t 10 -E alarm-clock-elapsed
```
## Per app profiles
One can lower the feedback level of an individual application
One can set the feedback profile of an individual application
via `GSettings`. E.g. for an app with app id `sm.puri.Phosh`
to set the profile to `quiet` do:
......
......@@ -8,6 +8,7 @@
#include <glib.h>
#include <gio/gio.h>
#include <glib-unix.h>
#include <locale.h>
......@@ -15,6 +16,15 @@
static GMainLoop *loop;
static gboolean
on_shutdown_signal (gpointer unused)
{
/* End right away, lfb_uninit will end running feedback */
g_main_loop_quit (loop);
return FALSE;
}
static gboolean
on_watch_expired (gpointer unused)
{
......@@ -39,29 +49,34 @@ on_user_input (GIOChannel *channel, GIOCondition cond, LfbEvent *event)
{
g_autoptr(GError) err = NULL;
if (cond == G_IO_IN) {
if (cond == G_IO_IN) {
g_print ("Ending feedback\n");
if (!lfb_event_end_feedback (event, &err))
g_warning("Failed to end feedback: %s", err->message);
g_warning ("Failed to end feedback: %s", err->message);
}
return FALSE;
}
static gboolean
trigger_event(const char *name, gint timeout)
trigger_event (const char *name, const gchar *profile, gint timeout)
{
g_autoptr(GError) err = NULL;
g_autoptr(LfbEvent) event = NULL;
g_autoptr(GIOChannel) input = NULL;
int success = FALSE;
g_print("Triggering feedback for event '%s'\n", name);
g_unix_signal_add (SIGTERM, on_shutdown_signal, NULL);
g_unix_signal_add (SIGINT, on_shutdown_signal, NULL);
g_print ("Triggering feedback for event '%s'\n", name);
event = lfb_event_new (name);
lfb_event_set_timeout (event, timeout);
if (profile)
lfb_event_set_feedback_profile (event, profile);
g_signal_connect (event, "feedback-ended", (GCallback)on_feedback_ended, &success);
if (!lfb_event_trigger_feedback (event, &err)) {
g_print("Failed to report event: %s\n", err->message);
g_print ("Failed to report event: %s\n", err->message);
return FALSE;
}
......@@ -79,8 +94,8 @@ trigger_event(const char *name, gint timeout)
static void
on_profile_changed (LfbGdbusFeedback *proxy, GParamSpec *psepc, gpointer unused)
{
g_print("Set feedback profile to: '%s'\n",
lfb_get_feedback_profile());
g_print ("Set feedback profile to: '%s'\n",
lfb_get_feedback_profile ());
g_main_loop_quit (loop);
}
......@@ -90,27 +105,28 @@ set_profile (const gchar *profile)
LfbGdbusFeedback *proxy;
const gchar *current;
current = lfb_get_feedback_profile();
g_debug("Current profile is %s", current);
current = lfb_get_feedback_profile ();
g_debug ("Current profile is %s", current);
if (!g_strcmp0 (current, profile)) {
g_print ("Profile is already set to %s\n", profile);
return TRUE;
}
g_debug("Setting profile to %s", profile);
g_debug ("Setting profile to %s", profile);
proxy = lfb_get_proxy ();
/* Set profile and wait until we got notified about the profile change */
loop = g_main_loop_new (NULL, FALSE);
lfb_set_feedback_profile(profile);
lfb_set_feedback_profile (profile);
g_signal_connect (proxy, "notify::profile", (GCallback)on_profile_changed, NULL);
g_main_loop_run (loop);
g_print("Current feedback profile is: '%s'\n",
lfb_get_feedback_profile());
g_print ("Current feedback profile is: '%s'\n",
lfb_get_feedback_profile ());
return TRUE;
}
int main(int argc, char *argv[0])
int
main (int argc, char *argv[0])
{
g_autoptr(GOptionContext) opt_context = NULL;
g_autoptr(GError) err = NULL;
......@@ -120,15 +136,15 @@ int main(int argc, char *argv[0])
int watch = 30;
int timeout = -1;
const GOptionEntry options [] = {
{"event", 'E', 0, G_OPTION_ARG_STRING, &name,
"Event name. (default: " DEFAULT_EVENT ").", NULL},
{"timeout", 't', 0, G_OPTION_ARG_INT, &timeout,
"Run feedback for timeout seconds", NULL},
{"profile", 'P', 0, G_OPTION_ARG_STRING, &profile,
"Profile name to set" , NULL},
{"watch", 'w', 0, G_OPTION_ARG_INT, &watch,
"How long to watch for feedback longest", NULL},
{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
{"event", 'E', 0, G_OPTION_ARG_STRING, &name,
"Event name. (default: " DEFAULT_EVENT ").", NULL},
{"timeout", 't', 0, G_OPTION_ARG_INT, &timeout,
"Run feedback for timeout seconds", NULL},
{"profile", 'P', 0, G_OPTION_ARG_STRING, &profile,
"Profile name to set", NULL},
{"watch", 'w', 0, G_OPTION_ARG_INT, &watch,
"How long to watch for feedback longest", NULL},
{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
};
setlocale (LC_ALL, "");
......@@ -136,22 +152,22 @@ int main(int argc, char *argv[0])
g_option_context_add_main_entries (opt_context, options, NULL);
if (!g_option_context_parse (opt_context, &argc, &argv, &err)) {
g_warning ("%s", err->message);
return 1;
return 1;
}
if (!lfb_init("org.sigxcpu.fbcli", &err)) {
g_print("Failed to init libfeedback: %s\n", err->message);
return 1;
if (!lfb_init ("org.sigxcpu.fbcli", &err)) {
g_print ("Failed to init libfeedback: %s\n", err->message);
return 1;
}
if (!name)
name = g_strdup (DEFAULT_EVENT);
g_timeout_add_seconds (watch, (GSourceFunc)on_watch_expired, NULL);
if (profile)
if (profile && !name)
success = set_profile (profile);
else
success = trigger_event (name, timeout);
success = trigger_event (name, profile, timeout);
lfb_uninit ();
return !success;
......
......@@ -14,6 +14,11 @@
"type" : "Sound",
"effect" : "button-pressed"
},
{
"event-name" : "button-released",
"type" : "Sound",
"effect" : "button-released"
},
{
"event-name" : "message-new-email",
"type" : "Sound",
......@@ -70,7 +75,12 @@
{
"event-name" : "button-pressed",
"type" : "VibraRumble",
"duration" : 25
"duration" : 15
},
{
"event-name" : "button-released",
"type" : "VibraRumble",
"duration" : 12
},
{
"event-name" : "message-new-email",
......@@ -101,11 +111,6 @@
"type" : "VibraPeriodic",
"duration" : 10000
},
{
"event-name" : "phone-missed-call",
"type" : "VibraRumble",
"duration" : 300
},
{
"event-name" : "timeout-completed",
"type" : "VibraRumble",
......@@ -120,7 +125,7 @@
{
"event-name" : "window-close",
"type" : "VibraRumble",
"duration" : 50
"duration" : 25
}
]
},
......@@ -129,28 +134,39 @@
"feedbacks" : [
{
"event-name" : "battery-caution",
"type" : "Dummy",
"duration" : 10000
"type" : "Led",
"color" : "red",
"frequency" : 5000
},
{
"event-name" : "phone-missed-call",
"type" : "Dummy",
"duration" : 10000
"type" : "Led",
"color" : "blue",
"frequency" : 3000
},
{
"event-name" : "message-missed-email",
"type" : "Dummy",
"duration" : 10000
"type" : "Led",
"color" : "blue",
"frequency" : 2000
},
{
"event-name" : "message-missed-instant",
"type" : "Dummy",
"duration" : 10000
"type" : "Led",
"color" : "blue",
"frequency" : 1000
},
{
"event-name" : "message-missed-notification",
"type" : "Led",
"color" : "blue",
"frequency" : 500
},
{
"event-name" : "message-missed-sms",
"type" : "Dummy",
"duration" : 10000
"type" : "Led",
"color" : "blue",
"frequency" : 2000
}
]
}
......
......@@ -12,21 +12,21 @@
Profile: The currently used profile.
The currently used feedback profile name. Applications should
usually not change this value but leave.
usually not change this value.
-->
<property name="Profile" type="s" access="readwrite" />
<!--
TriggerFeedback:
@app_id: The application id usually in reverse "reverse DNS" format
@app_id: The application id usually in "reverse DNS" format
@event: The event name from the Event naming spec
@hints: Additional hints (e.g. to prefer haptic feedback over audio feedback on button press events, currently unused)
@timeout: When the feedbacks for this event should end latest. The special values '-1' (just run each feedack once) and '0' (endless loop) are also supported.
@timeout: When the feedbacks for this event should end latest. The special values '-1' (just run each feedback once) and '0' (endless loop) are also supported.
@id: Event id for future reference
Give user feedback for an event by triggering feedbacks
defined in the daemon. The method call returns an event id
that can be used to later on to e.g. cancel the triggered
that can be used later on to e.g. cancel the triggered
feedbacks early.
Depending on the event, theme and profile several forms of
......
debian/modules-load.d etc/
/usr/bin/
/usr/libexec/
/usr/share/dbus-1/
......
......@@ -6,4 +6,7 @@ ACTION=="remove", GOTO="feedbackd_end"
SUBSYSTEM=="input", KERNEL=="event*", ENV{ID_INPUT}=="1", ENV{ID_PATH}=="platform-vibrator", TAG+="uaccess", ENV{FEEDBACKD_TYPE}="vibra"
# Front leds of the Librem5
SUBSYSTEM=="leds", DEVPATH=="*/phone:*:front", ENV{FEEDBACKD_TYPE}="led", RUN+="/usr/libexec/fbd-ledctrl -p %S%p -t pattern -G video"
LABEL="feedbackd_end"
......@@ -6,7 +6,7 @@ export DEB_BUILD_MAINT_OPTIONS = hardening=+all
dh $@ --builddirectory=_build
override_dh_auto_configure:
dh_auto_configure -- -Dgtk_doc=true
dh_auto_configure -- -Dgtk_doc=true -Dman=true
override_dh_installudev:
# Make sure all the symlink rules in 60 ran:
......
<refentry id="gtester">
<refentryinfo>
<title>fbcli</title>
<productname>feedbackd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Guido</firstname>
<surname>Günther</surname>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>fbcli</refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class="manual">User Commands</refmiscinfo>
</refmeta>
<refnamediv>
<refname>fbcli</refname>
<refpurpose>Emit events to feedbackd</refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>fbcli</command>
<arg choice="opt" rep="repeat">OPTION</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1><title>Description</title>
<para><command>fbcli</command> can be used to submit events to <command>feedbackd</command>
to trigger audio, visual or haptic feedback.
</para>
</refsect1>
<refsect1><title>Options</title>
<variablelist>
<varlistentry>
<term><option>-h</option>, <option>--help</option></term>
<listitem><para>
print help and exit
</para></listitem>
</varlistentry>
<varlistentry>
<term><option>-E=<replaceable>EVENT</replaceable></option></term>
<term><option>--event=<replaceable>EVENT</replaceable></option></term>
<para>
Submit the given event to <command>feedbackd</command>. Valid events are
listes in the event naming spec at
<ulink url="https://source.puri.sm/Librem5/feedbackd/-/blob/master/Event-naming-spec-0.0.0.md"/>
</para>
</varlistentry>
<varlistentry>
<term><option>-t=<replaceable>TIMEOUT</replaceable></option></term>
<term><option>--timeout=<replaceable>TIMEOUT</replaceable></option></term>
<para>
The timeout in seconds after which feedback for the given event should
be stopped.
</para>
</varlistentry>
<varlistentry>
<term><option>-p=<replaceable>PROFILE</replaceable></option></term>
<term><option>--profile=<replaceable>PROFILE</replaceable></option></term>
<para>
The feedback profile (<literal>full</literal>, <literal>quiet</literal>, <literal>silent</literal>)
to use for the given event. If no event is specified then the global
feedback profile is changed.
</para>
</varlistentry>
<varlistentry>
<term><option>-w=<replaceable>TIMEOUT</replaceable></option></term>
<term><option>--watch=<replaceable>TIMEOUT</replaceable></option></term>
<para>
Maximum timout to wait for the feedback for the given event to end and
<command>fbcli</command> to exit.
</para>
</varlistentry>
</variablelist>
</refsect1>
<refsect1><title>See also</title>
<para>
<citerefentry>
<refentrytitle>feedbackd</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>
</para>
</refsect1>
</refentry>
<refentry id="gtester">
<refentryinfo>
<title>feedbackd</title>
<productname>feedbackd</productname>
<authorgroup>
<author>
<contrib>Developer</contrib>
<firstname>Guido</firstname>
<surname>Günther</surname>
</author>
</authorgroup>
</refentryinfo>
<refmeta>
<refentrytitle>feedbackd</refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class="manual">User Commands</refmiscinfo>
</refmeta>
<refnamediv>
<refname>feedbackd</refname>
<refpurpose></refpurpose>
</refnamediv>
<refsynopsisdiv>
<cmdsynopsis>
<command>feedbackd</command>
<arg choice="opt" rep="repeat">OPTION</arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1><title>Description</title>
<para>
<command>feedbackd</command> is a daemon that runs in the users
session to trigger event feedback such as playing a sound, trigger
a haptic motor or blink a LED.
</para>
<para>
The feedback triggerd by a given event is determined by the feedback
them in use. Events are submitted via a DBus API. For details
refer to the event and feedback theme specs at
<ulink url="https://source.puri.sm/Librem5/feedbackd/"/>
</para>
</refsect1>
<refsect1><title>Options</title>
<variablelist>
<varlistentry>
<term><option>-h</option>, <option>--help</option></term>
<listitem><para>
print help and exit
</para></listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1><title>See also</title>
<para>
<citerefentry>
<refentrytitle>fbcli</refentrytitle>
<manvolnum>1</manvolnum>
</citerefentry>
</para>
</refsect1>
</refentry>
......@@ -36,5 +36,35 @@ gnome.gtkdoc('libfeedback',
install_dir: 'libfeedback',
content_files: content_files,
install: true)
endif
if get_option('man')
manpages = [
'fbcli',
'feedbackd',
]
xsltproc = find_program('xsltproc', required : true)
xsltproc_command = [
xsltproc,
'--nonet',
'--stringparam', 'man.output.quietly', '1',
'--stringparam', 'funcsynopsis.style', 'ansi',
'--stringparam', 'man.th.extra1.suppress', '1',
'--stringparam', 'man.authors.section.enabled', '0',
'--stringparam', 'man.copyright.section.enabled', '0',
'-o', '@OUTPUT@',
'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl',
'@INPUT@',
]
man1_dir = get_option('mandir') + '/man1'
foreach page : manpages
custom_target(page + '-man',
input : page + '.xml',
output : page + '.1',
command: xsltproc_command,
install: true,
install_dir: man1_dir)
endforeach
endif
<
......@@ -16,7 +16,9 @@
*
* #LfbEvent represents an event that should trigger
* audio, haptic and/or visual feedback to the user by triggering
* feedback on a feedback daemon.
* feedback on a feedback daemon. Valid event names are specified
* in the
* [Event naming specification](https://source.puri.sm/Librem5/feedbackd/-/blob/master/Event-naming-spec-0.0.0.md).
*
* One event can trigger multiple feedbacks at once (e.g. audio and
* haptic feedback). This is determined by the feedback theme in
......@@ -76,6 +78,7 @@ enum {
PROP_TIMEOUT,
PROP_STATE,
PROP_END_REASON,
PROP_FEEDBACK_PROFILE,
PROP_LAST_PROP,
};
static GParamSpec *props[PROP_LAST_PROP];
......@@ -91,6 +94,7 @@ typedef struct _LfbEvent {
char *event;
gint timeout;
gchar *profile;
guint id;
LfbEventState state;
......@@ -126,12 +130,14 @@ lfb_event_set_end_reason (LfbEvent *self, LfbEventEndReason reason)
}
static GVariant *
build_hints (void)
build_hints (LfbEvent *self)
{
GVariantBuilder hints_builder;
g_variant_builder_init (&hints_builder, G_VARIANT_TYPE ("a{sv}"));
return g_variant_new ("a{sv}", &hints_builder);
if (self->profile)
g_variant_builder_add (&hints_builder, "{sv}", "profile", g_variant_new_string (self->profile));
return g_variant_builder_end (&hints_builder);
}
static void
......@@ -160,6 +166,7 @@ on_trigger_feedback_finished (LfbGdbusFeedback *proxy,
} else {
g_task_return_boolean (task, TRUE);
state = LFB_EVENT_STATE_RUNNING;
_lfb_active_add_id (self->id);
}
lfb_event_set_state (self, state);
......@@ -213,6 +220,9 @@ lfb_event_set_property (GObject *object,
case PROP_TIMEOUT:
lfb_event_set_timeout (self, g_value_get_int (value));
break;
case PROP_FEEDBACK_PROFILE:
lfb_event_set_feedback_profile (self, g_value_get_string (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
......@@ -235,6 +245,9 @@ lfb_event_get_property (GObject *object,
case PROP_TIMEOUT:
g_value_set_int (value, self->timeout);
break;
case PROP_FEEDBACK_PROFILE: