Add daemon framework

This change adds the daemon configuration parser and command line
argument parser. This also adds the associated strings to the
translation files, and integrates the daemon into the existing autotools
build framework.
reverse-scroll
nirenjan 2021-07-15 15:53:56 -07:00
parent fc8e7b6b95
commit cbe7f00a5a
15 changed files with 884 additions and 6 deletions

1
.gitignore vendored
View File

@ -12,6 +12,7 @@ lib/libx52util/util_char_map.c
util/x52charmapgen* util/x52charmapgen*
lib/libusbx52/x52test* lib/libusbx52/x52test*
udev/*.rules udev/*.rules
daemon/x52d*
x52pro-linux-*.tar.gz x52pro-linux-*.tar.gz
# Module files # Module files

View File

@ -9,6 +9,7 @@ The format is based upon [Keep a Changelog].
- IO library to read and parse events from a supported joystick. - IO library to read and parse events from a supported joystick.
- Event test utility which displays the events similar to evtest. - Event test utility which displays the events similar to evtest.
- Import pinelog library for daemon logging. - Import pinelog library for daemon logging.
- Daemon to control and update the X52 joystick.
### Changed ### Changed
- Linux kernel driver to correctly handle the X52/X52 Pro. This is not required - Linux kernel driver to correctly handle the X52/X52 Pro. This is not required

View File

@ -10,7 +10,7 @@ if USE_NLS
po_SUBDIRS = po po_SUBDIRS = po
endif endif
SUBDIRS = $(po_SUBDIRS) lib utils tests udev SUBDIRS = $(po_SUBDIRS) lib utils daemon tests udev
# Extra files that need to be in the distribution # Extra files that need to be in the distribution
EXTRA_DIST = \ EXTRA_DIST = \

View File

@ -33,7 +33,7 @@ AM_CONDITIONAL([LINUX], [test "x${build_linux}" = "xyes"])
# Internationalization # Internationalization
AM_GNU_GETTEXT([external]) AM_GNU_GETTEXT([external])
AM_GNU_GETTEXT_VERSION(0.18) AM_GNU_GETTEXT_VERSION(0.19)
AM_CONDITIONAL([USE_NLS], [test "x${USE_NLS}" == "xyes"]) AM_CONDITIONAL([USE_NLS], [test "x${USE_NLS}" == "xyes"])
# Check for libusb-1.0 # Check for libusb-1.0
@ -129,6 +129,7 @@ AC_CONFIG_FILES([ po/Makefile.in
utils/cli/Makefile utils/cli/Makefile
utils/test/Makefile utils/test/Makefile
utils/evtest/Makefile utils/evtest/Makefile
daemon/Makefile
tests/Makefile tests/Makefile
]) ])
AC_OUTPUT AC_OUTPUT

34
daemon/Makefile.am 100644
View File

@ -0,0 +1,34 @@
# Automake for x52d
#
# Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org)
#
# SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
ACLOCAL_AMFLAGS = -I m4
bin_PROGRAMS = x52d
# Service daemon that manages the X52 device
x52d_SOURCES = \
x52d_main.c x52d_config_parser.c x52d_config.c
x52d_CFLAGS = \
-I $(top_srcdir) \
-I $(top_srcdir)/lib/libx52io \
-I $(top_srcdir)/lib/libx52 \
-I $(top_srcdir)/lib/libx52util \
-I $(top_srcdir)/lib/pinelog \
-DSYSCONFDIR=\"$(sysconfdir)\" \
-DLOCALEDIR=\"$(localedir)\" \
-DLOGDIR=\"$(localstatedir)/log\" \
-DRUNDIR=\"$(runstatedir)\" \
@INIH_CFLAGS@ $(WARN_CFLAGS)
x52d_LDFLAGS = @INIH_LIBS@ $(WARN_LDFLAGS)
x52d_LDADD = ../lib/pinelog/libpinelog.la
EXTRA_DIST = \
x52d_config.def \
x52d_config.h \
x52d_const.h \
x52d.conf

80
daemon/x52d.conf 100644
View File

@ -0,0 +1,80 @@
#######################################################################
# X52 Daemon Configuration
######################################################################
# The settings below are the defaults. Note that the section and key
# strings are case insensitive, but the values are not necessarily so,
# especially for those referring to paths or timezone names.
######################################################################
# Clock Settings
######################################################################
[Clock]
# Enabled controls whether the clock is enabled or not. Set this to no to
# disable the clock update. Keep in mind that if the clock was originally
# enabled on the X52, then disabling it here won't make the clock disappear on
# the MFD. You will need to unplug and reattach the X52 to make the clock
# disappear
Enabled=yes
# PrimaryIsLocal controls whether the primary clock displays local time or UTC.
# Set this to yes to display local time, no for UTC.
PrimaryIsLocal=yes
# Secondary controls the timezone of the secondary clock. Use the standard
# timezone name as defined by the Olson time database.
Secondary=UTC
# Tertiary controls the timezone of the tertiary clock. Use the standard
# timezone name as defined by the Olson time database.
Tertiary=UTC
######################################################################
# LED Settings - only applicable to X52Pro
######################################################################
[LED]
# The LED settings map a color code or state to the corresponding LED.
Fire=on
Throttle=on
A=green
B=green
D=green
E=green
T1=green
T2=green
T3=green
POV=green
Clutch=green
######################################################################
# Brightness Settings
######################################################################
[Brightness]
# The brightness settings map the brightness value to the LEDs/MFD.
MFD=128
LED=128
######################################################################
# Profiles - only valid on Linux
######################################################################
[Profiles]
# Directory is the location of the folder containing the individual profiles.
Directory=/etc/x52d/profiles.d
# ClutchEnabled determines if the clutch button is treated specially
ClutchEnabled=no
# ClutchLatched controls if the clutch button (if enabled) is a latched button
# (press once to enter clutch mode, press again to exit clutch mode), or must
# be held down to remain in clutch mode.
ClutchLatched=no
##################
#X52 Input Servic#
#Version 0.2.2 #
#OS: Linux #
##################

View File

@ -0,0 +1,42 @@
/*
* Saitek X52 Pro MFD & LED driver - Configuration parser
*
* Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org)
*
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
*/
#include "config.h"
#include "pinelog.h"
#include "x52d_config.h"
#include "x52d_const.h"
static struct x52d_config x52d_config;
void x52d_config_load(const char *cfg_file)
{
int rc;
if (cfg_file == NULL) {
cfg_file = X52D_SYS_CFG_FILE;
}
rc = x52d_config_set_defaults(&x52d_config);
if (rc != 0) {
PINELOG_FATAL(_("Error %d setting configuration defaults: %s"),
rc, strerror(rc));
}
rc = x52d_config_load_file(&x52d_config, cfg_file);
if (rc != 0) {
exit(EXIT_FAILURE);
}
// Apply overrides
rc = x52d_config_apply_overrides(&x52d_config);
x52d_config_clear_overrides();
if (rc != 0) {
exit(EXIT_FAILURE);
}
}

View File

@ -0,0 +1,70 @@
/**********************************************************************
* X52 Daemon Configuration
*********************************************************************/
// The settings below are the defaults. Note that the section and key
// strings are case insensitive, but the values are not necessarily so,
// especially for those referring to paths or timezone names.
/* CFG(section, key, name, parser, default) */
/**********************************************************************
* Clock Settings
*********************************************************************/
// Enabled controls whether the clock is enabled or not. Set this to no to
// disable the clock update. Keep in mind that if the clock was originally
// enabled on the X52, then disabling it here won't make the clock disappear
// on the MFD. You will need to unplug and reattach the X52 to make the
// clock disappear
CFG(Clock, Enabled, clock_enabled, bool_parser, true)
// PrimaryIsLocal controls whether the primary clock displays local time or UTC.
// Set this to yes to display local time, no for UTC.
CFG(Clock, PrimaryIsLocal, primary_clock_local, bool_parser, true)
// Secondary controls the timezone of the secondary clock. Use the standard
// timezone name as defined by the Olson time database.
CFG(Clock, Secondary, clock_2_tz, string_parser, UTC)
// Tertiary controls the timezone of the tertiary clock. Use the standard
// timezone name as defined by the Olson time database.
CFG(Clock, Tertiary, clock_3_tz, string_parser, UTC)
/**********************************************************************
* LED Settings - only applicable to X52Pro
*********************************************************************/
// The LED settings map a color code or state to the corresponding LED.
CFG(LED, Fire, leds[LIBX52_LED_FIRE], led_parser, on)
CFG(LED, Throttle, leds[LIBX52_LED_THROTTLE], led_parser, on)
CFG(LED, A, leds[LIBX52_LED_A], led_parser, green)
CFG(LED, B, leds[LIBX52_LED_B], led_parser, green)
CFG(LED, D, leds[LIBX52_LED_D], led_parser, green)
CFG(LED, E, leds[LIBX52_LED_E], led_parser, green)
CFG(LED, T1, leds[LIBX52_LED_T1], led_parser, green)
CFG(LED, T2, leds[LIBX52_LED_T2], led_parser, green)
CFG(LED, T3, leds[LIBX52_LED_T3], led_parser, green)
CFG(LED, POV, leds[LIBX52_LED_POV], led_parser, green)
CFG(LED, Clutch, leds[LIBX52_LED_CLUTCH], led_parser, green)
/**********************************************************************
* Brightness Settings
*********************************************************************/
// The brightness settings map the brightness value to the LEDs/MFD.
CFG(Brightness, MFD, brightness[0], int_parser, 128)
CFG(Brightness, LED, brightness[1], int_parser, 128)
/**********************************************************************
* Profiles - only valid on Linux
*********************************************************************/
// Directory is the location of the folder containing the individual profiles.
CFG(Profiles, Directory, profiles_dir, string_parser, /etc/x52d/profiles.d)
// ClutchEnabled determines if the clutch button is treated specially
CFG(Profiles, ClutchEnabled, clutch_enabled, bool_parser, false)
// ClutchLatched controls if the clutch button (if enabled) is a latched button
// (press once to enter clutch mode, press again to exit clutch mode), or must
// be held down to remain in clutch mode.
CFG(Profiles, ClutchLatched, clutch_latched, bool_parser, false)
#undef CFG

View File

@ -0,0 +1,52 @@
/*
* Saitek X52 Pro MFD & LED driver - Configuration parser header
*
* Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org)
*
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
*/
#ifndef X52D_CONFIG_H
#define X52D_CONFIG_H
#include <stdint.h>
#include <stdbool.h>
#include <limits.h>
#include "libx52.h"
/**
* @brief Configuration structure
*
* Keep this in sync with the sample configuration
*/
struct x52d_config {
bool clock_enabled;
bool primary_clock_local;
char clock_2_tz[NAME_MAX];
char clock_3_tz[NAME_MAX];
// Since we don't have a _MAX identifier for libx52_led_id, hardcode
// the length in the following declaration.
libx52_led_state leds[21];
uint16_t brightness[2];
bool clutch_enabled;
bool clutch_latched;
char profiles_dir[NAME_MAX];
};
int x52d_config_set_defaults(struct x52d_config *cfg);
int x52d_config_load_file(struct x52d_config *cfg, const char *cfg_file);
int x52d_config_save_override(const char *override_str);
int x52d_config_apply_overrides(struct x52d_config *cfg);
void x52d_config_clear_overrides(void);
void x52d_config_load(const char *cfg_file);
#endif // !defined X52D_CONFIG_H

View File

@ -0,0 +1,323 @@
/*
* Saitek X52 Pro MFD & LED driver - Configuration parser
*
* Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org)
*
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <stdlib.h>
#include <errno.h>
#include <stdbool.h>
#include "ini.h"
#include "pinelog.h"
#include "x52d_config.h"
#include "x52d_const.h"
/* Parser function typedef */
typedef int (*parser_fn)(struct x52d_config *, size_t, const char *);
// Check if the parameters are all valid
#define CHECK_PARAMS() do { if (cfg == NULL || value == NULL) { return EINVAL; } } while(0)
// Create a pointer "name" of type "type", which stores the pointer to the
// corresponding element within the config struct.
#define CONFIG_PTR(type, name) type name = (type)((uintptr_t)cfg + offset)
static int bool_parser(struct x52d_config *cfg, size_t offset, const char *value)
{
CONFIG_PTR(bool *, config);
CHECK_PARAMS();
if (!strcasecmp(value, "yes") || !strcasecmp(value, "true")) {
*config = true;
} else if (!strcasecmp(value, "no") || !strcasecmp(value, "false")) {
*config = false;
} else {
return EINVAL;
}
return 0;
}
static int string_parser(struct x52d_config *cfg, size_t offset, const char *value)
{
CONFIG_PTR(char *, config);
CHECK_PARAMS();
/* String parameters are all NAME_MAX len */
strncpy(config, value, NAME_MAX-1);
config[NAME_MAX-1] = '\0';
return 0;
}
static int int_parser(struct x52d_config *cfg, size_t offset, const char *value)
{
CONFIG_PTR(int *, config);
char *endptr;
int retval;
CHECK_PARAMS();
errno = 0;
retval = strtol(value, &endptr, 0);
if (errno != 0) {
return errno;
}
*config = retval;
return 0;
}
static int led_parser(struct x52d_config *cfg, size_t offset, const char *value)
{
CONFIG_PTR(libx52_led_state *, config);
CHECK_PARAMS();
#define MATCH_STATE(val) if (!strcasecmp(value, #val)) { *config = LIBX52_LED_STATE_ ## val ; }
MATCH_STATE(OFF)
else MATCH_STATE(ON)
else MATCH_STATE(RED)
else MATCH_STATE(AMBER)
else MATCH_STATE(GREEN)
else return EINVAL;
#undef MATCH_STATE
return 0;
}
/* Map for config->param */
#define CFG(section, key, name, parser, def) {#section, #key, parser, offsetof(struct x52d_config, name)},
const struct config_map {
const char *section;
const char *key;
parser_fn parser;
size_t offset;
} config_map[] = {
#include "x52d_config.def"
// Terminating entry
{NULL, NULL, NULL, 0}
};
static int process_config_kv(void *user, const char *section, const char *key, const char *value)
{
int i;
int rc = 0;
bool found = false;
struct x52d_config *cfg = (struct x52d_config*)user;
for (i = 0; config_map[i].key != NULL; i++) {
rc = 0;
if (!strcasecmp(config_map[i].key, key) &&
!strcasecmp(config_map[i].section, section)) {
found = true;
PINELOG_TRACE("Setting '%s.%s'='%s'",
config_map[i].section, config_map[i].key, value);
rc = config_map[i].parser(cfg, config_map[i].offset, value);
break;
}
}
if (!found) {
// Print error message, but continue
PINELOG_INFO(_("Ignoring unknown key '%s.%s'"), section, key);
}
return rc;
}
/**
* @brief Set configuration defaults
*
* @param[in] cfg Pointer to config struct
*
* @returns 0 on success, non-zero error code on failure
*/
int x52d_config_set_defaults(struct x52d_config *cfg) {
int rc;
if (cfg == NULL) {
return EINVAL;
}
PINELOG_TRACE("Setting configuration defaults");
#define CFG(section, key, name, parser, def) \
rc = process_config_kv(cfg, #section, #key, #def); \
if (rc != 0) { \
return rc; \
}
#include "x52d_config.def"
return 0;
}
int x52d_config_load_file(struct x52d_config *cfg, const char *cfg_file)
{
int rc;
if (cfg == NULL || cfg_file == NULL) {
return EINVAL;
}
PINELOG_TRACE("Loading configuration from file %s", cfg_file);
rc = ini_parse(cfg_file, process_config_kv, cfg);
if (rc < 0) {
PINELOG_ERROR(_("Failed processing configuration file %s - code %d"),
cfg_file, rc);
return EIO;
}
return 0;
}
struct x52d_config_override {
char *section;
char *key;
char *value;
struct x52d_config_override *next;
};
static struct x52d_config_override *override_head;
static struct x52d_config_override *override_tail;
int x52d_config_save_override(const char *override_str)
{
// Parse override string of the form section.key=value
struct x52d_config_override *override;
char *string = NULL;
char *free_ptr = NULL;
char *ptr;
int rc;
PINELOG_TRACE("Allocating memory (%lu bytes) for override structure", sizeof(*override));
override = calloc(1, sizeof(*override));
if (override == NULL) {
PINELOG_ERROR(_("Failed to allocate memory for override structure"));
rc = ENOMEM;
goto cleanup;
}
errno = 0;
PINELOG_TRACE("Duplicating override string");
string = strdup(override_str);
if (string == NULL) {
PINELOG_ERROR(_("Failed to allocate memory for override string"));
rc = errno;
goto cleanup;
}
free_ptr = string;
override->section = string;
// Ensure that the string is of the form ([^.]+\.[^=]+=.*)
ptr = strchr(string, '.');
if (ptr == NULL || ptr == string) {
// No section found
PINELOG_ERROR(_("No section found in override string '%s'"), string);
rc = EINVAL;
goto cleanup;
}
// Reset the . to NUL
*ptr = '\0';
ptr++;
PINELOG_TRACE("Splitting override string to '%s' and '%s'", string, ptr);
string = ptr;
override->key = string;
ptr = strchr(string, '=');
if (ptr == NULL || ptr == string) {
// No key found
PINELOG_ERROR(_("No key found in override string '%s'"), string);
rc = EINVAL;
goto cleanup;
}
// Reset the = to NUL
*ptr = '\0';
ptr++;
PINELOG_TRACE("Splitting override string to '%s' and '%s'", string, ptr);
if (*ptr == '\0') {
// No value found
PINELOG_ERROR(_("No value found in override string '%s'"), string);
rc = EINVAL;
goto cleanup;
}
override->value = ptr;
// Add the override to the linked list
if (override_tail != NULL) {
PINELOG_TRACE("Linking override to list tail");
override_tail->next = override;
}
PINELOG_TRACE("Setting list tail to override");
override_tail = override;
if (override_head == NULL) {
PINELOG_TRACE("Setting list head to override");
override_head = override;
}
return 0;
cleanup:
if (free_ptr != NULL) {
free(free_ptr);
}
if (override != NULL) {
free(override);
}
return rc;
}
int x52d_config_apply_overrides(struct x52d_config *cfg)
{
int rc;
struct x52d_config_override *tmp = override_head;
if (cfg == NULL) {
return EINVAL;
}
while (tmp != NULL) {
PINELOG_TRACE("Processing override '%s.%s=%s'",
tmp->section,
tmp->key,
tmp->value);
rc = process_config_kv(cfg,
tmp->section,
tmp->key,
tmp->value);
if (rc != 0) {
PINELOG_ERROR(_("Error processing override '%s.%s=%s'"),
tmp->section,
tmp->key,
tmp->value);
return rc;
}
tmp = tmp->next;
}
return 0;
}
void x52d_config_clear_overrides(void)
{
struct x52d_config_override *tmp;
while (override_head != NULL) {
tmp = override_head;
override_head = override_head->next;
PINELOG_TRACE("Freeing override '%s.%s=%s'",
tmp->section,
tmp->key,
tmp->value);
free(tmp);
}
override_tail = NULL;
}

View File

@ -0,0 +1,21 @@
/*
* Saitek X52 Pro MFD & LED driver - Application constants
*
* Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org)
*
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
*/
#ifndef X52D_CONST_H
#define X52D_CONST_H
#define X52D_APP_NAME "x52d"
#define X52D_LOG_FILE LOGDIR "/" X52D_APP_NAME ".log"
#define X52D_SYS_CFG_FILE SYSCONFDIR "/" X52D_APP_NAME "/" X52D_APP_NAME ".conf"
#include "gettext.h"
#define _(x) gettext(x)
#endif // !defined X52D_CONST_H

131
daemon/x52d_main.c 100644
View File

@ -0,0 +1,131 @@
/*
* Saitek X52 Pro MFD & LED driver - Service daemon
* * Copyright (C) 2021 Nirenjan Krishnan (nirenjan@nirenjan.org)
*
* SPDX-License-Identifier: GPL-2.0-only WITH Classpath-exception-2.0
*/
#include "config.h"
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include "x52d_const.h"
#include "x52d_config.h"
#include "pinelog.h"
static void set_log_file(bool foreground, const char *log_file)
{
int rc = 0;
if (log_file != NULL) {
rc = pinelog_set_output_file(log_file);
} else {
if (foreground) {
rc = pinelog_set_output_stream(stdout);
} else {
rc = pinelog_set_output_file(X52D_LOG_FILE);
}
}
if (rc != 0) {
fprintf(stderr, _("Error %d setting log file: %s\n"), rc, strerror(rc));
exit(EXIT_FAILURE);
}
}
static void usage(int exit_code)
{
fprintf(stderr,
_("Usage: %s [-f] [-v] [-q] [-l log-file] [-o override] [-c config-file]\n"),
X52D_APP_NAME);
exit(exit_code);
}
int main(int argc, char **argv)
{
int verbosity = 0;
bool quiet = false;
bool foreground = false;
char *log_file = NULL;
char *conf_file = NULL;
int opt;
/* Initialize gettext */
#if ENABLE_NLS
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
/* Set system defaults */
pinelog_set_level(PINELOG_LVL_WARNING);
/*
* Parse command line arguments
*
* -f run in foreground
* -c path to config file
* -o option overrides
* -v verbose logging
* -q silent behavior
* -l path to log file
*/
while ((opt = getopt(argc, argv, "fvql:o:c:h")) != -1) {
switch (opt) {
case 'f':
foreground = true;
break;
case 'v':
if (!quiet) {
if (verbosity <= PINELOG_LVL_TRACE) {
verbosity++;
pinelog_set_level(pinelog_get_level() + 1);
}
}
break;
case 'q':
quiet = true;
pinelog_set_level(PINELOG_LVL_ERROR);
break;
case 'l':
log_file = optarg;
break;
case 'o':
if (x52d_config_save_override(optarg)) {
fprintf(stderr,
_("Unable to parse configuration override '%s'\n"),
optarg);
exit(EXIT_FAILURE);
}
break;
case 'c':
conf_file = optarg;
break;
case 'h':
usage(EXIT_SUCCESS);
break;
default:
usage(EXIT_FAILURE);
break;
}
}
printf("Foreground = %s\n", foreground ? "true" : "false");
printf("Quiet = %s\n", quiet ? "true" : "false");
printf("Verbosity = %d\n", verbosity);
printf("Log file = %s\n", log_file);
printf("Config file = %s\n", conf_file);
set_log_file(foreground, log_file);
x52d_config_load(conf_file);
return 0;
}

View File

@ -10,3 +10,7 @@ utils/test/x52_test_clock.c
utils/test/x52_test_common.h utils/test/x52_test_common.h
utils/test/x52_test_led.c utils/test/x52_test_led.c
utils/test/x52_test_mfd.c utils/test/x52_test_mfd.c
daemon/x52d_main.c
daemon/x52d_config.c
daemon/x52d_config_parser.c

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: x52pro-linux 0.2.1\n" "Project-Id-Version: x52pro-linux 0.2.1\n"
"Report-Msgid-Bugs-To: https://github.com/nirenjan/x52pro-linux/issues\n" "Report-Msgid-Bugs-To: https://github.com/nirenjan/x52pro-linux/issues\n"
"POT-Creation-Date: 2020-07-16 04:24-0700\n" "POT-Creation-Date: 2021-07-15 15:08-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -369,3 +369,61 @@ msgstr ""
#: utils/test/x52_test_mfd.c:96 #: utils/test/x52_test_mfd.c:96
msgid "OK" msgid "OK"
msgstr "" msgstr ""
#: daemon/x52d_main.c:32
#, c-format
msgid "Error %d setting log file: %s\n"
msgstr ""
#: daemon/x52d_main.c:40
#, c-format
msgid "Usage: %s [-f] [-v] [-q] [-l log-file] [-o override] [-c config-file]\n"
msgstr ""
#: daemon/x52d_main.c:101
#, c-format
msgid "Unable to parse configuration override '%s'\n"
msgstr ""
#: daemon/x52d_config.c:26
#, c-format
msgid "Error %d setting configuration defaults: %s"
msgstr ""
#: daemon/x52d_config_parser.c:130
#, c-format
msgid "Ignoring unknown key '%s.%s'"
msgstr ""
#: daemon/x52d_config_parser.c:171
#, c-format
msgid "Failed processing configuration file %s - code %d"
msgstr ""
#: daemon/x52d_config_parser.c:201
msgid "Failed to allocate memory for override structure"
msgstr ""
#: daemon/x52d_config_parser.c:210
msgid "Failed to allocate memory for override string"
msgstr ""
#: daemon/x52d_config_parser.c:221
#, c-format
msgid "No section found in override string '%s'"
msgstr ""
#: daemon/x52d_config_parser.c:235
#, c-format
msgid "No key found in override string '%s'"
msgstr ""
#: daemon/x52d_config_parser.c:246
#, c-format
msgid "No value found in override string '%s'"
msgstr ""
#: daemon/x52d_config_parser.c:297
#, c-format
msgid "Error processing override '%s.%s=%s'"
msgstr ""

View File

@ -7,15 +7,15 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: x52pro-linux 0.2.1\n" "Project-Id-Version: x52pro-linux 0.2.1\n"
"Report-Msgid-Bugs-To: https://github.com/nirenjan/x52pro-linux/issues\n" "Report-Msgid-Bugs-To: https://github.com/nirenjan/x52pro-linux/issues\n"
"POT-Creation-Date: 2020-07-16 04:24-0700\n" "POT-Creation-Date: 2021-07-15 15:08-0700\n"
"PO-Revision-Date: 2020-07-13 18:05-0700\n" "PO-Revision-Date: 2021-07-15 15:09-0700\n"
"Last-Translator: Nirenjan Krishnan <nirenjan@gmail.com>\n" "Last-Translator: Nirenjan Krishnan <nirenjan@gmail.com>\n"
"Language-Team: Dummy Language for testing i18n\n" "Language-Team: Dummy Language for testing i18n\n"
"Language: xx_PL\n" "Language: xx_PL\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.3.1\n" "X-Generator: Poedit 3.0\n"
#: lib/libx52/x52_strerror.c:25 lib/libx52io/io_strings.c:104 #: lib/libx52/x52_strerror.c:25 lib/libx52io/io_strings.c:104
msgid "Success" msgid "Success"
@ -412,3 +412,63 @@ msgstr "Estingtay aracterchay 0x%02x..."
#: utils/test/x52_test_mfd.c:96 #: utils/test/x52_test_mfd.c:96
msgid "OK" msgid "OK"
msgstr "OKay" msgstr "OKay"
#: daemon/x52d_main.c:32
#, c-format
msgid "Error %d setting log file: %s\n"
msgstr "Erroray %d ettingsay oglay ilefay: %s\n"
#: daemon/x52d_main.c:40
#, c-format
msgid "Usage: %s [-f] [-v] [-q] [-l log-file] [-o override] [-c config-file]\n"
msgstr ""
"Usageay: %s [-f] [-v] [-q] [-l oglay-ilefay] [-o overrideay] [-c onfigcay-"
"ilefay]\n"
#: daemon/x52d_main.c:101
#, c-format
msgid "Unable to parse configuration override '%s'\n"
msgstr "Unableay otay arsepay onfigurationcay overrideay '%s'\n"
#: daemon/x52d_config.c:26
#, c-format
msgid "Error %d setting configuration defaults: %s"
msgstr "Erroray %d ettingsay onfigurationcay efaultsday: %s"
#: daemon/x52d_config_parser.c:130
#, c-format
msgid "Ignoring unknown key '%s.%s'"
msgstr "Ignoringay unknownay eykay '%s.%s'"
#: daemon/x52d_config_parser.c:171
#, c-format
msgid "Failed processing configuration file %s - code %d"
msgstr "Ailedfay ocessingpray onfigurationcay ilefay %s - odecay %d"
#: daemon/x52d_config_parser.c:201
msgid "Failed to allocate memory for override structure"
msgstr "Ailedfay otay allocateay emorymay orfay overrideay ucturestray"
#: daemon/x52d_config_parser.c:210
msgid "Failed to allocate memory for override string"
msgstr "Ailedfay otay allocateay emorymay orfay overrideay ingstray"
#: daemon/x52d_config_parser.c:221
#, c-format
msgid "No section found in override string '%s'"
msgstr "Onay ectionsay oundfay inay overrideay ingstray '%s'"
#: daemon/x52d_config_parser.c:235
#, c-format
msgid "No key found in override string '%s'"
msgstr "Onay eykay oundfay inay overrideay ingstray '%s'"
#: daemon/x52d_config_parser.c:246
#, c-format
msgid "No value found in override string '%s'"
msgstr "Onay aluevay oundfay inay overrideay ingstray '%s'"
#: daemon/x52d_config_parser.c:297
#, c-format
msgid "Error processing override '%s.%s=%s'"
msgstr "Erroray ocessingpray overriday '%s.%s=%s'"