mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-29 05:40:27 -04:00
daemon-conf: Add conf file parsing
Support to parse configuration files. By default, the default conf file
is parsed ({sysconfdir}/pinos/pinos.conf), but that can be changed with
an environment variable (PINOS_CONFIG_FILE). The file can contain
commands and assignments (no assignment supported this far).
Support for command module-load is added.
This commit is contained in:
parent
d654a1bcd6
commit
7d8e2d53f7
14 changed files with 729 additions and 59 deletions
16
configure.ac
16
configure.ac
|
|
@ -177,6 +177,12 @@ AS_IF([test "x$LIBLTDL" = "x"],
|
|||
[AC_MSG_ERROR([Unable to find libltdl version 2. Makes sure you have libtool 2.4 or later installed.])])
|
||||
AC_SUBST([LIBLTDL])
|
||||
|
||||
|
||||
#### Pinos runtime environment ####
|
||||
|
||||
AC_SUBST(pinosconfdir, ["${sysconfdir}/pinos"])
|
||||
AX_DEFINE_DIR(PINOS_CONFIG_DIR, pinosconfdir, [Directory for configuration files])
|
||||
|
||||
###################################
|
||||
# External libraries #
|
||||
###################################
|
||||
|
|
@ -260,6 +266,14 @@ AC_ARG_ENABLE([module-gst],
|
|||
AM_CONDITIONAL([BUILD_MODULE_GST], [test "x$enable_module_gst" != "xno"])
|
||||
AS_IF([test "x$enable_module_gst" != "xno"], ENABLE_MODULE_GST=yes, ENABLE_MODULE_GST=no)
|
||||
|
||||
#### module-spa (SPA module) ####
|
||||
AC_ARG_ENABLE([module-spa],
|
||||
AS_HELP_STRING([--disable-module-spa],[Disable building of SPA module]))
|
||||
|
||||
AM_CONDITIONAL([BUILD_MODULE_SPA], [test "x$enable_module_spa" != "xno"])
|
||||
AS_IF([test "x$enable_module_spa" != "xno"], ENABLE_MODULE_SPA=yes, ENABLE_MODULE_SPA=no)
|
||||
|
||||
|
||||
#### Build and Install man pages ####
|
||||
|
||||
AC_ARG_ENABLE([manpages],
|
||||
|
|
@ -273,6 +287,7 @@ dnl keep this alphabetic per directory, please
|
|||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
pinos/Makefile
|
||||
pinos/daemon/pinos.conf
|
||||
man/Makefile
|
||||
man/pinos.1.xml
|
||||
man/pinos-monitor.1.xml
|
||||
|
|
@ -292,6 +307,7 @@ Configuration
|
|||
|
||||
Modules
|
||||
module-gst : ${ENABLE_MODULE_GST}
|
||||
module-spa : ${ENABLE_MODULE_SPA}
|
||||
|
||||
pinos configured. Type 'make' to build.
|
||||
"
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ AM_CPPFLAGS = \
|
|||
-I$(top_builddir)/pinos/modules \
|
||||
-DPINOS_SRCDIR=\"$(abs_srcdir)\" \
|
||||
-DPINOS_BUILDDIR=\"$(abs_builddir)\"
|
||||
AM_CFLAGS = $(GLIB_CFLAGS) $(GST_CFLAGS)
|
||||
AM_CFLAGS = $(GLIB_CFLAGS)
|
||||
AM_CXXFLAGS = $(AM_CFLAGS)
|
||||
SERVER_CFLAGS = -D__INCLUDED_FROM_PINOS
|
||||
|
||||
|
|
@ -55,10 +55,14 @@ MODULE_LIBADD = $(AM_LIBADD) libpinoscore-@PINOS_MAJORMINOR@.la
|
|||
|
||||
EXTRA_DIST = \
|
||||
daemon/pinos-system.conf \
|
||||
daemon/pinos.conf.in \
|
||||
daemon/pinos.desktop.in \
|
||||
dbus/org.pinos.xml \
|
||||
client/private.h
|
||||
|
||||
pinosconf_DATA = \
|
||||
daemon/pinos.conf
|
||||
|
||||
dbuspolicy_DATA = \
|
||||
daemon/pinos-system.conf
|
||||
|
||||
|
|
@ -121,6 +125,7 @@ CLEANFILES = $(built_header_make) $(built_source_make)
|
|||
bin_PROGRAMS = pinos
|
||||
|
||||
pinos_SOURCES = \
|
||||
daemon/daemon-config.h daemon/daemon-config.c \
|
||||
daemon/main.c
|
||||
|
||||
pinos_CFLAGS = $(AM_CFLAGS)
|
||||
|
|
@ -205,14 +210,13 @@ lib_LTLIBRARIES += libpinoscore-@PINOS_MAJORMINOR@.la
|
|||
libpinoscore_@PINOS_MAJORMINOR@_la_SOURCES = \
|
||||
server/client.c server/client.h \
|
||||
server/client-node.c server/client-node.h \
|
||||
server/command.c server/command.h \
|
||||
server/daemon.c server/daemon.h \
|
||||
server/link.c server/link.h \
|
||||
server/module.c server/module.h \
|
||||
server/node.c server/node.h \
|
||||
server/port.c server/port.h \
|
||||
server/node-factory.c server/node-factory.h \
|
||||
modules/spa/spa-alsa-sink.c modules/spa/spa-alsa-sink.h \
|
||||
modules/spa/spa-v4l2-source.c modules/spa/spa-v4l2-source.h \
|
||||
dbus/org-pinos.c dbus/org-pinos.h
|
||||
|
||||
libpinoscore_@PINOS_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS)
|
||||
|
|
@ -240,6 +244,21 @@ module_gst_la_LDFLAGS = $(MODULE_LDFLAGS)
|
|||
module_gst_la_LIBADD = $(MODULE_LIBADD)
|
||||
endif
|
||||
|
||||
if BUILD_MODULE_SPA
|
||||
module_LTLIBRARIES += module-spa.la
|
||||
|
||||
module_spa_la_SOURCES = \
|
||||
modules/spa/spa-alsa-sink.c \
|
||||
modules/spa/spa-v4l2-source.c \
|
||||
modules/spa/module.c
|
||||
module_spa_la_CFLAGS = $(AM_CFLAGS)
|
||||
module_spa_la_LDFLAGS = $(MODULE_LDFLAGS)
|
||||
module_spa_la_LIBADD = $(MODULE_LIBADD)
|
||||
endif
|
||||
|
||||
|
||||
|
||||
|
||||
###################################
|
||||
# GStreamer Plugin #
|
||||
###################################
|
||||
|
|
|
|||
218
pinos/daemon/daemon-config.c
Normal file
218
pinos/daemon/daemon-config.c
Normal file
|
|
@ -0,0 +1,218 @@
|
|||
/* Pinos
|
||||
* Copyright (C) 2016 Axis Communications <dev-gstreamer@axis.com>
|
||||
* @author Linus Svensson <linus.svensson@axis.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <server/command.h>
|
||||
|
||||
#include "pinos/daemon/daemon-config.h"
|
||||
|
||||
#define DEFAULT_CONFIG_FILE PINOS_CONFIG_DIR G_DIR_SEPARATOR_S "pinos.conf"
|
||||
|
||||
GQuark
|
||||
pinos_daemon_config_error_quark (void)
|
||||
{
|
||||
static GQuark quark = 0;
|
||||
|
||||
if (quark == 0) {
|
||||
quark = g_quark_from_static_string ("pinos_daemon_config_error");
|
||||
}
|
||||
|
||||
return quark;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
parse_line (PinosDaemonConfig * config,
|
||||
const gchar * filename,
|
||||
gchar * line,
|
||||
guint lineno,
|
||||
GError ** err)
|
||||
{
|
||||
PinosCommand *command = NULL;
|
||||
gchar *p;
|
||||
gboolean ret = TRUE;
|
||||
GError *local_err = NULL;
|
||||
|
||||
/* search for comments */
|
||||
if ((p = strchr (line, '#')))
|
||||
*p = '\0';
|
||||
|
||||
/* remove whitespaces */
|
||||
g_strstrip (line);
|
||||
|
||||
if (*line == '\0') /* empty line */
|
||||
return TRUE;
|
||||
|
||||
if (!pinos_command_parse (&command, line, &local_err)) {
|
||||
g_set_error (err, PINOS_DAEMON_CONFIG_ERROR,
|
||||
PINOS_DAEMON_CONFIG_ERROR_COMMAND, "%s:%u: %s", filename, lineno,
|
||||
local_err->message);
|
||||
g_error_free (local_err);
|
||||
ret = FALSE;
|
||||
} else {
|
||||
config->commands = g_list_append (config->commands, command);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_daemon_config_new:
|
||||
*
|
||||
* Returns a new empty #PinosDaemonConfig.
|
||||
*/
|
||||
PinosDaemonConfig *
|
||||
pinos_daemon_config_new (void)
|
||||
{
|
||||
PinosDaemonConfig *config;
|
||||
|
||||
config = g_new (PinosDaemonConfig, 1);
|
||||
|
||||
config->commands = NULL;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_daemon_config_free:
|
||||
* @config: A #PinosDaemonConfig
|
||||
*
|
||||
* Free all resources associated to @config.
|
||||
*/
|
||||
void
|
||||
pinos_daemon_config_free (PinosDaemonConfig * config)
|
||||
{
|
||||
g_return_if_fail (config != NULL);
|
||||
|
||||
g_list_free_full (config->commands, (GDestroyNotify) pinos_command_free);
|
||||
|
||||
g_free (config);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_daemon_config_load_file:
|
||||
* @config: A #PinosDaemonConfig
|
||||
* @filename: A filename
|
||||
* @err: Return location for a #GError, or %NULL
|
||||
*
|
||||
* Loads pinos config from @filename.
|
||||
*
|
||||
* Returns: %TRUE on success, otherwise %FALSE and @err is set.
|
||||
*/
|
||||
gboolean
|
||||
pinos_daemon_config_load_file (PinosDaemonConfig * config,
|
||||
const gchar * filename,
|
||||
GError ** err)
|
||||
{
|
||||
gchar *data;
|
||||
gchar **lines;
|
||||
gboolean ret = TRUE;
|
||||
guint i;
|
||||
|
||||
g_return_val_if_fail (config != NULL, FALSE);
|
||||
g_return_val_if_fail (filename != NULL && *filename != '\0', FALSE);
|
||||
|
||||
g_debug ("deamon-config %p loading file %s", config, filename);
|
||||
|
||||
if (!g_file_get_contents (filename, &data, NULL, err)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
lines = g_strsplit (data, "\n", 0);
|
||||
for (i = 0; lines[i] != NULL; i++) {
|
||||
if (!parse_line (config, filename, lines[i], i+1, err)) {
|
||||
ret = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_strfreev (lines);
|
||||
g_free (data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_daemon_config_load:
|
||||
* @config: A #PinosDaemonConfig
|
||||
* @err: Return location for a #GError, or %NULL
|
||||
*
|
||||
* Loads the default config file for pinos. The filename can be overridden with
|
||||
* an evironment variable PINOS_CONFIG_FILE.
|
||||
*
|
||||
* Return: %TRUE on success, otherwise %FALSE and @err is set.
|
||||
*/
|
||||
gboolean
|
||||
pinos_daemon_config_load (PinosDaemonConfig * config,
|
||||
GError ** err)
|
||||
{
|
||||
const gchar *filename;
|
||||
|
||||
g_return_val_if_fail (config != NULL, FALSE);
|
||||
|
||||
filename = g_getenv ("PINOS_CONFIG_FILE");
|
||||
if (filename != NULL && *filename != '\0') {
|
||||
g_debug ("PINOS_CONFIG_FILE set to: %s", filename);
|
||||
} else {
|
||||
filename = DEFAULT_CONFIG_FILE;
|
||||
}
|
||||
|
||||
return pinos_daemon_config_load_file (config, filename, err);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_daemon_config_run_commands:
|
||||
* @config: A #PinosDaemonConfig
|
||||
* @daemon: A #PinosDaemon
|
||||
*
|
||||
* Run all commands that have been parsed. The list of commands will be cleared
|
||||
* when this function has been called.
|
||||
*
|
||||
* Returns: %TRUE if all commands where executed with success, otherwise %FALSE.
|
||||
*/
|
||||
gboolean
|
||||
pinos_daemon_config_run_commands (PinosDaemonConfig * config,
|
||||
PinosDaemon * daemon)
|
||||
{
|
||||
GList *walk;
|
||||
GError *err = NULL;
|
||||
gboolean ret = TRUE;
|
||||
|
||||
g_return_val_if_fail (config != NULL, FALSE);
|
||||
|
||||
for (walk = config->commands; walk != NULL; walk = walk->next) {
|
||||
PinosCommand *command = (PinosCommand *)walk->data;
|
||||
if (!pinos_command_run (command, daemon, &err)) {
|
||||
g_warning ("could not run command %s: %s",
|
||||
pinos_command_get_name (command), err->message);
|
||||
g_clear_error (&err);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
g_list_free_full (config->commands, (GDestroyNotify) pinos_command_free);
|
||||
|
||||
return ret;
|
||||
}
|
||||
75
pinos/daemon/daemon-config.h
Normal file
75
pinos/daemon/daemon-config.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/* Pinos
|
||||
* Copyright (C) 2016 Axis Communications <dev-gstreamer@axis.com>
|
||||
* @author Linus Svensson <linus.svensson@axis.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PINOS_DAEMON_CONFIG_H__
|
||||
#define __PINOS_DAEMON_CONFIG_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#include <server/daemon.h>
|
||||
|
||||
#define PINOS_TYPE_DAEMON_CONFIG (pinos_daemon_config_get_type ())
|
||||
|
||||
typedef struct _PinosDaemonConfig PinosDaemonConfig;
|
||||
|
||||
struct _PinosDaemonConfig {
|
||||
GList *commands;
|
||||
};
|
||||
|
||||
GQuark pinos_daemon_config_error_quark (void);
|
||||
/**
|
||||
* PINOS_DAEMON_CONFIG_ERROR:
|
||||
*
|
||||
* Pinos daemon config error.
|
||||
*/
|
||||
#define PINOS_DAEMON_CONFIG_ERROR (pinos_daemon_config_error_quark ())
|
||||
|
||||
/**
|
||||
* PinosDaemonConfigError:
|
||||
* @PINOS_DAEMON_CONFIG_ERROR_GENERIC: Generic daemon config error.
|
||||
* @PINOS_DAEMON_CONFIG_ERROR_ASSIGNMENT: Assignment error.
|
||||
* @PINOS_DAEMON_CONFIG_ERROR_COMMAND: Command error.
|
||||
*
|
||||
* Error codes for Pinos daemon config.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
PINOS_DAEMON_CONFIG_ERROR_GENERIC,
|
||||
PINOS_DAEMON_CONFIG_ERROR_ASSIGNMENT,
|
||||
PINOS_DAEMON_CONFIG_ERROR_COMMAND,
|
||||
} PinosDaemonConfigError;
|
||||
|
||||
GType pinos_daemon_config_get_type (void);
|
||||
|
||||
PinosDaemonConfig * pinos_daemon_config_new (void);
|
||||
void pinos_daemon_config_free (PinosDaemonConfig *config);
|
||||
gboolean pinos_daemon_config_load_file (PinosDaemonConfig *config,
|
||||
const gchar *filename,
|
||||
GError **err);
|
||||
gboolean pinos_daemon_config_load (PinosDaemonConfig *config,
|
||||
GError **err);
|
||||
gboolean pinos_daemon_config_run_commands (PinosDaemonConfig *config,
|
||||
PinosDaemon *daemon);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PINOS_DAEMON_CONFIG_H__ */
|
||||
|
|
@ -25,11 +25,14 @@
|
|||
#include <server/module.h>
|
||||
#include <spa/include/spa/memory.h>
|
||||
|
||||
#include "daemon-config.h"
|
||||
|
||||
gint
|
||||
main (gint argc, gchar *argv[])
|
||||
{
|
||||
PinosDaemon *daemon;
|
||||
GMainLoop *loop;
|
||||
PinosDaemonConfig *config;
|
||||
PinosProperties *props;
|
||||
GError *err = NULL;
|
||||
|
||||
|
|
@ -38,16 +41,18 @@ main (gint argc, gchar *argv[])
|
|||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
|
||||
props = pinos_properties_new ("test", "test", NULL);
|
||||
daemon = pinos_daemon_new (props);
|
||||
|
||||
if (pinos_module_load (daemon, "module-gst", &err) == NULL) {
|
||||
g_error ("could not load module-gst: %s", err->message);
|
||||
/* parse configuration */
|
||||
config = pinos_daemon_config_new ();
|
||||
if (!pinos_daemon_config_load (config, &err)) {
|
||||
g_error ("failed to parse config: %s", err->message);
|
||||
g_clear_error (&err);
|
||||
}
|
||||
|
||||
pinos_spa_alsa_sink_new (daemon, "alsa-sink", NULL);
|
||||
pinos_spa_v4l2_source_new (daemon, "v4l2-source", NULL);
|
||||
props = pinos_properties_new ("test", "test", NULL);
|
||||
daemon = pinos_daemon_new (props);
|
||||
|
||||
pinos_daemon_config_run_commands (config, daemon);
|
||||
|
||||
pinos_daemon_start (daemon);
|
||||
|
||||
g_main_loop_run (loop);
|
||||
|
|
|
|||
1
pinos/daemon/pinos.conf.in
Normal file
1
pinos/daemon/pinos.conf.in
Normal file
|
|
@ -0,0 +1 @@
|
|||
load-module module-gst
|
||||
|
|
@ -24,10 +24,10 @@
|
|||
#include "gst-manager.h"
|
||||
#include "gst-node-factory.h"
|
||||
|
||||
gboolean pinos__module_init (PinosModule *module);
|
||||
gboolean pinos__module_init (PinosModule *module, const gchar * args);
|
||||
|
||||
G_MODULE_EXPORT gboolean
|
||||
pinos__module_init (PinosModule * module)
|
||||
pinos__module_init (PinosModule * module, G_GNUC_UNUSED const gchar * args)
|
||||
{
|
||||
PinosNodeFactory *factory;
|
||||
|
||||
|
|
|
|||
36
pinos/modules/spa/module.c
Normal file
36
pinos/modules/spa/module.c
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
/* Pinos
|
||||
* Copyright (C) 2016 Axis Communications <dev-gstreamer@axis.com>
|
||||
* @author Linus Svensson <linus.svensson@axis.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <server/daemon.h>
|
||||
#include <server/module.h>
|
||||
|
||||
#include "spa-alsa-sink.h"
|
||||
#include "spa-v4l2-source.h"
|
||||
|
||||
gboolean pinos__module_init (PinosModule *module, const gchar * args);
|
||||
|
||||
G_MODULE_EXPORT gboolean
|
||||
pinos__module_init (PinosModule * module, G_GNUC_UNUSED const gchar * args)
|
||||
{
|
||||
pinos_spa_alsa_sink_new (module->daemon, "alsa-sink", NULL);
|
||||
pinos_spa_v4l2_source_new (module->daemon, "v4l2-source", NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
251
pinos/server/command.c
Normal file
251
pinos/server/command.c
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
/* Pinos
|
||||
* Copyright (C) 2016 Axis Communications <dev-gstreamer@axis.com>
|
||||
* @author Linus Svensson <linus.svensson@axis.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <server/module.h>
|
||||
|
||||
#include "command.h"
|
||||
|
||||
GQuark
|
||||
pinos_command_error_quark (void)
|
||||
{
|
||||
static GQuark quark = 0;
|
||||
|
||||
if (quark == 0) {
|
||||
quark = g_quark_from_static_string ("pinos_command_error");
|
||||
}
|
||||
|
||||
return quark;
|
||||
}
|
||||
|
||||
typedef gboolean (*PinosCommandFunc) (PinosCommand *command,
|
||||
PinosDaemon *daemon,
|
||||
GError **err);
|
||||
|
||||
static gboolean execute_command_module_load (PinosCommand *command,
|
||||
PinosDaemon *daemon,
|
||||
GError **err);
|
||||
|
||||
typedef PinosCommand * (*PinosCommandParseFunc) (const gchar *line,
|
||||
GError **err);
|
||||
|
||||
static PinosCommand * parse_command_module_load (const gchar *line,
|
||||
GError **err);
|
||||
|
||||
struct _PinosCommand
|
||||
{
|
||||
PinosCommandFunc func;
|
||||
gchar **args;
|
||||
gint n_args;
|
||||
};
|
||||
|
||||
typedef struct _CommandParse
|
||||
{
|
||||
const gchar *name;
|
||||
PinosCommandParseFunc func;
|
||||
} CommandParse;
|
||||
|
||||
static const CommandParse parsers[] = {
|
||||
{"load-module", parse_command_module_load},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static const gchar whitespace[] = " \t";
|
||||
|
||||
static gchar **
|
||||
tokenize (const gchar * line, gint max_tokens, gint * n_tokens)
|
||||
{
|
||||
gchar **res;
|
||||
GSList *tokens, *walk;
|
||||
const gchar *s;
|
||||
gint num;
|
||||
|
||||
s = line + strspn (line, whitespace);
|
||||
num = 0;
|
||||
tokens = NULL;
|
||||
|
||||
while (*s != '\0' && num + 1 < max_tokens) {
|
||||
gsize len;
|
||||
gchar *token;
|
||||
|
||||
len = strcspn (s, whitespace);
|
||||
token = g_strndup (s, len);
|
||||
tokens = g_slist_prepend (tokens, token);
|
||||
num++;
|
||||
|
||||
s += len;
|
||||
s += strspn (s, whitespace);
|
||||
}
|
||||
|
||||
if (*s != '\0') {
|
||||
tokens = g_slist_prepend (tokens, g_strdup (s));
|
||||
num++;
|
||||
}
|
||||
|
||||
res = g_new (gchar *, num + 1);
|
||||
res[num] = NULL;
|
||||
for (walk = tokens; walk != NULL; walk = walk->next) {
|
||||
res[--num] = walk->data;
|
||||
}
|
||||
g_slist_free (tokens);
|
||||
|
||||
*n_tokens = num;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static PinosCommand *
|
||||
parse_command_module_load (const gchar * line, GError ** err)
|
||||
{
|
||||
PinosCommand *command;
|
||||
|
||||
command = g_new0 (PinosCommand, 1);
|
||||
|
||||
command->func = execute_command_module_load;
|
||||
command->args = tokenize (line, 3, &command->n_args);
|
||||
|
||||
if (command->args[1] == NULL)
|
||||
goto no_module;
|
||||
|
||||
return command;
|
||||
|
||||
no_module:
|
||||
g_set_error (err, PINOS_COMMAND_ERROR, PINOS_COMMAND_ERROR_PARSE,
|
||||
"%s requires a module name", command->args[0]);
|
||||
|
||||
g_strfreev (command->args);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
execute_command_module_load (PinosCommand * command,
|
||||
PinosDaemon * daemon,
|
||||
GError ** err)
|
||||
{
|
||||
gchar *module;
|
||||
gchar *args;
|
||||
|
||||
module = command->args[1];
|
||||
args = command->args[2];
|
||||
|
||||
return pinos_module_load (daemon, module, args, err) != NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_command_free:
|
||||
* @command: A #PinosCommand
|
||||
*
|
||||
* Free all resources assicated with @command.
|
||||
*/
|
||||
void
|
||||
pinos_command_free (PinosCommand * command)
|
||||
{
|
||||
g_return_if_fail (command != NULL);
|
||||
|
||||
g_strfreev (command->args);
|
||||
|
||||
g_free (command);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_command_parse:
|
||||
* @command: (out): Return location for a #PinosCommand
|
||||
* @line: command line to parse
|
||||
* @err: Return location for a #GError, or %NULL
|
||||
*
|
||||
* Parses a command line, @line, and store the parsed command in @command.
|
||||
* A command can later be executed with pinos_command_run().
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
pinos_command_parse (PinosCommand ** command,
|
||||
gchar * line,
|
||||
GError ** err)
|
||||
{
|
||||
const CommandParse *parse;
|
||||
gchar *name;
|
||||
gsize len;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
g_return_val_if_fail (command != NULL && *command == NULL, FALSE);
|
||||
g_return_val_if_fail (line != NULL && *line != '\0', FALSE);
|
||||
|
||||
len = strcspn (line, whitespace);
|
||||
|
||||
name = g_strndup (line, len);
|
||||
|
||||
for (parse = parsers; parse->name != NULL; parse++) {
|
||||
if (g_strcmp0 (name, parse->name) == 0) {
|
||||
*command = parse->func (line, err);
|
||||
if (*command != NULL)
|
||||
ret = TRUE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
g_set_error (err, PINOS_COMMAND_ERROR, PINOS_COMMAND_ERROR_NO_SUCH_COMMAND,
|
||||
"Command \"%s\" does not exist", name);
|
||||
|
||||
out:
|
||||
g_free (name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_command_run:
|
||||
* @command: A #PinosCommand
|
||||
* @daemon: A #PinosDaemon
|
||||
* @err: Return location for a #GError, or %NULL
|
||||
*
|
||||
* Run @command.
|
||||
*
|
||||
* Returns: %TRUE if @command was executed successfully, %FALSE otherwise.
|
||||
*/
|
||||
gboolean
|
||||
pinos_command_run (PinosCommand * command,
|
||||
PinosDaemon * daemon,
|
||||
GError ** err)
|
||||
{
|
||||
g_return_val_if_fail (command != NULL, FALSE);
|
||||
g_return_val_if_fail (PINOS_IS_DAEMON (daemon), FALSE);
|
||||
|
||||
return command->func (command, daemon, err);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_command_get_name:
|
||||
* @command: A #PinosCommand
|
||||
*
|
||||
* Get the name of @command.
|
||||
*
|
||||
* Returns: The name of @command.
|
||||
*/
|
||||
const gchar *
|
||||
pinos_command_get_name (PinosCommand * command)
|
||||
{
|
||||
g_return_val_if_fail (command != NULL, NULL);
|
||||
|
||||
return command->args[0];
|
||||
}
|
||||
69
pinos/server/command.h
Normal file
69
pinos/server/command.h
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
/* Pinos
|
||||
* Copyright (C) 2016 Axis Communications <dev-gstreamer@axis.com>
|
||||
* @author Linus Svensson <linus.svensson@axis.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __PINOS_COMMAND_H__
|
||||
#define __PINOS_COMMAND_H__
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#include <server/daemon.h>
|
||||
|
||||
typedef struct _PinosCommand PinosCommand;
|
||||
|
||||
GQuark pinos_command_error_quark (void);
|
||||
/**
|
||||
* PINOS_COMMAND_ERROR:
|
||||
*
|
||||
* Pinos command error.
|
||||
*/
|
||||
#define PINOS_COMMAND_ERROR (pinos_command_error_quark ())
|
||||
|
||||
/**
|
||||
* PinosCommandError:
|
||||
* @PINOS_COMMAND_ERROR_GENERIC: Generic command error.
|
||||
* @PINOS_COMMAND_ERROR_NO_SUCH_COMMAND: No such command.
|
||||
* @PINOS_COMMAND_ERROR_PARSE: Failed to parse command.
|
||||
* @PINOS_COMMAND_ERROR_FAILED: Command failed to execute.
|
||||
*
|
||||
* Error codes for Pinos command.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
PINOS_COMMAND_ERROR_GENERIC,
|
||||
PINOS_COMMAND_ERROR_NO_SUCH_COMMAND,
|
||||
PINOS_COMMAND_ERROR_PARSE,
|
||||
PINOS_COMMAND_ERROR_FAILED,
|
||||
} PinosCommandError;
|
||||
|
||||
void pinos_command_free (PinosCommand *command);
|
||||
|
||||
gboolean pinos_command_parse (PinosCommand **command,
|
||||
gchar *line,
|
||||
GError **err);
|
||||
gboolean pinos_command_run (PinosCommand *command,
|
||||
PinosDaemon *daemon,
|
||||
GError **err);
|
||||
const gchar * pinos_command_get_name (PinosCommand *command);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PINOS_COMMAND_H__ */
|
||||
|
|
@ -205,6 +205,7 @@ find_module (const gchar * path, const gchar *name)
|
|||
* pinos_module_load:
|
||||
* @daemon: a #PinosDaemon
|
||||
* @name: name of the module to load
|
||||
* @args: A string with arguments for the module
|
||||
* @err: Return location for a #GError, or %NULL
|
||||
*
|
||||
* Load module with @name.
|
||||
|
|
@ -212,7 +213,10 @@ find_module (const gchar * path, const gchar *name)
|
|||
* Returns: A #PinosModule if the module could be loaded, or %NULL on failure.
|
||||
*/
|
||||
PinosModule *
|
||||
pinos_module_load (PinosDaemon * daemon, const gchar * name, GError ** err)
|
||||
pinos_module_load (PinosDaemon * daemon,
|
||||
const gchar * name,
|
||||
const gchar * args,
|
||||
GError ** err)
|
||||
{
|
||||
PinosModule *module;
|
||||
PinosModulePrivate *priv;
|
||||
|
|
@ -280,7 +284,7 @@ pinos_module_load (PinosDaemon * daemon, const gchar * name, GError ** err)
|
|||
/* don't unload this module again */
|
||||
g_module_make_resident (gmodule);
|
||||
|
||||
if (!init_func (module)) {
|
||||
if (!init_func (module, (gchar *) args)) {
|
||||
g_set_error (err, PINOS_MODULE_ERROR, PINOS_MODULE_ERROR_INIT,
|
||||
"\"%s\" failed to initialize", name);
|
||||
g_object_unref (module);
|
||||
|
|
|
|||
|
|
@ -81,18 +81,20 @@ typedef enum
|
|||
/**
|
||||
* PinosModuleInitFunc:
|
||||
* @module: A #PinosModule
|
||||
* @args: Arguments to the module
|
||||
*
|
||||
* A module should provide an init function with this signature. This function
|
||||
* will be called when a module is loaded.
|
||||
*
|
||||
* Returns: %TRUE on success, %FALSE otherwise
|
||||
*/
|
||||
typedef gboolean (*PinosModuleInitFunc) (PinosModule *module);
|
||||
typedef gboolean (*PinosModuleInitFunc) (PinosModule *module, gchar *args);
|
||||
|
||||
GType pinos_module_get_type (void);
|
||||
|
||||
PinosModule * pinos_module_load (PinosDaemon *daemon,
|
||||
const gchar *name,
|
||||
const gchar *args,
|
||||
GError **err);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <gst/gst.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include <client/pinos.h>
|
||||
|
|
@ -27,42 +26,6 @@
|
|||
|
||||
static GMainLoop *loop;
|
||||
|
||||
static void
|
||||
on_socket_notify (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
GSocket *socket;
|
||||
GstElement *pipeline, *src, *filter;
|
||||
GBytes *format;
|
||||
GstCaps *caps;
|
||||
GError *error = NULL;
|
||||
|
||||
pipeline = gst_parse_launch ("socketsrc name=src ! pinosdepay ! capsfilter name=filter ! videoconvert ! xvimagesink", &error);
|
||||
if (error != NULL) {
|
||||
g_warning ("error creating pipeline: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
g_assert (pipeline != NULL);
|
||||
}
|
||||
|
||||
/* configure socket in the socketsrc */
|
||||
g_object_get (gobject, "socket", &socket, NULL);
|
||||
g_print ("got socket %p\n", socket);
|
||||
src = gst_bin_get_by_name (GST_BIN (pipeline), "src");
|
||||
g_object_set (src, "socket", socket, NULL);
|
||||
|
||||
/* configure format as capsfilter */
|
||||
g_object_get (gobject, "format", &format, NULL);
|
||||
caps = gst_caps_from_string (g_bytes_get_data (format, NULL));
|
||||
g_bytes_unref (format);
|
||||
filter = gst_bin_get_by_name (GST_BIN (pipeline), "filter");
|
||||
g_object_set (filter, "caps", caps, NULL);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
/* and set to playing */
|
||||
gst_element_set_state (pipeline, GST_STATE_PLAYING);
|
||||
}
|
||||
|
||||
static void
|
||||
on_stream_notify (GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
|
|
@ -113,7 +76,6 @@ on_state_notify (GObject *gobject,
|
|||
|
||||
stream = pinos_stream_new (c, "test", NULL);
|
||||
g_signal_connect (stream, "notify::state", (GCallback) on_stream_notify, stream);
|
||||
g_signal_connect (stream, "notify::socket", (GCallback) on_socket_notify, stream);
|
||||
|
||||
possible = NULL;
|
||||
pinos_stream_connect (stream,
|
||||
|
|
|
|||
|
|
@ -311,6 +311,8 @@ struct _SpaNode {
|
|||
*
|
||||
* When @format is %NULL, the current format will be removed.
|
||||
*
|
||||
* This function takes a copy of the format.
|
||||
*
|
||||
* Returns: #SPA_RESULT_OK on success
|
||||
* #SPA_RESULT_INVALID_ARGUMENTS when node is %NULL
|
||||
* #SPA_RESULT_INVALID_PORT when port_id is not valid
|
||||
|
|
@ -364,12 +366,11 @@ struct _SpaNode {
|
|||
*
|
||||
* For an input port, all the buffers will remain dequeued. Once a buffer
|
||||
* has been pushed on a port with port_push_input, it should not be reused
|
||||
* until the buffer refcount reached 0 and the notify is called.
|
||||
* until the REUSE_BUFFER event is notified.
|
||||
*
|
||||
* For output ports, all buffers will be queued in the port. with
|
||||
* port_pull_output, a buffer can be dequeued. The notify of the buffers
|
||||
* will be set by @node so that buffers will be reused when the refcount
|
||||
* reaches 0.
|
||||
* port_pull_output, a buffer can be dequeued. When a buffer can be reused,
|
||||
* port_reuse_buffer() should be called.
|
||||
*
|
||||
* Passing %NULL as @buffers will remove the reference that the port has
|
||||
* on the buffers.
|
||||
|
|
@ -395,8 +396,8 @@ struct _SpaNode {
|
|||
* and pushed into the port. A notify should be configured so that you can
|
||||
* know when a buffer can be reused.
|
||||
*
|
||||
* For output ports, the buffers remain queued. The notify will be configured
|
||||
* so that buffers can be reused when no longer in use.
|
||||
* For output ports, the buffers remain queued. port_reuse_buffer() should
|
||||
* be called when a buffer can be reused.
|
||||
*
|
||||
* Returns: #SPA_RESULT_OK on success
|
||||
*/
|
||||
|
|
@ -407,6 +408,17 @@ struct _SpaNode {
|
|||
SpaBuffer **buffers,
|
||||
unsigned int *n_buffers);
|
||||
|
||||
/**
|
||||
* SpaNode::port_reuse_buffer:
|
||||
* @node: a #SpaNode
|
||||
* @port_id: a port id
|
||||
* @buffer_id: a buffer id to reuse
|
||||
*
|
||||
* Tell an output port to reuse a buffer.
|
||||
*
|
||||
* Returns: #SPA_RESULT_OK on success
|
||||
* #SPA_RESULT_INVALID_ARGUMENTS when node is %NULL
|
||||
*/
|
||||
SpaResult (*port_reuse_buffer) (SpaNode *node,
|
||||
uint32_t port_id,
|
||||
uint32_t buffer_id);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue