diff --git a/NEWS b/NEWS
index 1c1408e..20c55cf 100644
--- a/NEWS
+++ b/NEWS
@@ -1,10 +1,13 @@
-Changes in 1.NNN, released on YYYY-MM-DD:
+Changes in 1.1.0, released on YYYY-MM-DD:
* Fix regression when streaming formats other than Ogg (e.g. MP3). From
zygmund2000 on Github (#30) and Roland Hermans on GitLab (#2271).
* Fix build issue on OSX. From Mitchell Blank on GitLab (#2270).
* Support reproducible builds. Via Unit 193 on GitLab (#2276).
* Update autoconf requirement to 2.69
+* Add setting to look for files relative to the playlist
+ file location instead of the current working directory. From Dan Sanford
+ on GitLab (#2283).
diff --git a/configure.ac b/configure.ac
index de7926b..d0d9c28 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ dnl ###########
dnl ## SETUP ###########################################################
dnl ###########
-AC_INIT([ezstream], [1.0.2], [https://gitlab.xiph.org/xiph/ezstream/issues])
+AC_INIT([ezstream], [1.1.0], [https://gitlab.xiph.org/xiph/ezstream/issues])
AC_PREREQ([2.69])
AC_CONFIG_SRCDIR([src/ezstream.c])
AC_CONFIG_AUX_DIR([build-aux])
diff --git a/doc/ezstream.1.in.in b/doc/ezstream.1.in.in
index f944a47..c45bb4f 100644
--- a/doc/ezstream.1.in.in
+++ b/doc/ezstream.1.in.in
@@ -498,6 +498,19 @@ default).
.It Ar 1|Yes|True
After streaming all media input, exit.
.El
+.It Sy \&
+Boolean setting, whether to locate playlist entries
+.Qq relative to the list .
+Entries with absolute path names are not affected.
+.Pp
+.Bl -tag -width 0|NO|FALSE -compact
+.It Ar 0|No|False
+Find files relative to the current working directory of
+.Nm
+(the default).
+.It Ar 1|Yes|True
+Find files relative to the location of the playlist file or program.
+.El
.El
.Ss Metadata block
.Bl -tag -width -Ds
diff --git a/examples/ezstream-full.xml b/examples/ezstream-full.xml
index 07e20be..9ea7550 100644
--- a/examples/ezstream-full.xml
+++ b/examples/ezstream-full.xml
@@ -143,11 +143,14 @@
playlist.m3u
-
+
Yes
-
+
Yes
+
+
+ Yes
diff --git a/src/cfg_intake.c b/src/cfg_intake.c
index cc918d9..d1a62e7 100644
--- a/src/cfg_intake.c
+++ b/src/cfg_intake.c
@@ -35,6 +35,7 @@ struct cfg_intake {
char filename[PATH_MAX];
int shuffle;
int stream_once;
+ int rel_to_list;
};
TAILQ_HEAD(cfg_intake_list, cfg_intake);
@@ -227,6 +228,15 @@ cfg_intake_set_stream_once(struct cfg_intake *i, struct cfg_intake_list *not_use
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)
{
@@ -287,3 +297,9 @@ 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);
+}
diff --git a/src/cfg_intake.h b/src/cfg_intake.h
index 154f377..a1ec1dc 100644
--- a/src/cfg_intake.h
+++ b/src/cfg_intake.h
@@ -57,6 +57,8 @@ 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_set_rel_to_list(cfg_intake_t, cfg_intake_list_t,
+ const char *, const char **);
int cfg_intake_validate(cfg_intake_t, const char **);
@@ -70,5 +72,6 @@ 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);
+int cfg_intake_get_rel_to_list(cfg_intake_t);
#endif /* __CFG_INTAKE_H__ */
diff --git a/src/cfgfile_xml.c b/src/cfgfile_xml.c
index 37e9e1f..ce03223 100644
--- a/src/cfgfile_xml.c
+++ b/src/cfgfile_xml.c
@@ -222,6 +222,7 @@ _cfgfile_xml_parse_intake(xmlDocPtr doc, xmlNodePtr cur)
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");
+ XML_INPUT_SET(i, il, cfg_intake_set_rel_to_list, "rel_to_list");
}
if (0 > cfg_intake_validate(i, &errstr)) {
@@ -438,6 +439,7 @@ _cfgfile_xml_parse_encoders(xmlDocPtr doc, xmlNodePtr cur)
* filename
* shuffle
* stream_once
+ * rel_to_list
* ...
* metadata
* program
@@ -650,6 +652,8 @@ _cfgfile_xml_print_intake(cfg_intake_t i, void *arg)
fprintf(fp, " yes\n");
if (cfg_intake_get_stream_once(i))
fprintf(fp, " yes\n");
+ if (cfg_intake_get_rel_to_list(i))
+ fprintf(fp, " yes\n");
fprintf(fp, " \n");
}
diff --git a/src/ezstream.c b/src/ezstream.c
index 4134fe4..b26fb7e 100644
--- a/src/ezstream.c
+++ b/src/ezstream.c
@@ -684,7 +684,8 @@ streamPlaylist(stream_t stream)
while ((song_next = playlist_get_next(playlist)) != NULL) {
strlcpy(song_prev, song_next, sizeof(song_prev));
- if ('/' == song_next[0])
+ if ('/' == song_next[0] ||
+ !cfg_intake_get_rel_to_list(cfg_intake))
(void)snprintf(tmp_path, sizeof(tmp_path), "%s",
song_next);
else
diff --git a/tests/check_cfg_intake.c b/tests/check_cfg_intake.c
index afc8f57..e2315f9 100644
--- a/tests/check_cfg_intake.c
+++ b/tests/check_cfg_intake.c
@@ -105,6 +105,13 @@ START_TEST(test_intake_set_stream_once)
}
END_TEST
+START_TEST(test_intake_set_rel_to_list)
+{
+ TEST_BOOLEAN_T(cfg_intake_t, cfg_intake_list_get, intakes,
+ cfg_intake_set_rel_to_list, cfg_intake_get_rel_to_list);
+}
+END_TEST
+
START_TEST(test_intake_validate)
{
cfg_intake_t in = cfg_intake_list_get(intakes, "test_intake_validate");
@@ -147,6 +154,7 @@ cfg_suite(void)
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_set_rel_to_list);
tcase_add_test(tc_intake, test_intake_validate);
suite_add_tcase(s, tc_intake);
diff --git a/tests/config-bad.xml b/tests/config-bad.xml
index 86f2cc6..c1ef908 100644
--- a/tests/config-bad.xml
+++ b/tests/config-bad.xml
@@ -48,6 +48,7 @@
+