Initial commit

Signed-off-by: Guido Günther <agx@sigxcpu.org>
This commit is contained in:
Guido Günther
2020-02-14 17:40:34 +01:00
commit 3663b7d149
83 changed files with 8059 additions and 0 deletions
+617
View File
@@ -0,0 +1,617 @@
/*
* Copyright (C) 2020 Purism SPC
* SPDX-License-Identifier: GPL-3.0+
* Author: Guido Günther <agx@sigxcpu.org>
*/
#include "libfeedback.h"
#include "lfb-priv.h"
#include <gio/gio.h>
/**
* SECTION:lfb-event
* @Short_description: An event triggering feedback to the user
* @Title: LfbEvent
*
* #LfbEvent represents an event that should trigger
* audio, haptic and/or visual feedback to the user by triggering
* feedback on a feedback daemon.
*
* One event can trigger several feedbacks at once (e.g. audio and
* haptic feedback). This is determined by the feedback theme in
* use (which is not under the appliction's control) and the active
* feedback profile (see #lfb_set_feedback_profile()).
*
* After initializing the library feedback can be triggered like
*
* |[
* g_autoptr (GError) err = NULL;
* LpfEvent *event = lfb_event_new ("message-new-instant");
* ret = lfb_event_trigger_feedback (event, &err);
* ]|
*
* When all feedback for this event has ended the #LfbEvent::feedback-ended
* signal is emitted. If you want to end the feedback ahead of time use
* #lfb_event_end_feedback ().
* Since these methods involve DBus calls there are asynchronous variants
* available, see e.g. #lfb_event_trigger_feedback_async().
*/
enum {
PROP_0,
PROP_EVENT,
PROP_TIMEOUT,
PROP_STATE,
PROP_END_REASON,
PROP_LAST_PROP,
};
static GParamSpec *props[PROP_LAST_PROP];
enum {
SIGNAL_FEEDBACK_ENDED,
N_SIGNALS,
};
static guint signals[N_SIGNALS];
typedef struct _LfbEvent {
GObject parent;
char *event;
gint timeout;
guint id;
LfbEventState state;
gint end_reason;
gulong handler_id;
} LfbEvent;
G_DEFINE_TYPE (LfbEvent, lfb_event, G_TYPE_OBJECT);
typedef struct _LpfAsyncData {
LfbEvent *event;
GTask *task;
} LpfAsyncData;
static void
lfb_event_set_state (LfbEvent *self, LfbEventState state)
{
if (self->state == state)
return;
self->state = state;
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_STATE]);
}
static void
lfb_event_set_end_reason (LfbEvent *self, LfbEventEndReason reason)
{
if (self->end_reason == reason)
return;
self->end_reason = reason;
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_END_REASON]);
}
static GVariant *
build_hints (void)
{
GVariantBuilder hints_builder;
g_variant_builder_init (&hints_builder, G_VARIANT_TYPE ("a{sv}"));
return g_variant_new ("a{sv}", &hints_builder);
}
static void
on_trigger_feedback_finished (LfbGdbusFeedback *proxy,
GAsyncResult *res,
LpfAsyncData *data)
{
GTask *task = data->task;
LfbEvent *self = data->event;
GError *err = NULL;
gboolean success;
LfbEventState state;
g_return_if_fail (G_IS_TASK (task));
g_return_if_fail (LFB_GDBUS_IS_FEEDBACK (proxy));
g_return_if_fail (LFB_IS_EVENT (self));
success = lfb_gdbus_feedback_call_trigger_feedback_finish (proxy,
&self->id,
res,
&err);
if (!success) {
g_task_return_error (task, err);
state = LFB_EVENT_STATE_ERRORED;
} else {
g_task_return_boolean (task, TRUE);
state = LFB_EVENT_STATE_RUNNING;
}
lfb_event_set_state (self, state);
g_free (data);
g_object_unref (task);
g_object_unref (self);
}
static void
on_end_feedback_finished (LfbGdbusFeedback *proxy,
GAsyncResult *res,
LpfAsyncData *data)
{
GTask *task = data->task;
LfbEvent *self = data->event;
GError *err = NULL;
gboolean success;
g_return_if_fail (G_IS_TASK (task));
g_return_if_fail (LFB_GDBUS_IS_FEEDBACK (proxy));
g_return_if_fail (LFB_IS_EVENT (self));
success = lfb_gdbus_feedback_call_end_feedback_finish (proxy,
res,
&err);
if (!success) {
g_task_return_error (task, err);
} else
g_task_return_boolean (task, TRUE);
g_free (data);
g_object_unref (task);
g_object_unref (self);
}
static void
lfb_event_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
LfbEvent *self = LFB_EVENT (object);
switch (property_id) {
case PROP_EVENT:
g_free (self->event);
self->event = g_value_dup_string (value);
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_EVENT]);
break;
case PROP_TIMEOUT:
lfb_event_set_timeout (self, g_value_get_int (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
lfb_event_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
LfbEvent *self = LFB_EVENT (object);
switch (property_id) {
case PROP_EVENT:
g_value_set_string (value, self->event);
break;
case PROP_TIMEOUT:
g_value_set_int (value, self->timeout);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
lfb_event_finalize (GObject *object)
{
LfbEvent *self = LFB_EVENT (object);
/* Signal handler is disconnected automatically due to due to g_signal_connect_object */
self->handler_id = 0;
g_clear_pointer (&self->event, g_free);
G_OBJECT_CLASS (lfb_event_parent_class)->finalize (object);
}
static void
lfb_event_class_init (LfbEventClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = lfb_event_set_property;
object_class->get_property = lfb_event_get_property;
object_class->finalize = lfb_event_finalize;
/**
* LpfEvent:event:
*
* The type of event from the Event naming spec, e.g. 'message-new-instant'.
*/
props[PROP_EVENT] =
g_param_spec_string (
"event",
"Event",
"The name of the event triggering the feedback",
NULL,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
/**
* LpfEvent:timeout:
*
* How long feedback should be provided in milliseconds. The special value
* %-1 uses the natural length of each feedback while %0 plays each feedback
* in a loop until ended explicitly.
*/
props[PROP_TIMEOUT] =
g_param_spec_int (
"timeout",
"Timeout",
"When the event should timeout",
-1, G_MAXINT, -1,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
props[PROP_STATE] =
g_param_spec_enum (
"state",
"State",
"The event's state",
LFB_TYPE_EVENT_STATE,
LFB_EVENT_END_REASON_NATURAL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
props[PROP_END_REASON] =
g_param_spec_enum (
"end-reason",
"End reason",
"The reason why the feedbacks ended",
LFB_TYPE_EVENT_END_REASON,
LFB_EVENT_END_REASON_NATURAL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (object_class, PROP_LAST_PROP, props);
/**
* LfbEvent::feedback-ended:
*
* Emitted when all feedbacks triggered by the event have ended.
*/
signals[SIGNAL_FEEDBACK_ENDED] = g_signal_new ("feedback-ended",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST, 0, NULL, NULL,
NULL,
G_TYPE_NONE,
0);
}
static void
lfb_event_init (LfbEvent *self)
{
self->timeout = -1;
self->state = LFB_EVENT_STATE_NONE;
self->end_reason = LFB_EVENT_END_REASON_NATURAL;
}
LfbEvent *
lfb_event_new (const char *event)
{
return g_object_new (LFB_TYPE_EVENT, "event", event, NULL);
}
static void
on_feedback_ended (LfbEvent *self,
guint event_id,
guint reason,
LfbGdbusFeedback *proxy)
{
g_return_if_fail (LFB_IS_EVENT (self));
g_return_if_fail (LFB_GDBUS_IS_FEEDBACK (proxy));
if (event_id != self->id)
return;
lfb_event_set_end_reason (self, reason);
lfb_event_set_state (self, LFB_EVENT_STATE_ENDED);
g_signal_emit (self, signals[SIGNAL_FEEDBACK_ENDED], 0);
self->id = 0;
g_signal_handler_disconnect (proxy, self->handler_id);
self->handler_id = 0;
}
/**
* lfb_event_trigger_feedback:
* @self: The event to trigger feedback for.
* @error: The returned error information.
*
* Tells the feedback server to provide proper feedback for the give
* event to the user.
*
* Returns: %TRUE if successful. On error, this will return %FALSE and set
* @error.
*/
gboolean
lfb_event_trigger_feedback (LfbEvent *self, GError **error)
{
LfbGdbusFeedback *proxy;
gboolean success;
g_return_val_if_fail (LFB_IS_EVENT (self), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (!lfb_is_initted ()) {
g_warning ("you must call lfb_init() before triggering events");
g_assert_not_reached ();
}
proxy = _lfb_get_proxy ();
g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), FALSE);
if (self->handler_id == 0) {
self->handler_id = g_signal_connect_object (proxy,
"feedback-ended",
G_CALLBACK (on_feedback_ended),
self,
G_CONNECT_SWAPPED);
}
success = lfb_gdbus_feedback_call_trigger_feedback_sync (proxy,
lfb_get_app_id (),
self->event,
build_hints (),
self->timeout,
&self->id,
NULL,
error);
lfb_event_set_state (self, success ? LFB_EVENT_STATE_RUNNING : LFB_EVENT_STATE_ERRORED);
return success;
}
/**
* lfb_event_trigger_feedback_async:
* @self: The event to trigger feedback for.
* @cancellable: (nullable): A #GCancellable or %NULL.
* @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
* @user_data: User data to pass to @callback.
*
* Tells the feedback server to provide proper feedback for the give
* event to the user. This is the sync version of
* #lfb_event_trigger_feedback.
*/
void
lfb_event_trigger_feedback_async (LfbEvent *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
LpfAsyncData *data;
LfbGdbusFeedback *proxy;
g_return_if_fail (LFB_IS_EVENT (self));
if (!lfb_is_initted ()) {
g_warning ("you must call lfb_init() before triggering events");
g_assert_not_reached ();
}
proxy = _lfb_get_proxy ();
g_return_if_fail (LFB_GDBUS_IS_FEEDBACK (proxy));
data = g_new0 (LpfAsyncData, 1);
data->task = g_task_new (self, cancellable, callback, user_data);
data->event = g_object_ref (self);
lfb_gdbus_feedback_call_trigger_feedback (proxy,
lfb_get_app_id (),
self->event,
build_hints (),
self->timeout,
cancellable,
(GAsyncReadyCallback)on_trigger_feedback_finished,
data);
}
/**
* lfb_event_trigger_feedback_finish:
* @self: the event
* @res: Result object passed to the callback of
* #lfb_event_trigger_feedback_async
* @error: Return location for error
*
* Finish an async operation started by lfb_event_trigger_feedback_async. You
* must call this function in the callback to free memory and receive any
* errors which occurred.
*
* Returns: %TRUE if playing finished successfully
*/
gboolean
lfb_event_trigger_feedback_finish (LfbEvent *self,
GAsyncResult *res,
GError **error)
{
g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
return g_task_propagate_boolean (G_TASK (res), error);
}
/**
* lfb_event_end_feedback:
* @self: The event to end feedback for.
* @error: The returned error information.
*
* Tells the feedback server to end all feedback for the given event as
* soon as possible.
*
* Returns: %TRUE if successful. On error, this will return %FALSE and set
* @error.
*/
gboolean
lfb_event_end_feedback (LfbEvent *self, GError **error)
{
LfbGdbusFeedback *proxy;
g_return_val_if_fail (LFB_IS_EVENT (self), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (!lfb_is_initted ()) {
g_warning ("you must call lfb_init() before ending events");
g_assert_not_reached ();
}
proxy = _lfb_get_proxy ();
g_return_val_if_fail (LFB_GDBUS_IS_FEEDBACK (proxy), FALSE);
return lfb_gdbus_feedback_call_end_feedback_sync (proxy, self->id, NULL, error);
}
/**
* lfb_event_end_feedback_finish:
* @self: the event
* @res: Result object passed to the callback of
* #lfb_event_end_feedback_async
* @error: Return location for error
*
* Finish an async operation started by lfb_event_end_feedback_async. You
* must call this function in the callback to free memory and receive any
* errors which occurred.
*
* Returns: %TRUE if playing finished successfully
*/
gboolean
lfb_event_end_feedback_finish (LfbEvent *self,
GAsyncResult *res,
GError **error)
{
g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
return g_task_propagate_boolean (G_TASK (res), error);
}
/**
* lfb_event_end_feedback_async:
* @self: The event to end feedback for.
* @cancellable: (nullable): A #GCancellable or %NULL.
* @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
* @user_data: User data to pass to @callback.
*
* Tells the feedback server to end all feedback for the given event as
* soon as possible.
*/
void
lfb_event_end_feedback_async (LfbEvent *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
LpfAsyncData *data;
LfbGdbusFeedback *proxy;
g_return_if_fail (LFB_IS_EVENT (self));
if (!lfb_is_initted ()) {
g_warning ("you must call lfb_init() before ending events");
g_assert_not_reached ();
}
proxy = _lfb_get_proxy ();
g_return_if_fail (LFB_GDBUS_IS_FEEDBACK (proxy));
data = g_new0 (LpfAsyncData, 1);
data->task = g_task_new (self, cancellable, callback, user_data);
data->event = g_object_ref (self);
lfb_gdbus_feedback_call_end_feedback (proxy,
self->id,
cancellable,
(GAsyncReadyCallback)on_end_feedback_finished,
data);
}
/**
* lfb_event_set_timeout:
* @self: The event
* @timeout: The timeout
*
* Tells the feedback server to end feedack after #timeout seconds.
* The value -1 indicates to not set a timeout and let feedbacks stop
* on their own while 0 indicates to loop all feedbacks endlessly.
* They must be stopped via #lfb_event_end_feedback () in this case.
*
* It is an error to change the timeout after the feedback has been triggered
* via lfb_event_trigger.
*/
void
lfb_event_set_timeout (LfbEvent *self, gint timeout)
{
g_return_if_fail (LFB_IS_EVENT (self));
if (self->timeout == timeout)
return;
self->timeout = timeout;
g_object_notify_by_pspec (G_OBJECT (self), props[PROP_TIMEOUT]);
}
/**
* lfb_event_get_event:
* @self: The event
*
* Get the event's name according to the event naming spec.
*
* Returns: The event name
*/
const char *
lfb_event_get_event (LfbEvent *self)
{
g_return_val_if_fail (LFB_IS_EVENT (self), NULL);
return self->event;
}
/**
* lfb_event_get_timeout:
* @self: The event
*
* Get the currently set timeout.
*
* Returns: The event timeout in msecs
*/
gint
lfb_event_get_timeout (LfbEvent *self)
{
g_return_val_if_fail (LFB_IS_EVENT (self), -1);
return self->timeout;
}
/**
* lfb_event_get_state:
* @self: The event
*
* Get the current event state (e.g. if triggered feeedback is
* currently running.
*
* Returns: The state of the feedback triggered by event.
*/
LfbEventState
lfb_event_get_state (LfbEvent *self)
{
g_return_val_if_fail (LFB_IS_EVENT (self), LFB_EVENT_STATE_NONE);
return self->state;
}
/**
* lfb_event_get_end_reason:
* @self: The event
*
* Get the reason why the feadback ended.
*
* Returns: The reason why feedback ended.
*/
LfbEventEndReason
lfb_event_get_end_reason (LfbEvent *self)
{
g_return_val_if_fail (LFB_IS_EVENT (self), LFB_EVENT_END_REASON_NATURAL);
return self->end_reason;
}
+80
View File
@@ -0,0 +1,80 @@
/*
* Copyright (C) 2020 Purism SPC
*
* SPDX-License-Identifier: GPL-3.0+
*/
#pragma once
#include <gio/gio.h>
#include <glib-object.h>
#if !defined (__LIBFEEDBACK_H_INSIDE__) && !defined (LIBFEEDBACK_COMPILATION)
#error "Only <libfeedback.h> can be included directly."
#endif
G_BEGIN_DECLS
/**
* LfbEventState:
* @LFB_EVENT_STATE_ERRORED: An error occured triggering feedbacks
* @LFB_EVENT_STATE_NONE: No state information yet
* @LFB_EVENT_STATE_RUNNING: The feedbacks for this event are currently running
* @LFB_EVENT_STATE_ENDED: All feedbacks for this event ended
*
* Enum values to indicate the current state of the feedbacks
* triggered by an event.
*/
typedef enum _LfbEventState {
LFB_EVENT_STATE_ERRORED = -1,
LFB_EVENT_STATE_NONE = 0,
LFB_EVENT_STATE_RUNNING = 1,
LFB_EVENT_STATE_ENDED = 2,
} LfbEventState;
/**
* LfbEventEndReason:
* @LFB_EVENT_END_REASON_NOT_FOUND: There was no feedback in the current theme for this event
* so no feedback was provided to the user.
* @LFB_EVENT_END_REASON_NATURAL: All feedbacks finished playing their natural length
* @LFB_EVENT_END_REASON_EXPIRED: Feedbacks ran until the set timeout expired
* @LFB_EVENT_END_REASON_EXPLICIT: The feedbacks were ended explicitly
*
* Enum values used to indicate why the feedbacks for an event ended.
**/
typedef enum _LfbEventEndReason {
LFB_EVENT_END_REASON_NOT_FOUND = -1,
LFB_EVENT_END_REASON_NATURAL = 0,
LFB_EVENT_END_REASON_EXPIRED = 1,
LFB_EVENT_END_REASON_EXPLICIT = 2,
} LfbEventEndReason;
#define LFB_TYPE_EVENT (lfb_event_get_type())
G_DECLARE_FINAL_TYPE (LfbEvent, lfb_event, LFB, EVENT, GObject);
LfbEvent* lfb_event_new (const char *event);
gboolean lfb_event_trigger_feedback (LfbEvent *self, GError **error);
void lfb_event_trigger_feedback_async (LfbEvent *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean lfb_event_trigger_feedback_finish (LfbEvent *self,
GAsyncResult *res,
GError **error);
gboolean lfb_event_end_feedback (LfbEvent *self, GError **error);
void lfb_event_end_feedback_async (LfbEvent *self,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data);
gboolean lfb_event_end_feedback_finish (LfbEvent *self,
GAsyncResult *res,
GError **error);
void lfb_event_set_timeout (LfbEvent *self, gint timeout);
gint lfb_event_get_timeout (LfbEvent *self);
const char *lfb_event_get_event (LfbEvent *self);
LfbEventState lfb_event_get_state (LfbEvent *self);
LfbEventEndReason lfb_event_get_end_reason (LfbEvent *self);
G_END_DECLS
+12
View File
@@ -0,0 +1,12 @@
/*
* Copyright (C) 2020 Purism SPC
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#define FB_DBUS_NAME "org.sigxcpu.Feedback"
#define FB_DBUS_PATH "/org/sigxcpu/Feedback"
#define FB_DBUS_TYPE G_BUS_TYPE_SESSION
+16
View File
@@ -0,0 +1,16 @@
/*
* Copyright (C) 2020 Purism SPC
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include <gio/gio.h>
#include "lfb-gdbus.h"
G_BEGIN_DECLS
LfbGdbusFeedback *_lfb_get_proxy (void);
G_END_DECLS
+200
View File
@@ -0,0 +1,200 @@
/*
* Copyright (C) 2020 Purism SPC
* SPDX-License-Identifier: LGPL-2.1+
* Author: Guido Günther <agx@sigxcpu.org>
*/
#include "libfeedback.h"
#include "lfb-gdbus.h"
#include "lfb-priv.h"
#include "lfb-names.h"
/**
* SECTION:libfeedback
* @Short_description: Library initialization and helpers
* @Title: libfeedback
*
* To use the library call #lfb_init() with the id of your application
* (usually the desktop file name without the .desktop extension).
* When done call #lfb_uninit() to free any resources.
*
* |[
* #define LIBFEEDBACK_USE_UNSTABLE_API
* #include <libfeedback.h>
*
* int main(void)
* {
* g_autoptr (GError) *err = NULL;
* if (lfb_init ("com.example.appid", &err)) {
* g_error ("%s", err->message);
* }
* // run your application, emit events
* // ...
* // when done:
* lfb_uninit ();
* return 0;
* }
* ]|
*/
static LfbGdbusFeedback *_proxy;
static char *_app_id;
static gboolean _initted;
LfbGdbusFeedback *
_lfb_get_proxy (void)
{
/* Caller needs to check since the proxy might be gone when
the last event gets finalized */
return _proxy;
}
/**
* lfb_init:
* @app_id: The application id
* @error: Error information
*
* Initialize libfeedback. This must be called before any other functions.
*
* Returns: %TRUE if successful, or %FALSE on error.
*/
gboolean
lfb_init (const gchar *app_id, GError **error)
{
g_return_val_if_fail (app_id != NULL, FALSE);
g_return_val_if_fail (*app_id != '\0', FALSE);
if (_initted)
return TRUE;
lfb_set_app_id (app_id);
_proxy = lfb_gdbus_feedback_proxy_new_for_bus_sync(
FB_DBUS_TYPE, 0, FB_DBUS_NAME, FB_DBUS_PATH, NULL, error);
if (!_proxy)
return FALSE;
g_object_add_weak_pointer (G_OBJECT (_proxy), (gpointer *) &_proxy);
_initted = TRUE;
return TRUE;
}
/**
* lfb_uninit:
*
* Uninitialize the library when no longer used. Usually called
* on program shutdown.
*/
void
lfb_uninit (void)
{
g_clear_pointer (&_app_id, g_free);
g_clear_object (&_proxy);
_initted = FALSE;
}
/**
* lfb_set_app_id:
* @app_id: The application id
*
* Sets the application id.
*/
void
lfb_set_app_id (const char *app_id)
{
g_free (_app_id);
_app_id = g_strdup (app_id);
}
/**
* lfb_get_app_id:
*
* Returns: the application id.
*/
const gchar *
lfb_get_app_id (void)
{
return _app_id;
}
/**
* lfb_is_initted:
*
* Gets whether or not libfeedback is initialized.
*
* Returns: %TRUE if libfeedback is initialized, or %FALSE otherwise.
*/
gboolean
lfb_is_initted (void)
{
return _initted;
}
/**
* lfb_get_feedback_profile:
*
* Gets the currently set feedback profile.
*
* Returns: The current profile or %NULL on error.
*/
const char *
lfb_get_feedback_profile (void)
{
LfbGdbusFeedback *proxy;
g_autofree gchar *profile = NULL;
g_autoptr(GVariant) var = NULL;
if (!lfb_is_initted ()) {
g_warning ("you must call lfb_init() before getting the profile");
g_assert_not_reached ();
}
proxy = _lfb_get_proxy ();
g_return_val_if_fail (LFB_GDBUS_IS_FEEDBACK (proxy), NULL);
return lfb_gdbus_feedback_get_profile (LFB_GDBUS_FEEDBACK (proxy));
}
/**
* lfb_set_feedback_profile:
* @profile: The profile to set
*
* Sets the active feedback profile to #profile. It is up to the feedback
* daemon to ignore this request. The new profile might not become active
* immediately. You can listen to changes #LfbGdbusFeedback's ::profile
* property to get notified when it takes effect.
*/
void
lfb_set_feedback_profile (const gchar *profile)
{
LfbGdbusFeedback *proxy;
if (!lfb_is_initted ()) {
g_warning ("you must call lfb_init() before setting the profile");
g_assert_not_reached ();
}
proxy = _lfb_get_proxy ();
g_return_if_fail (LFB_GDBUS_IS_FEEDBACK (proxy));
lfb_gdbus_feedback_set_profile (LFB_GDBUS_FEEDBACK (proxy), profile);
}
/**
* lfb_get_proxy:
*
* This can be used to access the lower level API e.g. to listen to
* property changes. The object is not owned by the caller. Don't
* unref it after use.
*
* Returns: (transfer none): The DBus proxy.
*/
LfbGdbusFeedback *
lfb_get_proxy (void)
{
LfbGdbusFeedback *proxy = _lfb_get_proxy ();
g_return_val_if_fail (LFB_GDBUS_IS_FEEDBACK (proxy), NULL);
return proxy;
}
+31
View File
@@ -0,0 +1,31 @@
/*
* Copyright (C) 2020 Purism SPC
*
* SPDX-License-Identifier: LGPL-2.1+
*/
#pragma once
#include <glib.h>
G_BEGIN_DECLS
#define __LIBFEEDBACK_H_INSIDE__
#ifndef LIBFEEDBACK_USE_UNSTABLE_API
#error LIBFEEDBACK is unstable API. You must define LIBFEEDBACK_USE_UNSTABLE_API before including libfeedback.h
#endif
#include "lfb-enums.h"
#include "lfb-event.h"
#include "lfb-gdbus.h"
gboolean lfb_init (const gchar *app_id, GError **error);
void lfb_uninit (void);
void lfb_set_app_id (const char *app_id);
const char *lfb_get_app_id (void);
gboolean lfb_is_initted (void);
void lfb_set_feedback_profile (const char *profile);
const char *lfb_get_feedback_profile (void);
LfbGdbusFeedback *lfb_get_proxy (void);
G_END_DECLS
+109
View File
@@ -0,0 +1,109 @@
# Shared library and language bindings
libfeedback_libdir = get_option('libdir')
libfeedback_header_dir = get_option('includedir') / libname
lfb_enum_headers = files([
'lfb-event.h',
])
lfb_enum_sources = gnome.mkenums_simple('lfb-enums',
sources : lfb_enum_headers,
install_header : true,
install_dir: libfeedback_header_dir,
)
libfeedback_headers = [
'libfeedback.h',
'lfb-event.h',
]
libfeedback_sources = [
generated_dbus_sources,
lfb_enum_sources,
libfeedback_headers,
'libfeedback.c',
'lfb-event.c',
]
libfeedback_deps = [
gio,
gio_unix,
glib,
]
libfeedback_c_args = [
'-DG_LOG_DOMAIN="libfeedback"',
'-DFEEDBACK_COMPILATION',
'-DLIBFEEDBACK_USE_UNSTABLE_API',
]
libtype = 'shared_library'
libfeedback = build_target(
'feedback-' + apiversion,
libfeedback_sources,
soversion : 0,
c_args : libfeedback_c_args,
dependencies : libfeedback_deps,
install : true,
install_dir : libfeedback_libdir,
target_type : libtype,
)
libfeedback_inc = include_directories('.')
libfeedback_dep = declare_dependency(
sources : [generated_dbus_sources, lfb_enum_sources],
link_with : libfeedback,
dependencies: libfeedback_deps,
include_directories : libfeedback_inc,
)
install_headers(libfeedback_headers, subdir : libname)
pkgconfig = import('pkgconfig')
pkgconfig.generate(
libraries : [libfeedback],
subdirs : libname,
version : meson.project_version(),
name : 'Feedback',
filebase : 'libfeedback-@0@'.format(apiversion),
description : 'GNOME feedback library',
requires : 'gio-2.0',
install_dir : join_paths(libfeedback_libdir, 'pkgconfig'),
)
if introspection
libhandy_gir_extra_args = [
'-I' + dbus_header_dir,
'--c-include=libfeedback.h',
'--quiet',
'-DLIBFEEDBACK_COMPILATION',
'-DLIBFEEDBACK_USE_UNSTABLE_API',
'--warn-error',
'--warn-all',
]
libfeedback_gir = gnome.generate_gir(libfeedback,
sources : libfeedback_sources,
nsversion : apiversion,
namespace : 'Lfb',
export_packages : 'libfeedback-@0@'.format(apiversion),
symbol_prefix : 'lfb',
identifier_prefix : 'Lfb',
link_with : libfeedback,
includes : ['Gio-2.0'],
install : true,
install_dir_gir : girdir,
install_dir_typelib : typelibdir,
extra_args : libhandy_gir_extra_args,
)
if get_option('vapi')
libfeedback_vapi = gnome.generate_vapi('libfeedback-' + apiversion,
sources : libfeedback_gir[0],
packages : ['gio-2.0'],
install : true,
install_dir : vapidir,
metadata_dirs : [meson.current_source_dir()],
)
endif
endif