mirror of
https://gitlab.xiph.org/xiph/ezstream.git
synced 2025-06-30 22:18:27 -04:00
Merge branch 'release/0.6.0'
This commit is contained in:
commit
ee0700992e
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
Makefile.in
|
||||||
|
aclocal.m4
|
||||||
|
compile
|
||||||
|
config.guess
|
||||||
|
config.h.in
|
||||||
|
config.sub
|
||||||
|
configure
|
||||||
|
depcomp
|
||||||
|
install-sh
|
||||||
|
libtool.m4
|
||||||
|
ltmain.sh
|
||||||
|
ltoptions.m4
|
||||||
|
ltsugar.m4
|
||||||
|
ltversion.m4
|
||||||
|
lt~obsolete.m4
|
||||||
|
missing
|
2
COPYING
2
COPYING
@ -1,6 +1,6 @@
|
|||||||
ezstream - source client for Icecast with external en-/decoder support
|
ezstream - source client for Icecast with external en-/decoder support
|
||||||
Copyright (C) 2003, 2004, 2005, 2006 Ed Zaleski <oddsock@oddsock.org>
|
Copyright (C) 2003, 2004, 2005, 2006 Ed Zaleski <oddsock@oddsock.org>
|
||||||
Copyright (C) 2007, 2009 Moritz Grimm <mdgrimm@gmx.net>
|
Copyright (C) 2007, 2009, 2015 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
|
|
||||||
|
|
||||||
The ezstream program, in its entirety, is licensed under the terms and
|
The ezstream program, in its entirety, is licensed under the terms and
|
||||||
|
60
NEWS
60
NEWS
@ -1,3 +1,48 @@
|
|||||||
|
Changes in 0.6.0, released on 2015-01-18:
|
||||||
|
|
||||||
|
* This release contains a SECURITY FIX for a command injection vulnerability
|
||||||
|
that was found and reported by Alexandre Rebert:
|
||||||
|
|
||||||
|
The previous handling of metadata placeholders allowed for arbitrary shell
|
||||||
|
commands to be trivially injected and executed as the ezstream user, via
|
||||||
|
malicious media files.
|
||||||
|
|
||||||
|
This vulnerability depends on both a configuration using metadata
|
||||||
|
placeholders and the user streaming media files from untrusted sources
|
||||||
|
without noticing `commands` or $(commands) in artist or title fields.
|
||||||
|
|
||||||
|
While the group of actually affected users may be limited, all users are
|
||||||
|
advised to upgrade.
|
||||||
|
|
||||||
|
* This release requires users to ADJUST their CONFIGURATION:
|
||||||
|
|
||||||
|
To protect against the injection vulnerability above, metadata is now
|
||||||
|
properly quoted and escaped from the shell. This means that any extra
|
||||||
|
quoting must be removed from configuration files.
|
||||||
|
|
||||||
|
Remove all quoting from metadata placeholders in <encode/> and <decode/>
|
||||||
|
commands, e.g. replace "@M@" with @M@, and "@T@" with @T@, etc. Without
|
||||||
|
these changes, stream metadata will look both wrong and the injection
|
||||||
|
vulnerability may be re-introduced.
|
||||||
|
|
||||||
|
Configuration examples have been adjusted accordingly.
|
||||||
|
|
||||||
|
* src/ezstream.c:
|
||||||
|
- [FIX] Prevent certain characters from being interpreted by the shell.
|
||||||
|
- [FIX] Prevent ezstream from entering an infinite loop when stopping to
|
||||||
|
send data to standard input. From gquintard.
|
||||||
|
(Ticket #2045)
|
||||||
|
* various:
|
||||||
|
- [NEW] Add new <metadata_refreshinterval/> feature from Matthew Adams
|
||||||
|
(with minor changes plus documentation.) This allows for recurring
|
||||||
|
and custom metadata updates in between song changes via
|
||||||
|
<metadata_progname/>.
|
||||||
|
- [NEW] Add new command line option `-m' to disable any active metadata
|
||||||
|
updates. Idea from Richard Thomas.
|
||||||
|
(Ticket #1620)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Changes in 0.5.6, released on 2009-08-31:
|
Changes in 0.5.6, released on 2009-08-31:
|
||||||
|
|
||||||
* ezstream-file.sh:
|
* ezstream-file.sh:
|
||||||
@ -23,6 +68,7 @@ Changes in 0.5.6, released on 2009-08-31:
|
|||||||
- [NEW] Add a real-world example playlist script with logging feature.
|
- [NEW] Add a real-world example playlist script with logging feature.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Changes in 0.5.5, released on 2009-08-01:
|
Changes in 0.5.5, released on 2009-08-01:
|
||||||
|
|
||||||
* win32/config.h:
|
* win32/config.h:
|
||||||
@ -177,7 +223,7 @@ Changes in 0.4.0, released on 2007-03-11:
|
|||||||
program.
|
program.
|
||||||
|
|
||||||
* src/compat.c:
|
* src/compat.c:
|
||||||
- [ADD] Implement a basename() function for Windows that behaves like the
|
- [NEW] Implement a basename() function for Windows that behaves like the
|
||||||
ones used on Unix systems.
|
ones used on Unix systems.
|
||||||
|
|
||||||
* win32/:
|
* win32/:
|
||||||
@ -185,19 +231,19 @@ Changes in 0.4.0, released on 2007-03-11:
|
|||||||
distribution, and provide a much better PDF version instead.
|
distribution, and provide a much better PDF version instead.
|
||||||
|
|
||||||
* various:
|
* various:
|
||||||
- [ADD] Allow ezstream to use TagLib for reading metadata from media
|
- [NEW] Allow ezstream to use TagLib for reading metadata from media
|
||||||
files. TagLib (libtag_c) is now an optional dependency.
|
files. TagLib (libtag_c) is now an optional dependency.
|
||||||
- [ADD] When built with TagLib support, include the song length in the
|
- [NEW] When built with TagLib support, include the song length in the
|
||||||
"real-time" information line, if available.
|
"real-time" information line, if available.
|
||||||
- [ADD] New <metadata_progname> configuration option, which causes
|
- [NEW] New <metadata_progname> configuration option, which causes
|
||||||
metadata to be read from the output of an external program or
|
metadata to be read from the output of an external program or
|
||||||
script.
|
script.
|
||||||
- [ADD] New runtime control via the SIGUSR2 signal, which triggers reading
|
- [NEW] New runtime control via the SIGUSR2 signal, which triggers reading
|
||||||
of fresh metadata information from <metadata_progname> (metadata
|
of fresh metadata information from <metadata_progname> (metadata
|
||||||
is always read at song changes.)
|
is always read at song changes.)
|
||||||
- [ADD] New <metadata_format> configuration option, to customize metadata
|
- [NEW] New <metadata_format> configuration option, to customize metadata
|
||||||
strings when used with the new <metadata_progname> feature.
|
strings when used with the new <metadata_progname> feature.
|
||||||
- [ADD] New '@a@' and '@t@' placeholders for separate artist and title
|
- [NEW] New '@a@' and '@t@' placeholders for separate artist and title
|
||||||
metadata in de-/encoder commands.
|
metadata in de-/encoder commands.
|
||||||
|
|
||||||
|
|
||||||
|
4
README
4
README
@ -40,7 +40,7 @@ Ezstream optionally uses:
|
|||||||
- For reading metadata from Ogg Vorbis files:
|
- For reading metadata from Ogg Vorbis files:
|
||||||
* TagLib 1.x (1.4 or newer recommended, will be used via the libtag_c
|
* TagLib 1.x (1.4 or newer recommended, will be used via the libtag_c
|
||||||
wrapper)
|
wrapper)
|
||||||
(http://developer.kde.org/~wheeler/taglib.html)
|
(https://taglib.github.io/)
|
||||||
OR:
|
OR:
|
||||||
* libvorbis 1.x
|
* libvorbis 1.x
|
||||||
(http://www.vorbis.com)
|
(http://www.vorbis.com)
|
||||||
@ -48,7 +48,7 @@ Ezstream optionally uses:
|
|||||||
many additional media file types.
|
many additional media file types.
|
||||||
- For basic non-ASCII charset support in metadata and filenames:
|
- For basic non-ASCII charset support in metadata and filenames:
|
||||||
* Libiconv, if iconv() is not available in the system libc.
|
* Libiconv, if iconv() is not available in the system libc.
|
||||||
(http://www.gnu.org/software/libiconv/)
|
(https://www.gnu.org/software/libiconv/)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
.\" $OpenBSD: tree.3,v 1.20 2009/01/28 12:22:48 stsp Exp $
|
.\" $OpenBSD: tree.3,v 1.26 2014/09/08 01:27:55 schwarze Exp $
|
||||||
.\"/*
|
.\"/*
|
||||||
.\" * Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
.\" * Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||||
.\" * All rights reserved.
|
.\" * All rights reserved.
|
||||||
@ -23,7 +23,7 @@
|
|||||||
.\" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\" */
|
.\" */
|
||||||
.Dd $Mdocdate: January 28 2009 $
|
.Dd $Mdocdate: September 8 2014 $
|
||||||
.Dt TREE 3
|
.Dt TREE 3
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -63,13 +63,15 @@
|
|||||||
.Nm RB_RIGHT ,
|
.Nm RB_RIGHT ,
|
||||||
.Nm RB_PARENT ,
|
.Nm RB_PARENT ,
|
||||||
.Nm RB_FOREACH ,
|
.Nm RB_FOREACH ,
|
||||||
|
.Nm RB_FOREACH_SAFE ,
|
||||||
.Nm RB_FOREACH_REVERSE ,
|
.Nm RB_FOREACH_REVERSE ,
|
||||||
|
.Nm RB_FOREACH_REVERSE_SAFE ,
|
||||||
.Nm RB_INIT ,
|
.Nm RB_INIT ,
|
||||||
.Nm RB_INSERT ,
|
.Nm RB_INSERT ,
|
||||||
.Nm RB_REMOVE
|
.Nm RB_REMOVE
|
||||||
.Nd "implementations of splay and red-black trees"
|
.Nd implementations of splay and red-black trees
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Fd #include <sys/tree.h>
|
.In sys/tree.h
|
||||||
.Pp
|
.Pp
|
||||||
.Fn SPLAY_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP"
|
.Fn SPLAY_PROTOTYPE "NAME" "TYPE" "FIELD" "CMP"
|
||||||
.Fn SPLAY_GENERATE "NAME" "TYPE" "FIELD" "CMP"
|
.Fn SPLAY_GENERATE "NAME" "TYPE" "FIELD" "CMP"
|
||||||
@ -130,7 +132,9 @@
|
|||||||
.Ft "struct TYPE *"
|
.Ft "struct TYPE *"
|
||||||
.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME"
|
.Fn RB_PARENT "struct TYPE *elm" "RB_ENTRY NAME"
|
||||||
.Fn RB_FOREACH "VARNAME" "NAME" "RB_HEAD *head"
|
.Fn RB_FOREACH "VARNAME" "NAME" "RB_HEAD *head"
|
||||||
|
.Fn RB_FOREACH_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
|
||||||
.Fn RB_FOREACH_REVERSE "VARNAME" "NAME" "RB_HEAD *head"
|
.Fn RB_FOREACH_REVERSE "VARNAME" "NAME" "RB_HEAD *head"
|
||||||
|
.Fn RB_FOREACH_REVERSE_SAFE "VARNAME" "NAME" "RB_HEAD *head" "TEMP_VARNAME"
|
||||||
.Ft void
|
.Ft void
|
||||||
.Fn RB_INIT "RB_HEAD *head"
|
.Fn RB_INIT "RB_HEAD *head"
|
||||||
.Ft "struct TYPE *"
|
.Ft "struct TYPE *"
|
||||||
@ -258,6 +262,11 @@ The
|
|||||||
macro inserts the new element
|
macro inserts the new element
|
||||||
.Fa elm
|
.Fa elm
|
||||||
into the tree.
|
into the tree.
|
||||||
|
Upon success,
|
||||||
|
.Va NULL
|
||||||
|
is returned.
|
||||||
|
If a matching element already exists in the tree, the insertion is
|
||||||
|
aborted, and a pointer to the existing element is returned.
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
.Fn SPLAY_REMOVE
|
.Fn SPLAY_REMOVE
|
||||||
@ -265,6 +274,11 @@ macro removes the element
|
|||||||
.Fa elm
|
.Fa elm
|
||||||
from the tree pointed by
|
from the tree pointed by
|
||||||
.Fa head .
|
.Fa head .
|
||||||
|
Upon success, a pointer to the removed element is returned.
|
||||||
|
.Va NULL
|
||||||
|
is returned if
|
||||||
|
.Fa elm
|
||||||
|
is not present in the tree.
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
.Fn SPLAY_FIND
|
.Fn SPLAY_FIND
|
||||||
@ -405,6 +419,9 @@ macro removes the element
|
|||||||
.Fa elm
|
.Fa elm
|
||||||
from the tree pointed by
|
from the tree pointed by
|
||||||
.Fa head .
|
.Fa head .
|
||||||
|
.Fn RB_REMOVE
|
||||||
|
returns
|
||||||
|
.Fa elm .
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
.Fn RB_FIND
|
.Fn RB_FIND
|
||||||
@ -443,6 +460,18 @@ macros:
|
|||||||
RB_FOREACH(np, NAME, &head)
|
RB_FOREACH(np, NAME, &head)
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
|
The macros
|
||||||
|
.Fn RB_FOREACH_SAFE
|
||||||
|
and
|
||||||
|
.Fn RB_FOREACH_REVERSE_SAFE
|
||||||
|
traverse the tree referenced by head
|
||||||
|
in a forward or reverse direction respectively,
|
||||||
|
assigning each element in turn to np.
|
||||||
|
However, unlike their unsafe counterparts,
|
||||||
|
they permit both the removal of np
|
||||||
|
as well as freeing it from within the loop safely
|
||||||
|
without interfering with the traversal.
|
||||||
|
.Pp
|
||||||
The
|
The
|
||||||
.Fn RB_EMPTY
|
.Fn RB_EMPTY
|
||||||
macro should be used to check whether a red-black tree is empty.
|
macro should be used to check whether a red-black tree is empty.
|
||||||
@ -543,22 +572,6 @@ for (var = SPLAY_MIN(NAME, &head); var != NULL; var = nxt) {
|
|||||||
free(var);
|
free(var);
|
||||||
}
|
}
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
|
||||||
Both
|
|
||||||
.Fn RB_INSERT
|
|
||||||
and
|
|
||||||
.Fn SPLAY_INSERT
|
|
||||||
return
|
|
||||||
.Va NULL
|
|
||||||
if the element was inserted in the tree successfully, otherwise they
|
|
||||||
return a pointer to the element with the colliding key.
|
|
||||||
.Pp
|
|
||||||
Accordingly,
|
|
||||||
.Fn RB_REMOVE
|
|
||||||
and
|
|
||||||
.Fn SPLAY_REMOVE
|
|
||||||
return the pointer to the removed element, otherwise they return
|
|
||||||
.Va NULL
|
|
||||||
to indicate an error.
|
|
||||||
.Sh AUTHORS
|
.Sh AUTHORS
|
||||||
The author of the tree macros is Niels Provos.
|
The author of the tree macros is
|
||||||
|
.An Niels Provos .
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $OpenBSD: tree.h,v 1.11 2008/05/11 22:19:09 millert Exp $ */
|
/* $OpenBSD: tree.h,v 1.13 2011/07/09 00:19:45 pirofti Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
@ -329,7 +329,7 @@ struct { \
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#ifndef RB_AUGMENT
|
#ifndef RB_AUGMENT
|
||||||
#define RB_AUGMENT(x)
|
#define RB_AUGMENT(x) do {} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
|
#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
|
||||||
@ -730,9 +730,19 @@ name##_RB_MINMAX(struct name *head, int val) \
|
|||||||
(x) != NULL; \
|
(x) != NULL; \
|
||||||
(x) = name##_RB_NEXT(x))
|
(x) = name##_RB_NEXT(x))
|
||||||
|
|
||||||
|
#define RB_FOREACH_SAFE(x, name, head, y) \
|
||||||
|
for ((x) = RB_MIN(name, head); \
|
||||||
|
((x) != NULL) && ((y) = name##_RB_NEXT(x), 1); \
|
||||||
|
(x) = (y))
|
||||||
|
|
||||||
#define RB_FOREACH_REVERSE(x, name, head) \
|
#define RB_FOREACH_REVERSE(x, name, head) \
|
||||||
for ((x) = RB_MAX(name, head); \
|
for ((x) = RB_MAX(name, head); \
|
||||||
(x) != NULL; \
|
(x) != NULL; \
|
||||||
(x) = name##_RB_PREV(x))
|
(x) = name##_RB_PREV(x))
|
||||||
|
|
||||||
|
#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
|
||||||
|
for ((x) = RB_MAX(name, head); \
|
||||||
|
((x) != NULL) && ((y) = name##_RB_PREV(x), 1); \
|
||||||
|
(x) = (y))
|
||||||
|
|
||||||
#endif /* _SYS_TREE_H_ */
|
#endif /* _SYS_TREE_H_ */
|
||||||
|
@ -2,7 +2,7 @@ dnl ###########
|
|||||||
dnl ## SETUP ###########################################################
|
dnl ## SETUP ###########################################################
|
||||||
dnl ###########
|
dnl ###########
|
||||||
|
|
||||||
AC_INIT([ezstream], [0.5.6],
|
AC_INIT([ezstream], [0.6.0],
|
||||||
[https://trac.xiph.org/newticket?component=ezstream])
|
[https://trac.xiph.org/newticket?component=ezstream])
|
||||||
AC_REVISION([$Id$])
|
AC_REVISION([$Id$])
|
||||||
AC_PREREQ([2.61])
|
AC_PREREQ([2.61])
|
@ -1,6 +1,6 @@
|
|||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2009 Moritz Grimm <mdgrimm@gmx.net>
|
.\" Copyright (c) 2009, 2015 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
.\"
|
.\"
|
||||||
.\" Permission to use, copy, modify, and distribute this software for any
|
.\" Permission to use, copy, modify, and distribute this software for any
|
||||||
.\" purpose with or without fee is hereby granted, provided that the above
|
.\" purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -23,7 +23,7 @@
|
|||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Bk -words
|
.Bk -words
|
||||||
.Op Fl hnqVv
|
.Op Fl hmnqVv
|
||||||
.Op Fl T Ar cfg_template
|
.Op Fl T Ar cfg_template
|
||||||
.Op Ar
|
.Op Ar
|
||||||
.Ek
|
.Ek
|
||||||
@ -62,6 +62,12 @@ binary.
|
|||||||
.It Fl h
|
.It Fl h
|
||||||
Print a summary of available command line parameters with short descriptions
|
Print a summary of available command line parameters with short descriptions
|
||||||
and exit.
|
and exit.
|
||||||
|
.It Fl m
|
||||||
|
.Po
|
||||||
|
Passed to
|
||||||
|
.Nm ezstream .
|
||||||
|
.Pc
|
||||||
|
Disable all metadata updates and keep existing metadata in streams untouched.
|
||||||
.It Fl n
|
.It Fl n
|
||||||
.Po
|
.Po
|
||||||
Passed to
|
Passed to
|
||||||
@ -108,4 +114,4 @@ as well as example playlist and metadata scripts.
|
|||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
script and this manual were written by
|
script and this manual were written by
|
||||||
.An Moritz Grimm Aq mdgrimm@gmx.net .
|
.An Moritz Grimm .
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2007, 2009 Moritz Grimm <mdgrimm@gmx.net>
|
.\" Copyright (c) 2007, 2009, 2015 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
.\"
|
.\"
|
||||||
.\" This program is free software; you can redistribute it and/or modify
|
.\" This program is free software; you can redistribute it and/or modify
|
||||||
.\" it under the terms of the GNU General Public License version 2 as
|
.\" it under the terms of the GNU General Public License version 2 as
|
||||||
@ -24,7 +24,7 @@
|
|||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Bk -words
|
.Bk -words
|
||||||
.Op Fl hnqVv
|
.Op Fl hmnqVv
|
||||||
.Fl c Ar configfile
|
.Fl c Ar configfile
|
||||||
.Ek
|
.Ek
|
||||||
.Nm
|
.Nm
|
||||||
@ -52,6 +52,8 @@ Use the XML configuration in
|
|||||||
.It Fl h
|
.It Fl h
|
||||||
Print a summary of available command line parameters with short descriptions
|
Print a summary of available command line parameters with short descriptions
|
||||||
and exit.
|
and exit.
|
||||||
|
.It Fl m
|
||||||
|
Disable all metadata updates and keep existing metadata in streams untouched.
|
||||||
.It Fl n
|
.It Fl n
|
||||||
Normalize metadata strings by removing excess whitespaces.
|
Normalize metadata strings by removing excess whitespaces.
|
||||||
.It Fl q
|
.It Fl q
|
||||||
@ -275,6 +277,17 @@ See the
|
|||||||
.Sy METADATA
|
.Sy METADATA
|
||||||
section for details on how metadata is handled by
|
section for details on how metadata is handled by
|
||||||
.Nm .
|
.Nm .
|
||||||
|
.It Sy \&<metadata_refreshinterval\ /\&>
|
||||||
|
.Pq Optional.
|
||||||
|
Configures the time
|
||||||
|
.Pq in seconds
|
||||||
|
inbetween additional metadata updates via
|
||||||
|
.Li \&<metadata_progname/\&> .
|
||||||
|
A value of 0
|
||||||
|
.Pq zero
|
||||||
|
triggers updates as fast as possible, while a value of \&-1
|
||||||
|
.Pq minus one
|
||||||
|
or the absence of this configuration element disables this feature.
|
||||||
.It Sy \&<stream_once\ /\&>
|
.It Sy \&<stream_once\ /\&>
|
||||||
Set to
|
Set to
|
||||||
.Sy 1
|
.Sy 1
|
||||||
@ -428,7 +441,7 @@ For example, to decode Ogg Vorbis files using the
|
|||||||
.Cm oggdec
|
.Cm oggdec
|
||||||
utility:
|
utility:
|
||||||
.Pp
|
.Pp
|
||||||
.Dl \&<decode\&>oggdec -R -o - \&"@T@\&"\&</decode\&>
|
.Dl \&<decode\&>oggdec -R -o - @T@\&</decode\&>
|
||||||
.It Sy \&<encode\ /\&>
|
.It Sy \&<encode\ /\&>
|
||||||
Set the command to encode raw data, received from standard input, to the
|
Set the command to encode raw data, received from standard input, to the
|
||||||
specified stream format.
|
specified stream format.
|
||||||
@ -447,7 +460,7 @@ the
|
|||||||
.Cm oggenc
|
.Cm oggenc
|
||||||
utility:
|
utility:
|
||||||
.Pp
|
.Pp
|
||||||
.Dl \&<encode\&>oggenc -r -q 1.5 -t \&"@M@\&" -\&</encode\&>
|
.Dl \&<encode\&>oggenc -r -q 1.5 -t @M@ -\&</encode\&>
|
||||||
.El
|
.El
|
||||||
.Sh SCRIPTING
|
.Sh SCRIPTING
|
||||||
The
|
The
|
||||||
@ -506,9 +519,17 @@ The main tool for handling metadata with
|
|||||||
.Nm
|
.Nm
|
||||||
is placeholders in decoder and encoder commands that are replaced with real
|
is placeholders in decoder and encoder commands that are replaced with real
|
||||||
content during runtime.
|
content during runtime.
|
||||||
The tricky part is that one of the placeholders has to be handled differently,
|
.Pp
|
||||||
depending on where the metadata comes from.
|
.Em Note:
|
||||||
This section will explain each possible scenario.
|
To prevent malicious shell script in metadata
|
||||||
|
.Pq such as artist and title tags
|
||||||
|
from being executed, all metadata content is automatically enclosed in single
|
||||||
|
quotes, with escaped single quote and backslash characters inbetween.
|
||||||
|
To prevent this from causing unwanted side-effects
|
||||||
|
.Pq or introducting security risk ,
|
||||||
|
placeholders
|
||||||
|
.Em must not
|
||||||
|
be quoted any further.
|
||||||
.Ss Metadata Placeholders
|
.Ss Metadata Placeholders
|
||||||
.Bl -tag -width -Ds
|
.Bl -tag -width -Ds
|
||||||
.It Sy @T@
|
.It Sy @T@
|
||||||
@ -633,6 +654,8 @@ as well as example playlist and metadata scripts.
|
|||||||
was written by:
|
was written by:
|
||||||
.Pp
|
.Pp
|
||||||
.An Ed Zaleski Aq oddsock@oddsock.org
|
.An Ed Zaleski Aq oddsock@oddsock.org
|
||||||
.An Moritz Grimm Aq mdgrimm@gmx.net
|
.An Moritz Grimm Aq mgrimm@mrsserver.net
|
||||||
.Pp
|
.Pp
|
||||||
This manual was written by Moritz Grimm.
|
.An -nosplit
|
||||||
|
This manual was written by
|
||||||
|
.An Moritz Grimm .
|
||||||
|
@ -18,6 +18,11 @@
|
|||||||
configuration must be as follows:
|
configuration must be as follows:
|
||||||
-->
|
-->
|
||||||
<filename>%FILENAME%</filename>
|
<filename>%FILENAME%</filename>
|
||||||
|
<!--
|
||||||
|
If the generated playlist should not loop forever, set <stream_once />
|
||||||
|
to 1.
|
||||||
|
-->
|
||||||
|
<stream_once>0</stream_once>
|
||||||
<!--
|
<!--
|
||||||
The usual, remaining configuration statements follow. See the other
|
The usual, remaining configuration statements follow. See the other
|
||||||
examples and the documentation for details.
|
examples and the documentation for details.
|
||||||
@ -35,19 +40,19 @@
|
|||||||
<encdec>
|
<encdec>
|
||||||
<format>FLAC</format>
|
<format>FLAC</format>
|
||||||
<match>.flac</match>
|
<match>.flac</match>
|
||||||
<decode>flac -s -d --force-raw-format --sign=signed --endian=little -o - "@T@"</decode>
|
<decode>flac -s -d --force-raw-format --sign=signed --endian=little -o - @T@</decode>
|
||||||
</encdec>
|
</encdec>
|
||||||
<encdec>
|
<encdec>
|
||||||
<format>MP3</format>
|
<format>MP3</format>
|
||||||
<match>.mp3</match>
|
<match>.mp3</match>
|
||||||
<decode>madplay -b 16 -R 44100 -S -o raw:- "@T@"</decode>
|
<decode>madplay -b 16 -R 44100 -S -o raw:- @T@</decode>
|
||||||
<encode>lame --preset cbr 128 -r -s 44.1 --bitwidth 16 - -</encode>
|
<encode>lame --preset cbr 128 -r -s 44.1 --bitwidth 16 - -</encode>
|
||||||
</encdec>
|
</encdec>
|
||||||
<encdec>
|
<encdec>
|
||||||
<format>VORBIS</format>
|
<format>VORBIS</format>
|
||||||
<match>.ogg</match>
|
<match>.ogg</match>
|
||||||
<decode>oggdec -R -b 16 -e 0 -s 1 -o - "@T@"</decode>
|
<decode>oggdec -R -b 16 -e 0 -s 1 -o - @T@</decode>
|
||||||
<encode>oggenc -r -B 16 -C 2 -R 44100 --raw-endianness 0 -q 1.5 -t "@M@" -</encode>
|
<encode>oggenc -r -B 16 -C 2 -R 44100 --raw-endianness 0 -q 1.5 -t @M@ -</encode>
|
||||||
</encdec>
|
</encdec>
|
||||||
</reencode>
|
</reencode>
|
||||||
</ezstream>
|
</ezstream>
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
<metadata_progname>meta.sh</metadata_progname>
|
<metadata_progname>meta.sh</metadata_progname>
|
||||||
<!-- Set the metadata string according to this format: -->
|
<!-- Set the metadata string according to this format: -->
|
||||||
<metadata_format>@s@: @a@ - @t@</metadata_format>
|
<metadata_format>@s@: @a@ - @t@</metadata_format>
|
||||||
|
<!-- Update metadata from meta.sh at least once every 10 seconds: -->
|
||||||
|
<metadata_refreshinterval>10</metadata_refreshinterval>
|
||||||
<!--
|
<!--
|
||||||
The following settings are used to describe your stream to the server.
|
The following settings are used to describe your stream to the server.
|
||||||
It's up to you to make sure that the bitrate/quality/samplerate/channels
|
It's up to you to make sure that the bitrate/quality/samplerate/channels
|
||||||
|
@ -61,7 +61,7 @@
|
|||||||
<!-- Support for FLAC decoding: -->
|
<!-- Support for FLAC decoding: -->
|
||||||
<format>FLAC</format>
|
<format>FLAC</format>
|
||||||
<match>.flac</match>
|
<match>.flac</match>
|
||||||
<decode>flac -s -d --force-raw-format --sign=signed --endian=little -o - "@T@"</decode>
|
<decode>flac -s -d --force-raw-format --sign=signed --endian=little -o - @T@</decode>
|
||||||
<!-- <encode>Not supported Yet</encode> -->
|
<!-- <encode>Not supported Yet</encode> -->
|
||||||
</encdec>
|
</encdec>
|
||||||
<encdec>
|
<encdec>
|
||||||
@ -71,7 +71,7 @@
|
|||||||
<format>MP3</format>
|
<format>MP3</format>
|
||||||
<match>.mp3</match>
|
<match>.mp3</match>
|
||||||
<!-- Note: madplay uses host byte order for raw samples. -->
|
<!-- Note: madplay uses host byte order for raw samples. -->
|
||||||
<decode>madplay -b 16 -R 44100 -S -o raw:- "@T@"</decode>
|
<decode>madplay -b 16 -R 44100 -S -o raw:- @T@</decode>
|
||||||
<encode>lame --preset cbr 128 -r -s 44.1 --bitwidth 16 - -</encode>
|
<encode>lame --preset cbr 128 -r -s 44.1 --bitwidth 16 - -</encode>
|
||||||
</encdec>
|
</encdec>
|
||||||
<encdec>
|
<encdec>
|
||||||
@ -80,8 +80,8 @@
|
|||||||
-->
|
-->
|
||||||
<format>VORBIS</format>
|
<format>VORBIS</format>
|
||||||
<match>.ogg</match>
|
<match>.ogg</match>
|
||||||
<decode>oggdec -R -b 16 -e 0 -s 1 -o - "@T@"</decode>
|
<decode>oggdec -R -b 16 -e 0 -s 1 -o - @T@</decode>
|
||||||
<encode>oggenc -r -B 16 -C 2 -R 44100 --raw-endianness 0 -q 1.5 -t "@M@" -</encode>
|
<encode>oggenc -r -B 16 -C 2 -R 44100 --raw-endianness 0 -q 1.5 -t @M@ -</encode>
|
||||||
</encdec>
|
</encdec>
|
||||||
</reencode>
|
</reencode>
|
||||||
</ezstream>
|
</ezstream>
|
||||||
|
@ -67,12 +67,12 @@
|
|||||||
-->
|
-->
|
||||||
<format>THEORA</format>
|
<format>THEORA</format>
|
||||||
<match>.avi</match>
|
<match>.avi</match>
|
||||||
<decode>ffmpeg2theora -x 192 -y 128 -a 0 -v 4 --title "@M@" -o - "@T@"</decode>
|
<decode>ffmpeg2theora -x 192 -y 128 -a 0 -v 4 --title @M@ -o - @T@</decode>
|
||||||
</encdec>
|
</encdec>
|
||||||
<encdec>
|
<encdec>
|
||||||
<format>THEORA</format>
|
<format>THEORA</format>
|
||||||
<match>.mpg</match>
|
<match>.mpg</match>
|
||||||
<decode>ffmpeg2theora -x 192 -y 128 -a 0 -v 4 --title "@M@" -o - "@T@"</decode>
|
<decode>ffmpeg2theora -x 192 -y 128 -a 0 -v 4 --title @M@ -o - @T@</decode>
|
||||||
</encdec>
|
</encdec>
|
||||||
</reencode>
|
</reencode>
|
||||||
</ezstream>
|
</ezstream>
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
<!-- Support for FLAC decoding: -->
|
<!-- Support for FLAC decoding: -->
|
||||||
<format>FLAC</format>
|
<format>FLAC</format>
|
||||||
<match>.flac</match>
|
<match>.flac</match>
|
||||||
<decode>flac -s -d --force-raw-format --sign=signed --endian=little -o - "@T@"</decode>
|
<decode>flac -s -d --force-raw-format --sign=signed --endian=little -o - @T@</decode>
|
||||||
<!-- <encode>Not supported Yet</encode> -->
|
<!-- <encode>Not supported Yet</encode> -->
|
||||||
</encdec>
|
</encdec>
|
||||||
<encdec>
|
<encdec>
|
||||||
@ -72,7 +72,7 @@
|
|||||||
<format>MP3</format>
|
<format>MP3</format>
|
||||||
<match>.mp3</match>
|
<match>.mp3</match>
|
||||||
<!-- Note: madplay uses host byte order for raw samples. -->
|
<!-- Note: madplay uses host byte order for raw samples. -->
|
||||||
<decode>madplay -b 16 -R 44100 -S -o raw:- "@T@"</decode>
|
<decode>madplay -b 16 -R 44100 -S -o raw:- @T@</decode>
|
||||||
<encode>lame --preset cbr 128 -r -s 44.1 --bitwidth 16 - -</encode>
|
<encode>lame --preset cbr 128 -r -s 44.1 --bitwidth 16 - -</encode>
|
||||||
</encdec>
|
</encdec>
|
||||||
<encdec>
|
<encdec>
|
||||||
@ -81,8 +81,8 @@
|
|||||||
-->
|
-->
|
||||||
<format>VORBIS</format>
|
<format>VORBIS</format>
|
||||||
<match>.ogg</match>
|
<match>.ogg</match>
|
||||||
<decode>oggdec -R -b 16 -e 0 -s 1 -o - "@T@"</decode>
|
<decode>oggdec -R -b 16 -e 0 -s 1 -o - @T@</decode>
|
||||||
<encode>oggenc -r -B 16 -C 2 -R 44100 --raw-endianness 0 -q 1.5 -t "@M@" -</encode>
|
<encode>oggenc -r -B 16 -C 2 -R 44100 --raw-endianness 0 -q 1.5 -t @M@ -</encode>
|
||||||
</encdec>
|
</encdec>
|
||||||
</reencode>
|
</reencode>
|
||||||
</ezstream>
|
</ezstream>
|
||||||
|
3
mkcl.sh
3
mkcl.sh
@ -1,3 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
svn2cl --stdout -i --reparagraph --break-before-msg -o ChangeLog
|
|
@ -14,9 +14,8 @@ ezstream_SOURCES = \
|
|||||||
xalloc.c
|
xalloc.c
|
||||||
ezstream_LDADD = @LIBOBJS@ @EZ_LIBS@
|
ezstream_LDADD = @LIBOBJS@ @EZ_LIBS@
|
||||||
|
|
||||||
INCLUDES = @COMPAT_INCLUDES@
|
|
||||||
AM_CFLAGS = @EZ_CFLAGS@
|
AM_CFLAGS = @EZ_CFLAGS@
|
||||||
AM_CPPFLAGS = @EZ_CPPFLAGS@
|
AM_CPPFLAGS = @EZ_CPPFLAGS@ @COMPAT_INCLUDES@
|
||||||
AM_LDFLAGS = @EZ_LDFLAGS@
|
AM_LDFLAGS = @EZ_LDFLAGS@
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* ezstream - source client for Icecast with external en-/decoder support
|
* ezstream - source client for Icecast with external en-/decoder support
|
||||||
* Copyright (C) 2003, 2004, 2005, 2006 Ed Zaleski <oddsock@oddsock.org>
|
* Copyright (C) 2003, 2004, 2005, 2006 Ed Zaleski <oddsock@oddsock.org>
|
||||||
* Copyright (C) 2007, 2009 Moritz Grimm <mdgrimm@gmx.net>
|
* Copyright (C) 2007, 2009, 2015 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@ -89,7 +89,8 @@ parseConfig(const char *fileName)
|
|||||||
xmlNodePtr cur;
|
xmlNodePtr cur;
|
||||||
char *ls_xmlContentPtr;
|
char *ls_xmlContentPtr;
|
||||||
int program_set, reconnect_set, shuffle_set,
|
int program_set, reconnect_set, shuffle_set,
|
||||||
streamOnce_set, svrinfopublic_set;
|
streamOnce_set, svrinfopublic_set,
|
||||||
|
refresh_set;
|
||||||
unsigned int config_error;
|
unsigned int config_error;
|
||||||
|
|
||||||
xmlLineNumbersDefault(1);
|
xmlLineNumbersDefault(1);
|
||||||
@ -106,14 +107,17 @@ parseConfig(const char *fileName)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&ezConfig, '\000', sizeof(ezConfig));
|
memset(&ezConfig, 0, sizeof(ezConfig));
|
||||||
|
ezConfig.metadataRefreshInterval = -1;
|
||||||
|
|
||||||
config_error = 0;
|
config_error = 0;
|
||||||
program_set = 0;
|
program_set = 0;
|
||||||
reconnect_set = 0;
|
reconnect_set = 0;
|
||||||
|
refresh_set = 0;
|
||||||
shuffle_set = 0;
|
shuffle_set = 0;
|
||||||
streamOnce_set = 0;
|
streamOnce_set = 0;
|
||||||
svrinfopublic_set = 0;
|
svrinfopublic_set = 0;
|
||||||
|
|
||||||
for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
|
for (cur = cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
|
||||||
if (!xmlStrcmp(cur->name, (const xmlChar *)"url")) {
|
if (!xmlStrcmp(cur->name, (const xmlChar *)"url")) {
|
||||||
if (ezConfig.URL != NULL) {
|
if (ezConfig.URL != NULL) {
|
||||||
@ -230,6 +234,27 @@ parseConfig(const char *fileName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!xmlStrcmp(cur->name, (const xmlChar *)"metadata_refreshinterval")) {
|
||||||
|
if (refresh_set) {
|
||||||
|
printf("%s[%ld]: Error: Cannot have multiple <metadata_refreshinterval> elements\n",
|
||||||
|
fileName, xmlGetLineNo(cur));
|
||||||
|
config_error++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cur->xmlChildrenNode != NULL) {
|
||||||
|
const char *errstr;
|
||||||
|
ls_xmlContentPtr = (char *)xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
|
||||||
|
ezConfig.metadataRefreshInterval = (unsigned int)strtonum(ls_xmlContentPtr, -1LL, (long long)INT_MAX, &errstr);
|
||||||
|
if (errstr) {
|
||||||
|
printf("%s[%ld]: Error: In <metadata_refreshinterval>: '%s' is %s\n",
|
||||||
|
fileName, xmlGetLineNo(cur), ls_xmlContentPtr, errstr);
|
||||||
|
config_error++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
xmlFree(ls_xmlContentPtr);
|
||||||
|
refresh_set = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!xmlStrcmp(cur->name, (const xmlChar *)"playlist_program")) {
|
if (!xmlStrcmp(cur->name, (const xmlChar *)"playlist_program")) {
|
||||||
if (program_set) {
|
if (program_set) {
|
||||||
printf("%s[%ld]: Error: Cannot have multiple <playlist_program> elements\n",
|
printf("%s[%ld]: Error: Cannot have multiple <playlist_program> elements\n",
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* ezstream - source client for Icecast with external en-/decoder support
|
* ezstream - source client for Icecast with external en-/decoder support
|
||||||
* Copyright (C) 2003, 2004, 2005, 2006 Ed Zaleski <oddsock@oddsock.org>
|
* Copyright (C) 2003, 2004, 2005, 2006 Ed Zaleski <oddsock@oddsock.org>
|
||||||
* Copyright (C) 2007 Moritz Grimm <mdgrimm@gmx.net>
|
* Copyright (C) 2007, 2015 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@ -66,6 +66,7 @@ typedef struct tag_EZCONFIG {
|
|||||||
int fileNameIsProgram;
|
int fileNameIsProgram;
|
||||||
int streamOnce;
|
int streamOnce;
|
||||||
unsigned int reconnectAttempts;
|
unsigned int reconnectAttempts;
|
||||||
|
int metadataRefreshInterval;
|
||||||
} EZCONFIG;
|
} EZCONFIG;
|
||||||
|
|
||||||
EZCONFIG * getEZConfig(void);
|
EZCONFIG * getEZConfig(void);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
# Convenience/wrapper script that uses ezstream to stream one or more files
|
# Convenience/wrapper script that uses ezstream to stream one or more files
|
||||||
# given on the command line.
|
# given on the command line.
|
||||||
|
|
||||||
# Copyright (c) 2009 Moritz Grimm <mdgrimm@gmx.net>
|
# Copyright (c) 2009, 2015 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and distribute this software for any
|
# Permission to use, copy, modify, and distribute this software for any
|
||||||
# purpose with or without fee is hereby granted, provided that the above
|
# purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -21,10 +21,10 @@
|
|||||||
_myname="$(basename $0)"
|
_myname="$(basename $0)"
|
||||||
_filename_placeholder="%FILENAME%"
|
_filename_placeholder="%FILENAME%"
|
||||||
|
|
||||||
_opt_string="hnqT:Vv"
|
_opt_string="hmnqT:Vv"
|
||||||
print_usage()
|
print_usage()
|
||||||
{
|
{
|
||||||
echo "usage: ${_myname} [-hnqVv] [-T cfg_template] [file ...]" >&2
|
echo "usage: ${_myname} [-hmnqVv] [-T cfg_template] [file ...]" >&2
|
||||||
}
|
}
|
||||||
|
|
||||||
print_usage_help()
|
print_usage_help()
|
||||||
@ -32,6 +32,7 @@ print_usage_help()
|
|||||||
cat << __EOT >&2
|
cat << __EOT >&2
|
||||||
|
|
||||||
-h print this help and exit
|
-h print this help and exit
|
||||||
|
-m [ezstream] disable metadata updates
|
||||||
-n [ezstream] normalize metadata strings
|
-n [ezstream] normalize metadata strings
|
||||||
-q [ezstream] suppress STDERR output from external en-/decoders
|
-q [ezstream] suppress STDERR output from external en-/decoders
|
||||||
-T template run ezstream using template for configuration
|
-T template run ezstream using template for configuration
|
||||||
@ -45,6 +46,7 @@ See the ezstream-file.sh(1) manual for detailed information.
|
|||||||
__EOT
|
__EOT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_metadisable=""
|
||||||
_normalize=""
|
_normalize=""
|
||||||
_quiet=""
|
_quiet=""
|
||||||
_verbose=""
|
_verbose=""
|
||||||
@ -64,6 +66,8 @@ do
|
|||||||
print_usage_help
|
print_usage_help
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
|
-m)
|
||||||
|
_metadisable="-m"; shift ;;
|
||||||
-n)
|
-n)
|
||||||
_normalize="-n"; shift ;;
|
_normalize="-n"; shift ;;
|
||||||
-q)
|
-q)
|
||||||
@ -140,6 +144,6 @@ else
|
|||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
${EZSTREAM} ${_normalize} ${_quiet} ${_verbose} -c "${_cfg}"
|
${EZSTREAM} ${_metadisable} ${_normalize} ${_quiet} ${_verbose} -c "${_cfg}"
|
||||||
|
|
||||||
exit $?
|
exit $?
|
||||||
|
224
src/ezstream.c
224
src/ezstream.c
@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* ezstream - source client for Icecast with external en-/decoder support
|
* ezstream - source client for Icecast with external en-/decoder support
|
||||||
* Copyright (C) 2003, 2004, 2005, 2006 Ed Zaleski <oddsock@oddsock.org>
|
* Copyright (C) 2003, 2004, 2005, 2006 Ed Zaleski <oddsock@oddsock.org>
|
||||||
* Copyright (C) 2007, 2009 Moritz Grimm <mdgrimm@gmx.net>
|
* Copyright (C) 2007, 2009, 2015 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
@ -50,6 +50,7 @@ char *__progname;
|
|||||||
#endif /* HAVE___PROGNAME */
|
#endif /* HAVE___PROGNAME */
|
||||||
|
|
||||||
int nFlag;
|
int nFlag;
|
||||||
|
int mFlag;
|
||||||
int qFlag;
|
int qFlag;
|
||||||
int sFlag;
|
int sFlag;
|
||||||
int vFlag;
|
int vFlag;
|
||||||
@ -89,8 +90,8 @@ typedef struct tag_ID3Tag {
|
|||||||
} ID3Tag;
|
} ID3Tag;
|
||||||
|
|
||||||
int urlParse(const char *, char **, unsigned short *, char **);
|
int urlParse(const char *, char **, unsigned short *, char **);
|
||||||
void replaceString(const char *, char *, size_t, const char *,
|
char * shellQuote(const char *);
|
||||||
const char *);
|
char * replaceString(const char *, const char *, const char *);
|
||||||
char * buildCommandString(const char *, const char *, metadata_t *);
|
char * buildCommandString(const char *, const char *, metadata_t *);
|
||||||
char * getMetadataString(const char *, metadata_t *);
|
char * getMetadataString(const char *, metadata_t *);
|
||||||
metadata_t * getMetadata(const char *);
|
metadata_t * getMetadata(const char *);
|
||||||
@ -196,25 +197,67 @@ urlParse(const char *url, char **hostname, unsigned short *port,
|
|||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
#define SHELLQUOTE_INLEN_MAX 8191UL
|
||||||
replaceString(const char *source, char *dest, size_t size,
|
|
||||||
const char *from, const char *to)
|
|
||||||
{
|
|
||||||
const char *p1 = source;
|
|
||||||
const char *p2;
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
shellQuote(const char *in)
|
||||||
|
{
|
||||||
|
char *out, *out_p;
|
||||||
|
size_t out_len;
|
||||||
|
const char *in_p;
|
||||||
|
|
||||||
|
out_len = (strlen(in) > SHELLQUOTE_INLEN_MAX)
|
||||||
|
? SHELLQUOTE_INLEN_MAX
|
||||||
|
: strlen(in);
|
||||||
|
out_len = out_len * 2 + 2;
|
||||||
|
out = xcalloc(out_len + 1, sizeof(char));
|
||||||
|
|
||||||
|
out_p = out;
|
||||||
|
in_p = in;
|
||||||
|
|
||||||
|
*out_p++ = '\'';
|
||||||
|
out_len--;
|
||||||
|
while (*in_p && out_len > 2) {
|
||||||
|
switch (*in_p) {
|
||||||
|
case '\'':
|
||||||
|
case '\\':
|
||||||
|
*out_p++ = '\\';
|
||||||
|
out_len--;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
*out_p++ = *in_p++;
|
||||||
|
out_len--;
|
||||||
|
}
|
||||||
|
*out_p++ = '\'';
|
||||||
|
|
||||||
|
return (out);
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
replaceString(const char *source, const char *from, const char *to)
|
||||||
|
{
|
||||||
|
char *to_quoted, *dest;
|
||||||
|
size_t dest_size;
|
||||||
|
const char *p1, *p2;
|
||||||
|
|
||||||
|
to_quoted = shellQuote(to);
|
||||||
|
dest_size = strlen(source) + strlen(to_quoted) + 1;
|
||||||
|
dest = xcalloc(dest_size, sizeof(char));
|
||||||
|
|
||||||
|
p1 = source;
|
||||||
p2 = strstr(p1, from);
|
p2 = strstr(p1, from);
|
||||||
if (p2 != NULL) {
|
if (p2 != NULL) {
|
||||||
if ((unsigned int)(p2 - p1) >= size) {
|
|
||||||
printf("%s: replaceString(): Internal error: p2 - p1 >= size\n",
|
|
||||||
__progname);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
strncat(dest, p1, (size_t)(p2 - p1));
|
strncat(dest, p1, (size_t)(p2 - p1));
|
||||||
strlcat(dest, to, size);
|
strlcat(dest, to_quoted, dest_size);
|
||||||
p1 = p2 + strlen(from);
|
p1 = p2 + strlen(from);
|
||||||
}
|
}
|
||||||
strlcat(dest, p1, size);
|
strlcat(dest, p1, dest_size);
|
||||||
|
|
||||||
|
xfree(to_quoted);
|
||||||
|
|
||||||
|
return (dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
char *
|
||||||
@ -226,9 +269,7 @@ buildCommandString(const char *extension, const char *fileName,
|
|||||||
char *encoder = NULL;
|
char *encoder = NULL;
|
||||||
char *decoder = NULL;
|
char *decoder = NULL;
|
||||||
char *newDecoder = NULL;
|
char *newDecoder = NULL;
|
||||||
size_t newDecoderLen = 0;
|
|
||||||
char *newEncoder = NULL;
|
char *newEncoder = NULL;
|
||||||
size_t newEncoderLen = 0;
|
|
||||||
char *localTitle = UTF8toCHAR(metadata_get_title(mdata),
|
char *localTitle = UTF8toCHAR(metadata_get_title(mdata),
|
||||||
ICONV_REPLACE);
|
ICONV_REPLACE);
|
||||||
char *localArtist = UTF8toCHAR(metadata_get_artist(mdata),
|
char *localArtist = UTF8toCHAR(metadata_get_artist(mdata),
|
||||||
@ -246,23 +287,16 @@ buildCommandString(const char *extension, const char *fileName,
|
|||||||
xfree(decoder);
|
xfree(decoder);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
newDecoderLen = strlen(decoder) + strlen(fileName) + 1;
|
newDecoder = replaceString(decoder, TRACK_PLACEHOLDER, fileName);
|
||||||
newDecoder = xcalloc(newDecoderLen, sizeof(char));
|
|
||||||
replaceString(decoder, newDecoder, newDecoderLen, TRACK_PLACEHOLDER,
|
|
||||||
fileName);
|
|
||||||
if (strstr(decoder, ARTIST_PLACEHOLDER) != NULL) {
|
if (strstr(decoder, ARTIST_PLACEHOLDER) != NULL) {
|
||||||
size_t tmpLen = strlen(newDecoder) + strlen(localArtist) + 1;
|
char *tmpStr = replaceString(newDecoder, ARTIST_PLACEHOLDER,
|
||||||
char *tmpStr = xcalloc(tmpLen, sizeof(char));
|
localArtist);
|
||||||
replaceString(newDecoder, tmpStr, tmpLen, ARTIST_PLACEHOLDER,
|
|
||||||
localArtist);
|
|
||||||
xfree(newDecoder);
|
xfree(newDecoder);
|
||||||
newDecoder = tmpStr;
|
newDecoder = tmpStr;
|
||||||
}
|
}
|
||||||
if (strstr(decoder, TITLE_PLACEHOLDER) != NULL) {
|
if (strstr(decoder, TITLE_PLACEHOLDER) != NULL) {
|
||||||
size_t tmpLen = strlen(newDecoder) + strlen(localTitle) + 1;
|
char *tmpStr = replaceString(newDecoder, TITLE_PLACEHOLDER,
|
||||||
char *tmpStr = xcalloc(tmpLen, sizeof(char));
|
localTitle);
|
||||||
replaceString(newDecoder, tmpStr, tmpLen, TITLE_PLACEHOLDER,
|
|
||||||
localTitle);
|
|
||||||
xfree(newDecoder);
|
xfree(newDecoder);
|
||||||
newDecoder = tmpStr;
|
newDecoder = tmpStr;
|
||||||
}
|
}
|
||||||
@ -279,27 +313,20 @@ buildCommandString(const char *extension, const char *fileName,
|
|||||||
if (strstr(decoder, METADATA_PLACEHOLDER) != NULL) {
|
if (strstr(decoder, METADATA_PLACEHOLDER) != NULL) {
|
||||||
if (metadataFromProgram && pezConfig->metadataFormat != NULL) {
|
if (metadataFromProgram && pezConfig->metadataFormat != NULL) {
|
||||||
char *mdataString = getMetadataString(pezConfig->metadataFormat, mdata);
|
char *mdataString = getMetadataString(pezConfig->metadataFormat, mdata);
|
||||||
size_t tmpLen = strlen(newDecoder) + strlen(mdataString) + 1;
|
char *tmpStr = replaceString(newDecoder,
|
||||||
char *tmpStr = xcalloc(tmpLen, sizeof(char));
|
METADATA_PLACEHOLDER, mdataString);
|
||||||
replaceString(newDecoder, tmpStr, tmpLen,
|
|
||||||
METADATA_PLACEHOLDER, mdataString);
|
|
||||||
xfree(newDecoder);
|
xfree(newDecoder);
|
||||||
xfree(mdataString);
|
xfree(mdataString);
|
||||||
newDecoder = tmpStr;
|
newDecoder = tmpStr;
|
||||||
} else {
|
} else {
|
||||||
if (!metadataFromProgram && strstr(decoder, TITLE_PLACEHOLDER) != NULL) {
|
if (!metadataFromProgram && strstr(decoder, TITLE_PLACEHOLDER) != NULL) {
|
||||||
size_t tmpLen = strlen(newDecoder) + 1;
|
char *tmpStr = replaceString(newDecoder,
|
||||||
char *tmpStr = xcalloc(tmpLen, sizeof(char));
|
METADATA_PLACEHOLDER, "");
|
||||||
replaceString(newDecoder, tmpStr, tmpLen,
|
|
||||||
METADATA_PLACEHOLDER, "");
|
|
||||||
xfree(newDecoder);
|
xfree(newDecoder);
|
||||||
newDecoder = tmpStr;
|
newDecoder = tmpStr;
|
||||||
} else {
|
} else {
|
||||||
size_t tmpLen = strlen(newDecoder) + strlen(localMetaString) + 1;
|
char *tmpStr = replaceString(newDecoder,
|
||||||
char *tmpStr = xcalloc(tmpLen, sizeof(char));
|
METADATA_PLACEHOLDER, localMetaString);
|
||||||
replaceString(newDecoder, tmpStr, tmpLen,
|
|
||||||
METADATA_PLACEHOLDER,
|
|
||||||
localMetaString);
|
|
||||||
xfree(newDecoder);
|
xfree(newDecoder);
|
||||||
newDecoder = tmpStr;
|
newDecoder = tmpStr;
|
||||||
}
|
}
|
||||||
@ -325,42 +352,30 @@ buildCommandString(const char *extension, const char *fileName,
|
|||||||
return (commandString);
|
return (commandString);
|
||||||
}
|
}
|
||||||
|
|
||||||
newEncoderLen = strlen(encoder) + strlen(localArtist) + 1;
|
newEncoder = replaceString(encoder, ARTIST_PLACEHOLDER, localArtist);
|
||||||
newEncoder = xcalloc(newEncoderLen, sizeof(char));
|
|
||||||
replaceString(encoder, newEncoder, newEncoderLen, ARTIST_PLACEHOLDER,
|
|
||||||
localArtist);
|
|
||||||
if (strstr(encoder, TITLE_PLACEHOLDER) != NULL) {
|
if (strstr(encoder, TITLE_PLACEHOLDER) != NULL) {
|
||||||
size_t tmpLen = strlen(newEncoder) + strlen(localTitle) + 1;
|
char *tmpStr = replaceString(newEncoder, TITLE_PLACEHOLDER,
|
||||||
char *tmpStr = xcalloc(tmpLen, sizeof(char));
|
localTitle);
|
||||||
replaceString(newEncoder, tmpStr, tmpLen, TITLE_PLACEHOLDER,
|
|
||||||
localTitle);
|
|
||||||
xfree(newEncoder);
|
xfree(newEncoder);
|
||||||
newEncoder = tmpStr;
|
newEncoder = tmpStr;
|
||||||
}
|
}
|
||||||
if (strstr(encoder, METADATA_PLACEHOLDER) != NULL) {
|
if (strstr(encoder, METADATA_PLACEHOLDER) != NULL) {
|
||||||
if (metadataFromProgram && pezConfig->metadataFormat != NULL) {
|
if (metadataFromProgram && pezConfig->metadataFormat != NULL) {
|
||||||
char *mdataString = getMetadataString(pezConfig->metadataFormat, mdata);
|
char *mdataString = getMetadataString(pezConfig->metadataFormat, mdata);
|
||||||
size_t tmpLen = strlen(newEncoder) + strlen(mdataString) + 1;
|
char *tmpStr = replaceString(newEncoder,
|
||||||
char *tmpStr = xcalloc(tmpLen, sizeof(char));
|
METADATA_PLACEHOLDER, mdataString);
|
||||||
replaceString(newEncoder, tmpStr, tmpLen,
|
|
||||||
METADATA_PLACEHOLDER, mdataString);
|
|
||||||
xfree(newEncoder);
|
xfree(newEncoder);
|
||||||
xfree(mdataString);
|
xfree(mdataString);
|
||||||
newEncoder = tmpStr;
|
newEncoder = tmpStr;
|
||||||
} else {
|
} else {
|
||||||
if (!metadataFromProgram && strstr(encoder, TITLE_PLACEHOLDER) != NULL) {
|
if (!metadataFromProgram && strstr(encoder, TITLE_PLACEHOLDER) != NULL) {
|
||||||
size_t tmpLen = strlen(newEncoder) + 1;
|
char *tmpStr = replaceString(newEncoder,
|
||||||
char *tmpStr = xcalloc(tmpLen, sizeof(char));
|
METADATA_PLACEHOLDER, "");
|
||||||
replaceString(newEncoder, tmpStr, tmpLen,
|
|
||||||
METADATA_PLACEHOLDER, "");
|
|
||||||
xfree(newEncoder);
|
xfree(newEncoder);
|
||||||
newEncoder = tmpStr;
|
newEncoder = tmpStr;
|
||||||
} else {
|
} else {
|
||||||
size_t tmpLen = strlen(newEncoder) + strlen(localMetaString) + 1;
|
char *tmpStr = replaceString(newEncoder,
|
||||||
char *tmpStr = xcalloc(tmpLen, sizeof(char));
|
METADATA_PLACEHOLDER, localMetaString);
|
||||||
replaceString(newEncoder, tmpStr, tmpLen,
|
|
||||||
METADATA_PLACEHOLDER,
|
|
||||||
localMetaString);
|
|
||||||
xfree(newEncoder);
|
xfree(newEncoder);
|
||||||
newEncoder = tmpStr;
|
newEncoder = tmpStr;
|
||||||
}
|
}
|
||||||
@ -388,7 +403,6 @@ char *
|
|||||||
getMetadataString(const char *format, metadata_t *mdata)
|
getMetadataString(const char *format, metadata_t *mdata)
|
||||||
{
|
{
|
||||||
char *tmp, *str;
|
char *tmp, *str;
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (mdata == NULL) {
|
if (mdata == NULL) {
|
||||||
printf("%s: getMetadataString(): Internal error: NULL metadata_t\n",
|
printf("%s: getMetadataString(): Internal error: NULL metadata_t\n",
|
||||||
@ -402,34 +416,26 @@ getMetadataString(const char *format, metadata_t *mdata)
|
|||||||
str = xstrdup(format);
|
str = xstrdup(format);
|
||||||
|
|
||||||
if (strstr(format, ARTIST_PLACEHOLDER) != NULL) {
|
if (strstr(format, ARTIST_PLACEHOLDER) != NULL) {
|
||||||
len = strlen(str) + strlen(metadata_get_artist(mdata)) + 1;
|
tmp = replaceString(str, ARTIST_PLACEHOLDER,
|
||||||
tmp = xcalloc(len, sizeof(char));
|
metadata_get_artist(mdata));
|
||||||
replaceString(str, tmp, len, ARTIST_PLACEHOLDER,
|
|
||||||
metadata_get_artist(mdata));
|
|
||||||
xfree(str);
|
xfree(str);
|
||||||
str = tmp;
|
str = tmp;
|
||||||
}
|
}
|
||||||
if (strstr(format, TITLE_PLACEHOLDER) != NULL) {
|
if (strstr(format, TITLE_PLACEHOLDER) != NULL) {
|
||||||
len = strlen(str) + strlen(metadata_get_title(mdata)) + 1;
|
tmp = replaceString(str, TITLE_PLACEHOLDER,
|
||||||
tmp = xcalloc(len, sizeof(char));
|
metadata_get_title(mdata));
|
||||||
replaceString(str, tmp, len, TITLE_PLACEHOLDER,
|
|
||||||
metadata_get_title(mdata));
|
|
||||||
xfree(str);
|
xfree(str);
|
||||||
str = tmp;
|
str = tmp;
|
||||||
}
|
}
|
||||||
if (strstr(format, STRING_PLACEHOLDER) != NULL) {
|
if (strstr(format, STRING_PLACEHOLDER) != NULL) {
|
||||||
len = strlen(str) + strlen(metadata_get_string(mdata)) + 1;
|
tmp = replaceString(str, STRING_PLACEHOLDER,
|
||||||
tmp = xcalloc(len, sizeof(char));
|
metadata_get_string(mdata));
|
||||||
replaceString(str, tmp, len, STRING_PLACEHOLDER,
|
|
||||||
metadata_get_string(mdata));
|
|
||||||
xfree(str);
|
xfree(str);
|
||||||
str = tmp;
|
str = tmp;
|
||||||
}
|
}
|
||||||
if (strstr(format, TRACK_PLACEHOLDER) != NULL) {
|
if (strstr(format, TRACK_PLACEHOLDER) != NULL) {
|
||||||
len = strlen(str) + strlen(metadata_get_filename(mdata)) + 1;
|
tmp = replaceString(str, TRACK_PLACEHOLDER,
|
||||||
tmp = xcalloc(len, sizeof(char));
|
metadata_get_filename(mdata));
|
||||||
replaceString(str, tmp, len, TRACK_PLACEHOLDER,
|
|
||||||
metadata_get_filename(mdata));
|
|
||||||
xfree(str);
|
xfree(str);
|
||||||
str = tmp;
|
str = tmp;
|
||||||
}
|
}
|
||||||
@ -477,6 +483,9 @@ setMetadata(shout_t *shout, metadata_t *mdata, char **mdata_copy)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mFlag)
|
||||||
|
return (SHOUTERR_SUCCESS);
|
||||||
|
|
||||||
if (mdata == NULL)
|
if (mdata == NULL)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -750,6 +759,7 @@ sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
|
|||||||
int ret;
|
int ret;
|
||||||
double kbps = -1.0;
|
double kbps = -1.0;
|
||||||
struct timeval timeStamp, *startTime = tv;
|
struct timeval timeStamp, *startTime = tv;
|
||||||
|
struct timeval callTime, currentTime;
|
||||||
|
|
||||||
if (startTime == NULL) {
|
if (startTime == NULL) {
|
||||||
printf("%s: sendStream(): Internal error: startTime is NULL\n",
|
printf("%s: sendStream(): Internal error: startTime is NULL\n",
|
||||||
@ -757,6 +767,8 @@ sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ez_gettimeofday((void *)&callTime);
|
||||||
|
|
||||||
timeStamp.tv_sec = startTime->tv_sec;
|
timeStamp.tv_sec = startTime->tv_sec;
|
||||||
timeStamp.tv_usec = startTime->tv_usec;
|
timeStamp.tv_usec = startTime->tv_usec;
|
||||||
|
|
||||||
@ -795,7 +807,15 @@ sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
|
|||||||
ret = STREAM_SKIP;
|
ret = STREAM_SKIP;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (queryMetadata) {
|
|
||||||
|
ez_gettimeofday((void *)¤tTime);
|
||||||
|
|
||||||
|
if (queryMetadata ||
|
||||||
|
(pezConfig->metadataRefreshInterval != -1
|
||||||
|
&& (currentTime.tv_sec - callTime.tv_sec
|
||||||
|
>= pezConfig->metadataRefreshInterval)
|
||||||
|
)
|
||||||
|
) {
|
||||||
queryMetadata = 0;
|
queryMetadata = 0;
|
||||||
if (metadataFromProgram) {
|
if (metadataFromProgram) {
|
||||||
ret = STREAM_UPDMDATA;
|
ret = STREAM_UPDMDATA;
|
||||||
@ -805,8 +825,7 @@ sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
|
|||||||
|
|
||||||
total += bytes_read;
|
total += bytes_read;
|
||||||
if (qFlag && vFlag) {
|
if (qFlag && vFlag) {
|
||||||
struct timeval tval;
|
double oldTime, newTime;
|
||||||
double oldTime, newTime;
|
|
||||||
|
|
||||||
if (!isStdin && playlistMode) {
|
if (!isStdin && playlistMode) {
|
||||||
if (pezConfig->fileNameIsProgram) {
|
if (pezConfig->fileNameIsProgram) {
|
||||||
@ -822,20 +841,22 @@ sendStream(shout_t *shout, FILE *filepstream, const char *fileName,
|
|||||||
|
|
||||||
oldTime = (double)timeStamp.tv_sec
|
oldTime = (double)timeStamp.tv_sec
|
||||||
+ (double)timeStamp.tv_usec / 1000000.0;
|
+ (double)timeStamp.tv_usec / 1000000.0;
|
||||||
ez_gettimeofday((void *)&tval);
|
newTime = (double)currentTime.tv_sec
|
||||||
newTime = (double)tval.tv_sec
|
+ (double)currentTime.tv_usec / 1000000.0;
|
||||||
+ (double)tval.tv_usec / 1000000.0;
|
|
||||||
if (songLenStr == NULL)
|
if (songLenStr == NULL)
|
||||||
printf(" [ %s]",
|
printf(" [ %s]",
|
||||||
getTimeString(tval.tv_sec - startTime->tv_sec));
|
getTimeString(currentTime.tv_sec -
|
||||||
|
startTime->tv_sec));
|
||||||
else
|
else
|
||||||
printf(" [ %s/%s]",
|
printf(" [ %s/%s]",
|
||||||
getTimeString(tval.tv_sec - startTime->tv_sec),
|
getTimeString(currentTime.tv_sec -
|
||||||
|
startTime->tv_sec),
|
||||||
songLenStr);
|
songLenStr);
|
||||||
if (newTime - oldTime >= 1.0) {
|
if (newTime - oldTime >= 1.0) {
|
||||||
kbps = (((double)(total - oldTotal) / (newTime - oldTime)) * 8.0) / 1000.0;
|
kbps = (((double)(total - oldTotal)
|
||||||
timeStamp.tv_sec = tval.tv_sec;
|
/ (newTime - oldTime)) * 8.0) / 1000.0;
|
||||||
timeStamp.tv_usec = tval.tv_usec;
|
timeStamp.tv_sec = currentTime.tv_sec;
|
||||||
|
timeStamp.tv_usec = currentTime.tv_usec;
|
||||||
oldTotal = total;
|
oldTotal = total;
|
||||||
}
|
}
|
||||||
if (kbps < 0)
|
if (kbps < 0)
|
||||||
@ -936,6 +957,8 @@ streamFile(shout_t *shout, const char *fileName)
|
|||||||
}
|
}
|
||||||
if (ret == STREAM_UPDMDATA || queryMetadata) {
|
if (ret == STREAM_UPDMDATA || queryMetadata) {
|
||||||
queryMetadata = 0;
|
queryMetadata = 0;
|
||||||
|
if (mFlag)
|
||||||
|
continue;
|
||||||
if (metadataFromProgram) {
|
if (metadataFromProgram) {
|
||||||
char *mdataStr = NULL;
|
char *mdataStr = NULL;
|
||||||
metadata_t *prog_mdata;
|
metadata_t *prog_mdata;
|
||||||
@ -954,8 +977,9 @@ streamFile(shout_t *shout, const char *fileName)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
metadata_free(&prog_mdata);
|
metadata_free(&prog_mdata);
|
||||||
printf("%s: New metadata: ``%s''\n",
|
if (vFlag > 1)
|
||||||
__progname, mdataStr);
|
printf("%s: New metadata: ``%s''\n",
|
||||||
|
__progname, mdataStr);
|
||||||
xfree(mdataStr);
|
xfree(mdataStr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -969,7 +993,7 @@ streamFile(shout_t *shout, const char *fileName)
|
|||||||
|
|
||||||
if (popenFlag)
|
if (popenFlag)
|
||||||
pclose(filepstream);
|
pclose(filepstream);
|
||||||
else
|
else if (!isStdin)
|
||||||
fclose(filepstream);
|
fclose(filepstream);
|
||||||
|
|
||||||
if (songLenStr != NULL)
|
if (songLenStr != NULL)
|
||||||
@ -1073,7 +1097,7 @@ ez_shutdown(int exitval)
|
|||||||
void
|
void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
printf("usage: %s [-hnqVv] -c configfile\n", __progname);
|
printf("usage: %s [-hmnqVv] -c configfile\n", __progname);
|
||||||
printf(" %s -s [playlist]\n", __progname);
|
printf(" %s -s [playlist]\n", __progname);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1083,6 +1107,7 @@ usageHelp(void)
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
printf(" -c configfile use XML configuration in configfile (mandatory)\n");
|
printf(" -c configfile use XML configuration in configfile (mandatory)\n");
|
||||||
printf(" -h display this additional help and exit\n");
|
printf(" -h display this additional help and exit\n");
|
||||||
|
printf(" -m disable metadata updates\n");
|
||||||
printf(" -n normalize metadata strings\n");
|
printf(" -n normalize metadata strings\n");
|
||||||
printf(" -q suppress STDERR output from external en-/decoders\n");
|
printf(" -q suppress STDERR output from external en-/decoders\n");
|
||||||
printf(" -s [playlist] read lines from playlist (or STDIN), shuffle and print them to\n");
|
printf(" -s [playlist] read lines from playlist (or STDIN), shuffle and print them to\n");
|
||||||
@ -1120,11 +1145,12 @@ main(int argc, char *argv[])
|
|||||||
__progname = getProgname(argv[0]);
|
__progname = getProgname(argv[0]);
|
||||||
pezConfig = getEZConfig();
|
pezConfig = getEZConfig();
|
||||||
|
|
||||||
|
mFlag = 0;
|
||||||
nFlag = 0;
|
nFlag = 0;
|
||||||
qFlag = 0;
|
qFlag = 0;
|
||||||
vFlag = 0;
|
vFlag = 0;
|
||||||
|
|
||||||
while ((c = local_getopt(argc, argv, "c:hnqsVv")) != -1) {
|
while ((c = local_getopt(argc, argv, "c:hmnqsVv")) != -1) {
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'c':
|
case 'c':
|
||||||
if (configFile != NULL) {
|
if (configFile != NULL) {
|
||||||
@ -1138,6 +1164,9 @@ main(int argc, char *argv[])
|
|||||||
usage();
|
usage();
|
||||||
usageHelp();
|
usageHelp();
|
||||||
return (ez_shutdown(0));
|
return (ez_shutdown(0));
|
||||||
|
case 'm':
|
||||||
|
mFlag = 1;
|
||||||
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
nFlag = 1;
|
nFlag = 1;
|
||||||
break;
|
break;
|
||||||
@ -1316,7 +1345,6 @@ main(int argc, char *argv[])
|
|||||||
printf("%s: Using program '%s' to get filenames for streaming\n",
|
printf("%s: Using program '%s' to get filenames for streaming\n",
|
||||||
__progname, pezConfig->fileName);
|
__progname, pezConfig->fileName);
|
||||||
|
|
||||||
ret = 1;
|
|
||||||
do {
|
do {
|
||||||
if (playlistMode) {
|
if (playlistMode) {
|
||||||
ret = streamPlaylist(shout,
|
ret = streamPlaylist(shout,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007, 2009 Moritz Grimm <mdgrimm@gmx.net>
|
* Copyright (c) 2007, 2009 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
@ -27,9 +27,8 @@
|
|||||||
#endif /* HAVE_SYS_TYPES_H */
|
#endif /* HAVE_SYS_TYPES_H */
|
||||||
#ifdef HAVE_SYS_TIME_H
|
#ifdef HAVE_SYS_TIME_H
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
#else /* HAVE_SYS_TIME_H */
|
|
||||||
# include <time.h>
|
|
||||||
#endif /* HAVE_SYS_TIME_H */
|
#endif /* HAVE_SYS_TIME_H */
|
||||||
|
#include <time.h>
|
||||||
#ifdef HAVE_SYS_STAT_H
|
#ifdef HAVE_SYS_STAT_H
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
#endif /* HAVE_SYS_STAT_H */
|
#endif /* HAVE_SYS_STAT_H */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007, 2009 Moritz Grimm <mdgrimm@gmx.net>
|
* Copyright (c) 2007, 2009 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Moritz Grimm <mdgrimm@gmx.net>
|
* Copyright (c) 2007 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007, 2009 Moritz Grimm <mdgrimm@gmx.net>
|
* Copyright (c) 2007, 2009 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007 Moritz Grimm <mdgrimm@gmx.net>
|
* Copyright (c) 2007 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* ezstream - source client for Icecast with external en-/decoder support
|
* ezstream - source client for Icecast with external en-/decoder support
|
||||||
* Copyright (C) 2003, 2004, 2005, 2006 Ed Zaleski <oddsock@oddsock.org>
|
* Copyright (C) 2003, 2004, 2005, 2006 Ed Zaleski <oddsock@oddsock.org>
|
||||||
* Copyright (C) 2007, 2009 Moritz Grimm <mdgrimm@gmx.net>
|
* Copyright (C) 2007, 2009 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
/*
|
/*
|
||||||
* ezstream - source client for Icecast with external en-/decoder support
|
* ezstream - source client for Icecast with external en-/decoder support
|
||||||
* Copyright (C) 2003, 2004, 2005, 2006 Ed Zaleski <oddsock@oddsock.org>
|
* Copyright (C) 2003, 2004, 2005, 2006 Ed Zaleski <oddsock@oddsock.org>
|
||||||
* Copyright (C) 2007 Moritz Grimm <mdgrimm@gmx.net>
|
* Copyright (C) 2007 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2007 Moritz Grimm <mdgrimm@gmx.net>
|
* Copyright (C) 2007 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* and ensures that out-of-memory issues always cause the
|
* and ensures that out-of-memory issues always cause the
|
||||||
* application to exit.
|
* application to exit.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007 Moritz Grimm <mdgrimm@gmx.net>
|
* Copyright (C) 2007 Moritz Grimm <mgrimm@mrsserver.net>
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, and distribute this software for any
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -67,13 +67,13 @@ A few useful features are missing in the Windows version of ezstream:
|
|||||||
|
|
||||||
Ezstream uses:
|
Ezstream uses:
|
||||||
* zlib (http://www.zlib.net/, BSD-like license)
|
* zlib (http://www.zlib.net/, BSD-like license)
|
||||||
* libiconv (http://www.gnu.org/software/libiconv/, LGPL)
|
* libiconv (https://www.gnu.org/software/libiconv/, LGPL)
|
||||||
* libxml2 (http://xmlsoft.org/, BSD-like license)
|
* libxml2 (http://xmlsoft.org/, BSD-like license)
|
||||||
* libogg, libvorbis, libvorbisfile (http://www.vorbis.com/, BSD-like license)
|
* libogg, libvorbis, libvorbisfile (http://www.vorbis.com/, BSD-like license)
|
||||||
* libFLAC (http://flac.sourceforge.net/, BSD-like license)
|
* libFLAC (https://xiph.org/flac/, BSD-like license)
|
||||||
* libtheora (http://www.theora.org/, BSD-like license)
|
* libtheora (http://www.theora.org/, BSD-like license)
|
||||||
* libshout (http://www.icecast.org, LGPL)
|
* libshout (http://www.icecast.org, LGPL)
|
||||||
* TagLib (http://ktown.kde.org/~wheeler/taglib.html, LGPL)
|
* TagLib (https://taglib.github.io/, LGPL)
|
||||||
|
|
||||||
These libraries are statically linked into the ezstream.exe file.
|
These libraries are statically linked into the ezstream.exe file.
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#ifndef __WIN32_CONFIG_H__
|
#ifndef __WIN32_CONFIG_H__
|
||||||
#define __WIN32_CONFIG_H__
|
#define __WIN32_CONFIG_H__
|
||||||
|
|
||||||
#define PACKAGE_STRING "ezstream 0.5.6"
|
#define PACKAGE_STRING "ezstream 0.6.0"
|
||||||
|
|
||||||
#define HAVE_SYS_TYPES_H 1
|
#define HAVE_SYS_TYPES_H 1
|
||||||
#define HAVE_SYS_STAT_H 1
|
#define HAVE_SYS_STAT_H 1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user