mirror of
https://gitlab.xiph.org/xiph/ezstream.git
synced 2025-02-02 15:07:45 -05:00
Make media inputs ("intakes") a list of things, too
This commit is contained in:
parent
184e2dd8c3
commit
0b260b3c08
@ -307,6 +307,15 @@ The broadcast is private (the default).
|
|||||||
.It Ar 1|Yes|True
|
.It Ar 1|Yes|True
|
||||||
The broadcast is public.
|
The broadcast is public.
|
||||||
.El
|
.El
|
||||||
|
.It Sy \&<intake\ /\&>
|
||||||
|
Use the intake
|
||||||
|
.Po
|
||||||
|
input media
|
||||||
|
.Pc
|
||||||
|
configuration with the provided symbolic name for this stream.
|
||||||
|
.Pp
|
||||||
|
Default:
|
||||||
|
.Ar default
|
||||||
.It Sy \&<server\ /\&>
|
.It Sy \&<server\ /\&>
|
||||||
Use the server configuration with the provided symbolic name for this stream.
|
Use the server configuration with the provided symbolic name for this stream.
|
||||||
.Pp
|
.Pp
|
||||||
@ -376,17 +385,41 @@ Informational number of audio channels of the broadcast.
|
|||||||
Default:
|
Default:
|
||||||
.Em none
|
.Em none
|
||||||
.El
|
.El
|
||||||
.Ss Media block
|
.Ss Intakes block
|
||||||
.Bl -tag -width -Ds
|
.Bl -tag -width -Ds
|
||||||
.It Sy \&<media\ /\&>
|
.It Sy \&<intakes\ /\&>
|
||||||
.Pq Mandatory.
|
This element contains all intake blocks as child elements.
|
||||||
This element contains the entire input media configuration as child elements.
|
|
||||||
Its parent is the
|
Its parent is the
|
||||||
.Sy \&<ezstream\ /\&>
|
.Sy \&<ezstream\ /\&>
|
||||||
element.
|
element.
|
||||||
|
.Pp
|
||||||
|
A configuration file may contain multiple named intake configurations.
|
||||||
|
The stream configuration determines what intake
|
||||||
|
.Po
|
||||||
|
media input
|
||||||
|
.Pc
|
||||||
|
configuration should be used.
|
||||||
.El
|
.El
|
||||||
.Ss Media configuration
|
.Ss Intake block
|
||||||
.Bl -tag -width -Ds
|
.Bl -tag -width -Ds
|
||||||
|
.It Sy \&<intake\ /\&>
|
||||||
|
.Pq Mandatory.
|
||||||
|
This element contains the entire input media configuration as child elements.
|
||||||
|
Its parent is the
|
||||||
|
.Sy \&<intakes\ /\&>
|
||||||
|
element.
|
||||||
|
.El
|
||||||
|
.Ss Intake configuration
|
||||||
|
.Bl -tag -width -Ds
|
||||||
|
.It Sy \&<name\ /\&>
|
||||||
|
Set the name of the intake configuration.
|
||||||
|
This may be referenced in a
|
||||||
|
.Sy \&<stream\ /\&> .
|
||||||
|
.Pp
|
||||||
|
The name is case-aware, but not case-sensitive.
|
||||||
|
.Pp
|
||||||
|
Default:
|
||||||
|
.Ar default
|
||||||
.It Sy \&<type\ /\&>
|
.It Sy \&<type\ /\&>
|
||||||
Configure the input media type:
|
Configure the input media type:
|
||||||
.Pp
|
.Pp
|
||||||
|
@ -26,9 +26,11 @@
|
|||||||
</stream>
|
</stream>
|
||||||
</streams>
|
</streams>
|
||||||
|
|
||||||
<media>
|
<intakes>
|
||||||
|
<intake>
|
||||||
<filename>%FILENAME%</filename>
|
<filename>%FILENAME%</filename>
|
||||||
</media>
|
</intake>
|
||||||
|
</intakes>
|
||||||
|
|
||||||
<decoders>
|
<decoders>
|
||||||
<decoder>
|
<decoder>
|
||||||
|
@ -75,6 +75,9 @@
|
|||||||
<!-- Mount point on server -->
|
<!-- Mount point on server -->
|
||||||
<mountpoint>/stream.ogg</mountpoint>
|
<mountpoint>/stream.ogg</mountpoint>
|
||||||
|
|
||||||
|
<!-- Name of the intake entry to use (default: "default") -->
|
||||||
|
<intake>Default</intake>
|
||||||
|
|
||||||
<!-- Name of the server entry to use (default: "default") -->
|
<!-- Name of the server entry to use (default: "default") -->
|
||||||
<server>Default</server>
|
<server>Default</server>
|
||||||
|
|
||||||
@ -100,9 +103,13 @@
|
|||||||
</streams>
|
</streams>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Media configuration
|
Intake configuration
|
||||||
-->
|
-->
|
||||||
<media>
|
<intakes>
|
||||||
|
<intake>
|
||||||
|
<!-- Identifying name; default: "default" -->
|
||||||
|
<name>Default</name>
|
||||||
|
|
||||||
<!-- Media type: autodetect, file, playlist, program, stdin -->
|
<!-- Media type: autodetect, file, playlist, program, stdin -->
|
||||||
<type>autodetect</type>
|
<type>autodetect</type>
|
||||||
|
|
||||||
@ -112,9 +119,10 @@
|
|||||||
<!-- Setting to shuffle playlists -->
|
<!-- Setting to shuffle playlists -->
|
||||||
<shuffle>Yes</shuffle>
|
<shuffle>Yes</shuffle>
|
||||||
|
|
||||||
<!-- Setting whether to stream input indefinitely or only once -->
|
<!-- Setting whether to stream intake indefinitely or only once -->
|
||||||
<stream_once>No</stream_once>
|
<stream_once>No</stream_once>
|
||||||
</media>
|
</intake>
|
||||||
|
</intakes>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Metadata configuration
|
Metadata configuration
|
||||||
|
@ -22,8 +22,10 @@
|
|||||||
</stream>
|
</stream>
|
||||||
</streams>
|
</streams>
|
||||||
|
|
||||||
<media>
|
<intakes>
|
||||||
|
<intake>
|
||||||
<filename>playlist.m3u</filename>
|
<filename>playlist.m3u</filename>
|
||||||
</media>
|
</intake>
|
||||||
|
</intakes>
|
||||||
|
|
||||||
</ezstream>
|
</ezstream>
|
||||||
|
@ -22,8 +22,10 @@
|
|||||||
</stream>
|
</stream>
|
||||||
</streams>
|
</streams>
|
||||||
|
|
||||||
<media>
|
<intakes>
|
||||||
|
<intake>
|
||||||
<type>stdin</type>
|
<type>stdin</type>
|
||||||
</media>
|
</intake>
|
||||||
|
</intakes>
|
||||||
|
|
||||||
</ezstream>
|
</ezstream>
|
||||||
|
@ -21,9 +21,11 @@
|
|||||||
</stream>
|
</stream>
|
||||||
</streams>
|
</streams>
|
||||||
|
|
||||||
<media>
|
<intakes>
|
||||||
|
<intake>
|
||||||
<filename>playlist.m3u</filename>
|
<filename>playlist.m3u</filename>
|
||||||
</media>
|
</intake>
|
||||||
|
</intakes>
|
||||||
|
|
||||||
<decoders>
|
<decoders>
|
||||||
<decoder>
|
<decoder>
|
||||||
|
@ -6,6 +6,7 @@ noinst_HEADERS = \
|
|||||||
cfg.h \
|
cfg.h \
|
||||||
cfg_decoder.h \
|
cfg_decoder.h \
|
||||||
cfg_encoder.h \
|
cfg_encoder.h \
|
||||||
|
cfg_intake.h \
|
||||||
cfg_private.h \
|
cfg_private.h \
|
||||||
cfg_server.h \
|
cfg_server.h \
|
||||||
cfg_stream.h \
|
cfg_stream.h \
|
||||||
@ -22,6 +23,7 @@ libezstream_la_SOURCES = \
|
|||||||
cfg.c \
|
cfg.c \
|
||||||
cfg_decoder.c \
|
cfg_decoder.c \
|
||||||
cfg_encoder.c \
|
cfg_encoder.c \
|
||||||
|
cfg_intake.c \
|
||||||
cfg_server.c \
|
cfg_server.c \
|
||||||
cfg_stream.c \
|
cfg_stream.c \
|
||||||
cfg_xmlfile.c \
|
cfg_xmlfile.c \
|
||||||
|
124
src/cfg.c
124
src/cfg.c
@ -45,10 +45,11 @@ static void _cfg_commit(void);
|
|||||||
static void
|
static void
|
||||||
_cfg_reset(struct cfg *c)
|
_cfg_reset(struct cfg *c)
|
||||||
{
|
{
|
||||||
cfg_server_list_destroy(&c->servers);
|
|
||||||
cfg_stream_list_destroy(&c->streams);
|
cfg_stream_list_destroy(&c->streams);
|
||||||
cfg_decoder_list_destroy(&c->decoders);
|
cfg_server_list_destroy(&c->servers);
|
||||||
|
cfg_intake_list_destroy(&c->intakes);
|
||||||
cfg_encoder_list_destroy(&c->encoders);
|
cfg_encoder_list_destroy(&c->encoders);
|
||||||
|
cfg_decoder_list_destroy(&c->decoders);
|
||||||
|
|
||||||
xfree(c->metadata.format_str);
|
xfree(c->metadata.format_str);
|
||||||
|
|
||||||
@ -133,47 +134,13 @@ cfg_file_reload(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cfg_check(const char **errstrp)
|
cfg_check(const char **not_used)
|
||||||
{
|
{
|
||||||
if (!cfg_get_media_filename() &&
|
(void)not_used;
|
||||||
CFG_MEDIA_STDIN != cfg_get_media_type()) {
|
|
||||||
if (NULL != errstrp)
|
|
||||||
*errstrp = "media filename missing";
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
cfg_stream_str2fmt(const char *str, enum cfg_stream_format *fmt_p)
|
|
||||||
{
|
|
||||||
if (0 == strcasecmp(str, CFG_SFMT_VORBIS)) {
|
|
||||||
*fmt_p = CFG_STREAM_VORBIS;
|
|
||||||
} else if (0 == strcasecmp(str, CFG_SFMT_MP3)) {
|
|
||||||
*fmt_p = CFG_STREAM_MP3;
|
|
||||||
} else if (0 == strcasecmp(str, CFG_SFMT_THEORA)) {
|
|
||||||
*fmt_p = CFG_STREAM_THEORA;
|
|
||||||
} else
|
|
||||||
return (-1);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
cfg_stream_fmt2str(enum cfg_stream_format fmt)
|
|
||||||
{
|
|
||||||
switch (fmt) {
|
|
||||||
case CFG_STREAM_VORBIS:
|
|
||||||
return (CFG_SFMT_VORBIS);
|
|
||||||
case CFG_STREAM_MP3:
|
|
||||||
return (CFG_SFMT_MP3);
|
|
||||||
case CFG_STREAM_THEORA:
|
|
||||||
return (CFG_SFMT_THEORA);
|
|
||||||
default:
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
cfg_file_check(const char *file)
|
cfg_file_check(const char *file)
|
||||||
{
|
{
|
||||||
@ -215,6 +182,15 @@ cfg_get_encoders(void)
|
|||||||
return (cfg.encoders);
|
return (cfg.encoders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg_intake_list_t
|
||||||
|
cfg_get_intakes(void)
|
||||||
|
{
|
||||||
|
if (!cfg.intakes)
|
||||||
|
cfg.intakes = cfg_intake_list_create();
|
||||||
|
|
||||||
|
return (cfg.intakes);
|
||||||
|
}
|
||||||
|
|
||||||
cfg_server_list_t
|
cfg_server_list_t
|
||||||
cfg_get_servers(void)
|
cfg_get_servers(void)
|
||||||
{
|
{
|
||||||
@ -290,54 +266,6 @@ cfg_set_program_verbosity(unsigned int verbosity, const char **not_used)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
cfg_set_media_type(const char *type, const char **errstrp)
|
|
||||||
{
|
|
||||||
if (!type || !type[0]) {
|
|
||||||
if (errstrp)
|
|
||||||
*errstrp = "empty";
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0 == strcasecmp("autodetect", type))
|
|
||||||
cfg.media.type = CFG_MEDIA_AUTODETECT;
|
|
||||||
else if (0 == strcasecmp("file", type))
|
|
||||||
cfg.media.type = CFG_MEDIA_FILE;
|
|
||||||
else if (0 == strcasecmp("playlist", type))
|
|
||||||
cfg.media.type = CFG_MEDIA_PLAYLIST;
|
|
||||||
else if (0 == strcasecmp("program", type))
|
|
||||||
cfg.media.type = CFG_MEDIA_PROGRAM;
|
|
||||||
else if (0 == strcasecmp("stdin", type))
|
|
||||||
cfg.media.type = CFG_MEDIA_STDIN;
|
|
||||||
else {
|
|
||||||
if (errstrp)
|
|
||||||
*errstrp = "unsupported";
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
cfg_set_media_filename(const char *filename, const char **errstrp)
|
|
||||||
{
|
|
||||||
SET_STRLCPY(cfg.media.filename, filename, errstrp);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
cfg_set_media_shuffle(const char *shuffle, const char **errstrp)
|
|
||||||
{
|
|
||||||
SET_BOOLEAN(cfg.media.shuffle, shuffle, errstrp);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
cfg_set_media_stream_once(const char *stream_once, const char **errstrp)
|
|
||||||
{
|
|
||||||
SET_BOOLEAN(cfg.media.stream_once, stream_once, errstrp);
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
cfg_set_metadata_program(const char *program, const char **errstrp)
|
cfg_set_metadata_program(const char *program, const char **errstrp)
|
||||||
{
|
{
|
||||||
@ -433,30 +361,6 @@ cfg_get_program_verbosity(void)
|
|||||||
return (cfg_program.verbosity);
|
return (cfg_program.verbosity);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum cfg_media_type
|
|
||||||
cfg_get_media_type(void)
|
|
||||||
{
|
|
||||||
return (cfg.media.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
cfg_get_media_filename(void)
|
|
||||||
{
|
|
||||||
return (cfg.media.filename[0] ? cfg.media.filename : NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
cfg_get_media_shuffle(void)
|
|
||||||
{
|
|
||||||
return (cfg.media.shuffle);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
cfg_get_media_stream_once(void)
|
|
||||||
{
|
|
||||||
return (cfg.media.stream_once);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
cfg_get_metadata_program(void)
|
cfg_get_metadata_program(void)
|
||||||
{
|
{
|
||||||
|
42
src/cfg.h
42
src/cfg.h
@ -17,10 +17,6 @@
|
|||||||
#ifndef __CFG_H__
|
#ifndef __CFG_H__
|
||||||
#define __CFG_H__
|
#define __CFG_H__
|
||||||
|
|
||||||
#define CFG_SFMT_VORBIS "VORBIS"
|
|
||||||
#define CFG_SFMT_MP3 "MP3"
|
|
||||||
#define CFG_SFMT_THEORA "THEORA"
|
|
||||||
|
|
||||||
#define PLACEHOLDER_METADATA "@M@"
|
#define PLACEHOLDER_METADATA "@M@"
|
||||||
#define PLACEHOLDER_ARTIST "@a@"
|
#define PLACEHOLDER_ARTIST "@a@"
|
||||||
#define PLACEHOLDER_ALBUM "@b@"
|
#define PLACEHOLDER_ALBUM "@b@"
|
||||||
@ -36,27 +32,9 @@ enum cfg_config_type {
|
|||||||
CFG_TYPE_MAX = CFG_TYPE_XMLFILE,
|
CFG_TYPE_MAX = CFG_TYPE_XMLFILE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum cfg_media_type {
|
|
||||||
CFG_MEDIA_AUTODETECT = 0,
|
|
||||||
CFG_MEDIA_FILE,
|
|
||||||
CFG_MEDIA_PLAYLIST,
|
|
||||||
CFG_MEDIA_PROGRAM,
|
|
||||||
CFG_MEDIA_STDIN,
|
|
||||||
CFG_MEDIA_MIN = CFG_MEDIA_AUTODETECT,
|
|
||||||
CFG_MEDIA_MAX = CFG_MEDIA_STDIN,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum cfg_stream_format {
|
|
||||||
CFG_STREAM_INVALID = 0,
|
|
||||||
CFG_STREAM_VORBIS,
|
|
||||||
CFG_STREAM_MP3,
|
|
||||||
CFG_STREAM_THEORA,
|
|
||||||
CFG_STREAM_MIN = CFG_STREAM_VORBIS,
|
|
||||||
CFG_STREAM_MAX = CFG_STREAM_THEORA,
|
|
||||||
};
|
|
||||||
|
|
||||||
#include "cfg_decoder.h"
|
#include "cfg_decoder.h"
|
||||||
#include "cfg_encoder.h"
|
#include "cfg_encoder.h"
|
||||||
|
#include "cfg_intake.h"
|
||||||
#include "cfg_server.h"
|
#include "cfg_server.h"
|
||||||
#include "cfg_stream.h"
|
#include "cfg_stream.h"
|
||||||
|
|
||||||
@ -67,16 +45,14 @@ int cfg_file_reload(void);
|
|||||||
|
|
||||||
int cfg_check(const char **);
|
int cfg_check(const char **);
|
||||||
|
|
||||||
int cfg_stream_str2fmt(const char *, enum cfg_stream_format *);
|
|
||||||
const char *
|
|
||||||
cfg_stream_fmt2str(enum cfg_stream_format);
|
|
||||||
|
|
||||||
int cfg_file_check(const char *);
|
int cfg_file_check(const char *);
|
||||||
|
|
||||||
cfg_decoder_list_t
|
cfg_decoder_list_t
|
||||||
cfg_get_decoders(void);
|
cfg_get_decoders(void);
|
||||||
cfg_encoder_list_t
|
cfg_encoder_list_t
|
||||||
cfg_get_encoders(void);
|
cfg_get_encoders(void);
|
||||||
|
cfg_intake_list_t
|
||||||
|
cfg_get_intakes(void);
|
||||||
cfg_server_list_t
|
cfg_server_list_t
|
||||||
cfg_get_servers(void);
|
cfg_get_servers(void);
|
||||||
cfg_stream_list_t
|
cfg_stream_list_t
|
||||||
@ -90,11 +66,6 @@ int cfg_set_program_quiet_stderr(int, const char **);
|
|||||||
int cfg_set_program_rtstatus_output(int, const char **);
|
int cfg_set_program_rtstatus_output(int, const char **);
|
||||||
int cfg_set_program_verbosity(unsigned int, const char **);
|
int cfg_set_program_verbosity(unsigned int, const char **);
|
||||||
|
|
||||||
int cfg_set_media_type(const char *, const char **);
|
|
||||||
int cfg_set_media_filename(const char *, const char **);
|
|
||||||
int cfg_set_media_shuffle(const char *, const char **);
|
|
||||||
int cfg_set_media_stream_once(const char *, const char **);
|
|
||||||
|
|
||||||
int cfg_set_metadata_program(const char *, const char **);
|
int cfg_set_metadata_program(const char *, const char **);
|
||||||
int cfg_set_metadata_format_str(const char *, const char **);
|
int cfg_set_metadata_format_str(const char *, const char **);
|
||||||
int cfg_set_metadata_refresh_interval(const char *, const char **);
|
int cfg_set_metadata_refresh_interval(const char *, const char **);
|
||||||
@ -114,13 +85,6 @@ int cfg_get_program_rtstatus_output(void);
|
|||||||
unsigned int
|
unsigned int
|
||||||
cfg_get_program_verbosity(void);
|
cfg_get_program_verbosity(void);
|
||||||
|
|
||||||
enum cfg_media_type
|
|
||||||
cfg_get_media_type(void);
|
|
||||||
const char *
|
|
||||||
cfg_get_media_filename(void);
|
|
||||||
int cfg_get_media_shuffle(void);
|
|
||||||
int cfg_get_media_stream_once(void);
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
cfg_get_metadata_program(void);
|
cfg_get_metadata_program(void);
|
||||||
const char *
|
const char *
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#ifndef __CFG_ENCODER_H__
|
#ifndef __CFG_ENCODER_H__
|
||||||
#define __CFG_ENCODER_H__
|
#define __CFG_ENCODER_H__
|
||||||
|
|
||||||
|
#include "cfg_stream.h"
|
||||||
|
|
||||||
typedef struct cfg_encoder * cfg_encoder_t;
|
typedef struct cfg_encoder * cfg_encoder_t;
|
||||||
typedef struct cfg_encoder_list * cfg_encoder_list_t;
|
typedef struct cfg_encoder_list * cfg_encoder_list_t;
|
||||||
|
|
||||||
|
247
src/cfg_intake.c
Normal file
247
src/cfg_intake.c
Normal file
@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
#include <sys/queue.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "cfg_private.h"
|
||||||
|
#include "cfg_intake.h"
|
||||||
|
#include "xalloc.h"
|
||||||
|
|
||||||
|
struct cfg_intake {
|
||||||
|
TAILQ_ENTRY(cfg_intake) entry;
|
||||||
|
char *name;
|
||||||
|
enum cfg_intake_type type;
|
||||||
|
char filename[PATH_MAX];
|
||||||
|
int shuffle;
|
||||||
|
int stream_once;
|
||||||
|
};
|
||||||
|
|
||||||
|
TAILQ_HEAD(cfg_intake_list, cfg_intake);
|
||||||
|
|
||||||
|
struct cfg_intake_list *
|
||||||
|
cfg_intake_list_create(void)
|
||||||
|
{
|
||||||
|
struct cfg_intake_list *il;
|
||||||
|
|
||||||
|
il = xcalloc(1UL, sizeof(*il));
|
||||||
|
TAILQ_INIT(il);
|
||||||
|
|
||||||
|
return (il);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cfg_intake_list_destroy(cfg_intake_list_t *il_p)
|
||||||
|
{
|
||||||
|
struct cfg_intake_list *il = *il_p;
|
||||||
|
struct cfg_intake *i;
|
||||||
|
|
||||||
|
if (!il)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (NULL != (i = TAILQ_FIRST(il))) {
|
||||||
|
TAILQ_REMOVE(il, i, entry);
|
||||||
|
cfg_intake_destroy(&i);
|
||||||
|
}
|
||||||
|
|
||||||
|
xfree(il);
|
||||||
|
*il_p = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cfg_intake *
|
||||||
|
cfg_intake_list_find(struct cfg_intake_list *il, const char *name)
|
||||||
|
{
|
||||||
|
struct cfg_intake *i;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(i, il, entry) {
|
||||||
|
if (0 == strcasecmp(i->name, name))
|
||||||
|
return (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cfg_intake *
|
||||||
|
cfg_intake_list_get(struct cfg_intake_list *il, const char *name)
|
||||||
|
{
|
||||||
|
struct cfg_intake *i;
|
||||||
|
|
||||||
|
i = cfg_intake_list_find(il, name);
|
||||||
|
if (i)
|
||||||
|
return (i);
|
||||||
|
i = cfg_intake_create(name);
|
||||||
|
if (!i)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
TAILQ_INSERT_TAIL(il, i, entry);
|
||||||
|
|
||||||
|
return (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cfg_intake *
|
||||||
|
cfg_intake_create(const char *name)
|
||||||
|
{
|
||||||
|
struct cfg_intake *i;
|
||||||
|
|
||||||
|
if (!name || !name[0])
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
i = xcalloc(1UL, sizeof(*i));
|
||||||
|
i->name = xstrdup(name);
|
||||||
|
|
||||||
|
return (i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
cfg_intake_destroy(struct cfg_intake **i_p)
|
||||||
|
{
|
||||||
|
struct cfg_intake *i = *i_p;
|
||||||
|
|
||||||
|
xfree(i->name);
|
||||||
|
xfree(i);
|
||||||
|
*i_p = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cfg_intake_set_name(struct cfg_intake *i, struct cfg_intake_list *il,
|
||||||
|
const char *name, const char **errstrp)
|
||||||
|
{
|
||||||
|
struct cfg_intake *i2;
|
||||||
|
|
||||||
|
if (!name || !name[0]) {
|
||||||
|
if (errstrp)
|
||||||
|
*errstrp = "empty";
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
i2 = cfg_intake_list_find(il, name);
|
||||||
|
if (i2 && i2 != i) {
|
||||||
|
if (errstrp)
|
||||||
|
*errstrp = "already exists";
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SET_XSTRDUP(i->name, name, errstrp);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cfg_intake_set_type(struct cfg_intake *i, struct cfg_intake_list *not_used,
|
||||||
|
const char *type, const char **errstrp)
|
||||||
|
{
|
||||||
|
(void)not_used;
|
||||||
|
|
||||||
|
if (!type || !type[0]) {
|
||||||
|
if (errstrp)
|
||||||
|
*errstrp = "empty";
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == strcasecmp("autodetect", type))
|
||||||
|
i->type = CFG_INTAKE_AUTODETECT;
|
||||||
|
else if (0 == strcasecmp("file", type))
|
||||||
|
i->type = CFG_INTAKE_FILE;
|
||||||
|
else if (0 == strcasecmp("playlist", type))
|
||||||
|
i->type = CFG_INTAKE_PLAYLIST;
|
||||||
|
else if (0 == strcasecmp("program", type))
|
||||||
|
i->type = CFG_INTAKE_PROGRAM;
|
||||||
|
else if (0 == strcasecmp("stdin", type))
|
||||||
|
i->type = CFG_INTAKE_STDIN;
|
||||||
|
else {
|
||||||
|
if (errstrp)
|
||||||
|
*errstrp = "unsupported";
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cfg_intake_set_filename(struct cfg_intake *i, struct cfg_intake_list *not_used,
|
||||||
|
const char *filename, const char **errstrp)
|
||||||
|
{
|
||||||
|
(void)not_used;
|
||||||
|
SET_STRLCPY(i->filename, filename, errstrp);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cfg_intake_set_shuffle(struct cfg_intake *i, struct cfg_intake_list *not_used,
|
||||||
|
const char *shuffle, const char **errstrp)
|
||||||
|
{
|
||||||
|
(void)not_used;
|
||||||
|
SET_BOOLEAN(i->shuffle, shuffle, errstrp);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cfg_intake_set_stream_once(struct cfg_intake *i, struct cfg_intake_list *not_used,
|
||||||
|
const char *stream_once, const char **errstrp)
|
||||||
|
{
|
||||||
|
(void)not_used;
|
||||||
|
SET_BOOLEAN(i->stream_once, stream_once, errstrp);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cfg_intake_validate(struct cfg_intake *i, const char **errstrp)
|
||||||
|
{
|
||||||
|
if (!cfg_intake_get_filename(i) &&
|
||||||
|
CFG_INTAKE_STDIN != cfg_intake_get_type(i)) {
|
||||||
|
if (NULL != errstrp)
|
||||||
|
*errstrp = "intake filename missing";
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
cfg_intake_get_name(struct cfg_intake *i)
|
||||||
|
{
|
||||||
|
return (i->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum cfg_intake_type
|
||||||
|
cfg_intake_get_type(struct cfg_intake *i)
|
||||||
|
{
|
||||||
|
return (i->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
cfg_intake_get_filename(struct cfg_intake *i)
|
||||||
|
{
|
||||||
|
return (i->filename[0] ? i->filename : NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cfg_intake_get_shuffle(struct cfg_intake *i)
|
||||||
|
{
|
||||||
|
return (i->shuffle);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cfg_intake_get_stream_once(struct cfg_intake *i)
|
||||||
|
{
|
||||||
|
return (i->stream_once);
|
||||||
|
}
|
68
src/cfg_intake.h
Normal file
68
src/cfg_intake.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CFG_INTAKE_H__
|
||||||
|
#define __CFG_INTAKE_H__
|
||||||
|
|
||||||
|
enum cfg_intake_type {
|
||||||
|
CFG_INTAKE_AUTODETECT = 0,
|
||||||
|
CFG_INTAKE_FILE,
|
||||||
|
CFG_INTAKE_PLAYLIST,
|
||||||
|
CFG_INTAKE_PROGRAM,
|
||||||
|
CFG_INTAKE_STDIN,
|
||||||
|
CFG_INTAKE_MIN = CFG_INTAKE_AUTODETECT,
|
||||||
|
CFG_INTAKE_MAX = CFG_INTAKE_STDIN,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct cfg_intake * cfg_intake_t;
|
||||||
|
typedef struct cfg_intake_list * cfg_intake_list_t;
|
||||||
|
|
||||||
|
cfg_intake_list_t
|
||||||
|
cfg_intake_list_create(void);
|
||||||
|
void cfg_intake_list_destroy(cfg_intake_list_t *);
|
||||||
|
|
||||||
|
cfg_intake_t
|
||||||
|
cfg_intake_list_find(cfg_intake_list_t, const char *);
|
||||||
|
cfg_intake_t
|
||||||
|
cfg_intake_list_get(cfg_intake_list_t, const char *);
|
||||||
|
|
||||||
|
cfg_intake_t
|
||||||
|
cfg_intake_create(const char *);
|
||||||
|
void cfg_intake_destroy(cfg_intake_t *);
|
||||||
|
|
||||||
|
int cfg_intake_set_name(cfg_intake_t, cfg_intake_list_t, const char *,
|
||||||
|
const char **);
|
||||||
|
int cfg_intake_set_type(cfg_intake_t, cfg_intake_list_t, const char *,
|
||||||
|
const char **);
|
||||||
|
int cfg_intake_set_filename(cfg_intake_t, cfg_intake_list_t, const char *,
|
||||||
|
const char **);
|
||||||
|
int cfg_intake_set_shuffle(cfg_intake_t, cfg_intake_list_t, const char *,
|
||||||
|
const char **);
|
||||||
|
int cfg_intake_set_stream_once(cfg_intake_t, cfg_intake_list_t,
|
||||||
|
const char *, const char **);
|
||||||
|
|
||||||
|
int cfg_intake_validate(cfg_intake_t, const char **);
|
||||||
|
|
||||||
|
const char *
|
||||||
|
cfg_intake_get_name(cfg_intake_t);
|
||||||
|
enum cfg_intake_type
|
||||||
|
cfg_intake_get_type(cfg_intake_t);
|
||||||
|
const char *
|
||||||
|
cfg_intake_get_filename(cfg_intake_t);
|
||||||
|
int cfg_intake_get_shuffle(cfg_intake_t);
|
||||||
|
int cfg_intake_get_stream_once(cfg_intake_t);
|
||||||
|
|
||||||
|
#endif /* __CFG_INTAKE_H__ */
|
@ -44,14 +44,11 @@ struct cfg_program {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct cfg {
|
struct cfg {
|
||||||
|
cfg_decoder_list_t decoders;
|
||||||
|
cfg_encoder_list_t encoders;
|
||||||
|
cfg_intake_list_t intakes;
|
||||||
cfg_server_list_t servers;
|
cfg_server_list_t servers;
|
||||||
cfg_stream_list_t streams;
|
cfg_stream_list_t streams;
|
||||||
struct media {
|
|
||||||
enum cfg_media_type type;
|
|
||||||
char filename[PATH_MAX];
|
|
||||||
int shuffle;
|
|
||||||
int stream_once;
|
|
||||||
} media;
|
|
||||||
struct metadata {
|
struct metadata {
|
||||||
char program[PATH_MAX];
|
char program[PATH_MAX];
|
||||||
char *format_str;
|
char *format_str;
|
||||||
@ -59,8 +56,6 @@ struct cfg {
|
|||||||
int normalize_strings;
|
int normalize_strings;
|
||||||
int no_updates;
|
int no_updates;
|
||||||
} metadata;
|
} metadata;
|
||||||
cfg_decoder_list_t decoders;
|
|
||||||
cfg_encoder_list_t encoders;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SET_STRLCPY(t, s, e) do { \
|
#define SET_STRLCPY(t, s, e) do { \
|
||||||
|
@ -30,6 +30,7 @@ struct cfg_stream {
|
|||||||
TAILQ_ENTRY(cfg_stream) entry;
|
TAILQ_ENTRY(cfg_stream) entry;
|
||||||
char *name;
|
char *name;
|
||||||
char *mountpoint;
|
char *mountpoint;
|
||||||
|
char *intake;
|
||||||
char *server;
|
char *server;
|
||||||
int public;
|
int public;
|
||||||
enum cfg_stream_format format;
|
enum cfg_stream_format format;
|
||||||
@ -126,6 +127,7 @@ cfg_stream_destroy(struct cfg_stream **s_p)
|
|||||||
|
|
||||||
xfree(s->name);
|
xfree(s->name);
|
||||||
xfree(s->mountpoint);
|
xfree(s->mountpoint);
|
||||||
|
xfree(s->intake);
|
||||||
xfree(s->server);
|
xfree(s->server);
|
||||||
xfree(s->encoder);
|
xfree(s->encoder);
|
||||||
xfree(s->stream_name);
|
xfree(s->stream_name);
|
||||||
@ -140,6 +142,36 @@ cfg_stream_destroy(struct cfg_stream **s_p)
|
|||||||
*s_p = NULL;
|
*s_p = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cfg_stream_str2fmt(const char *str, enum cfg_stream_format *fmt_p)
|
||||||
|
{
|
||||||
|
if (0 == strcasecmp(str, CFG_SFMT_VORBIS)) {
|
||||||
|
*fmt_p = CFG_STREAM_VORBIS;
|
||||||
|
} else if (0 == strcasecmp(str, CFG_SFMT_MP3)) {
|
||||||
|
*fmt_p = CFG_STREAM_MP3;
|
||||||
|
} else if (0 == strcasecmp(str, CFG_SFMT_THEORA)) {
|
||||||
|
*fmt_p = CFG_STREAM_THEORA;
|
||||||
|
} else
|
||||||
|
return (-1);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
cfg_stream_fmt2str(enum cfg_stream_format fmt)
|
||||||
|
{
|
||||||
|
switch (fmt) {
|
||||||
|
case CFG_STREAM_VORBIS:
|
||||||
|
return (CFG_SFMT_VORBIS);
|
||||||
|
case CFG_STREAM_MP3:
|
||||||
|
return (CFG_SFMT_MP3);
|
||||||
|
case CFG_STREAM_THEORA:
|
||||||
|
return (CFG_SFMT_THEORA);
|
||||||
|
default:
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
cfg_stream_set_name(struct cfg_stream *s, struct cfg_stream_list *sl,
|
cfg_stream_set_name(struct cfg_stream *s, struct cfg_stream_list *sl,
|
||||||
const char *name, const char **errstrp)
|
const char *name, const char **errstrp)
|
||||||
@ -174,6 +206,15 @@ cfg_stream_set_mountpoint(struct cfg_stream *s,
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
cfg_stream_set_intake(struct cfg_stream *s, struct cfg_stream_list *not_used,
|
||||||
|
const char *intake, const char **errstrp)
|
||||||
|
{
|
||||||
|
(void)not_used;
|
||||||
|
SET_XSTRDUP(s->intake, intake, errstrp);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cfg_stream_set_server(struct cfg_stream *s, struct cfg_stream_list *not_used,
|
cfg_stream_set_server(struct cfg_stream *s, struct cfg_stream_list *not_used,
|
||||||
const char *server, const char **errstrp)
|
const char *server, const char **errstrp)
|
||||||
@ -330,6 +371,12 @@ cfg_stream_get_mountpoint(struct cfg_stream *s)
|
|||||||
return (s->mountpoint);
|
return (s->mountpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
cfg_stream_get_intake(struct cfg_stream *s)
|
||||||
|
{
|
||||||
|
return (s->intake);
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
cfg_stream_get_server(struct cfg_stream *s)
|
cfg_stream_get_server(struct cfg_stream *s)
|
||||||
{
|
{
|
||||||
|
@ -17,6 +17,19 @@
|
|||||||
#ifndef __CFG_STREAM_H__
|
#ifndef __CFG_STREAM_H__
|
||||||
#define __CFG_STREAM_H__
|
#define __CFG_STREAM_H__
|
||||||
|
|
||||||
|
#define CFG_SFMT_VORBIS "VORBIS"
|
||||||
|
#define CFG_SFMT_MP3 "MP3"
|
||||||
|
#define CFG_SFMT_THEORA "THEORA"
|
||||||
|
|
||||||
|
enum cfg_stream_format {
|
||||||
|
CFG_STREAM_INVALID = 0,
|
||||||
|
CFG_STREAM_VORBIS,
|
||||||
|
CFG_STREAM_MP3,
|
||||||
|
CFG_STREAM_THEORA,
|
||||||
|
CFG_STREAM_MIN = CFG_STREAM_VORBIS,
|
||||||
|
CFG_STREAM_MAX = CFG_STREAM_THEORA,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct cfg_stream * cfg_stream_t;
|
typedef struct cfg_stream * cfg_stream_t;
|
||||||
typedef struct cfg_stream_list * cfg_stream_list_t;
|
typedef struct cfg_stream_list * cfg_stream_list_t;
|
||||||
|
|
||||||
@ -33,10 +46,16 @@ cfg_stream_t
|
|||||||
cfg_stream_create(const char *);
|
cfg_stream_create(const char *);
|
||||||
void cfg_stream_destroy(cfg_stream_t *);
|
void cfg_stream_destroy(cfg_stream_t *);
|
||||||
|
|
||||||
|
int cfg_stream_str2fmt(const char *, enum cfg_stream_format *);
|
||||||
|
const char *
|
||||||
|
cfg_stream_fmt2str(enum cfg_stream_format);
|
||||||
|
|
||||||
int cfg_stream_set_name(cfg_stream_t, cfg_stream_list_t, const char *,
|
int cfg_stream_set_name(cfg_stream_t, cfg_stream_list_t, const char *,
|
||||||
const char **);
|
const char **);
|
||||||
int cfg_stream_set_mountpoint(cfg_stream_t, cfg_stream_list_t,
|
int cfg_stream_set_mountpoint(cfg_stream_t, cfg_stream_list_t,
|
||||||
const char *, const char **);
|
const char *, const char **);
|
||||||
|
int cfg_stream_set_intake(cfg_stream_t, cfg_stream_list_t, const char *,
|
||||||
|
const char **);
|
||||||
int cfg_stream_set_server(cfg_stream_t, cfg_stream_list_t, const char *,
|
int cfg_stream_set_server(cfg_stream_t, cfg_stream_list_t, const char *,
|
||||||
const char **);
|
const char **);
|
||||||
int cfg_stream_set_public(cfg_stream_t, cfg_stream_list_t, const char *,
|
int cfg_stream_set_public(cfg_stream_t, cfg_stream_list_t, const char *,
|
||||||
@ -68,6 +87,8 @@ const char *
|
|||||||
cfg_stream_get_name(cfg_stream_t);
|
cfg_stream_get_name(cfg_stream_t);
|
||||||
const char *
|
const char *
|
||||||
cfg_stream_get_mountpoint(cfg_stream_t);
|
cfg_stream_get_mountpoint(cfg_stream_t);
|
||||||
|
const char *
|
||||||
|
cfg_stream_get_intake(cfg_stream_t);
|
||||||
const char *
|
const char *
|
||||||
cfg_stream_get_server(cfg_stream_t);
|
cfg_stream_get_server(cfg_stream_t);
|
||||||
int cfg_stream_get_public(cfg_stream_t);
|
int cfg_stream_get_public(cfg_stream_t);
|
||||||
|
@ -29,7 +29,8 @@ static int _cfg_xmlfile_parse_server(xmlDocPtr, xmlNodePtr);
|
|||||||
static int _cfg_xmlfile_parse_servers(xmlDocPtr, xmlNodePtr);
|
static int _cfg_xmlfile_parse_servers(xmlDocPtr, xmlNodePtr);
|
||||||
static int _cfg_xmlfile_parse_stream(xmlDocPtr, xmlNodePtr);
|
static int _cfg_xmlfile_parse_stream(xmlDocPtr, xmlNodePtr);
|
||||||
static int _cfg_xmlfile_parse_streams(xmlDocPtr, xmlNodePtr);
|
static int _cfg_xmlfile_parse_streams(xmlDocPtr, xmlNodePtr);
|
||||||
static int _cfg_xmlfile_parse_media(xmlDocPtr, xmlNodePtr);
|
static int _cfg_xmlfile_parse_intake(xmlDocPtr, xmlNodePtr);
|
||||||
|
static int _cfg_xmlfile_parse_intakes(xmlDocPtr, xmlNodePtr);
|
||||||
static int _cfg_xmlfile_parse_metadata(xmlDocPtr, xmlNodePtr);
|
static int _cfg_xmlfile_parse_metadata(xmlDocPtr, xmlNodePtr);
|
||||||
static int _cfg_xmlfile_parse_decoder(xmlDocPtr, xmlNodePtr);
|
static int _cfg_xmlfile_parse_decoder(xmlDocPtr, xmlNodePtr);
|
||||||
static int _cfg_xmlfile_parse_decoders(xmlDocPtr, xmlNodePtr);
|
static int _cfg_xmlfile_parse_decoders(xmlDocPtr, xmlNodePtr);
|
||||||
@ -138,6 +139,7 @@ _cfg_xmlfile_parse_stream(xmlDocPtr doc, xmlNodePtr cur)
|
|||||||
for (cur = cur->xmlChildrenNode; cur; cur = cur->next) {
|
for (cur = cur->xmlChildrenNode; cur; cur = cur->next) {
|
||||||
XML_STREAM_SET(s, sl, cfg_stream_set_name, "name");
|
XML_STREAM_SET(s, sl, cfg_stream_set_name, "name");
|
||||||
XML_STREAM_SET(s, sl, cfg_stream_set_mountpoint, "mountpoint");
|
XML_STREAM_SET(s, sl, cfg_stream_set_mountpoint, "mountpoint");
|
||||||
|
XML_STREAM_SET(s, sl, cfg_stream_set_intake, "intake");
|
||||||
XML_STREAM_SET(s, sl, cfg_stream_set_server, "server");
|
XML_STREAM_SET(s, sl, cfg_stream_set_server, "server");
|
||||||
XML_STREAM_SET(s, sl, cfg_stream_set_public, "public");
|
XML_STREAM_SET(s, sl, cfg_stream_set_public, "public");
|
||||||
XML_STREAM_SET(s, sl, cfg_stream_set_format, "format");
|
XML_STREAM_SET(s, sl, cfg_stream_set_format, "format");
|
||||||
@ -172,6 +174,65 @@ _cfg_xmlfile_parse_streams(xmlDocPtr doc, xmlNodePtr cur)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define XML_INPUT_SET(c, l, f, e) do { \
|
||||||
|
if (0 == xmlStrcasecmp(cur->name, XML_CHAR((e)))) { \
|
||||||
|
xmlChar *val; \
|
||||||
|
const char *err_str; \
|
||||||
|
int error = 0; \
|
||||||
|
\
|
||||||
|
val = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); \
|
||||||
|
if (0 > (f)((c), (l), STD_CHAR(val), &err_str)) { \
|
||||||
|
log_error("%s[%ld]: intake (%s): %s: %s", \
|
||||||
|
doc->name, xmlGetLineNo(cur), \
|
||||||
|
cfg_intake_get_name((c)), (e), err_str); \
|
||||||
|
error = 1; \
|
||||||
|
} \
|
||||||
|
xmlFree(val); \
|
||||||
|
if (error) \
|
||||||
|
return (-1); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static int
|
||||||
|
_cfg_xmlfile_parse_intake(xmlDocPtr doc, xmlNodePtr cur)
|
||||||
|
{
|
||||||
|
cfg_intake_list_t il;
|
||||||
|
cfg_intake_t i;
|
||||||
|
const char *errstr;
|
||||||
|
long int line_no = xmlGetLineNo(cur);
|
||||||
|
|
||||||
|
il = cfg_get_intakes();
|
||||||
|
i = cfg_intake_list_get(il, CFG_DEFAULT);
|
||||||
|
|
||||||
|
for (cur = cur->xmlChildrenNode; cur; cur = cur->next) {
|
||||||
|
XML_INPUT_SET(i, il, cfg_intake_set_name, "name");
|
||||||
|
XML_INPUT_SET(i, il, cfg_intake_set_type, "type");
|
||||||
|
XML_INPUT_SET(i, il, cfg_intake_set_filename, "filename");
|
||||||
|
XML_INPUT_SET(i, il, cfg_intake_set_shuffle, "shuffle");
|
||||||
|
XML_INPUT_SET(i, il, cfg_intake_set_stream_once, "stream_once");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 > cfg_intake_validate(i, &errstr)) {
|
||||||
|
log_error("%s[%ld]: intake (%s): %s", doc->name, line_no,
|
||||||
|
cfg_intake_get_name(i), errstr);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_cfg_xmlfile_parse_intakes(xmlDocPtr doc, xmlNodePtr cur)
|
||||||
|
{
|
||||||
|
for (cur = cur->xmlChildrenNode; cur; cur = cur->next) {
|
||||||
|
if (0 == xmlStrcasecmp(cur->name, XML_CHAR("intake")) &&
|
||||||
|
0 > _cfg_xmlfile_parse_intake(doc, cur))
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
#define XML_STRCONFIG(s, f, e) do { \
|
#define XML_STRCONFIG(s, f, e) do { \
|
||||||
if (0 == xmlStrcasecmp(cur->name, XML_CHAR((e)))) { \
|
if (0 == xmlStrcasecmp(cur->name, XML_CHAR((e)))) { \
|
||||||
xmlChar *val; \
|
xmlChar *val; \
|
||||||
@ -187,24 +248,6 @@ _cfg_xmlfile_parse_streams(xmlDocPtr doc, xmlNodePtr cur)
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
static int
|
|
||||||
_cfg_xmlfile_parse_media(xmlDocPtr doc, xmlNodePtr cur)
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
|
|
||||||
for (cur = cur->xmlChildrenNode; cur; cur = cur->next) {
|
|
||||||
XML_STRCONFIG("media", cfg_set_media_type, "type");
|
|
||||||
XML_STRCONFIG("media", cfg_set_media_filename, "filename");
|
|
||||||
XML_STRCONFIG("media", cfg_set_media_shuffle, "shuffle");
|
|
||||||
XML_STRCONFIG("media", cfg_set_media_stream_once, "stream_once");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
return (-1);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_cfg_xmlfile_parse_metadata(xmlDocPtr doc, xmlNodePtr cur)
|
_cfg_xmlfile_parse_metadata(xmlDocPtr doc, xmlNodePtr cur)
|
||||||
{
|
{
|
||||||
@ -364,6 +407,7 @@ _cfg_xmlfile_parse_encoders(xmlDocPtr doc, xmlNodePtr cur)
|
|||||||
* name
|
* name
|
||||||
* mountpoint
|
* mountpoint
|
||||||
* public
|
* public
|
||||||
|
* intake
|
||||||
* server
|
* server
|
||||||
* format
|
* format
|
||||||
* encoder
|
* encoder
|
||||||
@ -376,11 +420,13 @@ _cfg_xmlfile_parse_encoders(xmlDocPtr doc, xmlNodePtr cur)
|
|||||||
* stream_samplerate
|
* stream_samplerate
|
||||||
* stream_channels
|
* stream_channels
|
||||||
* ...
|
* ...
|
||||||
* media
|
* intakes
|
||||||
|
* intake
|
||||||
* type
|
* type
|
||||||
* filename
|
* filename
|
||||||
* shuffle
|
* shuffle
|
||||||
* stream_once
|
* stream_once
|
||||||
|
* ...
|
||||||
* metadata
|
* metadata
|
||||||
* program
|
* program
|
||||||
* format_str
|
* format_str
|
||||||
@ -441,8 +487,8 @@ cfg_xmlfile_parse(const char *config_file)
|
|||||||
error = 1;
|
error = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (0 == xmlStrcasecmp(cur->name, XML_CHAR("media"))) {
|
if (0 == xmlStrcasecmp(cur->name, XML_CHAR("intakes"))) {
|
||||||
if (0 > _cfg_xmlfile_parse_media(doc, cur))
|
if (0 > _cfg_xmlfile_parse_intakes(doc, cur))
|
||||||
error = 1;
|
error = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -407,6 +407,7 @@ sendStream(stream_t stream, FILE *filepstream, const char *fileName,
|
|||||||
struct timespec timeStamp, *startTime = tv;
|
struct timespec timeStamp, *startTime = tv;
|
||||||
struct timespec callTime, currentTime;
|
struct timespec callTime, currentTime;
|
||||||
cfg_server_t cfg_server = stream_get_cfg_server(stream);
|
cfg_server_t cfg_server = stream_get_cfg_server(stream);
|
||||||
|
cfg_intake_t cfg_intake = stream_get_cfg_intake(stream);
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &callTime);
|
clock_gettime(CLOCK_MONOTONIC, &callTime);
|
||||||
|
|
||||||
@ -437,7 +438,7 @@ sendStream(stream_t stream, FILE *filepstream, const char *fileName,
|
|||||||
break;
|
break;
|
||||||
if (rereadPlaylist_notify) {
|
if (rereadPlaylist_notify) {
|
||||||
rereadPlaylist_notify = 0;
|
rereadPlaylist_notify = 0;
|
||||||
if (CFG_MEDIA_PLAYLIST == cfg_get_media_type())
|
if (CFG_INTAKE_PLAYLIST == cfg_intake_get_type(cfg_intake))
|
||||||
log_notice("HUP signal received: playlist re-read scheduled");
|
log_notice("HUP signal received: playlist re-read scheduled");
|
||||||
}
|
}
|
||||||
if (skipTrack) {
|
if (skipTrack) {
|
||||||
@ -464,8 +465,8 @@ sendStream(stream_t stream, FILE *filepstream, const char *fileName,
|
|||||||
double oldTime, newTime;
|
double oldTime, newTime;
|
||||||
|
|
||||||
if (!isStdin && playlistMode) {
|
if (!isStdin && playlistMode) {
|
||||||
if (CFG_MEDIA_PROGRAM == cfg_get_media_type()) {
|
if (CFG_INTAKE_PROGRAM == cfg_intake_get_type(cfg_intake)) {
|
||||||
char *tmp = xstrdup(cfg_get_media_filename());
|
char *tmp = xstrdup(cfg_intake_get_filename(cfg_intake));
|
||||||
printf(" [%s]", basename(tmp));
|
printf(" [%s]", basename(tmp));
|
||||||
xfree(tmp);
|
xfree(tmp);
|
||||||
} else
|
} else
|
||||||
@ -523,12 +524,13 @@ streamFile(stream_t stream, const char *fileName)
|
|||||||
FILE *filepstream = NULL;
|
FILE *filepstream = NULL;
|
||||||
int popenFlag = 0;
|
int popenFlag = 0;
|
||||||
char *songLenStr = NULL;
|
char *songLenStr = NULL;
|
||||||
int isStdin = cfg_get_media_type() == CFG_MEDIA_STDIN;
|
|
||||||
int ret, retval = 0;
|
int ret, retval = 0;
|
||||||
long songLen;
|
long songLen;
|
||||||
mdata_t md = NULL;
|
mdata_t md = NULL;
|
||||||
struct timespec startTime;
|
struct timespec startTime;
|
||||||
cfg_stream_t cfg_stream = stream_get_cfg_stream(stream);
|
cfg_stream_t cfg_stream = stream_get_cfg_stream(stream);
|
||||||
|
cfg_intake_t cfg_intake = stream_get_cfg_intake(stream);
|
||||||
|
int isStdin = cfg_intake_get_type(cfg_intake) == CFG_INTAKE_STDIN;
|
||||||
|
|
||||||
if ((filepstream = openResource(stream, fileName, &popenFlag, &md, &isStdin, &songLen))
|
if ((filepstream = openResource(stream, fileName, &popenFlag, &md, &isStdin, &songLen))
|
||||||
== NULL) {
|
== NULL) {
|
||||||
@ -633,23 +635,24 @@ streamPlaylist(stream_t stream)
|
|||||||
{
|
{
|
||||||
const char *song;
|
const char *song;
|
||||||
char lastSong[PATH_MAX];
|
char lastSong[PATH_MAX];
|
||||||
|
cfg_intake_t cfg_intake = stream_get_cfg_intake(stream);
|
||||||
|
|
||||||
if (playlist == NULL) {
|
if (playlist == NULL) {
|
||||||
switch (cfg_get_media_type()) {
|
switch (cfg_intake_get_type(cfg_intake)) {
|
||||||
case CFG_MEDIA_PROGRAM:
|
case CFG_INTAKE_PROGRAM:
|
||||||
if ((playlist = playlist_program(cfg_get_media_filename())) == NULL)
|
if ((playlist = playlist_program(cfg_intake_get_filename(cfg_intake))) == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
break;
|
break;
|
||||||
case CFG_MEDIA_STDIN:
|
case CFG_INTAKE_STDIN:
|
||||||
if ((playlist = playlist_read(NULL)) == NULL)
|
if ((playlist = playlist_read(NULL)) == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if ((playlist = playlist_read(cfg_get_media_filename())) == NULL)
|
if ((playlist = playlist_read(cfg_intake_get_filename(cfg_intake))) == NULL)
|
||||||
return (0);
|
return (0);
|
||||||
if (playlist_get_num_items(playlist) == 0)
|
if (playlist_get_num_items(playlist) == 0)
|
||||||
log_warning("%s: playlist empty",
|
log_warning("%s: playlist empty",
|
||||||
cfg_get_media_filename());
|
cfg_intake_get_filename(cfg_intake));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -661,8 +664,8 @@ streamPlaylist(stream_t stream)
|
|||||||
playlist_rewind(playlist);
|
playlist_rewind(playlist);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CFG_MEDIA_PROGRAM != cfg_get_media_type() &&
|
if (CFG_INTAKE_PROGRAM != cfg_intake_get_type(cfg_intake) &&
|
||||||
cfg_get_media_shuffle())
|
cfg_intake_get_shuffle(cfg_intake))
|
||||||
playlist_shuffle(playlist);
|
playlist_shuffle(playlist);
|
||||||
|
|
||||||
while ((song = playlist_get_next(playlist)) != NULL) {
|
while ((song = playlist_get_next(playlist)) != NULL) {
|
||||||
@ -673,12 +676,12 @@ streamPlaylist(stream_t stream)
|
|||||||
break;
|
break;
|
||||||
if (rereadPlaylist) {
|
if (rereadPlaylist) {
|
||||||
rereadPlaylist = rereadPlaylist_notify = 0;
|
rereadPlaylist = rereadPlaylist_notify = 0;
|
||||||
if (CFG_MEDIA_PROGRAM == cfg_get_media_type())
|
if (CFG_INTAKE_PROGRAM == cfg_intake_get_type(cfg_intake))
|
||||||
continue;
|
continue;
|
||||||
log_notice("rereading playlist");
|
log_notice("rereading playlist");
|
||||||
if (!playlist_reread(&playlist))
|
if (!playlist_reread(&playlist))
|
||||||
return (0);
|
return (0);
|
||||||
if (cfg_get_media_shuffle())
|
if (cfg_intake_get_shuffle(cfg_intake))
|
||||||
playlist_shuffle(playlist);
|
playlist_shuffle(playlist);
|
||||||
else {
|
else {
|
||||||
playlist_goto_entry(playlist, lastSong);
|
playlist_goto_entry(playlist, lastSong);
|
||||||
@ -716,6 +719,7 @@ main(int argc, char *argv[])
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
cfg_server_t cfg_server;
|
cfg_server_t cfg_server;
|
||||||
cfg_stream_t cfg_stream;
|
cfg_stream_t cfg_stream;
|
||||||
|
cfg_intake_t cfg_intake;
|
||||||
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
if (0 > cfg_init() ||
|
if (0 > cfg_init() ||
|
||||||
@ -736,6 +740,7 @@ main(int argc, char *argv[])
|
|||||||
return (ez_shutdown(1));
|
return (ez_shutdown(1));
|
||||||
cfg_server = stream_get_cfg_server(main_stream);
|
cfg_server = stream_get_cfg_server(main_stream);
|
||||||
cfg_stream = stream_get_cfg_stream(main_stream);
|
cfg_stream = stream_get_cfg_stream(main_stream);
|
||||||
|
cfg_intake = stream_get_cfg_intake(main_stream);
|
||||||
|
|
||||||
memset(&act, 0, sizeof(act));
|
memset(&act, 0, sizeof(act));
|
||||||
act.sa_handler = sig_handler;
|
act.sa_handler = sig_handler;
|
||||||
@ -774,11 +779,11 @@ main(int argc, char *argv[])
|
|||||||
cfg_server_get_port(cfg_server),
|
cfg_server_get_port(cfg_server),
|
||||||
cfg_stream_get_mountpoint(cfg_stream));
|
cfg_stream_get_mountpoint(cfg_stream));
|
||||||
|
|
||||||
if (CFG_MEDIA_PROGRAM == cfg_get_media_type() ||
|
if (CFG_INTAKE_PROGRAM == cfg_intake_get_type(cfg_intake) ||
|
||||||
CFG_MEDIA_PLAYLIST == cfg_get_media_type() ||
|
CFG_INTAKE_PLAYLIST == cfg_intake_get_type(cfg_intake) ||
|
||||||
(CFG_MEDIA_AUTODETECT == cfg_get_media_type() &&
|
(CFG_INTAKE_AUTODETECT == cfg_intake_get_type(cfg_intake) &&
|
||||||
(util_strrcasecmp(cfg_get_media_filename(), ".m3u") == 0 ||
|
(util_strrcasecmp(cfg_intake_get_filename(cfg_intake), ".m3u") == 0 ||
|
||||||
util_strrcasecmp(cfg_get_media_filename(), ".txt") == 0)))
|
util_strrcasecmp(cfg_intake_get_filename(cfg_intake), ".txt") == 0)))
|
||||||
playlistMode = 1;
|
playlistMode = 1;
|
||||||
else
|
else
|
||||||
playlistMode = 0;
|
playlistMode = 0;
|
||||||
@ -788,11 +793,11 @@ main(int argc, char *argv[])
|
|||||||
cont = streamPlaylist(main_stream);
|
cont = streamPlaylist(main_stream);
|
||||||
} else {
|
} else {
|
||||||
cont = streamFile(main_stream,
|
cont = streamFile(main_stream,
|
||||||
cfg_get_media_filename());
|
cfg_intake_get_filename(cfg_intake));
|
||||||
}
|
}
|
||||||
if (quit)
|
if (quit)
|
||||||
break;
|
break;
|
||||||
if (cfg_get_media_stream_once())
|
if (cfg_intake_get_stream_once(cfg_intake))
|
||||||
break;
|
break;
|
||||||
} while (cont);
|
} while (cont);
|
||||||
|
|
||||||
|
13
src/stream.c
13
src/stream.c
@ -447,6 +447,19 @@ stream_get_cfg_stream(struct stream *s)
|
|||||||
return (cfg_stream_list_find(cfg_get_streams(), s->name));
|
return (cfg_stream_list_find(cfg_get_streams(), s->name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cfg_intake_t
|
||||||
|
stream_get_cfg_intake(struct stream *s)
|
||||||
|
{
|
||||||
|
cfg_stream_t cfg_stream;
|
||||||
|
const char *intake;
|
||||||
|
|
||||||
|
cfg_stream = cfg_stream_list_get(cfg_get_streams(), s->name);
|
||||||
|
intake = cfg_stream_get_intake(cfg_stream);
|
||||||
|
if (!intake)
|
||||||
|
intake = CFG_DEFAULT;
|
||||||
|
return (cfg_intake_list_get(cfg_get_intakes(), intake));
|
||||||
|
}
|
||||||
|
|
||||||
cfg_server_t
|
cfg_server_t
|
||||||
stream_get_cfg_server(struct stream *s)
|
stream_get_cfg_server(struct stream *s)
|
||||||
{
|
{
|
||||||
|
@ -39,6 +39,8 @@ const char *
|
|||||||
int stream_get_connected(stream_t);
|
int stream_get_connected(stream_t);
|
||||||
cfg_stream_t
|
cfg_stream_t
|
||||||
stream_get_cfg_stream(stream_t);
|
stream_get_cfg_stream(stream_t);
|
||||||
|
cfg_intake_t
|
||||||
|
stream_get_cfg_intake(stream_t);
|
||||||
cfg_server_t
|
cfg_server_t
|
||||||
stream_get_cfg_server(stream_t);
|
stream_get_cfg_server(stream_t);
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ TESTS = \
|
|||||||
check_cfg \
|
check_cfg \
|
||||||
check_cfg_decoder \
|
check_cfg_decoder \
|
||||||
check_cfg_encoder \
|
check_cfg_encoder \
|
||||||
|
check_cfg_intake \
|
||||||
check_cfg_server \
|
check_cfg_server \
|
||||||
check_cfg_stream \
|
check_cfg_stream \
|
||||||
check_cfg_xmlfile \
|
check_cfg_xmlfile \
|
||||||
@ -30,6 +31,10 @@ check_cfg_encoder_SOURCES = check_cfg_encoder.c
|
|||||||
check_cfg_encoder_DEPENDENCIES = $(top_builddir)/src/libezstream.la
|
check_cfg_encoder_DEPENDENCIES = $(top_builddir)/src/libezstream.la
|
||||||
check_cfg_encoder_LDADD = $(check_cfg_encoder_DEPENDENCIES) @CHECK_LIBS@
|
check_cfg_encoder_LDADD = $(check_cfg_encoder_DEPENDENCIES) @CHECK_LIBS@
|
||||||
|
|
||||||
|
check_cfg_intake_SOURCES = check_cfg_intake.c
|
||||||
|
check_cfg_intake_DEPENDENCIES = $(top_builddir)/src/libezstream.la
|
||||||
|
check_cfg_intake_LDADD = $(check_cfg_intake_DEPENDENCIES) @CHECK_LIBS@
|
||||||
|
|
||||||
check_cfg_server_SOURCES = check_cfg_server.c
|
check_cfg_server_SOURCES = check_cfg_server.c
|
||||||
check_cfg_server_DEPENDENCIES = $(top_builddir)/src/libezstream.la
|
check_cfg_server_DEPENDENCIES = $(top_builddir)/src/libezstream.la
|
||||||
check_cfg_server_LDADD = $(check_cfg_server_DEPENDENCIES) @CHECK_LIBS@
|
check_cfg_server_LDADD = $(check_cfg_server_DEPENDENCIES) @CHECK_LIBS@
|
||||||
@ -87,6 +92,7 @@ EXTRA_DIST = \
|
|||||||
config-bad3.xml \
|
config-bad3.xml \
|
||||||
config-bad4.xml \
|
config-bad4.xml \
|
||||||
config-bad5.xml \
|
config-bad5.xml \
|
||||||
|
config-bad6.xml \
|
||||||
play-bad.sh \
|
play-bad.sh \
|
||||||
play-bad2.sh \
|
play-bad2.sh \
|
||||||
play-bad3.sh \
|
play-bad3.sh \
|
||||||
|
@ -13,49 +13,7 @@ void teardown_checked(void);
|
|||||||
|
|
||||||
START_TEST(test_check)
|
START_TEST(test_check)
|
||||||
{
|
{
|
||||||
const char *errstr = NULL;
|
|
||||||
|
|
||||||
ck_assert_int_eq(cfg_check(NULL), -1);
|
|
||||||
ck_assert_int_eq(cfg_check(&errstr), -1);
|
|
||||||
ck_assert_str_eq(errstr, "media filename missing");
|
|
||||||
ck_assert_int_eq(cfg_set_media_type("stdin", NULL), 0);
|
|
||||||
|
|
||||||
ck_assert_int_eq(cfg_check(NULL), 0);
|
ck_assert_int_eq(cfg_check(NULL), 0);
|
||||||
|
|
||||||
ck_assert_int_eq(cfg_set_media_type("autodetect", NULL), 0);
|
|
||||||
ck_assert_int_eq(cfg_check(NULL), -1);
|
|
||||||
ck_assert_int_eq(cfg_check(&errstr), -1);
|
|
||||||
ck_assert_str_eq(errstr, "media filename missing");
|
|
||||||
ck_assert_int_eq(cfg_set_media_filename(SRCDIR "/playlist.txt", NULL),
|
|
||||||
0);
|
|
||||||
|
|
||||||
ck_assert_int_eq(cfg_check(NULL), 0);
|
|
||||||
}
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
START_TEST(test_stream_str2fmt)
|
|
||||||
{
|
|
||||||
enum cfg_stream_format fmt;
|
|
||||||
|
|
||||||
ck_assert_int_eq(cfg_stream_str2fmt(CFG_SFMT_VORBIS, &fmt), 0);
|
|
||||||
ck_assert_int_eq(fmt, CFG_STREAM_VORBIS);
|
|
||||||
ck_assert_int_eq(cfg_stream_str2fmt(CFG_SFMT_MP3, &fmt), 0);
|
|
||||||
ck_assert_int_eq(fmt, CFG_STREAM_MP3);
|
|
||||||
ck_assert_int_eq(cfg_stream_str2fmt(CFG_SFMT_THEORA, &fmt), 0);
|
|
||||||
ck_assert_int_eq(fmt, CFG_STREAM_THEORA);
|
|
||||||
ck_assert_int_eq(cfg_stream_str2fmt("<something else>", &fmt), -1);
|
|
||||||
}
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
START_TEST(test_stream_fmt2str)
|
|
||||||
{
|
|
||||||
ck_assert_str_eq(cfg_stream_fmt2str(CFG_STREAM_VORBIS),
|
|
||||||
CFG_SFMT_VORBIS);
|
|
||||||
ck_assert_str_eq(cfg_stream_fmt2str(CFG_STREAM_MP3),
|
|
||||||
CFG_SFMT_MP3);
|
|
||||||
ck_assert_str_eq(cfg_stream_fmt2str(CFG_STREAM_THEORA),
|
|
||||||
CFG_SFMT_THEORA);
|
|
||||||
ck_assert_ptr_eq(cfg_stream_fmt2str(CFG_STREAM_INVALID), NULL);
|
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
@ -121,46 +79,6 @@ START_TEST(test_program_verbosity)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_media_type)
|
|
||||||
{
|
|
||||||
const char *errstr2;
|
|
||||||
|
|
||||||
TEST_EMPTYSTR(cfg_set_media_type);
|
|
||||||
|
|
||||||
ck_assert_int_eq(cfg_set_media_type("<something else>", &errstr2), -1);
|
|
||||||
ck_assert_str_eq(errstr2, "unsupported");
|
|
||||||
|
|
||||||
ck_assert_int_eq(cfg_set_media_type("aUtOdEtEcT", NULL), 0);
|
|
||||||
ck_assert_int_eq(cfg_get_media_type(), CFG_MEDIA_AUTODETECT);
|
|
||||||
ck_assert_int_eq(cfg_set_media_type("FiLe", NULL), 0);
|
|
||||||
ck_assert_int_eq(cfg_get_media_type(), CFG_MEDIA_FILE);
|
|
||||||
ck_assert_int_eq(cfg_set_media_type("pLaYlIsT", NULL), 0);
|
|
||||||
ck_assert_int_eq(cfg_get_media_type(), CFG_MEDIA_PLAYLIST);
|
|
||||||
ck_assert_int_eq(cfg_set_media_type("PrOgRaM", NULL), 0);
|
|
||||||
ck_assert_int_eq(cfg_get_media_type(), CFG_MEDIA_PROGRAM);
|
|
||||||
ck_assert_int_eq(cfg_set_media_type("sTdIn", NULL), 0);
|
|
||||||
ck_assert_int_eq(cfg_get_media_type(), CFG_MEDIA_STDIN);
|
|
||||||
}
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
START_TEST(test_media_filename)
|
|
||||||
{
|
|
||||||
TEST_STRLCPY(cfg_set_media_filename, cfg_get_media_filename, PATH_MAX);
|
|
||||||
}
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
START_TEST(test_media_shuffle)
|
|
||||||
{
|
|
||||||
TEST_BOOLEAN(cfg_set_media_shuffle, cfg_get_media_shuffle);
|
|
||||||
}
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
START_TEST(test_media_stream_once)
|
|
||||||
{
|
|
||||||
TEST_BOOLEAN(cfg_set_media_stream_once, cfg_get_media_stream_once);
|
|
||||||
}
|
|
||||||
END_TEST
|
|
||||||
|
|
||||||
START_TEST(test_metadata_program)
|
START_TEST(test_metadata_program)
|
||||||
{
|
{
|
||||||
ck_assert_ptr_eq(cfg_get_metadata_program(), NULL);
|
ck_assert_ptr_eq(cfg_get_metadata_program(), NULL);
|
||||||
@ -240,7 +158,6 @@ cfg_suite(void)
|
|||||||
Suite *s;
|
Suite *s;
|
||||||
TCase *tc_core;
|
TCase *tc_core;
|
||||||
TCase *tc_program;
|
TCase *tc_program;
|
||||||
TCase *tc_media;
|
|
||||||
TCase *tc_metadata;
|
TCase *tc_metadata;
|
||||||
|
|
||||||
s = suite_create("Config");
|
s = suite_create("Config");
|
||||||
@ -248,8 +165,6 @@ cfg_suite(void)
|
|||||||
tc_core = tcase_create("Core");
|
tc_core = tcase_create("Core");
|
||||||
tcase_add_checked_fixture(tc_core, setup_checked, teardown_checked);
|
tcase_add_checked_fixture(tc_core, setup_checked, teardown_checked);
|
||||||
tcase_add_test(tc_core, test_check);
|
tcase_add_test(tc_core, test_check);
|
||||||
tcase_add_test(tc_core, test_stream_str2fmt);
|
|
||||||
tcase_add_test(tc_core, test_stream_fmt2str);
|
|
||||||
tcase_add_test(tc_core, test_file_check);
|
tcase_add_test(tc_core, test_file_check);
|
||||||
suite_add_tcase(s, tc_core);
|
suite_add_tcase(s, tc_core);
|
||||||
|
|
||||||
@ -265,14 +180,6 @@ cfg_suite(void)
|
|||||||
tcase_add_test(tc_program, test_program_verbosity);
|
tcase_add_test(tc_program, test_program_verbosity);
|
||||||
suite_add_tcase(s, tc_program);
|
suite_add_tcase(s, tc_program);
|
||||||
|
|
||||||
tc_media = tcase_create("Media");
|
|
||||||
tcase_add_checked_fixture(tc_media, setup_checked, teardown_checked);
|
|
||||||
tcase_add_test(tc_media, test_media_type);
|
|
||||||
tcase_add_test(tc_media, test_media_filename);
|
|
||||||
tcase_add_test(tc_media, test_media_shuffle);
|
|
||||||
tcase_add_test(tc_media, test_media_stream_once);
|
|
||||||
suite_add_tcase(s, tc_media);
|
|
||||||
|
|
||||||
tc_metadata = tcase_create("Metadata");
|
tc_metadata = tcase_create("Metadata");
|
||||||
tcase_add_checked_fixture(tc_metadata, setup_checked,
|
tcase_add_checked_fixture(tc_metadata, setup_checked,
|
||||||
teardown_checked);
|
teardown_checked);
|
||||||
|
170
tests/check_cfg_intake.c
Normal file
170
tests/check_cfg_intake.c
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
#include <check.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
|
||||||
|
#include "cfg_private.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
|
#include "check_cfg.h"
|
||||||
|
|
||||||
|
Suite * cfg_suite(void);
|
||||||
|
void setup_checked(void);
|
||||||
|
void teardown_checked(void);
|
||||||
|
|
||||||
|
cfg_intake_list_t intakes;
|
||||||
|
|
||||||
|
START_TEST(test_intake_list_get)
|
||||||
|
{
|
||||||
|
cfg_intake_t in, in2;
|
||||||
|
|
||||||
|
ck_assert_ptr_eq(cfg_intake_list_get(intakes, NULL), NULL);
|
||||||
|
ck_assert_ptr_eq(cfg_intake_list_get(intakes, ""), NULL);
|
||||||
|
|
||||||
|
in = cfg_intake_list_get(intakes, "TeSt");
|
||||||
|
in2 = cfg_intake_list_get(intakes, "test");
|
||||||
|
ck_assert_ptr_eq(in, in2);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_intake_set_name)
|
||||||
|
{
|
||||||
|
TEST_XSTRDUP_T(cfg_intake_t, cfg_intake_list_get, intakes,
|
||||||
|
cfg_intake_set_name, cfg_intake_get_name);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_intake_set_type)
|
||||||
|
{
|
||||||
|
const char *errstr2;
|
||||||
|
cfg_intake_t in = cfg_intake_list_get(intakes, "test_intake_set_type");
|
||||||
|
|
||||||
|
TEST_EMPTYSTR_T(cfg_intake_t, cfg_intake_list_get, intakes,
|
||||||
|
cfg_intake_set_type);
|
||||||
|
|
||||||
|
ck_assert_int_eq(cfg_intake_set_type(in, intakes, "<something else>",
|
||||||
|
NULL), -1);
|
||||||
|
ck_assert_int_eq(cfg_intake_set_type(in, intakes, "<something else>",
|
||||||
|
&errstr2), -1);
|
||||||
|
ck_assert_str_eq(errstr2, "unsupported");
|
||||||
|
|
||||||
|
ck_assert_int_eq(cfg_intake_set_type(in, intakes, "aUtOdEtEcT", NULL),
|
||||||
|
0);
|
||||||
|
ck_assert_int_eq(cfg_intake_get_type(in), CFG_INTAKE_AUTODETECT);
|
||||||
|
ck_assert_int_eq(cfg_intake_set_type(in, intakes, "FiLe", NULL), 0);
|
||||||
|
ck_assert_int_eq(cfg_intake_get_type(in), CFG_INTAKE_FILE);
|
||||||
|
ck_assert_int_eq(cfg_intake_set_type(in, intakes, "pLaYlIsT", NULL),
|
||||||
|
0);
|
||||||
|
ck_assert_int_eq(cfg_intake_get_type(in), CFG_INTAKE_PLAYLIST);
|
||||||
|
ck_assert_int_eq(cfg_intake_set_type(in, intakes, "PrOgRaM", NULL), 0);
|
||||||
|
ck_assert_int_eq(cfg_intake_get_type(in), CFG_INTAKE_PROGRAM);
|
||||||
|
ck_assert_int_eq(cfg_intake_set_type(in, intakes, "sTdIn", NULL), 0);
|
||||||
|
ck_assert_int_eq(cfg_intake_get_type(in), CFG_INTAKE_STDIN);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_intake_set_filename)
|
||||||
|
{
|
||||||
|
TEST_STRLCPY_T(cfg_intake_t, cfg_intake_list_get, intakes,
|
||||||
|
cfg_intake_set_filename, cfg_intake_get_filename, PATH_MAX);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_intake_set_shuffle)
|
||||||
|
{
|
||||||
|
TEST_BOOLEAN_T(cfg_intake_t, cfg_intake_list_get, intakes,
|
||||||
|
cfg_intake_set_shuffle, cfg_intake_get_shuffle);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_intake_set_stream_once)
|
||||||
|
{
|
||||||
|
TEST_BOOLEAN_T(cfg_intake_t, cfg_intake_list_get, intakes,
|
||||||
|
cfg_intake_set_stream_once, cfg_intake_get_stream_once);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_intake_validate)
|
||||||
|
{
|
||||||
|
cfg_intake_t in = cfg_intake_list_get(intakes, "test_intake_validate");
|
||||||
|
const char *errstr;
|
||||||
|
|
||||||
|
ck_assert_int_ne(cfg_intake_validate(in, NULL), 0);
|
||||||
|
ck_assert_int_ne(cfg_intake_validate(in, &errstr), 0);
|
||||||
|
ck_assert_str_eq(errstr, "intake filename missing");
|
||||||
|
|
||||||
|
ck_assert_int_eq(cfg_intake_set_type(in, intakes, "stdin", NULL), 0);
|
||||||
|
|
||||||
|
ck_assert_int_eq(cfg_intake_validate(in, NULL), 0);
|
||||||
|
|
||||||
|
ck_assert_int_eq(cfg_intake_set_type(in, intakes, "autodetect", NULL),
|
||||||
|
0);
|
||||||
|
ck_assert_int_ne(cfg_intake_validate(in, NULL), 0);
|
||||||
|
ck_assert_int_ne(cfg_intake_validate(in, &errstr), 0);
|
||||||
|
ck_assert_str_eq(errstr, "intake filename missing");
|
||||||
|
ck_assert_int_eq(cfg_intake_set_filename(in, intakes,
|
||||||
|
SRCDIR "/playlist.txt", NULL), 0);
|
||||||
|
|
||||||
|
ck_assert_int_eq(cfg_intake_validate(in, NULL), 0);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
Suite *
|
||||||
|
cfg_suite(void)
|
||||||
|
{
|
||||||
|
Suite *s;
|
||||||
|
TCase *tc_intake;
|
||||||
|
|
||||||
|
s = suite_create("Config");
|
||||||
|
|
||||||
|
tc_intake = tcase_create("Intake");
|
||||||
|
tcase_add_checked_fixture(tc_intake, setup_checked,
|
||||||
|
teardown_checked);
|
||||||
|
tcase_add_test(tc_intake, test_intake_list_get);
|
||||||
|
tcase_add_test(tc_intake, test_intake_set_name);
|
||||||
|
tcase_add_test(tc_intake, test_intake_set_type);
|
||||||
|
tcase_add_test(tc_intake, test_intake_set_filename);
|
||||||
|
tcase_add_test(tc_intake, test_intake_set_shuffle);
|
||||||
|
tcase_add_test(tc_intake, test_intake_set_stream_once);
|
||||||
|
tcase_add_test(tc_intake, test_intake_validate);
|
||||||
|
suite_add_tcase(s, tc_intake);
|
||||||
|
|
||||||
|
return (s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
setup_checked(void)
|
||||||
|
{
|
||||||
|
if (0 < cfg_init() ||
|
||||||
|
0 < log_init())
|
||||||
|
ck_abort_msg("setup_checked failed");
|
||||||
|
|
||||||
|
intakes = cfg_intake_list_create();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
teardown_checked(void)
|
||||||
|
{
|
||||||
|
cfg_intake_list_destroy(&intakes);
|
||||||
|
|
||||||
|
log_exit();
|
||||||
|
cfg_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(void)
|
||||||
|
{
|
||||||
|
int num_failed;
|
||||||
|
Suite *s;
|
||||||
|
SRunner *sr;
|
||||||
|
|
||||||
|
s = cfg_suite();
|
||||||
|
sr = srunner_create(s);
|
||||||
|
|
||||||
|
srunner_run_all(sr, CK_NORMAL);
|
||||||
|
num_failed = srunner_ntests_failed(sr);
|
||||||
|
srunner_free(sr);
|
||||||
|
|
||||||
|
if (num_failed)
|
||||||
|
return (1);
|
||||||
|
return (0);
|
||||||
|
}
|
@ -26,6 +26,32 @@ START_TEST(test_stream_list_get)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_stream_str2fmt)
|
||||||
|
{
|
||||||
|
enum cfg_stream_format fmt;
|
||||||
|
|
||||||
|
ck_assert_int_eq(cfg_stream_str2fmt(CFG_SFMT_VORBIS, &fmt), 0);
|
||||||
|
ck_assert_int_eq(fmt, CFG_STREAM_VORBIS);
|
||||||
|
ck_assert_int_eq(cfg_stream_str2fmt(CFG_SFMT_MP3, &fmt), 0);
|
||||||
|
ck_assert_int_eq(fmt, CFG_STREAM_MP3);
|
||||||
|
ck_assert_int_eq(cfg_stream_str2fmt(CFG_SFMT_THEORA, &fmt), 0);
|
||||||
|
ck_assert_int_eq(fmt, CFG_STREAM_THEORA);
|
||||||
|
ck_assert_int_eq(cfg_stream_str2fmt("<something else>", &fmt), -1);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_stream_fmt2str)
|
||||||
|
{
|
||||||
|
ck_assert_str_eq(cfg_stream_fmt2str(CFG_STREAM_VORBIS),
|
||||||
|
CFG_SFMT_VORBIS);
|
||||||
|
ck_assert_str_eq(cfg_stream_fmt2str(CFG_STREAM_MP3),
|
||||||
|
CFG_SFMT_MP3);
|
||||||
|
ck_assert_str_eq(cfg_stream_fmt2str(CFG_STREAM_THEORA),
|
||||||
|
CFG_SFMT_THEORA);
|
||||||
|
ck_assert_ptr_eq(cfg_stream_fmt2str(CFG_STREAM_INVALID), NULL);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_stream_name)
|
START_TEST(test_stream_name)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -38,6 +64,13 @@ START_TEST(test_stream_mountpoint)
|
|||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
START_TEST(test_stream_intake)
|
||||||
|
{
|
||||||
|
TEST_XSTRDUP_T(cfg_stream_t, cfg_stream_list_get, streams,
|
||||||
|
cfg_stream_set_intake, cfg_stream_get_intake);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
|
||||||
START_TEST(test_stream_server)
|
START_TEST(test_stream_server)
|
||||||
{
|
{
|
||||||
TEST_XSTRDUP_T(cfg_stream_t, cfg_stream_list_get, streams,
|
TEST_XSTRDUP_T(cfg_stream_t, cfg_stream_list_get, streams,
|
||||||
@ -164,8 +197,11 @@ cfg_suite(void)
|
|||||||
tc_stream = tcase_create("Stream");
|
tc_stream = tcase_create("Stream");
|
||||||
tcase_add_checked_fixture(tc_stream, setup_checked, teardown_checked);
|
tcase_add_checked_fixture(tc_stream, setup_checked, teardown_checked);
|
||||||
tcase_add_test(tc_stream, test_stream_list_get);
|
tcase_add_test(tc_stream, test_stream_list_get);
|
||||||
|
tcase_add_test(tc_stream, test_stream_str2fmt);
|
||||||
|
tcase_add_test(tc_stream, test_stream_fmt2str);
|
||||||
tcase_add_test(tc_stream, test_stream_name);
|
tcase_add_test(tc_stream, test_stream_name);
|
||||||
tcase_add_test(tc_stream, test_stream_mountpoint);
|
tcase_add_test(tc_stream, test_stream_mountpoint);
|
||||||
|
tcase_add_test(tc_stream, test_stream_intake);
|
||||||
tcase_add_test(tc_stream, test_stream_server);
|
tcase_add_test(tc_stream, test_stream_server);
|
||||||
tcase_add_test(tc_stream, test_stream_public);
|
tcase_add_test(tc_stream, test_stream_public);
|
||||||
tcase_add_test(tc_stream, test_stream_format);
|
tcase_add_test(tc_stream, test_stream_format);
|
||||||
|
@ -40,6 +40,9 @@ START_TEST(test_reload)
|
|||||||
ck_assert_int_eq(cfg_set_program_config_file(SRCDIR "/config-bad5.xml",
|
ck_assert_int_eq(cfg_set_program_config_file(SRCDIR "/config-bad5.xml",
|
||||||
NULL), 0);
|
NULL), 0);
|
||||||
ck_assert_int_eq(cfg_file_reload(), -1);
|
ck_assert_int_eq(cfg_file_reload(), -1);
|
||||||
|
ck_assert_int_eq(cfg_set_program_config_file(SRCDIR "/config-bad6.xml",
|
||||||
|
NULL), 0);
|
||||||
|
ck_assert_int_eq(cfg_file_reload(), -1);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ START_TEST(test_stream)
|
|||||||
ck_assert_ptr_ne(srv_cfg, NULL);
|
ck_assert_ptr_ne(srv_cfg, NULL);
|
||||||
str_cfg = stream_get_cfg_stream(s);
|
str_cfg = stream_get_cfg_stream(s);
|
||||||
ck_assert_ptr_ne(str_cfg, NULL);
|
ck_assert_ptr_ne(str_cfg, NULL);
|
||||||
|
ck_assert_ptr_ne(stream_get_cfg_intake(s), NULL);
|
||||||
|
|
||||||
ck_assert_int_ne(stream_configure(s), 0);
|
ck_assert_int_ne(stream_configure(s), 0);
|
||||||
cfg_server_set_hostname(srv_cfg, servers, "localhost", NULL);
|
cfg_server_set_hostname(srv_cfg, servers, "localhost", NULL);
|
||||||
@ -94,6 +95,8 @@ START_TEST(test_stream)
|
|||||||
m_str = NULL;
|
m_str = NULL;
|
||||||
|
|
||||||
mdata_destroy(&m);
|
mdata_destroy(&m);
|
||||||
|
|
||||||
|
stream_destroy(&s);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
<name></name>
|
<name></name>
|
||||||
<mountpoint></mountpoint>
|
<mountpoint></mountpoint>
|
||||||
<public></public>
|
<public></public>
|
||||||
|
<intake></intake>
|
||||||
<server></server>
|
<server></server>
|
||||||
<format></format>
|
<format></format>
|
||||||
<encoder></encoder>
|
<encoder></encoder>
|
||||||
@ -40,12 +41,15 @@
|
|||||||
<!-- ... -->
|
<!-- ... -->
|
||||||
</streams>
|
</streams>
|
||||||
|
|
||||||
<media>
|
<intakes>
|
||||||
|
<intake>
|
||||||
|
<name></name>
|
||||||
<type></type>
|
<type></type>
|
||||||
<filename></filename>
|
<filename></filename>
|
||||||
<shuffle></shuffle>
|
<shuffle></shuffle>
|
||||||
<stream_once></stream_once>
|
<stream_once></stream_once>
|
||||||
</media>
|
</intake>
|
||||||
|
</intakes>
|
||||||
|
|
||||||
<metadata>
|
<metadata>
|
||||||
<program></program>
|
<program></program>
|
||||||
|
@ -15,6 +15,17 @@
|
|||||||
</server>
|
</server>
|
||||||
</servers>
|
</servers>
|
||||||
|
|
||||||
|
<intakes>
|
||||||
|
<intake>
|
||||||
|
<filename>secret</filename>
|
||||||
|
<name>duplicate</name>
|
||||||
|
</intake>
|
||||||
|
<intake>
|
||||||
|
<filename>secret</filename>
|
||||||
|
<name>duplicate</name>
|
||||||
|
</intake>
|
||||||
|
</intakes>
|
||||||
|
|
||||||
<streams>
|
<streams>
|
||||||
<stream>
|
<stream>
|
||||||
<format>vorbis</format>
|
<format>vorbis</format>
|
||||||
|
32
tests/config-bad6.xml
Normal file
32
tests/config-bad6.xml
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<ezstream>
|
||||||
|
|
||||||
|
<servers>
|
||||||
|
<server>
|
||||||
|
<hostname>127.0.0.1</hostname>
|
||||||
|
</server>
|
||||||
|
</servers>
|
||||||
|
|
||||||
|
<streams>
|
||||||
|
<stream>
|
||||||
|
<mountpoint>/stream.ogg</mountpoint>
|
||||||
|
</stream>
|
||||||
|
</streams>
|
||||||
|
|
||||||
|
<intakes>
|
||||||
|
<intake>
|
||||||
|
</intake>
|
||||||
|
</intakes>
|
||||||
|
|
||||||
|
<decoders>
|
||||||
|
<decoder>
|
||||||
|
</decoder>
|
||||||
|
</decoders>
|
||||||
|
|
||||||
|
<encoders>
|
||||||
|
<encoder>
|
||||||
|
</encoder>
|
||||||
|
</encoders>
|
||||||
|
|
||||||
|
</ezstream>
|
Loading…
x
Reference in New Issue
Block a user