mirror of
https://gitlab.xiph.org/xiph/ezstream.git
synced 2025-02-02 15:07:45 -05:00
Retain current behavior by default, where files are found based on the current working directory.
306 lines
5.8 KiB
C
306 lines
5.8 KiB
C
/*
|
|
* 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;
|
|
int rel_to_list;
|
|
};
|
|
|
|
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;
|
|
}
|
|
|
|
unsigned int
|
|
cfg_intake_list_nentries(struct cfg_intake_list *il)
|
|
{
|
|
struct cfg_intake *i;
|
|
unsigned int n = 0;
|
|
|
|
TAILQ_FOREACH(i, il, entry) {
|
|
n++;
|
|
}
|
|
|
|
return (n);
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
void
|
|
cfg_intake_list_foreach(struct cfg_intake_list *il,
|
|
void (*cb)(cfg_intake_t, void *), void *cb_arg)
|
|
{
|
|
struct cfg_intake *i;
|
|
|
|
TAILQ_FOREACH(i, il, entry) {
|
|
cb(i, cb_arg);
|
|
}
|
|
}
|
|
|
|
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_set_rel_to_list(struct cfg_intake *i, struct cfg_intake_list *not_used,
|
|
const char *rel_to_list, const char **errstrp)
|
|
{
|
|
(void)not_used;
|
|
SET_BOOLEAN(i->rel_to_list, rel_to_list, 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_type_str(struct cfg_intake *i)
|
|
{
|
|
switch (i->type) {
|
|
case CFG_INTAKE_FILE:
|
|
return ("file");
|
|
case CFG_INTAKE_PLAYLIST:
|
|
return ("playlist");
|
|
case CFG_INTAKE_PROGRAM:
|
|
return ("program");
|
|
case CFG_INTAKE_STDIN:
|
|
return ("stdin");
|
|
case CFG_INTAKE_AUTODETECT:
|
|
default:
|
|
return ("autodetect");
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
int
|
|
cfg_intake_get_rel_to_list(struct cfg_intake *i)
|
|
{
|
|
return (i->rel_to_list);
|
|
}
|