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:
Linus Svensson 2016-08-29 18:29:07 +02:00 committed by Wim Taymans
parent d654a1bcd6
commit 7d8e2d53f7
14 changed files with 729 additions and 59 deletions

View file

@ -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.
"

View file

@ -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 #
###################################

View 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;
}

View 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__ */

View file

@ -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);

View file

@ -0,0 +1 @@
load-module module-gst

View file

@ -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;

View 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
View 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
View 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__ */

View file

@ -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);

View file

@ -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

View file

@ -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,

View file

@ -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);