Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libshout for openSUSE:Factory 
checked in at 2021-02-11 12:46:40
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libshout (Old)
 and      /work/SRC/openSUSE:Factory/.libshout.new.28504 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libshout"

Thu Feb 11 12:46:40 2021 rev:26 rq:869214 version:2.4.5

Changes:
--------
--- /work/SRC/openSUSE:Factory/libshout/libshout.changes        2020-10-12 
13:46:25.877899789 +0200
+++ /work/SRC/openSUSE:Factory/.libshout.new.28504/libshout.changes     
2021-02-11 12:47:44.157519326 +0100
@@ -1,0 +2,13 @@
+Sun Jan 17 23:31:06 UTC 2021 - Dirk M??ller <[email protected]>
+
+- update to 2.4.5:
+  * Improved shout.h for reading, and understanding.
+  * Marked dumpfile support as obsolete (as SHOUT_PROTOCOL_XAUDIOCAST already 
is).
+  * Added Support for setting the content language.
+  * Avoid the use of obsolete functions (#2317).
+  * Several small fixes for non-blocking mode (#2321, #2315).
+  * Corrected detection of libogg (mostly for windows targets).
+  * Now accept TLS mode "auto" when build without TLS support.
+  * Added new tool shout(1).
+
+-------------------------------------------------------------------

Old:
----
  libshout-2.4.4.tar.gz

New:
----
  libshout-2.4.5.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libshout.spec ++++++
--- /var/tmp/diff_new_pack.1as3rr/_old  2021-02-11 12:47:44.753520194 +0100
+++ /var/tmp/diff_new_pack.1as3rr/_new  2021-02-11 12:47:44.753520194 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package libshout
 #
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2021 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           libshout
-Version:        2.4.4
+Version:        2.4.5
 Release:        0
 Summary:        Library for communcating with Icecast servers
 License:        LGPL-2.1-or-later
@@ -80,8 +80,10 @@
 %files devel
 %doc README doc/*.xml examples/*.c
 %license COPYING
+%_bindir/shout
 %_libdir/*.so
 %_includedir/shout
+%_mandir/man1/shout.1%{?ext_man}
 %_datadir/aclocal/*.m4
 %_libdir/pkgconfig/*.pc
 

++++++ libshout-2.4.4.tar.gz -> libshout-2.4.5.tar.gz ++++++
++++ 2511 lines of diff (skipped)
++++    retrying with extended exclude list
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/libshout-2.4.4/Makefile.am new/libshout-2.4.5/Makefile.am
--- old/libshout-2.4.4/Makefile.am      2019-05-20 20:33:51.000000000 +0200
+++ new/libshout-2.4.5/Makefile.am      2020-12-16 13:50:13.000000000 +0100
@@ -3,7 +3,7 @@
 AUTOMAKE_OPTIONS = 1.6 foreign
 ACLOCAL_AMFLAGS = -I m4
 
-SUBDIRS = include src doc win32
+SUBDIRS = include src doc win32 tools
 if HAVE_EXAMPLES
 SUBDIRS += examples
 endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/libshout-2.4.4/NEWS new/libshout-2.4.5/NEWS
--- old/libshout-2.4.4/NEWS     2020-10-02 00:34:44.000000000 +0200
+++ new/libshout-2.4.5/NEWS     2020-12-19 14:50:01.000000000 +0100
@@ -1,3 +1,14 @@
+libshout 2.4.5 (20201219)
+
+* Improved shout.h for reading, and understanding.
+* Marked dumpfile support as obsolete (as SHOUT_PROTOCOL_XAUDIOCAST already 
is).
+* Added Support for setting the content language.
+* Avoid the use of obsolete functions (#2317).
+* Several small fixes for non-blocking mode (#2321, #2315).
+* Corrected detection of libogg (mostly for windows targets).
+* Now accept TLS mode "auto" when build without TLS support.
+* Added new tool shout(1).
+
 libshout 2.4.4 (20201001)
 
 * Fixed handling of blocking/non-blocking mode
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/libshout-2.4.4/README new/libshout-2.4.5/README
--- old/libshout-2.4.4/README   2016-09-04 16:23:16.000000000 +0200
+++ new/libshout-2.4.5/README   2020-12-19 14:49:22.000000000 +0100
@@ -2,11 +2,11 @@
 --------
 
 Libshout is a library for communicating with and sending data to an
-icecast server.  It handles the socket connection, the timing of the
-data, and prevents bad data from getting to the icecast server.
+Icecast server.  It handles the socket connection, the timing of the
+data, and prevents bad data from getting to the Icecast server.
 
 With just a few lines of code, a programmer can easily turn any application
-into a streaming source for an icecast server.  Libshout also allows 
+into a streaming source for an Icecast server.  Libshout also allows
 developers who want a specific feature set (database access, request taking)
 to concentrate on that feature set, instead of worrying about how server
 communication works.
@@ -17,4 +17,4 @@
 Libshout is licensed under the LGPL.  Please see the COPYING file for details.
 
 If you have any questions or comments, please visit us at 
-http://www.icecast.org or email us at [email protected].
+https://www.icecast.org/ or email us at [email protected].
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/libshout-2.4.4/configure.ac new/libshout-2.4.5/configure.ac
--- old/libshout-2.4.4/configure.ac     2020-10-02 00:06:56.000000000 +0200
+++ new/libshout-2.4.5/configure.ac     2020-12-19 13:33:42.000000000 +0100
@@ -3,7 +3,7 @@
 
 m4_define(libshout_major, 2)
 m4_define(libshout_minor, 4)
-m4_define(libshout_micro, 4)
+m4_define(libshout_micro, 5)
 m4_define(libshout_version, libshout_major.libshout_minor.libshout_micro)
 
 AC_INIT([libshout], libshout_version, [[email protected]])
@@ -124,7 +124,14 @@
   AC_DEFINE([NO_THREAD], 1, [Define if you don't want to use the thread 
library])
 fi
 
-SHOUT_REQUIRES="ogg"
+PKG_CHECK_MODULES([OGG], [ogg], [
+    HAVE_OGG="yes"
+    SHOUT_REQUIRES="$SHOUT_REQUIRES, ogg"
+  ], [
+    XIPH_PATH_OGG(, [AC_MSG_ERROR([required Ogg library not found])])
+  ])
+OGG_LIBS="$OGG_LDFLAGS $OGG_LIBS"
+XIPH_CFLAGS="$XIPH_CFLAGS $OGG_CFLAGS"
 
 PKG_CHECK_MODULES(VORBIS, vorbis, [
     HAVE_VORBIS="yes"
@@ -241,4 +248,4 @@
 AC_OUTPUT([Makefile include/Makefile include/shout/Makefile
   include/shout/shout.h src/Makefile src/common/net/Makefile 
src/common/timing/Makefile
   src/common/thread/Makefile src/common/avl/Makefile src/common/httpp/Makefile 
doc/Makefile
-  examples/Makefile win32/Makefile shout.pc])
+  tools/Makefile examples/Makefile win32/Makefile shout.pc])
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/libshout-2.4.4/examples/nonblocking.c 
new/libshout-2.4.5/examples/nonblocking.c
--- old/libshout-2.4.4/examples/nonblocking.c   2019-08-24 13:52:16.000000000 
+0200
+++ new/libshout-2.4.5/examples/nonblocking.c   2020-12-15 22:38:46.000000000 
+0100
@@ -8,6 +8,10 @@
 #include <string.h>
 #include <unistd.h>
 
+#if !(defined(WIN32) && !defined(__MINGW64__) && !defined(__MINGW32__))
+#include <time.h>
+#endif
+
 #include <shout/shout.h>
 
 int main()
@@ -70,8 +74,13 @@
     if (ret == SHOUTERR_BUSY)
         printf("Connection pending...\n");
 
-    while (ret == SHOUTERR_BUSY) {
+    while (ret == SHOUTERR_BUSY || ret == SHOUTERR_RETRY) {
+#if !(defined(WIN32) && !defined(__MINGW64__) && !defined(__MINGW32__))
+        static const struct timespec ts = {.tv_sec = 0, .tv_nsec = 10 * 1000 * 
1000};
+        nanosleep(&ts, NULL);
+#else
         usleep(10000);
+#endif
         ret = shout_get_connected(shout);
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/libshout-2.4.4/include/shout/shout.h.in 
new/libshout-2.4.5/include/shout/shout.h.in
--- old/libshout-2.4.4/include/shout/shout.h.in 2019-08-24 13:52:16.000000000 
+0200
+++ new/libshout-2.4.5/include/shout/shout.h.in 2020-12-07 16:59:40.000000000 
+0100
@@ -123,6 +123,9 @@
 
 typedef int (*shout_callback_t)(shout_t *shout, shout_event_t event, void 
*userdata, va_list ap);
 
+
+/* ----------------[ Generic ]---------------- */
+
 /* initializes the shout library. Must be called before anything else */
 void shout_init(void);
 
@@ -151,6 +154,8 @@
 /* returns SHOUTERR_CONNECTED or SHOUTERR_UNCONNECTED */
 int shout_get_connected(shout_t *self);
 
+
+/* ----------------[ Configuration ]---------------- */
 /* Parameter manipulation functions.  libshout makes copies of all parameters,
  * the caller may free its copies after giving them to libshout.  May return
  * SHOUTERR_MALLOC */
@@ -207,21 +212,7 @@
 const char *shout_get_mount(shout_t *self);
 
 /* Other parameters */
-int shout_set_name(shout_t *self, const char *name); // obsolete
-const char *shout_get_name(shout_t *self); // obsolete
-
-int shout_set_url(shout_t *self, const char *url); // obsolete
-const char *shout_get_url(shout_t *self); // obsolete
-
-int shout_set_genre(shout_t *self, const char *genre); // obsolete
-const char *shout_get_genre(shout_t *self); // obsolete
-
-int shout_set_description(shout_t *self, const char *description); // obsolete
-const char *shout_get_description(shout_t *self); // obsolete
-
-int shout_set_dumpfile(shout_t *self, const char *dumpfile);
-const char *shout_get_dumpfile(shout_t *self);
-
+/* takes a SHOUT_AI_xxxx argument */
 int shout_set_audio_info(shout_t *self, const char *name, const char *value);
 const char *shout_get_audio_info(shout_t *self, const char *name);
 
@@ -232,9 +223,20 @@
 int shout_set_public(shout_t *self, unsigned int make_public);
 unsigned int shout_get_public(shout_t *self);
 
-/* takes a SHOUT_FORMAT_xxxx argument */
-int shout_set_format(shout_t *self, unsigned int format); // obsolete
-unsigned int shout_get_format(shout_t *self); // obsolete
+/* Set the content language.
+ * Values as per RFC5646 Section 2.1.
+ * This lists the target audiance language(s), not the language of songs
+ * (unless the station has a focus on songs in a specific language).
+ * The value of NULL is allowed if the content language is not known or is 
expected to change.
+ *
+ * Examples:
+ *  A German station with moderations and news in German and Gamern and 
international songs
+ *  would generally set this to "de-DE".
+ *  A similar station in Switzerland would set this to "de-CH".
+ *  A station with content in Portuguese, and Klingon should set this to "pt, 
tlh".
+ */
+int shout_set_content_language(shout_t *self, const char *content_language);
+const char *shout_get_content_language(shout_t *self);
 
 /* Set the format of the content to send.
  * * format is one of SHOUT_FORMAT_xxxx.
@@ -254,6 +256,9 @@
 int shout_set_nonblocking(shout_t* self, unsigned int nonblocking);
 unsigned int shout_get_nonblocking(shout_t *self);
 
+
+/* ----------------[ Actions ]---------------- */
+
 /* Opens a connection to the server.  All parameters must already be set */
 int shout_open(shout_t *self);
 
@@ -279,6 +284,10 @@
 /* Amount of time in ms caller should wait before sending again */
 int shout_delay(shout_t *self);
 
+
+/* ----------------[ MP3/AAC ONLY ]---------------- */
+/* Functions in this block are for use with MP3, and AAC streams only */
+
 /* Sets MP3 metadata.
  * Returns:
  *   SHOUTERR_SUCCESS
@@ -303,10 +312,38 @@
  *   SHOUTERR_MALLOC if memory can't be allocated */
 int shout_metadata_add(shout_metadata_t *self, const char *name, const char 
*value);
 
+
+/* ----------------[ Advanced ]---------------- */
 /* Advanced. Do not use. */
+
 int shout_control(shout_t *self, shout_control_t control, ...);
 int shout_set_callback(shout_t *self, shout_callback_t callback, void 
*userdata);
 
+
+/* ----------------[ Obsolete ]---------------- */
+/* Those functions are obsolete and MUST NOT be used in newer software.
+ * They may be removed with any future version.
+ */
+
+int shout_set_name(shout_t *self, const char *name); // obsolete
+const char *shout_get_name(shout_t *self); // obsolete
+
+int shout_set_url(shout_t *self, const char *url); // obsolete
+const char *shout_get_url(shout_t *self); // obsolete
+
+int shout_set_genre(shout_t *self, const char *genre); // obsolete
+const char *shout_get_genre(shout_t *self); // obsolete
+
+int shout_set_description(shout_t *self, const char *description); // obsolete
+const char *shout_get_description(shout_t *self); // obsolete
+
+/* takes a SHOUT_FORMAT_xxxx argument */
+int shout_set_format(shout_t *self, unsigned int format); // obsolete
+unsigned int shout_get_format(shout_t *self); // obsolete
+
+int shout_set_dumpfile(shout_t *self, const char *dumpfile); // obsolete
+const char *shout_get_dumpfile(shout_t *self); // obsolete
+
 #ifdef __cplusplus
 }
 #endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/libshout-2.4.4/src/Makefile.am new/libshout-2.4.5/src/Makefile.am
--- old/libshout-2.4.4/src/Makefile.am  2020-09-30 01:46:00.000000000 +0200
+++ new/libshout-2.4.5/src/Makefile.am  2020-12-16 13:47:08.000000000 +0100
@@ -34,7 +34,7 @@
 AM_CPPFLAGS = -I$(top_builddir)/include -I$(srcdir)/common @XIPH_CPPFLAGS@
 
 libshout_la_LIBADD = common/net/libicenet.la common/timing/libicetiming.la 
common/avl/libiceavl.la\
-               common/httpp/libicehttpp.la $(MAYBE_THREAD_LIB) $(THEORA_LIBS) 
$(VORBIS_LIBS) $(SPEEX_LIBS) @XIPH_LIBS@
+               common/httpp/libicehttpp.la $(MAYBE_THREAD_LIB) $(THEORA_LIBS) 
$(OGG_LIBS) $(VORBIS_LIBS) $(SPEEX_LIBS) @XIPH_LIBS@
 
 
 debug:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/libshout-2.4.4/src/connection.c new/libshout-2.4.5/src/connection.c
--- old/libshout-2.4.4/src/connection.c 2020-08-24 18:59:36.000000000 +0200
+++ new/libshout-2.4.5/src/connection.c 2020-12-07 16:59:40.000000000 +0100
@@ -563,7 +563,7 @@
     if (con->socket != SOCK_ERROR || con->current_socket_state != 
SHOUT_SOCKSTATE_UNCONNECTED)
         return SHOUTERR_BUSY;
 
-    if (con->nonblocking == SHOUT_BLOCKING_DEFAULT)
+    if (con->nonblocking != SHOUT_BLOCKING_DEFAULT)
         shout_connection_set_nonblocking(con, shout_get_nonblocking(shout));
 
     port = shout->port;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/libshout-2.4.4/src/proto_http.c new/libshout-2.4.5/src/proto_http.c
--- old/libshout-2.4.4/src/proto_http.c 2019-05-22 11:05:32.000000000 +0200
+++ new/libshout-2.4.5/src/proto_http.c 2020-12-15 22:35:10.000000000 +0100
@@ -125,6 +125,8 @@
             break;
         if (shout_queue_printf(connection, "Content-Type: %s\r\n", mimetype))
             break;
+        if (self->content_language && shout_queue_printf(connection, 
"Content-Language: %s\r\n", self->content_language))
+            break;
         if (poke) {
             if (shout_queue_str(connection, "Content-Length: 0\r\nConnection: 
Keep-Alive\r\n"))
                 break;
@@ -149,6 +151,8 @@
             }
             free(ai);
         }
+        if (shout_queue_str(connection, "Prefer: return=minimal\r\n"))
+            break;
         if (shout_queue_str(connection, "\r\n"))
             break;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/libshout-2.4.4/src/shout.c new/libshout-2.4.5/src/shout.c
--- old/libshout-2.4.4/src/shout.c      2020-08-12 18:31:43.000000000 +0200
+++ new/libshout-2.4.5/src/shout.c      2020-12-16 13:47:08.000000000 +0100
@@ -149,6 +149,8 @@
         free(self->host);
     if (self->password)
         free(self->password);
+    if (self->content_language)
+        free(self->content_language);
     if (self->mount)
         free(self->mount);
     if (self->user)
@@ -678,6 +680,47 @@
     return self->useragent;
 }
 
+int shout_set_content_language(shout_t *self, const char *content_language)
+{
+    const char *p;
+
+    if (!self)
+        return SHOUTERR_INSANE;
+
+    if (!content_language) {
+        if (self->content_language)
+            free(self->content_language);
+        return self->error = SHOUTERR_SUCCESS;
+    }
+
+    // we do at least a simple check for the correct format. This will at 
least detect unsafe chars.
+    for (p = content_language; *p; p++) {
+        if (*p == ' ' || *p == ',')
+            continue;
+        if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' 
&& *p <= '9'))
+            continue;
+        if (*p == '-')
+            continue;
+
+        return self->error = SHOUTERR_INSANE;
+    }
+
+
+    if (self->content_language)
+        free(self->content_language);
+
+    if ( !(self->content_language = _shout_util_strdup(content_language)) )
+        return self->error = SHOUTERR_MALLOC;
+
+    return self->error = SHOUTERR_SUCCESS;
+}
+
+const char *shout_get_content_language(shout_t *self)
+{
+    if (!self)
+        return NULL;
+    return self->content_language;
+}
 
 int shout_set_user(shout_t *self, const char *username)
 {
@@ -1145,10 +1188,11 @@
     if (!self)
         return SHOUTERR_INSANE;
 
-    if (mode == SHOUT_TLS_DISABLED)
-        return SHOUTERR_SUCCESS;
+    if (mode != SHOUT_TLS_DISABLED &&
+        mode != SHOUT_TLS_AUTO)
+        return self->error = SHOUTERR_UNSUPPORTED;
 
-    return self->error = SHOUTERR_UNSUPPORTED;
+    return SHOUTERR_SUCCESS;
 }
 
 int shout_get_tls(shout_t *self)
@@ -1335,6 +1379,7 @@
     }
 
     ret = shout_connection_iter(self->connection, self);
+    self->error = ret;
 
     if (self->connection->current_message_state == SHOUT_MSGSTATE_SENDING1 && 
!self->send) {
         int rc;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/libshout-2.4.4/src/shout_private.h new/libshout-2.4.5/src/shout_private.h
--- old/libshout-2.4.4/src/shout_private.h      2019-08-24 13:52:16.000000000 
+0200
+++ new/libshout-2.4.5/src/shout_private.h      2020-12-07 16:59:40.000000000 
+0100
@@ -93,19 +93,6 @@
     size_t           len;
 } shout_queue_t;
 
-/*
-typedef enum {
-    SHOUT_STATE_UNCONNECTED = 0,
-    SHOUT_STATE_CONNECT_PENDING,
-    SHOUT_STATE_TLS_PENDING,
-    SHOUT_STATE_REQ_CREATION,
-    SHOUT_STATE_REQ_PENDING,
-    SHOUT_STATE_RESP_PENDING,
-    SHOUT_STATE_CONNECTED,
-    SHOUT_STATE_RECONNECT
-} shout_state_e;
-*/
-
 typedef enum {
     SHOUT_SOCKSTATE_UNCONNECTED = 0,
     SHOUT_SOCKSTATE_CONNECTING,
@@ -218,6 +205,8 @@
     unsigned int usage;
     /* audio encoding parameters */
     util_dict *audio_info;
+    /* content-language */
+    char *content_language;
 
     /* user-agent to use when doing HTTP login */
     char *useragent;
@@ -323,7 +312,7 @@
 shout_connection_return_state_t shout_get_xaudiocast_response(shout_t *self, 
shout_connection_t *connection);
 shout_connection_return_state_t shout_parse_xaudiocast_response(shout_t *self, 
shout_connection_t *connection);
 
-/* containsers */
+/* containers */
 int shout_open_ogg(shout_t *self);
 int shout_open_mp3(shout_t *self);
 int shout_open_webm(shout_t *self);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/libshout-2.4.4/tools/Makefile.am new/libshout-2.4.5/tools/Makefile.am
--- old/libshout-2.4.4/tools/Makefile.am        1970-01-01 01:00:00.000000000 
+0100
+++ new/libshout-2.4.5/tools/Makefile.am        2020-12-19 14:33:37.000000000 
+0100
@@ -0,0 +1,11 @@
+AUTOMAKE_OPTIONS = foreign
+
+EXTRA_DIST = shout.1
+
+bin_PROGRAMS = shout
+AM_CFLAGS = @XIPH_CFLAGS@ -I$(top_builddir)/include -Wall -Wextra
+
+man1_MANS = shout.1
+
+shout_SOURCES = shout.c
+shout_LDADD = $(top_builddir)/src/libshout.la
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/libshout-2.4.4/tools/shout.1 new/libshout-2.4.5/tools/shout.1
--- old/libshout-2.4.4/tools/shout.1    1970-01-01 01:00:00.000000000 +0100
+++ new/libshout-2.4.5/tools/shout.1    2020-12-16 13:50:13.000000000 +0100
@@ -0,0 +1,122 @@
+.Dd $Mdocdate: Dec 16 2020$
+.Dt SHOUT 1
+.Os
+.\"
+.Sh NAME
+.\"
+.Nm shout
+.Nd Icecast source client
+.\"
+.Sh SYNOPSIS
+.\"
+.Nm
+[OPTIONS]
+.\"
+.Sh DESCRIPTION
+.\"
+.Nm
+reads data from standard input and streams it to Icecast.
+.\"
+.Sh OPTIONS
+.\"
+.Bl -tag -width 4n
+.\"
+.It Fl \-format Ar format
+Set stream format. This can be "ogg", "mp3", or "webm". Default is "ogg".
+.\"
+.It Fl H Ar host
+See
+.Fl \-host
+.\"
+.It Fl h
+See
+.Fl \-help
+.\"
+.It Fl \-help
+Show help.
+.\"
+.It Fl \-host Ar host
+Set destination host. Default is "localhost".
+.It Fl \-mount Ar string
+Set mountpoint. Default is "/example.ogg".
+.\"
+.It Fl P Ar port
+See
+.Fl \-port
+.\"
+.It Fl \-pass Ar string
+Set source password. Default is "hackme".
+.\"
+.It Fl \-port Ar port
+Set destination port. Symbolic names are supported. Default is 8000.
+.\"
+.It Fl \-proto Ar protocol
+Set protocol. Default is "http".
+.\" STATION METADATA
+.It Fl \-station-description Ar string
+Set stream description.
+.\"
+.It Fl \-station-genre Ar string
+Set stream genre.
+.\"
+.\" --station-meta
+.It Fl \-station-meta Ar key Ns No = Ns Ar value
+Set meta information. Both
+.Ar key
+and
+.Ar value
+are arbitrary strings.
+.\"
+.It Fl \-station-name Ar string
+Set stream name.
+.\"
+.It Fl \-station-url Ar string
+Set stream URL.
+.\"
+.It Fl \-tls-mode Ar tls-mode
+Set TLS mode. This can be "disabled", "auto", "auto_no_plain", "rfc2818", or 
"rfc2817". Default is "auto".
+
+When libshout is build without TLS support only "disabled", and "auto" are 
supported.
+.\"
+.It Fl \-usage Ar usage{,usage}
+Set stream usages. This can be:
+.Bl -tag -width 13n -compact
+.It Qq audio
+for audio substreams
+.It Qq visual
+for picture/video substreams (most often combined with "audio")
+.It Qq text
+for text substreams that are not subtitles
+.It Qq subtitle
+for subtitle substreams
+.It Qq light
+for light control substreams
+.It Qq ui
+for user interface data, such as DVD menus or buttons
+.It Qq metadata
+for substreams that include metadata for the stream
+.It Qq application
+for application specific data substreams
+.It Qq control
+for substreams that control the infrastructure
+.It Qq complex
+for substreams that are themself a mixture of other types
+.It Qq other
+for substream of types not listed here
+.It Qq unknown
+for streams that may contain additional substreams of unknown nature
+.It Qq 3d
+for streams that contain information for 3D playback
+.It Qq 4d
+for streams that contain information for 4D/XD playback
+.El
+.\"
+.It Fl \-user Ar string
+Set source user. Default is "source".
+.\"
+.El
+.\"
+.Sh NOTES
+If this binary is symlinked, or hardlinked to the name "oggfwd" it provides 
drop-in compatibly with
+.Xr oggfwd 1 .
+.\"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude 
config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 
--exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh 
old/libshout-2.4.4/tools/shout.c new/libshout-2.4.5/tools/shout.c
--- old/libshout-2.4.4/tools/shout.c    1970-01-01 01:00:00.000000000 +0100
+++ new/libshout-2.4.5/tools/shout.c    2020-12-16 13:50:13.000000000 +0100
@@ -0,0 +1,770 @@
+/*
+ *  Copyright (C) 2020      Philipp "ph3-der-loewe" Schafft 
<[email protected]>
+ *  Copyright (C) 2020      Jakob Wied <[email protected]>
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the Free
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <getopt.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#   include <config.h>
+#endif
+
+#include <stdbool.h>
+
+#ifndef _WIN32
+#include <arpa/inet.h>
+#include <netdb.h>
+#else
+#include <winsock2.h>
+#include <io.h>
+#include <fcntl.h>
+#endif
+
+#include <shout/shout.h>
+
+#define DEFAULT_MOUNT           "/example.ogg"
+#define DEFAULT_PASSWORD        "hackme"
+
+/* only long options need a flag value */
+enum flag {
+    FLAG__NONE                  = 0,
+    FLAG_PROTO                  = 1,
+    FLAG_MOUNT                  = 2,
+    FLAG_USER                   = 3,
+    FLAG_PASS                   = 4,
+    FLAG_TLS_MODE               = 5,
+    FLAG_FORMAT                 = 6,
+
+    /* metadata */
+    FLAG_STATION_DESCRIPTION    = 7,
+    FLAG_STATION_GENRE          = 8,
+    FLAG_STATION_NAME           = 9,
+    FLAG_STATION_URL            = 10,
+    FLAG_STATION_META           = 11,
+
+    /* other */
+    FLAG_USAGE                  = 20
+};
+
+struct format_usage {
+    char *name;
+    unsigned int flag;
+};
+
+static struct format_usage format_usages[] = {
+    {"audio",       SHOUT_USAGE_AUDIO},
+    {"visual",      SHOUT_USAGE_VISUAL},
+    {"text",        SHOUT_USAGE_TEXT},
+    {"subtitle",    SHOUT_USAGE_SUBTITLE},
+    {"light",       SHOUT_USAGE_LIGHT},
+    {"ui",          SHOUT_USAGE_UI},
+    {"metadata",    SHOUT_USAGE_METADATA},
+    {"application", SHOUT_USAGE_APPLICATION},
+    {"control",     SHOUT_USAGE_CONTROL},
+    {"complex",     SHOUT_USAGE_COMPLEX},
+    {"other",       SHOUT_USAGE_OTHER},
+    {"unknown",     SHOUT_USAGE_UNKNOWN},
+    {"3d",          SHOUT_USAGE_3D},
+    {"4d",          SHOUT_USAGE_4D},
+};
+
+#ifdef SHOUT_TLS
+static const char supported_tls_modes[] = 
"disabled|auto|auto_no_plain|rfc2818|rfc2817";
+#else
+static const char supported_tls_modes[] = "disabled|auto";
+#endif
+
+static inline int string2format(const char *name, unsigned int *format)
+{
+    if (!format)
+        return -1;
+
+    if (strcmp(name, "ogg") == 0) {
+        *format = SHOUT_FORMAT_OGG;
+    } else if (strcmp(name, "mp3") == 0) {
+        *format = SHOUT_FORMAT_MP3;
+    } else if (strcmp(name, "webm") == 0) {
+        *format = SHOUT_FORMAT_WEBM;
+    } else {
+        return -1;
+    }
+
+    return 0;
+}
+
+static inline int string2proto(const char *name, unsigned int *res)
+{
+    if (!res)
+        return -1;
+
+    if (strcmp(name, "http") == 0) {
+        *res = SHOUT_PROTOCOL_HTTP;
+    } else if (strcmp(name, "icy") == 0) {
+        *res = SHOUT_PROTOCOL_ICY;
+    } else if (strcmp(name, "roar") == 0) {
+        *res = SHOUT_PROTOCOL_ROARAUDIO;
+    } else {
+        return -1;
+    }
+
+    return 0;
+}
+
+static inline int string2tlsmode(const char *name, int *res)
+{
+    if (!res)
+        return -1;
+
+    if (strcasecmp(name, "disabled") == 0) {
+        *res = SHOUT_TLS_DISABLED;
+    } else if (strcasecmp(name, "auto") == 0) {
+        *res = SHOUT_TLS_AUTO;
+    } else if (strcasecmp(name, "auto_no_plain") == 0) {
+        *res = SHOUT_TLS_AUTO_NO_PLAIN;
+    } else if (strcasecmp(name, "rfc2818") == 0) {
+        *res = SHOUT_TLS_RFC2818;
+    } else if (strcasecmp(name, "rfc2817") == 0) {
+        *res = SHOUT_TLS_RFC2817;
+    } else {
+        return -1;
+    }
+
+    return 0;
+}
+
+static inline int string2port(const char *name, int *res)
+{
+    const struct servent *service;
+
+    if (!name || !res)
+        return -1;
+
+    service = getservbyname(name, "tcp");
+    if (service) {
+        *res = ntohs(service->s_port);
+        return 0;
+    } else {
+        *res = atoi(name);
+        if (*res < 1 || *res > 65535)
+            return -1;
+        return 0;
+    }
+}
+
+int set_mount(shout_t *self, const char *mount)
+{
+    if (!mount || *mount != '/' || strlen(mount) < 2)
+        fprintf(stderr, "Warning: Mount point not starting with a slash 
(\"/\").\n");
+    return shout_set_mount(self, mount);
+}
+
+int set_meta(shout_t *self, const char *name, const char *value, bool 
allow_unknown_key)
+{
+
+    if (!name || !value)
+        return SHOUTERR_INSANE;
+
+    if (strcmp(name, SHOUT_META_NAME) != 0 && strcmp(name, SHOUT_META_URL) != 
0 &&
+        strcmp(name, SHOUT_META_GENRE) != 0 && strcmp(name, 
SHOUT_META_DESCRIPTION) != 0 &&
+        strcmp(name, SHOUT_META_IRC) != 0 && strcmp(name, SHOUT_META_AIM) != 0 
&&
+        strcmp(name, SHOUT_META_ICQ) != 0) {
+        if (allow_unknown_key) {
+            fprintf(stderr, "Warning: Invalid station metadata key (but trying 
to set anyway): %s\n", name);
+        } else {
+            // just reject, the caller must handle.
+            return SHOUTERR_INSANE;
+        }
+    }
+
+    if (strcmp(name, SHOUT_META_URL) == 0) {
+        if (strstr(value, ":") == NULL) {
+            fprintf(stderr, "Warning: URL \"%s\" is not absolute. This may not 
work as expected. Please include a protocol. E.g. 
\"https://www.example.org/\".\n";, value);
+        } else {
+            if (strncmp(value, "http://";, 7) != 0 && strncmp(value, 
"https://";, 8) != 0) {
+                fprintf(stderr, "Warning: Unusual protocol in URL \"%s\". This 
may not work as expected.\n", value);
+            }
+        }
+    }
+
+    return shout_set_meta(self, name, value);
+}
+
+void usage_oggfwd(const char *progname)
+{
+    fprintf(stderr,
+        "Usage: %s [OPTIONS] address port password mountpoint\n"
+        "\n"
+        "OPTIONS:\n"
+        "  -d <description>    set stream description\n"
+        "  -g <genre>          set stream genre\n"
+        "  -h                  show this help\n"
+        "  -m <file>           parse metadata from file\n"
+        "  -n <name>           set stream name\n"
+        "  -p                  make stream public\n"
+        "  -u <url>            set stream url\n"
+        "  ???T {%s}\n"
+        "                      set TLS mode\n"
+        , progname, supported_tls_modes);
+}
+
+void usage_shout(const char *progname)
+{
+    fprintf(stderr,
+        "Usage: %s [OPTIONS]\n"
+        "\n"
+        "OPTIONS:\n"
+        "General options:\n"
+        "  --format <format>                    set format {ogg|mp3|webm}\n"
+        "  -H <host>, --host <host>             set host\n"
+        "  -h, --help                           show this help\n"
+        "  --mount <mountpoint>                 set mountpoint (e.g. 
\"/example.ogg\")\n"
+        "  -P <port>, --port <port>             set port (e.g. \"http\", or 
\"8300\")\n"
+        "  --pass <password>                    set source password\n"
+        "  --proto <protocol>                   set protocol (e.g. \"http\")\n"
+        "  --user <user>                        set source user\n"
+        "  --tls-mode <tls-mode>                set TLS mode {%s}\n"
+        "  --usage <usage>                      set usage (e.g. \"audio\", or 
\"visual,audio,subtitle\")\n"
+        "Station metadata options:\n"
+        "  --station-description <string>       set station description\n"
+        "  --station-genre <string>             set station genre\n"
+        "  --station-meta <key>=<value>         set station meta information\n"
+        "  --station-name <string>              set station name\n"
+        "  --station-url <string>               set station URL\n"
+        , progname, supported_tls_modes);
+}
+
+/* parse_metadata_file is called at `oggfwd -m`.
+ * It fills the shout struct with information read from file.
+ * It returns 0 on success, or -1 on error.
+ */
+static int parse_metadata_file(const char *path, shout_t *shout)
+{
+    FILE *fh;
+    char line[256];
+    int lineno = 0;
+    size_t len;
+    char *pos;
+    char c;
+
+    if ((fh = fopen(path, "r")) == NULL) {
+        perror(path);
+        return -1;
+    }
+
+    while (fgets(line, sizeof(line), fh)) {
+        lineno++;
+
+        len = strlen(line);
+        if (len == 0) {
+            continue;
+        }
+
+        /* skip comments and empty lines */
+        c = line[0];
+        if ((c == '#') || (c == '\r') || (c == '\n')) {
+            continue;
+        }
+
+        /* strip line endings */
+        if (line[len-1] == '\n') {
+            line[len-1] = '\0';
+            len--;
+        }
+        if (line[len-1] == '\r') {
+            line[len-1] = '\0';
+            len--;
+        }
+
+        /* find '=' */
+        if ((pos = strchr(line, '=')) == NULL) {
+            fprintf(stderr, "%s:%d: syntax error\n", path, lineno);
+            continue; /* oggfwd doesn't abort */
+        }
+
+        *pos = '\0'; /* terminate key */
+        pos++;
+
+        if (set_meta(shout, line, pos, false) != SHOUTERR_SUCCESS) {
+            fprintf(stderr, "%s:%d: \"%s\" is not a valid key\n",
+                    path, lineno, line);
+            continue; /* oggfwd doesn't abort */
+        }
+    }
+
+    if (feof(fh) == 0) {
+        perror(path);
+        fclose(fh);
+        return -1;
+    }
+
+    fclose(fh);
+    return 0;
+}
+
+static int string2usage(char *str, unsigned int *usage)
+{
+    char *tok;
+    size_t i;
+
+    if (!usage)
+        return -1;
+
+    *usage = 0; /* clean for ORing */
+
+    /* split string on commas */
+    for (tok = strtok(str, ","); tok; (tok = strtok(NULL, ","))) {
+        int found = 0;
+
+        /* match token with predefined usages */
+        for (i = 0; i < (sizeof(format_usages) / sizeof(format_usages[0])); 
i++) {
+            if (strcmp(tok, format_usages[i].name) == 0) {
+                *usage |= format_usages[i].flag;
+                found = 1;
+                break;
+            }
+        }
+
+        if (!found)
+            return -1;
+    }
+
+    return 0;
+}
+
+static int getopts_oggfwd(int argc, char *argv[], shout_t *shout)
+{
+    const int ok = SHOUTERR_SUCCESS; /* helps to keep lines at 80 chars */
+    int c;
+    int tls_mode;
+    int port;
+
+    while ((c = getopt(argc, argv, "d:g:hm:n:pu:T:")) != -1) {
+        switch (c) {
+            case 'd':
+                if (set_meta(shout, SHOUT_META_DESCRIPTION, optarg, false) != 
ok) {
+                    fprintf(stderr, "Error setting description: %s\n",
+                            shout_get_error(shout));
+                    return -1;
+                }
+                break;
+
+            case 'g':
+                if (set_meta(shout, SHOUT_META_GENRE, optarg, false) != ok) {
+                    fprintf(stderr, "Error setting genre: %s\n",
+                            shout_get_error(shout));
+                    return -1;
+                }
+                break;
+
+            case 'h':
+                usage_oggfwd(argv[0]);
+                return -1; /* stop further processing */
+
+            case 'm':
+                if (parse_metadata_file(optarg, shout) != 0) {
+                    return -1;
+                }
+                break;
+
+            case 'n':
+                if (set_meta(shout, SHOUT_META_NAME, optarg, false) != ok) {
+                    fprintf(stderr, "Error setting name: %s\n",
+                            shout_get_error(shout));
+                    return -1;
+                }
+                break;
+
+            case 'p':
+                if (shout_set_public(shout, 1) != ok) {
+                    fprintf(stderr, "Error setting public: %s\n",
+                            shout_get_error(shout));
+                    return -1;
+                }
+                break;
+
+            case 'u':
+                if (set_meta(shout, SHOUT_META_URL, optarg, false) != ok) {
+                    fprintf(stderr, "Error setting url: %s\n",
+                            shout_get_error(shout));
+                    return -1;
+                }
+                break;
+            case 'T':
+                if (string2tlsmode(optarg, &tls_mode) != 0) {
+                    fprintf(stderr, "Error parsing TLS mode: %s: Invalid 
protocol name", optarg);
+                    return -1;
+                }
+
+                if (shout_set_tls(shout, tls_mode) != ok) {
+                    fprintf(stderr, "Error setting TLS mode: %s\n",
+                            shout_get_error(shout));
+                    return -1;
+                }
+                break;
+
+            default:
+                usage_oggfwd(argv[0]);
+                return -1;
+        }
+    }
+
+    /* need exacly 4 remaining arguments */
+    if ((argc - optind) != 4) {
+        fprintf(stderr, "Wrong number of arguments\n");
+        usage_oggfwd(argv[0]);
+        return -1;
+    }
+
+    if (shout_set_host(shout, argv[optind++]) != SHOUTERR_SUCCESS) {
+        fprintf(stderr, "Error setting hostname: %s\n", 
shout_get_error(shout));
+        return -1;
+    }
+
+    if (string2port(argv[optind], &port) != 0) {
+        fprintf(stderr, "Error parsing port: %s: Invalid port name\n", 
argv[optind]);
+        return -1;
+    }
+    if (shout_set_port(shout, port) != SHOUTERR_SUCCESS) {
+        fprintf(stderr, "Error setting port: %s\n", shout_get_error(shout));
+        return -1;
+    }
+    optind++;
+
+    if (shout_set_password(shout, argv[optind++]) != SHOUTERR_SUCCESS) {
+        fprintf(stderr, "Error setting password: %s\n", 
shout_get_error(shout));
+        return -1;
+    }
+
+    if (set_mount(shout, argv[optind++]) != SHOUTERR_SUCCESS) {
+        fprintf(stderr, "Error setting mount: %s\n", shout_get_error(shout));
+        return -1;
+    }
+
+    return 0;
+}
+
+static int getopts_shout(int argc, char *argv[], shout_t *shout)
+{
+    int flag = FLAG__NONE;
+    const struct option possible[] = {
+        /* connection options */
+        {"proto",               required_argument, &flag, FLAG_PROTO},
+        {"host",                required_argument, NULL, 'H'},
+        {"port",                required_argument, NULL, 'P'},
+        {"mount",               required_argument, &flag, FLAG_MOUNT},
+        {"user",                required_argument, &flag, FLAG_USER},
+        {"pass",                required_argument, &flag, FLAG_PASS},
+        {"tls-mode",            required_argument, &flag, FLAG_TLS_MODE},
+        /* metadata options */
+        {"station-description", required_argument, &flag, 
FLAG_STATION_DESCRIPTION},
+        {"station-genre",       required_argument, &flag, FLAG_STATION_GENRE},
+        {"station-name",        required_argument, &flag, FLAG_STATION_NAME},
+        {"station-url",         required_argument, &flag, FLAG_STATION_URL},
+        {"station-meta",        required_argument, &flag, FLAG_STATION_META},
+        /* other options */
+        {"format",              required_argument, &flag, FLAG_FORMAT},
+        {"usage",               required_argument, &flag, FLAG_USAGE},
+        {"help",                no_argument,       NULL, 'h'},
+        {NULL,                  0,                 NULL,  0},
+    };
+
+    int format_set = 0, format_usage_set = 0;
+    unsigned int format, format_usage;
+    unsigned int proto;
+    int tls_mode;
+    char *pos;
+    int port;
+    int c;
+    int i = 0;
+
+    while ((c = getopt_long(argc, argv, "H:hP:", possible, &i)) != -1) {
+        switch (c) {
+            case 'H':
+                if (shout_set_host(shout, optarg) != SHOUTERR_SUCCESS) {
+                    fprintf(stderr, "Error setting hostname: %s\n",
+                            shout_get_error(shout));
+                    return -1;
+                }
+                break;
+
+            case 'h':
+                usage_shout(argv[0]);
+                return -1;
+
+            case 'P':
+                if (string2port(optarg, &port) != 0) {
+                    fprintf(stderr, "Error parsing port: %s: Invalid port 
name\n", optarg);
+                    return -1;
+                }
+                if (shout_set_port(shout, port) != SHOUTERR_SUCCESS) {
+                    fprintf(stderr, "Error setting port: %s\n",
+                            shout_get_error(shout));
+                    return -1;
+                }
+                break;
+
+            case 0: /* long-only option */
+                switch ((enum flag)flag) {
+                    case FLAG_PROTO:
+                        if (string2proto(optarg, &proto) != 0) {
+                            fprintf(stderr, "Error parsing protocol: %s: 
Invalid protocol name\n", optarg);
+                            return -1;
+                        }
+                        if (shout_set_protocol(shout, proto) !=
+                                SHOUTERR_SUCCESS) {
+                            fprintf(stderr, "Error setting protocol: %s\n",
+                                    shout_get_error(shout));
+                            return -1;
+                        }
+                        break;
+                    case FLAG_MOUNT:
+                        if (set_mount(shout, optarg) !=
+                                SHOUTERR_SUCCESS) {
+                            fprintf(stderr, "Error setting mount: %s\n",
+                                    shout_get_error(shout));
+                            return -1;
+                        }
+                        break;
+                    case FLAG_USER:
+                        if (shout_set_user(shout, optarg) !=
+                                SHOUTERR_SUCCESS) {
+                            fprintf(stderr, "Error setting user: %s\n",
+                                    shout_get_error(shout));
+                            return -1;
+                        }
+                        break;
+                    case FLAG_PASS:
+                        if (shout_set_password(shout, optarg) !=
+                                SHOUTERR_SUCCESS) {
+                            fprintf(stderr, "Error setting password: %s\n",
+                                    shout_get_error(shout));
+                            return -1;
+                        }
+                        break;
+                    case FLAG_TLS_MODE:
+                        if (string2tlsmode(optarg, &tls_mode) != 0) {
+                            fprintf(stderr, "Error parsing TLS mode: %s: 
Invalid protocol name", optarg);
+                            return -1;
+                        }
+
+                        if (shout_set_tls(shout, tls_mode) !=
+                                SHOUTERR_SUCCESS) {
+                            fprintf(stderr, "Error setting TLS mode: %s\n",
+                                    shout_get_error(shout));
+                            return -1;
+                        }
+                        break;
+
+                    /* metadata options */
+                    case FLAG_STATION_DESCRIPTION:
+                        if (set_meta(shout, SHOUT_META_DESCRIPTION, optarg, 
false) != SHOUTERR_SUCCESS) {
+                            fprintf(stderr, "Error setting description: %s\n", 
shout_get_error(shout));
+                            return -1;
+                        }
+                        break;
+                    case FLAG_STATION_GENRE:
+                        if (set_meta(shout, SHOUT_META_GENRE, optarg, false) 
!= SHOUTERR_SUCCESS) {
+                            fprintf(stderr, "Error setting genre: %s\n", 
shout_get_error(shout));
+                            return -1;
+                        }
+                        break;
+                    case FLAG_STATION_NAME:
+                        if (set_meta(shout, SHOUT_META_NAME, optarg, false) != 
SHOUTERR_SUCCESS) {
+                            fprintf(stderr, "Error setting name: %s\n", 
shout_get_error(shout));
+                            return -1;
+                        }
+                        break;
+                    case FLAG_STATION_URL:
+                        if (set_meta(shout, SHOUT_META_URL, optarg, false) != 
SHOUTERR_SUCCESS) {
+                            fprintf(stderr, "Error setting URL: %s\n", 
shout_get_error(shout));
+                            return -1;
+                        }
+                        break;
+                    case FLAG_STATION_META:
+                        /* find '=' */
+                        if ((pos = strchr(optarg, '=')) == NULL) {
+                            fprintf(stderr, "%s: Missing '='\n", optarg);
+                            return -1;
+                        }
+                        *pos = '\0'; /* terminate key */
+
+                        if (set_meta(shout, optarg, pos + 1, true) != 
SHOUTERR_SUCCESS) {
+                            fprintf(stderr, "Error setting meta information: 
%s\n", shout_get_error(shout));
+                            return -1;
+                        }
+                        break;
+
+                    /* other options */
+                    case FLAG_FORMAT:
+                        /* backup usage */
+                        shout_get_content_format(shout, &format, 
&format_usage, NULL);
+
+                        if (string2format(optarg, &format) != 0) {
+                            fprintf(stderr, "%s: Invalid format name\n", 
optarg);
+                            return -1;
+                        }
+                        if (shout_set_content_format(shout, format, 
format_usage, NULL) != SHOUTERR_SUCCESS) {
+                            fprintf(stderr, "Error setting format: %s\n",
+                                    shout_get_error(shout));
+                            return -1;
+                        }
+                        format_set = 1; /* may need to set usage below */
+                        break;
+
+                    case FLAG_USAGE:
+                        /* backup format */
+                        shout_get_content_format(shout, &format, 
&format_usage, NULL);
+
+                        if (string2usage(optarg, &format_usage) != 0) {
+                            fprintf(stderr, "Invalid format usage\n");
+                            return -1;
+                        }
+
+                        if (shout_set_content_format(shout, format, 
format_usage, NULL) != SHOUTERR_SUCCESS) {
+                            fprintf(stderr, "Error setting format and usage: 
%s\n", shout_get_error(shout));
+                            return -1;
+                        }
+                        format_usage_set = 1; /* don't override usage below */
+                        break;
+
+                    default:
+                        usage_shout(argv[0]);
+                        return -1;
+                        break;
+                }
+                break;
+            default: /* unknown short option */
+                usage_shout(argv[0]);
+                return -1;
+                break;
+        }
+    }
+
+    /* set default usage for format */
+    if (format_set && !format_usage_set) {
+        switch (format) {
+            case SHOUT_FORMAT_OGG:
+                format_usage = SHOUT_USAGE_UNKNOWN;
+                break;
+            case SHOUT_FORMAT_MP3:
+                format_usage = SHOUT_USAGE_AUDIO;
+                break;
+            case SHOUT_FORMAT_WEBM:
+                format_usage = SHOUT_USAGE_AUDIO|SHOUT_USAGE_VISUAL;
+                break;
+            default: /* unknown format => unknown usage */
+                format_usage = SHOUT_USAGE_UNKNOWN;
+                break;
+        }
+
+        if (shout_set_content_format(shout, format, format_usage, NULL) != 
SHOUTERR_SUCCESS) {
+            fprintf(stderr, "Error setting format and usage: %s\n", 
shout_get_error(shout));
+            return -1;
+        }
+        format_usage_set = 1;
+    }
+
+    /* prohibit trailing arguments
+     * NOTE: maybe we should treat them as input files
+     */
+    if (optind != argc) {
+        for (; optind < argc; optind++) {
+            fprintf(stderr, "%s: unused argument\n", argv[optind]);
+        }
+        fprintf(stderr, "\n"); /* don't stick usage to warnings */
+        usage_shout(argv[0]);
+        return -1;
+    }
+
+    return 0;
+}
+
+int main (int argc, char *argv[])
+{
+    unsigned char buf[4096];
+    int err;
+    size_t nread = 0;
+    const char *progname; /* don't use __progname from glibc */
+    shout_t *shout;
+
+#ifdef _WIN32
+    if (_setmode(_fileno(stdin), _O_BINARY) == -1) {
+        fprintf(stderr, "Could not set stdin to binary mode\n");
+        return EXIT_FAILURE;
+    }
+#endif
+
+    shout_init();
+
+    if (!(shout = shout_new())) {
+        fprintf(stderr, "Could not allocate shout_t\n");
+        return EXIT_FAILURE;
+    }
+
+    if ((progname = basename(argv[0])) && (strcmp(progname, "oggfwd") == 0 || 
strcmp(progname, "oggfwd.exe") == 0)) {
+        err = getopts_oggfwd(argc, argv, shout);
+    } else {
+        err = getopts_shout(argc, argv, shout);
+    }
+    if (err) {
+        return EXIT_FAILURE;
+    }
+
+    /* mount is not set by shout_new */
+    if (!shout_get_mount(shout)) {
+        if (set_mount(shout, DEFAULT_MOUNT) != SHOUTERR_SUCCESS) {
+            fprintf(stderr, "Error setting mount: %s\n", 
shout_get_error(shout));
+            return EXIT_FAILURE;
+        }
+    }
+
+    /* password is not set by shout_new */
+    if (!shout_get_password(shout)) {
+        if (shout_set_password(shout, DEFAULT_PASSWORD) != SHOUTERR_SUCCESS) {
+            fprintf(stderr, "Error setting password: %s\n", 
shout_get_error(shout));
+            return EXIT_FAILURE;
+        }
+    }
+
+    if (shout_open(shout) != SHOUTERR_SUCCESS) {
+        fprintf(stderr, "Error connecting: %s\n", shout_get_error(shout));
+        return EXIT_FAILURE;
+    }
+
+    while ((nread = fread(buf, 1, sizeof(buf), stdin)) > 0) {
+        if(shout_send(shout, buf, nread) != SHOUTERR_SUCCESS) {
+            fprintf(stderr, "Error sending: %s\n", shout_get_error(shout));
+            return EXIT_FAILURE;
+        }
+
+        shout_sync(shout);
+    }
+
+    shout_close(shout);
+    shout_shutdown();
+
+    /* don't return 0 if the loop isn't terminated by EOF */
+    if (feof(stdin) == 0) {
+        return EXIT_FAILURE;
+    }
+
+    return EXIT_SUCCESS;
+}

Reply via email to