From b8fd18be31fbc1d9501e62ad521b3ee4ed9c3f8f Mon Sep 17 00:00:00 2001
From: ale <ale@incal.net>
Date: Tue, 24 May 2016 09:30:48 +0100
Subject: [PATCH] switch to libshout

---
 configure.ac    |   9 +-
 m4/libcurl.m4   | 272 ------------------------------------------------
 m4/shout.m4     |  79 ++++++++++++++
 m4/uriparser.m4 |  25 +++++
 src/config.h.in |  75 ++-----------
 src/http.cc     | 213 ++++++++++++++++++++++++-------------
 src/http.h      |  33 ++----
 7 files changed, 264 insertions(+), 442 deletions(-)
 delete mode 100644 m4/libcurl.m4
 create mode 100644 m4/shout.m4
 create mode 100644 m4/uriparser.m4

diff --git a/configure.ac b/configure.ac
index 95f4133..9047515 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,7 +19,8 @@ AC_HEADER_TIME
 AC_ARG_ENABLE([gui],
   AS_HELP_STRING([--disable-gui], [Disable GUI]))
 
-dnl Check base libraries (audio, and libcurl).
+dnl Check base libraries.
+AX_CHECK_URIPARSER
 AX_CHECK_PORTAUDIO
 AX_CHECK_LAME
 AX_CHECK_OGG
@@ -27,7 +28,7 @@ AX_CHECK_OPUS
 XIPH_PATH_VORBIS([
   AC_DEFINE(HAVE_VORBIS, 1, [Define if Vorbis library is available])
 ])
-LIBCURL_CHECK_CONFIG([], [], [], [AC_MSG_ERROR([libcurl not found])])
+XIPH_PATH_SHOUT([], [AC_MSG_ERROR([libshout not found])])
 
 dnl Optionally check for FLTK.
 AS_IF([test "x$enable_gui" != "xno"], [
@@ -37,8 +38,8 @@ AS_IF([test "x$enable_gui" != "xno"], [
 AM_CONDITIONAL([ENABLE_GUI], [test "x$enable_gui" != "xno"])
 
 dnl Assemble all flags together as we're building a single binary.
-CXXFLAGS="$CXXFLAGS $FLTK_CFLAGS $LIBCURL_CPPFLAGS $PORTAUDIO_CFLAGS $OGG_CFLAGS $OPUS_CFLAGS $VORBIS_CFLAGS"
-LIBS="$LIBS $FLTK_LIBS $LIBCURL $PORTAUDIO_LIBS $OGG_LIBS $OPUS_LIBS $VORBIS_LIBS $VORBISENC_LIBS"
+CXXFLAGS="$CXXFLAGS $FLTK_CFLAGS $SHOUT_CPPFLAGS $PORTAUDIO_CFLAGS $OGG_CFLAGS $OPUS_CFLAGS $VORBIS_CFLAGS $URIPARSER_CFLAGS"
+LIBS="$LIBS $FLTK_LIBS $SHOUT_LIBS $PORTAUDIO_LIBS $OGG_LIBS $OPUS_LIBS $VORBIS_LIBS $VORBISENC_LIBS $URIPARSER_LIBS"
 
 dnl Add more compiler flags (standards compliance, etc).
 CFLAGS="$CFLAGS -std=c99 -pedantic -Wall -Werror"
diff --git a/m4/libcurl.m4 b/m4/libcurl.m4
deleted file mode 100644
index f6ebdd2..0000000
--- a/m4/libcurl.m4
+++ /dev/null
@@ -1,272 +0,0 @@
-#***************************************************************************
-#                                  _   _ ____  _
-#  Project                     ___| | | |  _ \| |
-#                             / __| | | | |_) | |
-#                            | (__| |_| |  _ <| |___
-#                             \___|\___/|_| \_\_____|
-#
-# Copyright (C) 2006, David Shaw <dshaw@jabberwocky.com>
-#
-# This software is licensed as described in the file COPYING, which
-# you should have received as part of this distribution. The terms
-# are also available at http://curl.haxx.se/docs/copyright.html.
-#
-# You may opt to use, copy, modify, merge, publish, distribute and/or sell
-# copies of the Software, and permit persons to whom the Software is
-# furnished to do so, under the terms of the COPYING file.
-#
-# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
-# KIND, either express or implied.
-#
-###########################################################################
-# LIBCURL_CHECK_CONFIG ([DEFAULT-ACTION], [MINIMUM-VERSION],
-#                       [ACTION-IF-YES], [ACTION-IF-NO])
-# ----------------------------------------------------------
-#      David Shaw <dshaw@jabberwocky.com>   May-09-2006
-#
-# Checks for libcurl.  DEFAULT-ACTION is the string yes or no to
-# specify whether to default to --with-libcurl or --without-libcurl.
-# If not supplied, DEFAULT-ACTION is yes.  MINIMUM-VERSION is the
-# minimum version of libcurl to accept.  Pass the version as a regular
-# version number like 7.10.1. If not supplied, any version is
-# accepted.  ACTION-IF-YES is a list of shell commands to run if
-# libcurl was successfully found and passed the various tests.
-# ACTION-IF-NO is a list of shell commands that are run otherwise.
-# Note that using --without-libcurl does run ACTION-IF-NO.
-#
-# This macro #defines HAVE_LIBCURL if a working libcurl setup is
-# found, and sets @LIBCURL@ and @LIBCURL_CPPFLAGS@ to the necessary
-# values.  Other useful defines are LIBCURL_FEATURE_xxx where xxx are
-# the various features supported by libcurl, and LIBCURL_PROTOCOL_yyy
-# where yyy are the various protocols supported by libcurl.  Both xxx
-# and yyy are capitalized.  See the list of AH_TEMPLATEs at the top of
-# the macro for the complete list of possible defines.  Shell
-# variables $libcurl_feature_xxx and $libcurl_protocol_yyy are also
-# defined to 'yes' for those features and protocols that were found.
-# Note that xxx and yyy keep the same capitalization as in the
-# curl-config list (e.g. it's "HTTP" and not "http").
-#
-# Users may override the detected values by doing something like:
-# LIBCURL="-lcurl" LIBCURL_CPPFLAGS="-I/usr/myinclude" ./configure
-#
-# For the sake of sanity, this macro assumes that any libcurl that is
-# found is after version 7.7.2, the first version that included the
-# curl-config script.  Note that it is very important for people
-# packaging binary versions of libcurl to include this script!
-# Without curl-config, we can only guess what protocols are available,
-# or use curl_version_info to figure it out at runtime.
-
-AC_DEFUN([LIBCURL_CHECK_CONFIG],
-[
-  AH_TEMPLATE([LIBCURL_FEATURE_SSL],[Defined if libcurl supports SSL])
-  AH_TEMPLATE([LIBCURL_FEATURE_KRB4],[Defined if libcurl supports KRB4])
-  AH_TEMPLATE([LIBCURL_FEATURE_IPV6],[Defined if libcurl supports IPv6])
-  AH_TEMPLATE([LIBCURL_FEATURE_LIBZ],[Defined if libcurl supports libz])
-  AH_TEMPLATE([LIBCURL_FEATURE_ASYNCHDNS],[Defined if libcurl supports AsynchDNS])
-  AH_TEMPLATE([LIBCURL_FEATURE_IDN],[Defined if libcurl supports IDN])
-  AH_TEMPLATE([LIBCURL_FEATURE_SSPI],[Defined if libcurl supports SSPI])
-  AH_TEMPLATE([LIBCURL_FEATURE_NTLM],[Defined if libcurl supports NTLM])
-
-  AH_TEMPLATE([LIBCURL_PROTOCOL_HTTP],[Defined if libcurl supports HTTP])
-  AH_TEMPLATE([LIBCURL_PROTOCOL_HTTPS],[Defined if libcurl supports HTTPS])
-  AH_TEMPLATE([LIBCURL_PROTOCOL_FTP],[Defined if libcurl supports FTP])
-  AH_TEMPLATE([LIBCURL_PROTOCOL_FTPS],[Defined if libcurl supports FTPS])
-  AH_TEMPLATE([LIBCURL_PROTOCOL_FILE],[Defined if libcurl supports FILE])
-  AH_TEMPLATE([LIBCURL_PROTOCOL_TELNET],[Defined if libcurl supports TELNET])
-  AH_TEMPLATE([LIBCURL_PROTOCOL_LDAP],[Defined if libcurl supports LDAP])
-  AH_TEMPLATE([LIBCURL_PROTOCOL_DICT],[Defined if libcurl supports DICT])
-  AH_TEMPLATE([LIBCURL_PROTOCOL_TFTP],[Defined if libcurl supports TFTP])
-  AH_TEMPLATE([LIBCURL_PROTOCOL_RTSP],[Defined if libcurl supports RTSP])
-  AH_TEMPLATE([LIBCURL_PROTOCOL_POP3],[Defined if libcurl supports POP3])
-  AH_TEMPLATE([LIBCURL_PROTOCOL_IMAP],[Defined if libcurl supports IMAP])
-  AH_TEMPLATE([LIBCURL_PROTOCOL_SMTP],[Defined if libcurl supports SMTP])
-
-  AC_ARG_WITH(libcurl,
-     AC_HELP_STRING([--with-libcurl=PREFIX],[look for the curl library in PREFIX/lib and headers in PREFIX/include]),
-     [_libcurl_with=$withval],[_libcurl_with=ifelse([$1],,[yes],[$1])])
-
-  if test "$_libcurl_with" != "no" ; then
-
-     AC_PROG_AWK
-
-     _libcurl_version_parse="eval $AWK '{split(\$NF,A,\".\"); X=256*256*A[[1]]+256*A[[2]]+A[[3]]; print X;}'"
-
-     _libcurl_try_link=yes
-
-     if test -d "$_libcurl_with" ; then
-        LIBCURL_CPPFLAGS="-I$withval/include"
-        _libcurl_ldflags="-L$withval/lib"
-        AC_PATH_PROG([_libcurl_config],[curl-config],[],
-                     ["$withval/bin"])
-     else
-        AC_PATH_PROG([_libcurl_config],[curl-config],[],[$PATH])
-     fi
-
-     if test x$_libcurl_config != "x" ; then
-        AC_CACHE_CHECK([for the version of libcurl],
-           [libcurl_cv_lib_curl_version],
-           [libcurl_cv_lib_curl_version=`$_libcurl_config --version | $AWK '{print $[]2}'`])
-
-        _libcurl_version=`echo $libcurl_cv_lib_curl_version | $_libcurl_version_parse`
-        _libcurl_wanted=`echo ifelse([$2],,[0],[$2]) | $_libcurl_version_parse`
-
-        if test $_libcurl_wanted -gt 0 ; then
-           AC_CACHE_CHECK([for libcurl >= version $2],
-              [libcurl_cv_lib_version_ok],
-              [
-              if test $_libcurl_version -ge $_libcurl_wanted ; then
-                 libcurl_cv_lib_version_ok=yes
-              else
-                 libcurl_cv_lib_version_ok=no
-              fi
-              ])
-        fi
-
-        if test $_libcurl_wanted -eq 0 || test x$libcurl_cv_lib_version_ok = xyes ; then
-           if test x"$LIBCURL_CPPFLAGS" = "x" ; then
-              LIBCURL_CPPFLAGS=`$_libcurl_config --cflags`
-           fi
-           if test x"$LIBCURL" = "x" ; then
-              LIBCURL=`$_libcurl_config --libs`
-
-              # This is so silly, but Apple actually has a bug in their
-              # curl-config script.  Fixed in Tiger, but there are still
-              # lots of Panther installs around.
-              case "${host}" in
-                 powerpc-apple-darwin7*)
-                    LIBCURL=`echo $LIBCURL | sed -e 's|-arch i386||g'`
-                 ;;
-              esac
-           fi
-
-           # All curl-config scripts support --feature
-           _libcurl_features=`$_libcurl_config --feature`
-
-           # Is it modern enough to have --protocols? (7.12.4)
-           if test $_libcurl_version -ge 461828 ; then
-              _libcurl_protocols=`$_libcurl_config --protocols`
-           fi
-        else
-           _libcurl_try_link=no
-        fi
-
-        unset _libcurl_wanted
-     fi
-
-     if test $_libcurl_try_link = yes ; then
-
-        # we didn't find curl-config, so let's see if the user-supplied
-        # link line (or failing that, "-lcurl") is enough.
-        LIBCURL=${LIBCURL-"$_libcurl_ldflags -lcurl"}
-
-        AC_CACHE_CHECK([whether libcurl is usable],
-           [libcurl_cv_lib_curl_usable],
-           [
-           _libcurl_save_cppflags=$CPPFLAGS
-           CPPFLAGS="$LIBCURL_CPPFLAGS $CPPFLAGS"
-           _libcurl_save_libs=$LIBS
-           LIBS="$LIBCURL $LIBS"
-
-           AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <curl/curl.h>]],[[
-/* Try and use a few common options to force a failure if we are
-   missing symbols or can't link. */
-int x;
-curl_easy_setopt(NULL,CURLOPT_URL,NULL);
-x=CURL_ERROR_SIZE;
-x=CURLOPT_WRITEFUNCTION;
-x=CURLOPT_WRITEDATA;
-x=CURLOPT_ERRORBUFFER;
-x=CURLOPT_STDERR;
-x=CURLOPT_VERBOSE;
-if (x) {;}
-]])],libcurl_cv_lib_curl_usable=yes,libcurl_cv_lib_curl_usable=no)
-
-           CPPFLAGS=$_libcurl_save_cppflags
-           LIBS=$_libcurl_save_libs
-           unset _libcurl_save_cppflags
-           unset _libcurl_save_libs
-           ])
-
-        if test $libcurl_cv_lib_curl_usable = yes ; then
-
-           # Does curl_free() exist in this version of libcurl?
-           # If not, fake it with free()
-
-           _libcurl_save_cppflags=$CPPFLAGS
-           CPPFLAGS="$CPPFLAGS $LIBCURL_CPPFLAGS"
-           _libcurl_save_libs=$LIBS
-           LIBS="$LIBS $LIBCURL"
-
-           AC_CHECK_FUNC(curl_free,,
-              AC_DEFINE(curl_free,free,
-                [Define curl_free() as free() if our version of curl lacks curl_free.]))
-
-           CPPFLAGS=$_libcurl_save_cppflags
-           LIBS=$_libcurl_save_libs
-           unset _libcurl_save_cppflags
-           unset _libcurl_save_libs
-
-           AC_DEFINE(HAVE_LIBCURL,1,
-             [Define to 1 if you have a functional curl library.])
-           AC_SUBST(LIBCURL_CPPFLAGS)
-           AC_SUBST(LIBCURL)
-
-           for _libcurl_feature in $_libcurl_features ; do
-              AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_feature_$_libcurl_feature),[1])
-              eval AS_TR_SH(libcurl_feature_$_libcurl_feature)=yes
-           done
-
-           if test "x$_libcurl_protocols" = "x" ; then
-
-              # We don't have --protocols, so just assume that all
-              # protocols are available
-              _libcurl_protocols="HTTP FTP FILE TELNET LDAP DICT TFTP"
-
-              if test x$libcurl_feature_SSL = xyes ; then
-                 _libcurl_protocols="$_libcurl_protocols HTTPS"
-
-                 # FTPS wasn't standards-compliant until version
-                 # 7.11.0 (0x070b00 == 461568)
-                 if test $_libcurl_version -ge 461568; then
-                    _libcurl_protocols="$_libcurl_protocols FTPS"
-                 fi
-              fi
-
-              # RTSP, IMAP, POP3 and SMTP were added in
-              # 7.20.0 (0x071400 == 463872)
-              if test $_libcurl_version -ge 463872; then
-                 _libcurl_protocols="$_libcurl_protocols RTSP IMAP POP3 SMTP"
-              fi
-           fi
-
-           for _libcurl_protocol in $_libcurl_protocols ; do
-              AC_DEFINE_UNQUOTED(AS_TR_CPP(libcurl_protocol_$_libcurl_protocol),[1])
-              eval AS_TR_SH(libcurl_protocol_$_libcurl_protocol)=yes
-           done
-        else
-           unset LIBCURL
-           unset LIBCURL_CPPFLAGS
-        fi
-     fi
-
-     unset _libcurl_try_link
-     unset _libcurl_version_parse
-     unset _libcurl_config
-     unset _libcurl_feature
-     unset _libcurl_features
-     unset _libcurl_protocol
-     unset _libcurl_protocols
-     unset _libcurl_version
-     unset _libcurl_ldflags
-  fi
-
-  if test x$_libcurl_with = xno || test x$libcurl_cv_lib_curl_usable != xyes ; then
-     # This is the IF-NO path
-     ifelse([$4],,:,[$4])
-  else
-     # This is the IF-YES path
-     ifelse([$3],,:,[$3])
-  fi
-
-  unset _libcurl_with
-])dnl
diff --git a/m4/shout.m4 b/m4/shout.m4
new file mode 100644
index 0000000..9fad512
--- /dev/null
+++ b/m4/shout.m4
@@ -0,0 +1,79 @@
+dnl XIPH_PATH_SHOUT
+dnl Jack Moffitt <jack@icecast.org> 08-06-2001
+dnl Rewritten for libshout 2
+dnl Brendan Cully <brendan@xiph.org> 20030612
+dnl 
+dnl $Id: shout.m4 7180 2004-07-20 02:50:54Z brendan $
+
+# XIPH_PATH_SHOUT([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+# Test for libshout, and define SHOUT_CPPFLAGS SHOUT_CFLAGS SHOUT_LIBS, and
+# SHOUT_THREADSAFE
+AC_DEFUN([XIPH_PATH_SHOUT],
+[dnl
+xt_have_shout="no"
+SHOUT_THREADSAFE="no"
+SHOUT_CPPFLAGS=""
+SHOUT_CFLAGS=""
+SHOUT_LIBS=""
+
+# NB: PKG_CHECK_MODULES exits if pkg-config is unavailable on the target
+# system, so we can't use it.
+
+# seed pkg-config with the default libshout location
+PKG_CONFIG_PATH=${PKG_CONFIG_PATH:-/usr/local/lib/pkgconfig}
+export PKG_CONFIG_PATH
+
+# Step 1: Use pkg-config if available
+AC_PATH_PROG([PKGCONFIG], [pkg-config], [no])
+if test "$PKGCONFIG" != "no" && `$PKGCONFIG --exists shout`
+then
+  SHOUT_CFLAGS=`$PKGCONFIG --variable=cflags_only shout`
+  SHOUT_CPPFLAGS=`$PKGCONFIG --variable=cppflags shout`
+  SHOUT_LIBS=`$PKGCONFIG --libs shout`
+  xt_have_shout="maybe"
+else
+  if test "$PKGCONFIG" != "no"
+  then
+    AC_MSG_NOTICE([$PKGCONFIG couldn't find libshout. Try adjusting PKG_CONFIG_PATH.])
+  fi
+  # pkg-config unavailable, try shout-config
+  AC_PATH_PROG([SHOUTCONFIG], [shout-config], [no])
+  if test "$SHOUTCONFIG" != "no" && test `$SHOUTCONFIG --package` = "libshout"
+  then
+    SHOUT_CPPFLAGS=`$SHOUTCONFIG --cppflags`
+    SHOUT_CFLAGS=`$SHOUTCONFIG --cflags-only`
+    SHOUT_LIBS=`$SHOUTCONFIG --libs`
+    xt_have_shout="maybe"
+  fi
+fi
+
+# Now try actually using libshout
+if test "$xt_have_shout" != "no"
+then
+  ac_save_CPPFLAGS="$CPPFLAGS"
+  ac_save_CFLAGS="$CFLAGS"
+  ac_save_LIBS="$LIBS"
+  CPPFLAGS="$CPPFLAGS $SHOUT_CPPFLAGS"
+  CFLAGS="$CFLAGS $SHOUT_CFLAGS"
+  LIBS="$SHOUT_LIBS $LIBS"
+  AC_CHECK_HEADERS([shout/shout.h], [
+    AC_CHECK_FUNC([shout_new], [
+      ifelse([$1], , :, [$1])
+      xt_have_shout="yes"
+    ])
+    AC_EGREP_CPP([yes], [#include <shout/shout.h>
+#if SHOUT_THREADSAFE
+yes
+#endif
+], [SHOUT_THREADSAFE="yes"])
+  ])
+  CPPFLAGS="$ac_save_CPPFLAGS"
+  CFLAGS="$ac_save_CFLAGS"
+  LIBS="$ac_save_LIBS"
+fi
+
+if test "$xt_have_shout" != "yes"
+then
+  ifelse([$2], , :, [$2])
+fi
+])dnl XIPH_PATH_SHOUT
diff --git a/m4/uriparser.m4 b/m4/uriparser.m4
new file mode 100644
index 0000000..4b0761d
--- /dev/null
+++ b/m4/uriparser.m4
@@ -0,0 +1,25 @@
+AC_DEFUN([AX_CHECK_URIPARSER], [
+  URIPARSER_LIBS=
+  URIPARSER_CFLAGS=
+  AC_PATH_PROG([PKG_CONFIG], [pkg-config])
+  if test x"$PKG_CONFIG" != x; then
+    URIPARSER_LIBS=`$PKG_CONFIG --libs liburiparser`
+    if test $? -eq 0; then
+      URIPARSER_CFLAGS=`$PKG_CONFIG --cflags liburiparser`
+    fi
+  fi
+
+  _uriparser_cflags="$CFLAGS"
+  _uriparser_libs="$LIBS"
+  CFLAGS="$CFLAGS $URIPARSER_CFLAGS"
+  LIBS="$LIBS $URIPARSER_LIBS"
+
+  found=true
+  AC_CHECK_HEADER([uriparser/Uri.h], [], [found=false])
+  AC_CHECK_LIB([uriparser], [UriParseA], [], [found=false])
+
+  CFLAGS="$_uriparser_cflags"
+  LIBS="$_uriparser_libs"
+  AC_SUBST([URIPARSER_LIBS])
+  AC_SUBST([URIPARSER_CFLAGS])
+])
diff --git a/src/config.h.in b/src/config.h.in
index fef1a78..6a966a2 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -9,9 +9,6 @@
 /* Define if Lame mp3 library is available */
 #undef HAVE_LAME
 
-/* Define to 1 if you have a functional curl library. */
-#undef HAVE_LIBCURL
-
 /* Define to 1 if you have the `mp3lame' library (-lmp3lame). */
 #undef HAVE_LIBMP3LAME
 
@@ -21,6 +18,9 @@
 /* Define to 1 if you have the `opus' library (-lopus). */
 #undef HAVE_LIBOPUS
 
+/* Define to 1 if you have the `uriparser' library (-luriparser). */
+#undef HAVE_LIBURIPARSER
+
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
@@ -30,6 +30,9 @@
 /* Define if OPUS codec is available */
 #undef HAVE_OPUS
 
+/* Define to 1 if you have the <shout/shout.h> header file. */
+#undef HAVE_SHOUT_SHOUT_H
+
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
@@ -54,69 +57,6 @@
 /* Define if Vorbis library is available */
 #undef HAVE_VORBIS
 
-/* Defined if libcurl supports AsynchDNS */
-#undef LIBCURL_FEATURE_ASYNCHDNS
-
-/* Defined if libcurl supports IDN */
-#undef LIBCURL_FEATURE_IDN
-
-/* Defined if libcurl supports IPv6 */
-#undef LIBCURL_FEATURE_IPV6
-
-/* Defined if libcurl supports KRB4 */
-#undef LIBCURL_FEATURE_KRB4
-
-/* Defined if libcurl supports libz */
-#undef LIBCURL_FEATURE_LIBZ
-
-/* Defined if libcurl supports NTLM */
-#undef LIBCURL_FEATURE_NTLM
-
-/* Defined if libcurl supports SSL */
-#undef LIBCURL_FEATURE_SSL
-
-/* Defined if libcurl supports SSPI */
-#undef LIBCURL_FEATURE_SSPI
-
-/* Defined if libcurl supports DICT */
-#undef LIBCURL_PROTOCOL_DICT
-
-/* Defined if libcurl supports FILE */
-#undef LIBCURL_PROTOCOL_FILE
-
-/* Defined if libcurl supports FTP */
-#undef LIBCURL_PROTOCOL_FTP
-
-/* Defined if libcurl supports FTPS */
-#undef LIBCURL_PROTOCOL_FTPS
-
-/* Defined if libcurl supports HTTP */
-#undef LIBCURL_PROTOCOL_HTTP
-
-/* Defined if libcurl supports HTTPS */
-#undef LIBCURL_PROTOCOL_HTTPS
-
-/* Defined if libcurl supports IMAP */
-#undef LIBCURL_PROTOCOL_IMAP
-
-/* Defined if libcurl supports LDAP */
-#undef LIBCURL_PROTOCOL_LDAP
-
-/* Defined if libcurl supports POP3 */
-#undef LIBCURL_PROTOCOL_POP3
-
-/* Defined if libcurl supports RTSP */
-#undef LIBCURL_PROTOCOL_RTSP
-
-/* Defined if libcurl supports SMTP */
-#undef LIBCURL_PROTOCOL_SMTP
-
-/* Defined if libcurl supports TELNET */
-#undef LIBCURL_PROTOCOL_TELNET
-
-/* Defined if libcurl supports TFTP */
-#undef LIBCURL_PROTOCOL_TFTP
-
 /* Name of package */
 #undef PACKAGE
 
@@ -146,6 +86,3 @@
 
 /* Version number of package */
 #undef VERSION
-
-/* Define curl_free() as free() if our version of curl lacks curl_free. */
-#undef curl_free
diff --git a/src/http.cc b/src/http.cc
index ef242fb..5f9891f 100644
--- a/src/http.cc
+++ b/src/http.cc
@@ -22,118 +22,185 @@
 #include "config.h"
 #include <stdio.h>
 #include <unistd.h>
+#include <uriparser/Uri.h>
 
 namespace microb {
 
-int Uploader::curl_read_cb(char *buffer, size_t size, size_t nitems,
-                           void *user_data) {
-  Uploader *up = static_cast<Uploader *>(user_data);
-  return up->callback(buffer, size, nitems);
-}
+class URL {
+public:
 
-int Uploader::curl_write_cb(char *buffer, size_t size, size_t nitems,
-                            void *user_data) {
-  return size * nitems;
-}
+  URL(const string& uristr) {
+    UriParserStateA state;
+    state.uri = &uri_;
+    ok_ = (uriParseUriA(&state, uristr.c_str()) == URI_SUCCESS);
+  }
 
-void Uploader::close() {
-  stop_.set();
-  ring_buffer_->close();
-}
+  ~URL() {
+    if (ok_) {
+      uriFreeUriMembersA(&uri_);
+    }
+  }    
+
+  bool ok() { return ok_; }
+  
+  string scheme() { return from_range(uri_.scheme, "http"); }
+  
+  string host() { return from_range(uri_.hostText, ""); }
 
-int Uploader::callback(char *buf, size_t size, size_t nitems) {
-  if (stop_.is_set()) {
-    return CURL_READFUNC_ABORT;
+  string path() { return from_list(uri_.pathHead, "/"); }
+
+  int port() {
+    string default_port = "80";
+    if (scheme() == "https") {
+      default_port = "443";
+    }
+    return atoi(from_range(uri_.portText, default_port).c_str());
   }
-  int n = ring_buffer_->read(buf, size * nitems);
-  if (n < 0) {
-    return CURL_READFUNC_ABORT;
+  
+  string from_range(const UriTextRangeA &rng, const string& default_value) const {
+    if (rng.first != nullptr && rng.afterLast != nullptr) {
+      return string(rng.first, rng.afterLast);
+    }
+    return default_value;
   }
-  return n;
+
+  string from_list(UriPathSegmentA *xs, const string& delim) const {
+    UriPathSegmentStructA *head = xs;
+    string accum;
+    while (head) {
+      accum += delim + from_range(head->text, "");
+      head = head->next;
+    }
+    return accum;
+  }
+
+protected:
+  UriUriA uri_;
+  bool ok_;
+};
+
+void Uploader::close() {
+  stop_.set();
+  ring_buffer_->close();
 }
 
 // Detect retriable, transient network errors.
-static bool is_curl_temporary_error(CURLcode err) {
+static bool is_temporary_error(int err) {
   switch (err) {
-  case CURLE_COULDNT_CONNECT:
-  // case CURLE_COULDNT_RESOLVE_HOST:
-  case CURLE_READ_ERROR:
-  case CURLE_SEND_ERROR:
-  case CURLE_RECV_ERROR:
+  // ?? Just guessing here...
+  case SHOUTERR_NOCONNECT:
+  case SHOUTERR_UNCONNECTED:
+  case SHOUTERR_SOCKET:
     return true;
   default:
     return false;
   }
 }
 
-util::Status Uploader::init_request() {
-  // Set up libcurl.
-  handle_ = curl_easy_init();
-  if (handle_ == nullptr) {
-    return util::Status(ERR) << "failed to initialize libcurl";
+static int shout_format(const string& content_type) {
+  if (content_type == "application/ogg") {
+    return SHOUT_FORMAT_OGG;
+  } else if (content_type == "audio/mpeg") {
+    return SHOUT_FORMAT_MP3;
+  }
+  // Unreached.
+  return SHOUT_FORMAT_MP3;
+}
+  
+util::Status Uploader::run() {
+  util::Status status;
+  while (!stop_.is_set()) {
+    status = run_once();
+    if (!status.ok()) {
+      break;
+    }
+  }
+  saved_status_ = status;
+  done_.set();
+  return status;
+}
+  
+util::Status Uploader::run_once() {
+  util::Status status;
+
+  URL url(url_);
+  if (!url.ok()) {
+    return util::Status(ERR) << "could not parse URL " << url_;
+  }
+  if (url.scheme() != "http" && url.scheme() != "https") {
+    return util::Status(ERR) << "unsupported URL scheme " << url.scheme();
   }
 
-  string ctype_hdr = string("Content-Type: ") + content_type_;
-  headers_ = curl_slist_append(headers_, ctype_hdr.c_str());
-  curl_easy_setopt(handle_, CURLOPT_HTTPHEADER, headers_);
-  curl_easy_setopt(handle_, CURLOPT_URL, url_.c_str());
+  shout_t *handle = shout_new();
+  if (handle == nullptr) {
+    return util::Status(ERR) << "failed to initialize libshout";
+  }
+  
+  shout_set_host(handle, url.host().c_str());
+  shout_set_port(handle, (unsigned short)(url.port()));
+  shout_set_mount(handle, url.path().c_str());
+  fprintf(stderr, "shout: host=%s port=%d path=%s\n",
+          url.host().c_str(),
+          url.port(),
+          url.path().c_str());
+
+  shout_set_format(handle, shout_format(content_type_));
+  shout_set_protocol(handle, SHOUT_PROTOCOL_HTTP);
+  shout_set_agent(handle, PACKAGE_NAME "/" PACKAGE_VERSION);
   if (!username_.empty()) {
-    curl_easy_setopt(handle_, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
-    curl_easy_setopt(handle_, CURLOPT_USERNAME, username_.c_str());
-    curl_easy_setopt(handle_, CURLOPT_PASSWORD, password_.c_str());
+    shout_set_user(handle, username_.c_str());
   }
-  curl_easy_setopt(handle_, CURLOPT_NOSIGNAL, 1);
-  // curl_easy_setopt(handle_, CURLOPT_HTTP_TRANSFER_DECODING, 0);
-  curl_easy_setopt(handle_, CURLOPT_UPLOAD, 1);
-  curl_easy_setopt(handle_, CURLOPT_FAILONERROR, 1);
-  curl_easy_setopt(handle_, CURLOPT_ERRORBUFFER, errbuf_);
-  curl_easy_setopt(handle_, CURLOPT_FOLLOWLOCATION, 1);
-  curl_easy_setopt(handle_, CURLOPT_READFUNCTION, curl_read_cb);
-  curl_easy_setopt(handle_, CURLOPT_READDATA, static_cast<void *>(this));
-  curl_easy_setopt(handle_, CURLOPT_WRITEFUNCTION, curl_write_cb);
-  curl_easy_setopt(handle_, CURLOPT_USERAGENT,
-                   PACKAGE_NAME "/" PACKAGE_VERSION);
-  return util::Status(OK);
-}
+  // Libshout always wants a password (even if empty).
+  shout_set_password(handle, password_.c_str());
 
-util::Status Uploader::run() {
-  util::Status status = init_request();
-  if (!status.ok()) {
+  int err = shout_open(handle);
+  if (err < 0) {
+    status = util::Status(err) << "libshout error: " << shout_get_error(handle);
+    shout_free(handle);
     return status;
   }
 
+  int bufsz = 4096;
+  char *buf = (char *)malloc(bufsz);
+  
   while (!stop_.is_set()) {
-    // Repeat the request on error.
-    CURLcode err = curl_easy_perform(handle_);
-    if (err == CURLE_ABORTED_BY_CALLBACK) {
-      // stop_ will also be true, so exit.
+    // Retrieve some data from the ring buffer.
+    int n = ring_buffer_->read(buf, bufsz);
+    if (n < 0) {
+      status = util::Status(n) << "read error";
       break;
     }
-    if (err != CURLE_OK) {
-      const char *errmsg = errbuf_;
-      if (errmsg[0] == '\0') {
-        errmsg = curl_easy_strerror(err);
-      }
-      if (is_curl_temporary_error(err)) {
-        // Sleep for 200ms.
-        fprintf(stderr, "uploader warning: %s, retrying...\n", errmsg);
+    
+    // Send it to libshout.
+    fprintf(stderr, "shout_send(%d)\n", n);
+    n = shout_send(handle, (unsigned char *)buf, n);
+    if (n < 0) {
+      if (is_temporary_error(n)) {
+        // Sleep for a little while and return OK so the outer loop
+        // will retry the connection.
+        fprintf(stderr, "libshout error: %s, retrying...\n", shout_get_error(handle));
         usleep(200000);
-        continue;
+        status = util::Status(OK);
+      } else {
+        status = util::Status(n) << "libshout error: " << shout_get_error(handle);
       }
-      // Fatal error.
-      status = util::Status(err) << "HTTP error: " << errmsg;
       break;
     }
   }
 
-  saved_status_ = status;
-  done_.set();
+  shout_close(handle);
+  shout_free(handle);
+  free(buf);
 
   return status;
 }
 
-void http_initialize() { curl_global_init(CURL_GLOBAL_ALL); }
+void http_initialize() {
+  shout_init();
+}
 
-void http_close() { curl_global_cleanup(); }
+void http_close() {
+  shout_shutdown();
+}
 
 } // namespace
diff --git a/src/http.h b/src/http.h
index f75d4ad..56ed133 100644
--- a/src/http.h
+++ b/src/http.h
@@ -22,7 +22,7 @@
 #ifndef __microb_http_H
 #define __microb_http_H 1
 
-#include <curl/curl.h>
+#include <shout/shout.h>
 #include <memory>
 #include <string>
 
@@ -41,10 +41,9 @@ public:
   Uploader(const string &url, const string &username, const string &password,
            const string &content_type)
       : util::JoinableThread(), url_(url), username_(username),
-        password_(password), content_type_(content_type), handle_(nullptr),
-        headers_(nullptr), ring_buffer_(new RingBuffer()),
-        errbuf_((char *)calloc(1, CURL_ERROR_SIZE)),
-        saved_status_(util::Status(OK)) {}
+        password_(password), content_type_(content_type),
+        ring_buffer_(new RingBuffer())
+  {}
 
   Uploader(const s_config &config, const string &content_type)
       : Uploader(config.http_url, config.http_username, config.http_password,
@@ -53,14 +52,6 @@ public:
   ~Uploader() {
     close();
     wait();
-
-    if (handle_) {
-      curl_easy_cleanup(handle_);
-    }
-    if (headers_) {
-      curl_slist_free_all(headers_);
-    }
-    free(errbuf_);
   }
 
   void close();
@@ -73,29 +64,23 @@ public:
     return ring_buffer_->write(buf, len);
   }
 
-  util::Status status() { return saved_status_; }
+  util::Status status() {
+    return saved_status_;
+  }
 
 protected:
   string url_;
   string username_;
   string password_;
   string content_type_;
-  CURL *handle_;
-  curl_slist *headers_;
   util::Flag stop_;
   unique_ptr<RingBuffer> ring_buffer_;
   char *errbuf_;
   util::Flag done_;
   util::Status saved_status_;
-
-  int callback(char *buf, size_t size, size_t nitems);
+  
   virtual util::Status run();
-  util::Status init_request();
-
-  static int curl_read_cb(char *buffer, size_t size, size_t nitems,
-                          void *user_data);
-  static int curl_write_cb(char *buffer, size_t size, size_t nitems,
-                           void *user_data);
+  util::Status run_once();
 };
 
 void http_initialize();
-- 
GitLab