mirror of
https://gitlab.xiph.org/xiph/ezstream.git
synced 2024-11-03 04:17:18 -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
|
||||
The broadcast is public.
|
||||
.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\ /\&>
|
||||
Use the server configuration with the provided symbolic name for this stream.
|
||||
.Pp
|
||||
@ -376,17 +385,41 @@ Informational number of audio channels of the broadcast.
|
||||
Default:
|
||||
.Em none
|
||||
.El
|
||||
.Ss Media block
|
||||
.Ss Intakes block
|
||||
.Bl -tag -width -Ds
|
||||
.It Sy \&<media\ /\&>
|
||||
.Pq Mandatory.
|
||||
This element contains the entire input media configuration as child elements.
|
||||
.It Sy \&<intakes\ /\&>
|
||||
This element contains all intake blocks as child elements.
|
||||
Its parent is the
|
||||
.Sy \&<ezstream\ /\&>
|
||||
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
|
||||
.Ss Media configuration
|
||||
.Ss Intake block
|
||||
.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\ /\&>
|
||||
Configure the input media type:
|
||||
.Pp
|
||||
|
@ -26,9 +26,11 @@
|
||||
</stream>
|
||||
</streams>
|
||||
|
||||
<media>
|
||||
<filename>%FILENAME%</filename>
|
||||
</media>
|
||||
<intakes>
|
||||
<intake>
|
||||
<filename>%FILENAME%</filename>
|
||||
</intake>
|
||||
</intakes>
|
||||
|
||||
<decoders>
|
||||
<decoder>
|
||||
|
@ -75,6 +75,9 @@
|
||||
<!-- Mount point on server -->
|
||||
<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") -->
|
||||
<server>Default</server>
|
||||
|
||||
@ -100,21 +103,26 @@
|
||||
</streams>
|
||||
|
||||
<!--
|
||||
Media configuration
|
||||
Intake configuration
|
||||
-->
|
||||
<media>
|
||||
<!-- Media type: autodetect, file, playlist, program, stdin -->
|
||||
<type>autodetect</type>
|
||||
<intakes>
|
||||
<intake>
|
||||
<!-- Identifying name; default: "default" -->
|
||||
<name>Default</name>
|
||||
|
||||
<!-- Input file, program name, or "stdin" keyword -->
|
||||
<filename>playlist.m3u</filename>
|
||||
<!-- Media type: autodetect, file, playlist, program, stdin -->
|
||||
<type>autodetect</type>
|
||||
|
||||
<!-- Setting to shuffle playlists -->
|
||||
<shuffle>Yes</shuffle>
|
||||
<!-- Input file, program name, or "stdin" keyword -->
|
||||
<filename>playlist.m3u</filename>
|
||||
|
||||
<!-- Setting whether to stream input indefinitely or only once -->
|
||||
<stream_once>No</stream_once>
|
||||
</media>
|
||||
<!-- Setting to shuffle playlists -->
|
||||
<shuffle>Yes</shuffle>
|
||||
|
||||
<!-- Setting whether to stream intake indefinitely or only once -->
|
||||
<stream_once>No</stream_once>
|
||||
</intake>
|
||||
</intakes>
|
||||
|
||||
<!--
|
||||
Metadata configuration
|
||||
|
@ -22,8 +22,10 @@
|
||||
</stream>
|
||||
</streams>
|
||||
|
||||
<media>
|
||||
<filename>playlist.m3u</filename>
|
||||
</media>
|
||||
<intakes>
|
||||
<intake>
|
||||
<filename>playlist.m3u</filename>
|
||||
</intake>
|
||||
</intakes>
|
||||
|
||||
</ezstream>
|
||||
|
@ -22,8 +22,10 @@
|
||||
</stream>
|
||||
</streams>
|
||||
|
||||
<media>
|
||||
<type>stdin</type>
|
||||
</media>
|
||||
<intakes>
|
||||
<intake>
|
||||
<type>stdin</type>
|
||||
</intake>
|
||||
</intakes>
|
||||
|
||||
</ezstream>
|
||||
|
@ -21,9 +21,11 @@
|
||||
</stream>
|
||||
</streams>
|
||||
|
||||
<media>
|
||||
<filename>playlist.m3u</filename>
|
||||
</media>
|
||||
<intakes>
|
||||
<intake>
|
||||
<filename>playlist.m3u</filename>
|
||||
</intake>
|
||||
</intakes>
|
||||
|
||||
<decoders>
|
||||
<decoder>
|
||||
|
@ -6,6 +6,7 @@ noinst_HEADERS = \
|
||||
cfg.h \
|
||||
cfg_decoder.h \
|
||||
cfg_encoder.h \
|
||||
cfg_intake.h \
|
||||
cfg_private.h \
|
||||
cfg_server.h \
|
||||
cfg_stream.h \
|
||||
@ -22,6 +23,7 @@ libezstream_la_SOURCES = \
|
||||
cfg.c \
|
||||
cfg_decoder.c \
|
||||
cfg_encoder.c \
|
||||
cfg_intake.c \
|
||||
cfg_server.c \
|
||||
cfg_stream.c \
|
||||
cfg_xmlfile.c \
|
||||
|
124
src/cfg.c
124
src/cfg.c
@ -45,10 +45,11 @@ static void _cfg_commit(void);
|
||||
static void
|
||||
_cfg_reset(struct cfg *c)
|
||||
{
|
||||
cfg_server_list_destroy(&c->servers);
|
||||
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_decoder_list_destroy(&c->decoders);
|
||||
|
||||
xfree(c->metadata.format_str);
|
||||
|
||||
@ -133,47 +134,13 @@ cfg_file_reload(void)
|
||||
}
|
||||
|
||||
int
|
||||
cfg_check(const char **errstrp)
|
||||
cfg_check(const char **not_used)
|
||||
{
|
||||
if (!cfg_get_media_filename() &&
|
||||
CFG_MEDIA_STDIN != cfg_get_media_type()) {
|
||||
if (NULL != errstrp)
|
||||
*errstrp = "media filename missing";
|
||||
return (-1);
|
||||
}
|
||||
(void)not_used;
|
||||
|
||||
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
|
||||
cfg_file_check(const char *file)
|
||||
{
|
||||
@ -215,6 +182,15 @@ cfg_get_encoders(void)
|
||||
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_get_servers(void)
|
||||
{
|
||||
@ -290,54 +266,6 @@ cfg_set_program_verbosity(unsigned int verbosity, const char **not_used)
|
||||
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
|
||||
cfg_set_metadata_program(const char *program, const char **errstrp)
|
||||
{
|
||||
@ -433,30 +361,6 @@ cfg_get_program_verbosity(void)
|
||||
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 *
|
||||
cfg_get_metadata_program(void)
|
||||
{
|
||||
|
42
src/cfg.h
42
src/cfg.h
@ -17,10 +17,6 @@
|
||||
#ifndef __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_ARTIST "@a@"
|
||||
#define PLACEHOLDER_ALBUM "@b@"
|
||||
@ -36,27 +32,9 @@ enum cfg_config_type {
|
||||
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_encoder.h"
|
||||
#include "cfg_intake.h"
|
||||
#include "cfg_server.h"
|
||||
#include "cfg_stream.h"
|
||||
|
||||
@ -67,16 +45,14 @@ int cfg_file_reload(void);
|
||||
|
||||
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 *);
|
||||
|
||||
cfg_decoder_list_t
|
||||
cfg_get_decoders(void);
|
||||
cfg_encoder_list_t
|
||||
cfg_get_encoders(void);
|
||||
cfg_intake_list_t
|
||||
cfg_get_intakes(void);
|
||||
cfg_server_list_t
|
||||
cfg_get_servers(void);
|
||||
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_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_format_str(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
|
||||
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 *
|
||||
cfg_get_metadata_program(void);
|
||||
const char *
|
||||
|
@ -17,6 +17,8 @@
|
||||
#ifndef __CFG_ENCODER_H__
|
||||
#define __CFG_ENCODER_H__
|
||||
|
||||
#include "cfg_stream.h"
|
||||
|
||||
typedef struct cfg_encoder * cfg_encoder_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 {
|
||||
cfg_decoder_list_t decoders;
|
||||
cfg_encoder_list_t encoders;
|
||||
cfg_intake_list_t intakes;
|
||||
cfg_server_list_t servers;
|
||||
cfg_stream_list_t streams;
|
||||
struct media {
|
||||
enum cfg_media_type type;
|
||||
char filename[PATH_MAX];
|
||||
int shuffle;
|
||||
int stream_once;
|
||||
} media;
|
||||
struct metadata {
|
||||
char program[PATH_MAX];
|
||||
char *format_str;
|
||||
@ -59,8 +56,6 @@ struct cfg {
|
||||
int normalize_strings;
|
||||
int no_updates;
|
||||
} metadata;
|
||||
cfg_decoder_list_t decoders;
|
||||
cfg_encoder_list_t encoders;
|
||||
};
|
||||
|
||||
#define SET_STRLCPY(t, s, e) do { \
|
||||
|
@ -30,6 +30,7 @@ struct cfg_stream {
|
||||
TAILQ_ENTRY(cfg_stream) entry;
|
||||
char *name;
|
||||
char *mountpoint;
|
||||
char *intake;
|
||||
char *server;
|
||||
int public;
|
||||
enum cfg_stream_format format;
|
||||
@ -126,6 +127,7 @@ cfg_stream_destroy(struct cfg_stream **s_p)
|
||||
|
||||
xfree(s->name);
|
||||
xfree(s->mountpoint);
|
||||
xfree(s->intake);
|
||||
xfree(s->server);
|
||||
xfree(s->encoder);
|
||||
xfree(s->stream_name);
|
||||
@ -140,6 +142,36 @@ cfg_stream_destroy(struct cfg_stream **s_p)
|
||||
*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
|
||||
cfg_stream_set_name(struct cfg_stream *s, struct cfg_stream_list *sl,
|
||||
const char *name, const char **errstrp)
|
||||
@ -174,6 +206,15 @@ cfg_stream_set_mountpoint(struct cfg_stream *s,
|
||||
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
|
||||
cfg_stream_set_server(struct cfg_stream *s, struct cfg_stream_list *not_used,
|
||||
const char *server, const char **errstrp)
|
||||
@ -330,6 +371,12 @@ cfg_stream_get_mountpoint(struct cfg_stream *s)
|
||||
return (s->mountpoint);
|
||||
}
|
||||
|
||||
const char *
|
||||
cfg_stream_get_intake(struct cfg_stream *s)
|
||||
{
|
||||
return (s->intake);
|
||||
}
|
||||
|
||||
const char *
|
||||
cfg_stream_get_server(struct cfg_stream *s)
|
||||
{
|
||||
|
@ -17,6 +17,19 @@
|
||||
#ifndef __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_list * cfg_stream_list_t;
|
||||
|
||||
@ -33,10 +46,16 @@ cfg_stream_t
|
||||
cfg_stream_create(const char *);
|
||||
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 *,
|
||||
const char **);
|
||||
int cfg_stream_set_mountpoint(cfg_stream_t, cfg_stream_list_t,
|
||||
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 *,
|
||||
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);
|
||||
const char *
|
||||
cfg_stream_get_mountpoint(cfg_stream_t);
|
||||
const char *
|
||||
cfg_stream_get_intake(cfg_stream_t);
|
||||
const char *
|
||||
cfg_stream_get_server(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_stream(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_decoder(xmlDocPtr, xmlNodePtr);
|
||||
static int _cfg_xmlfile_parse_decoders(xmlDocPtr, xmlNodePtr);
|
||||
@ -46,7 +47,7 @@ static int _cfg_xmlfile_parse_encoders(xmlDocPtr, xmlNodePtr);
|
||||
int error = 0; \
|
||||
\
|
||||
val = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); \
|
||||
if (0 > (f)((c), (l), STD_CHAR(val), &err_str)) { \
|
||||
if (0 > (f)((c), (l), STD_CHAR(val), &err_str)) { \
|
||||
log_error("%s[%ld]: server (%s): %s: %s", \
|
||||
doc->name, xmlGetLineNo(cur), \
|
||||
cfg_server_get_name((c)), (e), err_str); \
|
||||
@ -112,7 +113,7 @@ _cfg_xmlfile_parse_servers(xmlDocPtr doc, xmlNodePtr cur)
|
||||
int error = 0; \
|
||||
\
|
||||
val = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); \
|
||||
if (0 > (f)((c), (l), STD_CHAR(val), &err_str)) { \
|
||||
if (0 > (f)((c), (l), STD_CHAR(val), &err_str)) { \
|
||||
log_error("%s[%ld]: stream (%s): %s: %s", \
|
||||
doc->name, xmlGetLineNo(cur), \
|
||||
cfg_stream_get_name((c)), (e), err_str); \
|
||||
@ -138,6 +139,7 @@ _cfg_xmlfile_parse_stream(xmlDocPtr doc, xmlNodePtr cur)
|
||||
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_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_public, "public");
|
||||
XML_STREAM_SET(s, sl, cfg_stream_set_format, "format");
|
||||
@ -172,6 +174,65 @@ _cfg_xmlfile_parse_streams(xmlDocPtr doc, xmlNodePtr cur)
|
||||
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 { \
|
||||
if (0 == xmlStrcasecmp(cur->name, XML_CHAR((e)))) { \
|
||||
xmlChar *val; \
|
||||
@ -187,24 +248,6 @@ _cfg_xmlfile_parse_streams(xmlDocPtr doc, xmlNodePtr cur)
|
||||
} \
|
||||
} 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
|
||||
_cfg_xmlfile_parse_metadata(xmlDocPtr doc, xmlNodePtr cur)
|
||||
{
|
||||
@ -233,7 +276,7 @@ _cfg_xmlfile_parse_metadata(xmlDocPtr doc, xmlNodePtr cur)
|
||||
int error = 0; \
|
||||
\
|
||||
val = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); \
|
||||
if (0 > (f)((c), (l), STD_CHAR(val), &err_str)) { \
|
||||
if (0 > (f)((c), (l), STD_CHAR(val), &err_str)) { \
|
||||
log_error("%s[%ld]: decoder (%s): %s: %s", \
|
||||
doc->name, xmlGetLineNo(cur), \
|
||||
cfg_decoder_get_name((c)), (e), err_str); \
|
||||
@ -290,7 +333,7 @@ _cfg_xmlfile_parse_decoders(xmlDocPtr doc, xmlNodePtr cur)
|
||||
int error = 0; \
|
||||
\
|
||||
val = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1); \
|
||||
if (0 > (f)((c), (l), STD_CHAR(val), &err_str)) { \
|
||||
if (0 > (f)((c), (l), STD_CHAR(val), &err_str)) { \
|
||||
log_error("%s[%ld]: encoder (%s): %s: %s", \
|
||||
doc->name, xmlGetLineNo(cur), \
|
||||
cfg_encoder_get_name((c)), (e), err_str); \
|
||||
@ -364,6 +407,7 @@ _cfg_xmlfile_parse_encoders(xmlDocPtr doc, xmlNodePtr cur)
|
||||
* name
|
||||
* mountpoint
|
||||
* public
|
||||
* intake
|
||||
* server
|
||||
* format
|
||||
* encoder
|
||||
@ -376,11 +420,13 @@ _cfg_xmlfile_parse_encoders(xmlDocPtr doc, xmlNodePtr cur)
|
||||
* stream_samplerate
|
||||
* stream_channels
|
||||
* ...
|
||||
* media
|
||||
* type
|
||||
* filename
|
||||
* shuffle
|
||||
* stream_once
|
||||
* intakes
|
||||
* intake
|
||||
* type
|
||||
* filename
|
||||
* shuffle
|
||||
* stream_once
|
||||
* ...
|
||||
* metadata
|
||||
* program
|
||||
* format_str
|
||||
@ -441,8 +487,8 @@ cfg_xmlfile_parse(const char *config_file)
|
||||
error = 1;
|
||||
continue;
|
||||
}
|
||||
if (0 == xmlStrcasecmp(cur->name, XML_CHAR("media"))) {
|
||||
if (0 > _cfg_xmlfile_parse_media(doc, cur))
|
||||
if (0 == xmlStrcasecmp(cur->name, XML_CHAR("intakes"))) {
|
||||
if (0 > _cfg_xmlfile_parse_intakes(doc, cur))
|
||||
error = 1;
|
||||
continue;
|
||||
}
|
||||
|
@ -407,6 +407,7 @@ sendStream(stream_t stream, FILE *filepstream, const char *fileName,
|
||||
struct timespec timeStamp, *startTime = tv;
|
||||
struct timespec callTime, currentTime;
|
||||
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);
|
||||
|
||||
@ -437,7 +438,7 @@ sendStream(stream_t stream, FILE *filepstream, const char *fileName,
|
||||
break;
|
||||
if (rereadPlaylist_notify) {
|
||||
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");
|
||||
}
|
||||
if (skipTrack) {
|
||||
@ -464,8 +465,8 @@ sendStream(stream_t stream, FILE *filepstream, const char *fileName,
|
||||
double oldTime, newTime;
|
||||
|
||||
if (!isStdin && playlistMode) {
|
||||
if (CFG_MEDIA_PROGRAM == cfg_get_media_type()) {
|
||||
char *tmp = xstrdup(cfg_get_media_filename());
|
||||
if (CFG_INTAKE_PROGRAM == cfg_intake_get_type(cfg_intake)) {
|
||||
char *tmp = xstrdup(cfg_intake_get_filename(cfg_intake));
|
||||
printf(" [%s]", basename(tmp));
|
||||
xfree(tmp);
|
||||
} else
|
||||
@ -523,12 +524,13 @@ streamFile(stream_t stream, const char *fileName)
|
||||
FILE *filepstream = NULL;
|
||||
int popenFlag = 0;
|
||||
char *songLenStr = NULL;
|
||||
int isStdin = cfg_get_media_type() == CFG_MEDIA_STDIN;
|
||||
int ret, retval = 0;
|
||||
long songLen;
|
||||
mdata_t md = NULL;
|
||||
struct timespec startTime;
|
||||
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))
|
||||
== NULL) {
|
||||
@ -633,23 +635,24 @@ streamPlaylist(stream_t stream)
|
||||
{
|
||||
const char *song;
|
||||
char lastSong[PATH_MAX];
|
||||
cfg_intake_t cfg_intake = stream_get_cfg_intake(stream);
|
||||
|
||||
if (playlist == NULL) {
|
||||
switch (cfg_get_media_type()) {
|
||||
case CFG_MEDIA_PROGRAM:
|
||||
if ((playlist = playlist_program(cfg_get_media_filename())) == NULL)
|
||||
switch (cfg_intake_get_type(cfg_intake)) {
|
||||
case CFG_INTAKE_PROGRAM:
|
||||
if ((playlist = playlist_program(cfg_intake_get_filename(cfg_intake))) == NULL)
|
||||
return (0);
|
||||
break;
|
||||
case CFG_MEDIA_STDIN:
|
||||
case CFG_INTAKE_STDIN:
|
||||
if ((playlist = playlist_read(NULL)) == NULL)
|
||||
return (0);
|
||||
break;
|
||||
default:
|
||||
if ((playlist = playlist_read(cfg_get_media_filename())) == NULL)
|
||||
if ((playlist = playlist_read(cfg_intake_get_filename(cfg_intake))) == NULL)
|
||||
return (0);
|
||||
if (playlist_get_num_items(playlist) == 0)
|
||||
log_warning("%s: playlist empty",
|
||||
cfg_get_media_filename());
|
||||
cfg_intake_get_filename(cfg_intake));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@ -661,8 +664,8 @@ streamPlaylist(stream_t stream)
|
||||
playlist_rewind(playlist);
|
||||
}
|
||||
|
||||
if (CFG_MEDIA_PROGRAM != cfg_get_media_type() &&
|
||||
cfg_get_media_shuffle())
|
||||
if (CFG_INTAKE_PROGRAM != cfg_intake_get_type(cfg_intake) &&
|
||||
cfg_intake_get_shuffle(cfg_intake))
|
||||
playlist_shuffle(playlist);
|
||||
|
||||
while ((song = playlist_get_next(playlist)) != NULL) {
|
||||
@ -673,12 +676,12 @@ streamPlaylist(stream_t stream)
|
||||
break;
|
||||
if (rereadPlaylist) {
|
||||
rereadPlaylist = rereadPlaylist_notify = 0;
|
||||
if (CFG_MEDIA_PROGRAM == cfg_get_media_type())
|
||||
if (CFG_INTAKE_PROGRAM == cfg_intake_get_type(cfg_intake))
|
||||
continue;
|
||||
log_notice("rereading playlist");
|
||||
if (!playlist_reread(&playlist))
|
||||
return (0);
|
||||
if (cfg_get_media_shuffle())
|
||||
if (cfg_intake_get_shuffle(cfg_intake))
|
||||
playlist_shuffle(playlist);
|
||||
else {
|
||||
playlist_goto_entry(playlist, lastSong);
|
||||
@ -716,6 +719,7 @@ main(int argc, char *argv[])
|
||||
unsigned int i;
|
||||
cfg_server_t cfg_server;
|
||||
cfg_stream_t cfg_stream;
|
||||
cfg_intake_t cfg_intake;
|
||||
|
||||
ret = 1;
|
||||
if (0 > cfg_init() ||
|
||||
@ -736,6 +740,7 @@ main(int argc, char *argv[])
|
||||
return (ez_shutdown(1));
|
||||
cfg_server = stream_get_cfg_server(main_stream);
|
||||
cfg_stream = stream_get_cfg_stream(main_stream);
|
||||
cfg_intake = stream_get_cfg_intake(main_stream);
|
||||
|
||||
memset(&act, 0, sizeof(act));
|
||||
act.sa_handler = sig_handler;
|
||||
@ -774,11 +779,11 @@ main(int argc, char *argv[])
|
||||
cfg_server_get_port(cfg_server),
|
||||
cfg_stream_get_mountpoint(cfg_stream));
|
||||
|
||||
if (CFG_MEDIA_PROGRAM == cfg_get_media_type() ||
|
||||
CFG_MEDIA_PLAYLIST == cfg_get_media_type() ||
|
||||
(CFG_MEDIA_AUTODETECT == cfg_get_media_type() &&
|
||||
(util_strrcasecmp(cfg_get_media_filename(), ".m3u") == 0 ||
|
||||
util_strrcasecmp(cfg_get_media_filename(), ".txt") == 0)))
|
||||
if (CFG_INTAKE_PROGRAM == cfg_intake_get_type(cfg_intake) ||
|
||||
CFG_INTAKE_PLAYLIST == cfg_intake_get_type(cfg_intake) ||
|
||||
(CFG_INTAKE_AUTODETECT == cfg_intake_get_type(cfg_intake) &&
|
||||
(util_strrcasecmp(cfg_intake_get_filename(cfg_intake), ".m3u") == 0 ||
|
||||
util_strrcasecmp(cfg_intake_get_filename(cfg_intake), ".txt") == 0)))
|
||||
playlistMode = 1;
|
||||
else
|
||||
playlistMode = 0;
|
||||
@ -788,11 +793,11 @@ main(int argc, char *argv[])
|
||||
cont = streamPlaylist(main_stream);
|
||||
} else {
|
||||
cont = streamFile(main_stream,
|
||||
cfg_get_media_filename());
|
||||
cfg_intake_get_filename(cfg_intake));
|
||||
}
|
||||
if (quit)
|
||||
break;
|
||||
if (cfg_get_media_stream_once())
|
||||
if (cfg_intake_get_stream_once(cfg_intake))
|
||||
break;
|
||||
} 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));
|
||||
}
|
||||
|
||||
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
|
||||
stream_get_cfg_server(struct stream *s)
|
||||
{
|
||||
|
@ -39,6 +39,8 @@ const char *
|
||||
int stream_get_connected(stream_t);
|
||||
cfg_stream_t
|
||||
stream_get_cfg_stream(stream_t);
|
||||
cfg_intake_t
|
||||
stream_get_cfg_intake(stream_t);
|
||||
cfg_server_t
|
||||
stream_get_cfg_server(stream_t);
|
||||
|
||||
|
@ -4,6 +4,7 @@ TESTS = \
|
||||
check_cfg \
|
||||
check_cfg_decoder \
|
||||
check_cfg_encoder \
|
||||
check_cfg_intake \
|
||||
check_cfg_server \
|
||||
check_cfg_stream \
|
||||
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_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_DEPENDENCIES = $(top_builddir)/src/libezstream.la
|
||||
check_cfg_server_LDADD = $(check_cfg_server_DEPENDENCIES) @CHECK_LIBS@
|
||||
@ -87,6 +92,7 @@ EXTRA_DIST = \
|
||||
config-bad3.xml \
|
||||
config-bad4.xml \
|
||||
config-bad5.xml \
|
||||
config-bad6.xml \
|
||||
play-bad.sh \
|
||||
play-bad2.sh \
|
||||
play-bad3.sh \
|
||||
|
@ -13,49 +13,7 @@ void teardown_checked(void);
|
||||
|
||||
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_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
|
||||
|
||||
@ -121,46 +79,6 @@ START_TEST(test_program_verbosity)
|
||||
}
|
||||
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)
|
||||
{
|
||||
ck_assert_ptr_eq(cfg_get_metadata_program(), NULL);
|
||||
@ -240,7 +158,6 @@ cfg_suite(void)
|
||||
Suite *s;
|
||||
TCase *tc_core;
|
||||
TCase *tc_program;
|
||||
TCase *tc_media;
|
||||
TCase *tc_metadata;
|
||||
|
||||
s = suite_create("Config");
|
||||
@ -248,8 +165,6 @@ cfg_suite(void)
|
||||
tc_core = tcase_create("Core");
|
||||
tcase_add_checked_fixture(tc_core, setup_checked, teardown_checked);
|
||||
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);
|
||||
suite_add_tcase(s, tc_core);
|
||||
|
||||
@ -265,14 +180,6 @@ cfg_suite(void)
|
||||
tcase_add_test(tc_program, test_program_verbosity);
|
||||
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");
|
||||
tcase_add_checked_fixture(tc_metadata, setup_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
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
@ -38,6 +64,13 @@ START_TEST(test_stream_mountpoint)
|
||||
}
|
||||
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)
|
||||
{
|
||||
TEST_XSTRDUP_T(cfg_stream_t, cfg_stream_list_get, streams,
|
||||
@ -164,8 +197,11 @@ cfg_suite(void)
|
||||
tc_stream = tcase_create("Stream");
|
||||
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_str2fmt);
|
||||
tcase_add_test(tc_stream, test_stream_fmt2str);
|
||||
tcase_add_test(tc_stream, test_stream_name);
|
||||
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_public);
|
||||
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",
|
||||
NULL), 0);
|
||||
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
|
||||
|
||||
|
@ -31,6 +31,7 @@ START_TEST(test_stream)
|
||||
ck_assert_ptr_ne(srv_cfg, NULL);
|
||||
str_cfg = stream_get_cfg_stream(s);
|
||||
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);
|
||||
cfg_server_set_hostname(srv_cfg, servers, "localhost", NULL);
|
||||
@ -94,6 +95,8 @@ START_TEST(test_stream)
|
||||
m_str = NULL;
|
||||
|
||||
mdata_destroy(&m);
|
||||
|
||||
stream_destroy(&s);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
<name></name>
|
||||
<mountpoint></mountpoint>
|
||||
<public></public>
|
||||
<intake></intake>
|
||||
<server></server>
|
||||
<format></format>
|
||||
<encoder></encoder>
|
||||
@ -40,12 +41,15 @@
|
||||
<!-- ... -->
|
||||
</streams>
|
||||
|
||||
<media>
|
||||
<type></type>
|
||||
<filename></filename>
|
||||
<shuffle></shuffle>
|
||||
<stream_once></stream_once>
|
||||
</media>
|
||||
<intakes>
|
||||
<intake>
|
||||
<name></name>
|
||||
<type></type>
|
||||
<filename></filename>
|
||||
<shuffle></shuffle>
|
||||
<stream_once></stream_once>
|
||||
</intake>
|
||||
</intakes>
|
||||
|
||||
<metadata>
|
||||
<program></program>
|
||||
|
@ -15,6 +15,17 @@
|
||||
</server>
|
||||
</servers>
|
||||
|
||||
<intakes>
|
||||
<intake>
|
||||
<filename>secret</filename>
|
||||
<name>duplicate</name>
|
||||
</intake>
|
||||
<intake>
|
||||
<filename>secret</filename>
|
||||
<name>duplicate</name>
|
||||
</intake>
|
||||
</intakes>
|
||||
|
||||
<streams>
|
||||
<stream>
|
||||
<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…
Reference in New Issue
Block a user