[xiph-commits] r17097 - in icecast/branches/kh/icecast: . src web win32

karl at svn.xiph.org karl at svn.xiph.org
Sun Mar 28 19:14:55 PDT 2010


Author: karl
Date: 2010-03-28 19:14:55 -0700 (Sun, 28 Mar 2010)
New Revision: 17097

Added:
   icecast/branches/kh/icecast/src/mpeg.c
   icecast/branches/kh/icecast/src/mpeg.h
Modified:
   icecast/branches/kh/icecast/NEWS
   icecast/branches/kh/icecast/config.h.vc6
   icecast/branches/kh/icecast/configure.in
   icecast/branches/kh/icecast/src/Makefile.am
   icecast/branches/kh/icecast/src/auth.c
   icecast/branches/kh/icecast/src/cfgfile.c
   icecast/branches/kh/icecast/src/cfgfile.h
   icecast/branches/kh/icecast/src/client.h
   icecast/branches/kh/icecast/src/connection.c
   icecast/branches/kh/icecast/src/format.c
   icecast/branches/kh/icecast/src/format.h
   icecast/branches/kh/icecast/src/format_mp3.c
   icecast/branches/kh/icecast/src/format_mp3.h
   icecast/branches/kh/icecast/src/format_ogg.c
   icecast/branches/kh/icecast/src/format_ogg.h
   icecast/branches/kh/icecast/src/fserve.c
   icecast/branches/kh/icecast/src/global.c
   icecast/branches/kh/icecast/src/global.h
   icecast/branches/kh/icecast/src/logging.c
   icecast/branches/kh/icecast/src/main.c
   icecast/branches/kh/icecast/src/source.c
   icecast/branches/kh/icecast/src/stats.c
   icecast/branches/kh/icecast/src/util.c
   icecast/branches/kh/icecast/src/util.h
   icecast/branches/kh/icecast/src/xslt.c
   icecast/branches/kh/icecast/web/Makefile.am
   icecast/branches/kh/icecast/win32/icecast.dsp
   icecast/branches/kh/icecast/win32/icecast2.iss
Log:
bump to kh22. Crash fix from kh20, the rest is mainly internal changes. Option
for access log skipping and global bandwidth limiting if specified. Buffers for
mpeg streams are made to be on frame boundaries which should help with listener
moves.


Modified: icecast/branches/kh/icecast/NEWS
===================================================================
--- icecast/branches/kh/icecast/NEWS	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/NEWS	2010-03-29 02:14:55 UTC (rev 17097)
@@ -16,6 +16,24 @@
 any extra tags are show in the conf/icecast.xml.dist file
 
 
+2.3.2-kh22
+. Add mp3/aac sync marker alignment code. This makes the internal buffers contain
+  whole frames. allows for better transistion when moving listeners.
+. The number of logs is not limited to 25 now
+. small changes to client scheduling
+. removed format url lock, source lock is always taken, so this is not needed
+. Add <skip-accesslog> boolean to per-mount settings. Prevents logging listener
+  client details to access log
+. evaluate bandwidth usage when adding to the global bitrate, and change throttle
+  indicator if max bandwidth specified. listeners have varying degrees of
+  scheduling limits applied. lagging listeners get delayed first, then all do.
+. fix long standing bug which could cause a crash on a bad xsl.
+. report line numbers on xml errors.
+. small work-around to handle odd handling of ICY response for mpc and expected
+  the content-type header for shoutcast relay and streamtranscoder.
+. kh21a. kh20 introduced a bug which could occur with listeners being moved between
+  workers.
+
 2.3.2-kh21
 . Fix possible stall bug when a source exits and when adding a listener, only
   keep the source_tree lock held until a source lock can be acquired. 

Modified: icecast/branches/kh/icecast/config.h.vc6
===================================================================
--- icecast/branches/kh/icecast/config.h.vc6	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/config.h.vc6	2010-03-29 02:14:55 UTC (rev 17097)
@@ -95,7 +95,7 @@
 #define PACKAGE_NAME "Icecast"
 
 /* Version number of package */
-#define VERSION "2.3.2-kh21"
+#define VERSION "2.3.2-kh22"
 
 /* Define to the version of this package. */
 #define PACKAGE_VERSION VERSION

Modified: icecast/branches/kh/icecast/configure.in
===================================================================
--- icecast/branches/kh/icecast/configure.in	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/configure.in	2010-03-29 02:14:55 UTC (rev 17097)
@@ -1,4 +1,4 @@
-AC_INIT([Icecast], [2.3.2-kh21], [karl at xiph.org])
+AC_INIT([Icecast], [2.3.2-kh22], [karl at xiph.org])
 
 LT_INIT
 AC_PREREQ(2.59)

Modified: icecast/branches/kh/icecast/src/Makefile.am
===================================================================
--- icecast/branches/kh/icecast/src/Makefile.am	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/Makefile.am	2010-03-29 02:14:55 UTC (rev 17097)
@@ -13,12 +13,12 @@
     fnmatch_loop.c fnmatch.h \
     format.h format_ogg.h format_mp3.h \
     format_vorbis.h format_theora.h format_flac.h format_speex.h format_midi.h \
-    format_kate.h format_skeleton.h
+    format_kate.h format_skeleton.h mpeg.h
 icecast_SOURCES = cfgfile.c main.c logging.c sighandler.c connection.c global.c \
     util.c slave.c source.c stats.c refbuf.c client.c \
     xslt.c fserve.c event.c admin.c md5.c \
     format.c format_ogg.c format_mp3.c format_midi.c format_flac.c \
-    auth.c auth_htpasswd.c format_kate.c format_skeleton.c
+    auth.c auth_htpasswd.c format_kate.c format_skeleton.c mpeg.c
 EXTRA_icecast_SOURCES = yp.c \
     auth_url.c auth_cmd.c \
     format_vorbis.c format_theora.c format_speex.c fnmatch.c

Modified: icecast/branches/kh/icecast/src/auth.c
===================================================================
--- icecast/branches/kh/icecast/src/auth.c	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/auth.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -531,11 +531,16 @@
     }
     config = config_get_config();
     mountinfo = config_find_mount (config, mount);
-    if (mountinfo && mountinfo->no_mount)
+    if (mountinfo)
     {
-        config_release_config ();
-        client_send_403 (client, "mountpoint unavailable");
-        return;
+        if (mountinfo->skip_accesslog)
+            client->flags |= CLIENT_SKIP_ACCESSLOG;
+        if (mountinfo->no_mount)
+        {
+            config_release_config ();
+            client_send_403 (client, "mountpoint unavailable");
+            return;
+        }
     }
     if ((client->flags & CLIENT_AUTHENTICATED) == 0 && mountinfo && mountinfo->auth && mountinfo->auth->authenticate)
     {

Modified: icecast/branches/kh/icecast/src/cfgfile.c
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.c	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/cfgfile.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -192,7 +192,8 @@
                         ret = 0;
                         continue;
                     }
-                    xmlParserWarning (NULL, "skipping element \"%s\" parsing \"%s\"\n", node->name, parent->name);
+                    xmlParserWarning (NULL, "skipping element \"%s\" parsing \"%s\" "
+                            "at line %ld\n", node->name, parent->name, xmlGetLineNo(node));
                     ret = 0;
                 }
                 break;
@@ -200,7 +201,8 @@
             argp++;
         }
         if (argp->name == NULL)
-            WARN2 ("unknown element \"%s\" parsing \"%s\"", node->name, parent->name);
+            WARN3 ("unknown element \"%s\" parsing \"%s\" at line %ld", node->name,
+                    parent->name, xmlGetLineNo(node));
     }
     if (ret == 0 && seen_element == 0)
         return 2;
@@ -246,7 +248,6 @@
 {
     config_options_t *option;
 
-    if (mount->mountname)   xmlFree (mount->mountname);
     if (mount->username)    xmlFree (mount->username);
     if (mount->password)    xmlFree (mount->password);
     if (mount->dumpfile)    xmlFree (mount->dumpfile);
@@ -279,6 +280,7 @@
         log_close (mount->access_log.logid);
     xmlFree (mount->access_log.name);
     xmlFree (mount->access_log.exclude_ext);
+    xmlFree (mount->mountname);
     free (mount);
 }
 
@@ -777,6 +779,7 @@
         { "wait-time",          config_get_int,     &mount->wait_time },
         { "filter-theora",      config_get_bool,    &mount->filter_theora },
         { "limit-rate",         config_get_bitrate, &mount->limit_rate },
+        { "skip-accesslog",     config_get_bool,    &mount->skip_accesslog },
         { "avg-bitrate-duration",
                                 config_get_int,     &mount->avg_bitrate_duration },
         { "charset",            config_get_str,     &mount->charset },

Modified: icecast/branches/kh/icecast/src/cfgfile.h
===================================================================
--- icecast/branches/kh/icecast/src/cfgfile.h	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/cfgfile.h	2010-03-29 02:14:55 UTC (rev 17097)
@@ -112,11 +112,12 @@
     int url_ogg_meta; /* enable to allow updates via url requests for ogg */
     int ogg_passthrough; /* enable to prevent the ogg stream being rebuilt */
     int admin_comments_only; /* enable to only show comments set from the admin page */
+    int skip_accesslog;         /* skip logging client to access log */
 
     /* duration in seconds for sampling the bandwidth */
     int avg_bitrate_duration;
 
-    long limit_rate;
+    int64_t limit_rate;
 
     /* duration (secs) for mountpoint to be kept reserved after source client exits */
     int wait_time;

Modified: icecast/branches/kh/icecast/src/client.h
===================================================================
--- icecast/branches/kh/icecast/src/client.h	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/client.h	2010-03-29 02:14:55 UTC (rev 17097)
@@ -143,6 +143,7 @@
 #define CLIENT_IN_FSERVE            (010)
 #define CLIENT_NO_CONTENT_LENGTH    (020)
 #define CLIENT_HAS_INTRO_CONTENT    (040)
+#define CLIENT_SKIP_ACCESSLOG       (0100)
 #define CLIENT_FORMAT_BIT           (01000)
 
 #endif  /* __CLIENT_H__ */

Modified: icecast/branches/kh/icecast/src/connection.c
===================================================================
--- icecast/branches/kh/icecast/src/connection.c	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/connection.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -617,7 +617,6 @@
             }
         }
         global_unlock ();
-        stats_event_inc (NULL, "connections");
         if (sock_set_blocking (con->sock, 0) || sock_set_nodelay (con->sock))
         {
             WARN0 ("failed to set tcp options on client connection, dropping");
@@ -927,6 +926,7 @@
  */
 int connection_complete_source (source_t *source, http_parser_t *parser)
 {
+    client_t *client = source->client;
     const char *contenttype = httpp_getvar (parser, "content-type");
     mount_proxy *mountinfo;
     format_type_t format_type;
@@ -953,7 +953,7 @@
     source->format->type = format_type;
     source->format->mount = source->mount;
     source->format->parser = parser;
-    if (format_get_plugin (source->format) < 0)
+    if (format_get_plugin (source->format, client) < 0)
     {
         WARN1 ("plugin format failed for \"%s\"", source->mount);
         return -1;
@@ -1162,7 +1162,7 @@
         int len = strcspn (pattern, " ");
         if (strncmp (extension, pattern, len) == 0 && extension[len] == '\0')
         {
-            httpp_setvar (client->parser, "__avoid_access_log", "");
+            client->flags |= CLIENT_SKIP_ACCESSLOG;
             return;
         }
         pattern += len;

Modified: icecast/branches/kh/icecast/src/format.c
===================================================================
--- icecast/branches/kh/icecast/src/format.c	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/format.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -55,18 +55,24 @@
         return FORMAT_TYPE_OGG;
     else if(strcmp(contenttype, "video/ogg") == 0)
         return FORMAT_TYPE_OGG;
+    else if(strcmp(contenttype, "audio/aac") == 0)
+        return FORMAT_TYPE_AAC;
+    else if(strcmp(contenttype, "audio/aacp") == 0)
+        return FORMAT_TYPE_AAC;
+    else if(strcmp(contenttype, "audio/mpeg") == 0)
+        return FORMAT_TYPE_MPEG;
     else
         /* We default to the Generic format handler, which
            can handle many more formats than just mp3 */
         return FORMAT_TYPE_GENERIC;
 }
 
-void format_plugin_clear (format_plugin_t *format)
+void format_plugin_clear (format_plugin_t *format, client_t *client)
 {
     if (format == NULL)
         return;
     if (format->free_plugin)
-        format->free_plugin (format);
+        format->free_plugin (format, client);
     rate_free (format->in_bitrate);
     rate_free (format->out_bitrate);
     free (format->charset);
@@ -74,19 +80,24 @@
 }
 
 
-int format_get_plugin (format_plugin_t *plugin)
+int format_get_plugin (format_plugin_t *plugin, client_t *client)
 {
     int ret = -1;
 
-    switch (plugin->type) {
-    case FORMAT_TYPE_OGG:
-        ret = format_ogg_get_plugin (plugin);
-        break;
-    case FORMAT_TYPE_GENERIC:
-        ret = format_mp3_get_plugin (plugin);
-        break;
-    default:
-        break;
+    if (client)
+        plugin->parser = client->parser;
+    switch (plugin->type)
+    {
+        case FORMAT_TYPE_OGG:
+            ret = format_ogg_get_plugin (plugin, client);
+            break;
+        case FORMAT_TYPE_AAC:
+        case FORMAT_TYPE_MPEG:
+        case FORMAT_TYPE_GENERIC:
+            ret = format_mp3_get_plugin (plugin, client);
+            break;
+        default:
+            break;
     }
 
     return ret;
@@ -165,10 +176,17 @@
     {
         const char *useragent = httpp_getvar (client->parser, "user-agent");
         const char *protocol = "HTTP/1.0";
-        if (useragent && strstr(useragent, "shoutcastsource")) /* hack for mpc */
-            protocol = "ICY";
+        const char *contenttypehdr = "Content-Type";
+
+        if (useragent)
+        {
+            if (strstr (useragent, "shoutcastsource")) /* hack for mpc */
+                protocol = "ICY";
+            if (strstr (useragent, "Shoutcast Server")) /* hack for sc_serv */
+                contenttypehdr = "content-type";
+        }
         bytes = snprintf (ptr, remaining, "%s 200 OK\r\n"
-                "content-type: %s\r\n", protocol, plugin->contenttype);
+                "%s: %s\r\n", protocol, contenttypehdr, plugin->contenttype);
         remaining -= bytes;
         ptr += bytes;
         client->respcode = 200;

Modified: icecast/branches/kh/icecast/src/format.h
===================================================================
--- icecast/branches/kh/icecast/src/format.h	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/format.h	2010-03-29 02:14:55 UTC (rev 17097)
@@ -28,6 +28,8 @@
 {
     FORMAT_ERROR, /* No format, source not processable */
     FORMAT_TYPE_OGG,
+    FORMAT_TYPE_AAC,
+    FORMAT_TYPE_MPEG,
     FORMAT_TYPE_GENERIC
 } format_type_t;
 
@@ -53,7 +55,7 @@
     void (*write_buf_to_file)(struct source_tag *source, refbuf_t *refbuf);
     int (*create_client_data)(format_plugin_t *plugin, client_t *client);
     void (*set_tag)(struct _format_plugin_tag *plugin, const char *tag, const char *value, const char *charset);
-    void (*free_plugin)(struct _format_plugin_tag *self);
+    void (*free_plugin)(struct _format_plugin_tag *self, client_t *client);
     void (*apply_settings)(struct _format_plugin_tag *format, struct _mount_proxy *mount);
     int (*get_image)(client_t *client, struct _format_plugin_tag *format);
 
@@ -62,7 +64,7 @@
 };
 
 format_type_t format_get_type(const char *contenttype);
-int format_get_plugin (format_plugin_t *plugin);
+int format_get_plugin (format_plugin_t *plugin, client_t *client);
 int format_generic_write_to_client (client_t *client);
 
 int format_file_read (client_t *client, FILE *fp);
@@ -71,7 +73,7 @@
 void format_send_general_headers(format_plugin_t *format, 
         struct source_tag *source, client_t *client);
 
-void format_plugin_clear (format_plugin_t *format);
+void format_plugin_clear (format_plugin_t *format, client_t *client);
 
 #endif  /* __FORMAT_H__ */
 

Modified: icecast/branches/kh/icecast/src/format_mp3.c
===================================================================
--- icecast/branches/kh/icecast/src/format_mp3.c	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/format_mp3.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -39,6 +39,7 @@
 #include "logging.h"
 
 #include "format_mp3.h"
+#include "mpeg.h"
 
 #define CATMODULE "format-mp3"
 
@@ -47,13 +48,13 @@
  */
 #define ICY_METADATA_INTERVAL 16000
 
-static void format_mp3_free_plugin(format_plugin_t *plugin);
+static void format_mp3_free_plugin(format_plugin_t *plugin, client_t *client);
 static refbuf_t *mp3_get_filter_meta (source_t *source);
 static refbuf_t *mp3_get_no_meta (source_t *source);
 
 static int  format_mp3_create_client_data (format_plugin_t *plugin, client_t *client);
 static void free_mp3_client_data (client_t *client);
-static int format_mp3_write_buf_to_client(client_t *client);
+static int  format_mp3_write_buf_to_client(client_t *client);
 static void write_mp3_to_file (struct source_tag *source, refbuf_t *refbuf);
 static void mp3_set_tag (format_plugin_t *plugin, const char *tag, const char *in_value, const char *charset);
 static void format_mp3_apply_settings (format_plugin_t *format, mount_proxy *mount);
@@ -73,7 +74,7 @@
 static refbuf_t blank_meta = { 17, 1, "\001StreamTitle='';", NULL, NULL, 0 };
 
 
-int format_mp3_get_plugin (format_plugin_t *plugin)
+int format_mp3_get_plugin (format_plugin_t *plugin, client_t *client)
 {
     const char *metadata;
     mp3_state *state = calloc(1, sizeof(mp3_state));
@@ -115,7 +116,14 @@
             state->interval = state->inline_metadata_interval;
         }
     }
-    thread_mutex_create (&state->url_lock);
+    if (client)
+    {
+        if (plugin->type == FORMAT_TYPE_AAC || plugin->type == FORMAT_TYPE_MPEG)
+        {
+            client->format_data = malloc (sizeof (mpeg_sync));
+            mpeg_setup (client->format_data);
+        }
+    }
 
     return 0;
 }
@@ -126,13 +134,9 @@
     mp3_state *source_mp3 = plugin->_state;
     char *value = NULL;
 
-    /* protect against multiple updaters */
-    thread_mutex_lock (&source_mp3->url_lock);
-
     if (tag==NULL)
     {
         source_mp3->update_metadata = 1;
-        thread_mutex_unlock (&source_mp3->url_lock);
         return;
     }
 
@@ -170,7 +174,6 @@
     }
     else
         free (value);
-    thread_mutex_unlock (&source_mp3->url_lock);
 }
 
 
@@ -248,9 +251,6 @@
     unsigned int len = sizeof(streamtitle) + 2; /* the StreamTitle, quotes, ; and null */
     mp3_state *source_mp3 = source->format->_state;
 
-    /* make sure the url data does not disappear from under us */
-    thread_mutex_lock (&source_mp3->url_lock);
-
     /* work out message length */
     if (source_mp3->url_artist)
         len += strlen (source_mp3->url_artist);
@@ -269,7 +269,6 @@
 #define MAX_META_LEN 255*16
     if (len > MAX_META_LEN)
     {
-        thread_mutex_unlock (&source_mp3->url_lock);
         WARN1 ("Metadata too long at %d chars", len);
         return;
     }
@@ -315,7 +314,6 @@
         refbuf_release (source_mp3->metadata);
         source_mp3->metadata = p;
     }
-    thread_mutex_unlock (&source_mp3->url_lock);
 }
 
 
@@ -480,12 +478,17 @@
     return written == 0 ? -1 : written;
 }
 
-static void format_mp3_free_plugin (format_plugin_t *plugin)
+static void format_mp3_free_plugin (format_plugin_t *plugin, client_t *client)
 {
     /* free the plugin instance */
     mp3_state *format_mp3 = plugin->_state;
 
-    thread_mutex_destroy (&format_mp3->url_lock);
+    if (client)
+    {
+        mpeg_cleanup (client->format_data);
+        free (client->format_data);
+        client->format_data = NULL;
+    }
     free (format_mp3->url_artist);
     free (format_mp3->url_title);
     free (format_mp3->url);
@@ -535,11 +538,47 @@
 }
 
 
+static int validate_mpeg (mp3_state *source_mp3, mpeg_sync *mpeg_sync, refbuf_t *refbuf)
+{
+    int unprocessed = mpeg_complete_frames (mpeg_sync, refbuf, 0);
+    if (unprocessed < 0)
+        return -1;
+    if (unprocessed > 0)
+    {
+        /* make sure the new block has a minimum of queue_block_size */
+        size_t len = unprocessed > source_mp3->queue_block_size ? unprocessed : source_mp3->queue_block_size;
+        refbuf_t *leftover = refbuf_new (len);
+        memcpy (leftover->data, refbuf->data + refbuf->len, unprocessed);
+        leftover->len = unprocessed;
+
+        if (source_mp3->inline_metadata_interval > 0)
+        {
+            /* inline metadata may need reading before the rest of the mpeg data */
+            if (source_mp3->build_metadata_len == 0 && source_mp3->offset > unprocessed)
+            {
+                source_mp3->offset -= unprocessed;
+                source_mp3->read_data = leftover;
+                source_mp3->read_count = unprocessed;
+            }
+            else
+                mpeg_data_insert (mpeg_sync, leftover); /* will need to merge this after metadata */
+        }
+        else
+        {
+            source_mp3->read_data = leftover;
+            source_mp3->read_count = unprocessed;
+        }
+    }
+    return 0;
+}
+
+
 /* read an mp3 stream which does not have shoutcast style metadata */
 static refbuf_t *mp3_get_no_meta (source_t *source)
 {
     refbuf_t *refbuf;
     mp3_state *source_mp3 = source->format->_state;
+    client_t *client = source->client;  // maybe move mp3_state into client instead of plugin?
 
     if (complete_read (source) == 0)
         return NULL;
@@ -547,6 +586,11 @@
     refbuf = source_mp3->read_data;
     source_mp3->read_data = NULL;
 
+    if (client->format_data && validate_mpeg (source_mp3, client->format_data, refbuf) < 0)
+    {
+        refbuf_release (refbuf);
+        return NULL;
+    }
     source->client->queue_pos += refbuf->len;
     if (source_mp3->update_metadata)
     {
@@ -569,6 +613,7 @@
     refbuf_t *refbuf;
     format_plugin_t *plugin = source->format;
     mp3_state *source_mp3 = plugin->_state;
+    client_t *client = source->client;  // maybe move mp3_state into client instead of plugin?
     unsigned char *src;
     unsigned int bytes, mp3_block;
 
@@ -679,6 +724,11 @@
         refbuf_release (refbuf);
         return NULL;
     }
+    if (client->format_data && validate_mpeg (source_mp3, client->format_data, refbuf) < 0)
+    {
+        refbuf_release (refbuf);
+        return NULL;
+    }
     source->client->queue_pos += refbuf->len;
     refbuf->associated = source_mp3->metadata;
     refbuf_addref (source_mp3->metadata);

Modified: icecast/branches/kh/icecast/src/format_mp3.h
===================================================================
--- icecast/branches/kh/icecast/src/format_mp3.h	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/format_mp3.h	2010-03-29 02:14:55 UTC (rev 17097)
@@ -18,6 +18,8 @@
 #ifndef __FORMAT_MP3_H__
 #define __FORMAT_MP3_H__
 
+#include "format.h"
+
 typedef struct {
     /* These are for inline metadata */
     int inline_metadata_interval;
@@ -33,13 +35,12 @@
     refbuf_t *metadata;
     refbuf_t *read_data;
     int read_count;
-    mutex_t url_lock;
 
     unsigned build_metadata_len;
     unsigned build_metadata_offset;
     char build_metadata[4081];
 } mp3_state;
 
-int format_mp3_get_plugin (format_plugin_t *plugin);
+int format_mp3_get_plugin (format_plugin_t *plugin, client_t *client);
 
 #endif  /* __FORMAT_MP3_H__ */

Modified: icecast/branches/kh/icecast/src/format_ogg.c
===================================================================
--- icecast/branches/kh/icecast/src/format_ogg.c	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/format_ogg.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -50,7 +50,7 @@
 
 struct _ogg_state_tag;
 
-static void format_ogg_free_plugin (format_plugin_t *plugin);
+static void format_ogg_free_plugin (format_plugin_t *plugin, client_t *client);
 static int  create_ogg_client_data(format_plugin_t *plugin, client_t *client);
 static void free_ogg_client_data (client_t *client);
 
@@ -155,7 +155,7 @@
 }
 
 
-int format_ogg_get_plugin (format_plugin_t *plugin)
+int format_ogg_get_plugin (format_plugin_t *plugin, client_t *client)
 {
     ogg_state_t *state = calloc (1, sizeof (ogg_state_t));
 
@@ -187,7 +187,7 @@
 }
 
 
-static void format_ogg_free_plugin (format_plugin_t *plugin)
+static void format_ogg_free_plugin (format_plugin_t *plugin, client_t *client)
 {
     ogg_state_t *state = plugin->_state;
 

Modified: icecast/branches/kh/icecast/src/format_ogg.h
===================================================================
--- icecast/branches/kh/icecast/src/format_ogg.h	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/format_ogg.h	2010-03-29 02:14:55 UTC (rev 17097)
@@ -72,6 +72,6 @@
 refbuf_t *make_refbuf_with_page (ogg_codec_t *codec, ogg_page *page);
 void format_ogg_attach_header (ogg_codec_t *codec, ogg_page *page);
 void format_ogg_free_headers (ogg_state_t *ogg_info);
-int  format_ogg_get_plugin (format_plugin_t *plugin);
+int  format_ogg_get_plugin (format_plugin_t *plugin, client_t *client);
 
 #endif  /* __FORMAT_OGG_H__ */

Modified: icecast/branches/kh/icecast/src/fserve.c
===================================================================
--- icecast/branches/kh/icecast/src/fserve.c	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/fserve.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -201,7 +201,7 @@
     stats_event (fh->finfo.mount, NULL, NULL);
     if (fh->format)
     {
-        format_plugin_clear (fh->format);
+        format_plugin_clear (fh->format, NULL);
         free (fh->format);
     }
     avl_tree_free (fh->clients, NULL);
@@ -286,7 +286,7 @@
             fh->format->type = format_get_type (contenttype);
             free (contenttype);
             fh->format->mount = fh->finfo.mount;
-            if (format_get_plugin (fh->format) < 0)
+            if (format_get_plugin (fh->format, NULL) < 0)
             {
                 avl_tree_unlock (fh_cache);
                 free (fullpath);
@@ -760,6 +760,13 @@
     time_t now = client->worker->current_time.tv_sec;
 
     client->schedule_ms = client->worker->time_ms;
+    /* slowdown if max bandwidth is exceeded, but allow for short-lived connections to avoid 
+     * this, eg admin requests */
+    if (throttle_sends > 1 && now - client->connection.con_time > 1)
+    {
+        client->schedule_ms += 500;
+        loop = 1; 
+    }
     while (loop && written < 30000)
     {
         loop--;
@@ -827,6 +834,7 @@
             /* loop fallback file  */
             thread_mutex_unlock (&fh->lock);
             client->intro_offset = 0;
+            client->pos = refbuf->len = 0;
             client->schedule_ms = client->worker->time_ms + 150;
             return 0;
         }
@@ -840,6 +848,10 @@
     global_add_bitrates (global.out_bitrate, bytes, client->worker->time_ms);
     client->counter += bytes;
     client->schedule_ms = client->worker->time_ms + (1000/(fh->finfo.limit/1400*2));
+
+    /* progessive slowdown if max bandwidth is exceeded. */
+    if (throttle_sends > 1)
+        client->schedule_ms += 300;
     return 0;
 }
 

Modified: icecast/branches/kh/icecast/src/global.c
===================================================================
--- icecast/branches/kh/icecast/src/global.c	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/global.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -48,7 +48,7 @@
     thread_mutex_create(&_global_mutex);
     thread_spin_create (&global.spinlock);
     thread_rwlock_create (&global.shutdown_lock);
-    global.out_bitrate = rate_setup (10000, 1000);
+    global.out_bitrate = rate_setup (20000, 1000);
 }
 
 void global_shutdown(void)
@@ -76,8 +76,23 @@
 
 void global_add_bitrates (struct rate_calc *rate, unsigned long value, uint64_t milli)
 {
+    float avg;
     thread_spin_lock (&global.spinlock);
     rate_add (rate, value, milli);
+    avg = rate_avg (rate);
+
+    if (global.max_rate)
+    {
+        float ratio = avg / global.max_rate;
+        if (ratio > 0.99)
+            throttle_sends = 3;
+        else if (ratio > 0.9)
+            throttle_sends = 2;
+        else if (ratio > 0.8)
+            throttle_sends = 1;
+        else if (throttle_sends > 0)
+            throttle_sends--;
+    }
     thread_spin_unlock (&global.spinlock);
 }
 

Modified: icecast/branches/kh/icecast/src/global.h
===================================================================
--- icecast/branches/kh/icecast/src/global.h	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/global.h	2010-03-29 02:14:55 UTC (rev 17097)
@@ -53,12 +53,18 @@
     /* redirection to slaves */
     unsigned int redirect_count;
 
+    /* a copy of what is in the config xml */
+    int64_t max_rate;
+
     spin_t spinlock;
     struct rate_calc *out_bitrate;
 
     cond_t shutdown_cond;
 } ice_global_t;
 
+extern unsigned int throttle_sends;
+
+
 #ifdef MY_ALLOC
 #define calloc(x,y) my_calloc(__func__,__LINE__,x,y)
 #define malloc(x) my_calloc(__func__,__LINE__,1,x)

Modified: icecast/branches/kh/icecast/src/logging.c
===================================================================
--- icecast/branches/kh/icecast/src/logging.c	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/logging.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -114,7 +114,7 @@
     time_t stayed;
     const char *referrer, *user_agent, *username, *ip = "-";
 
-    if (httpp_getvar (client->parser, "__avoid_access_log"))
+    if (client->flags & CLIENT_SKIP_ACCESSLOG)
         return;
 
     now = time(NULL);
@@ -231,7 +231,7 @@
         if (*id < 0)
         {
             char buf[1024];
-            snprintf (buf,1024, "FATAL: could not open log %s: %s", fn, strerror(errno));
+            snprintf (buf,1024, "could not open log %s: %s", fn, strerror(errno));
             fatal_error (buf);
             return -1;
         }

Modified: icecast/branches/kh/icecast/src/main.c
===================================================================
--- icecast/branches/kh/icecast/src/main.c	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/main.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -76,7 +76,7 @@
 #elif defined(WIN32)
     MessageBox(NULL, perr, "Error", MB_OK);
 #else
-    fprintf(stdout, "%s\n", perr);
+    ERROR1("%s", perr);
 #endif
 }
 

Added: icecast/branches/kh/icecast/src/mpeg.c
===================================================================
--- icecast/branches/kh/icecast/src/mpeg.c	                        (rev 0)
+++ icecast/branches/kh/icecast/src/mpeg.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -0,0 +1,282 @@
+/* Icecast
+ *
+ * This program is distributed under the GNU General Public License, version 2.
+ * A copy of this license is included with this source.
+ *
+ * Copyright 2009-2010,  Karl Heyes <karl at xiph.org>
+ */
+
+/* mpeg.c
+ *
+ * routines to handle locating the frame sync markers for mpeg/1/2/3/aac streams.
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "compat.h"
+#include "mpeg.h"
+#include "format_mp3.h"
+
+#define CATMODULE "mpeg"
+#include "logging.h"
+
+int aacp_sample_freq[] = {
+    96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, -1, -1, -1, -1
+};
+
+int aacp_num_channels[] = {
+    -1, 1, 2, 3, 4, 5, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+#define LAYER_1     3
+#define LAYER_2     2
+#define LAYER_3     1
+
+
+static int get_aac_frame_len (unsigned char *p)
+{
+    return ((p[3] & 0x3) << 11) + (p[4] << 3) + ((p[5] & 0xE0) >> 5);
+}
+
+static int handle_aac_frame (struct mpeg_sync *mp, unsigned char *p, int len)
+{
+    int frame_len = get_aac_frame_len (p);
+    if (len - frame_len < 0)
+        return 0;
+
+    return frame_len;
+}
+
+static int get_mpeg_bitrate (struct mpeg_sync *mp, unsigned char *p)
+{
+    int bitrate = -1;
+    int bitrate_code = (p[2] & 0xF0) >> 4;
+
+    if (mp->ver == 3) // MPEG1
+    {
+        static int bitrates [3][16] = {
+            { 0, 32, 40, 48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, -1 },
+            { 0, 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 348, -1 },
+            { 0, 32, 54, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, -1 } };
+        if (mp->layer != 0)
+            bitrate = bitrates [mp->layer-1][bitrate_code];
+    }
+    else // MPEG2/2.5
+    {
+        static int bitrates [2][16] = { 
+            { 0,  8, 16, 24, 32, 40, 48,  56,  64,  80,  96, 112, 128, 144, 160, -1 },
+            { 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, -1 } };
+        if (mp->layer == 3)
+            bitrate = bitrates [1][bitrate_code];
+        else
+            bitrate = bitrates [0][bitrate_code];
+    }
+    return bitrate;
+}
+
+
+static int get_frame_samples (struct mpeg_sync *mp, unsigned char *p)
+{
+    int padding = (p[2] & 0x2) >> 1;
+    int frame_len = 0;
+
+    int64_t bitrate = get_mpeg_bitrate (mp, p);
+    if (bitrate > 0)
+    {
+        bitrate *= 1000;
+        if (mp->layer == LAYER_1)
+        {
+            frame_len = (12 * bitrate / mp->samplerate + padding) * 4;
+        }
+        else
+        {
+            frame_len = 144 * bitrate / mp->samplerate + padding;
+        }
+    }
+    return frame_len;
+}
+
+
+static int handle_mpeg_frame (struct mpeg_sync *mp, unsigned char *p, int remaining)
+{
+    int frame_len = get_frame_samples (mp, p);
+
+    if (remaining - frame_len < 0)
+        return 0;
+    return frame_len;
+}
+
+
+static int get_initial_frame (struct mpeg_sync *mp, unsigned char *p, unsigned remaining)
+{
+    if (p[1] < 0xE0) 
+        return 0;
+    mp->layer = (p[1] & 0x6) >> 1;
+    //nocrc = p[1] & 0x1;
+    if (mp->layer == 0 && (p[1] >= 0xF0))
+    {
+        int frame_len;
+        int samplerate_idx = (p[2] & 0x3C) >> 2,
+            v = (p[2] << 8) + p[3],
+            channels_idx = (v & 0x1C0) >> 6;
+        int id =  p[1] & 0x8;
+
+        frame_len = get_aac_frame_len (p);
+        if (frame_len >= remaining || p[frame_len] != 255)
+            return -1;
+        // profile = p[1] & 0xC0;
+        mp->samplerate = aacp_sample_freq [samplerate_idx];
+        mp->channels = aacp_num_channels [channels_idx];
+        if (mp->samplerate == -1 || mp->channels == -1)
+        {
+            DEBUG0 ("ADTS samplerate/channel setting invalid");
+            return -1;
+        }
+        mp->syncbytes = 3;
+        memcpy (&mp->fixed_headerbits[0], p, 3);
+        //mp->samplerate <<= 1;
+        DEBUG3 ("detected AAC MPEG-%s, rate %d, channels %d", id ? "2" : "4", mp->samplerate, mp->channels);
+        mp->process_frame = handle_aac_frame;
+        return 1;
+    }
+    if (mp->layer && (p[1] >= 0xE0))
+    {
+        const char *version[] = { "MPEG 2.5", NULL, "MPEG 2", "MPEG 1" };
+        const char *layer[] =   { NULL, "Layer 3", "Layer 2", "Layer 1" };
+        mp->ver = (p[1] & 0x18) >> 3;
+        if (mp->layer && version [mp->ver] && layer[mp->layer]) 
+        {
+            int frame_len;
+            int samplerates [4][4] = {
+                { 11025, 0, 22050, 44100},
+                { 12000, 0, 24000, 48000 },
+                {  8000, 0, 16000, 32000 },
+                { 0,0,0 } };
+
+            // au.crc = (p[1] & 0x1) == 0;
+            mp->samplerate = samplerates [(p[2]&0xC) >> 2][mp->ver];
+            if (mp->samplerate == 0)
+                return -1;
+            frame_len = get_frame_samples (mp, p);
+            if (frame_len > 0)
+            {
+                if (frame_len >= remaining || p[frame_len] != 255)
+                    return -1;
+                if  (((p[3] & 0xC0) >> 6) == 3)
+                    mp->channels = 1;
+                else
+                    mp->channels = 2;
+                mp->syncbytes = 2;
+                memcpy (&mp->fixed_headerbits[0], p, 2);
+                //DEBUG4 ("%s %s detected (%d, %d)", version [mp->ver], layer[mp->layer], mp->samplerate, mp->channels);
+                mp->process_frame = handle_mpeg_frame;
+                return 1;
+            }
+        }
+    }
+    return 0;
+}
+
+
+/* return number from 1 to remaining */
+static int find_align_sync (unsigned char *start, int remaining)
+{
+    unsigned char *p = memchr (start, 255, remaining);
+    if (p)
+    {
+        remaining -= (p - start);
+        memmove (start, p, remaining);
+    }
+    return remaining;
+}
+
+
+int mpeg_complete_frames (mpeg_sync *mp, refbuf_t *new_block, unsigned offset)
+{
+    unsigned char *start, *end;
+    int remaining, frame_len = 0, completed = 0;
+
+    if (mp == NULL)
+        return 0;  /* leave as-is */
+    
+    if (mp->surplus)
+    {
+        int new_len = mp->surplus->len + new_block->len;
+        unsigned char *p = realloc (mp->surplus->data, new_len);
+
+        memcpy (p+mp->surplus->len, new_block->data, new_block->len);
+        mp->surplus->data = new_block->data;
+        new_block->data = (void*)p;
+        new_block->len = new_len;
+        refbuf_release (mp->surplus);
+        mp->surplus = NULL;
+    }
+    start = (unsigned char *)new_block->data + offset;
+    remaining = new_block->len - offset;
+    end = start + remaining;
+    while (1)
+    {
+        remaining = end - start;
+        if (remaining < 10)
+            break;
+        if (*start != 255)
+        {
+            // need to resync
+            int ret = find_align_sync (start, remaining);
+            if (ret == remaining)
+                break; // no sync in the rest, so dump it
+            new_block->len -= (remaining - ret);
+            remaining = ret;
+            end = start + remaining;
+        }
+        if (mp->syncbytes == 0)
+        {
+            if (get_initial_frame (mp, start, remaining) <= 0)
+            {
+                // no a complete frame not here, try again
+                start++;
+                continue;
+            }
+        }
+        if (memcmp (start, &mp->fixed_headerbits[0], mp->syncbytes) != 0)
+        {
+            start++;
+            continue;
+        }
+        frame_len = mp->process_frame (mp, start, remaining);
+        if (frame_len <= 0)  // frame fragment at the end
+            break;
+        start += frame_len;
+        completed++;
+    }
+    if (completed == 0)
+        return -1;
+    new_block->len -= remaining;
+    return remaining;
+}
+
+
+void mpeg_data_insert (mpeg_sync *mp, refbuf_t *inserted)
+{
+    if (mp)
+        mp->surplus = inserted;
+}
+
+void mpeg_setup (mpeg_sync *mpsync)
+{
+    memset (mpsync, 0, sizeof (mpeg_sync));
+}
+
+void mpeg_cleanup (mpeg_sync *mpsync)
+{
+    if (mpsync)
+    {
+        refbuf_release (mpsync->surplus);
+    }
+}

Added: icecast/branches/kh/icecast/src/mpeg.h
===================================================================
--- icecast/branches/kh/icecast/src/mpeg.h	                        (rev 0)
+++ icecast/branches/kh/icecast/src/mpeg.h	2010-03-29 02:14:55 UTC (rev 17097)
@@ -0,0 +1,37 @@
+/* Icecast
+ *
+ * This program is distributed under the GNU General Public License, version 2.
+ * A copy of this license is included with this source.
+ *
+ * Copyright 2009-2010,  Karl Heyes <karl at xiph.org>
+ */
+
+/* mpeg.c
+ *
+ * routines to handle locating the frame sync markers for mpeg/1/2/3/aac streams.
+ *
+ */
+#ifndef __MPEG_SYNC_H
+#define __MPEG_SYNC_H
+
+#include "refbuf.h"
+
+typedef struct mpeg_sync
+{
+    unsigned char fixed_headerbits[3];
+    int syncbytes;
+    int (*process_frame) (struct mpeg_sync *mp, unsigned char *p, int len);
+    refbuf_t *surplus;
+    int ver;
+    int layer;
+    int samplerate;
+    int channels;
+} mpeg_sync;
+
+void mpeg_setup (mpeg_sync *mpsync);
+void mpeg_cleanup (mpeg_sync *mpsync);
+
+int  mpeg_complete_frames (mpeg_sync *mp, refbuf_t *new_block, unsigned offset);
+void mpeg_data_insert (mpeg_sync *mp, refbuf_t *inserted);
+
+#endif /* __MPEG_SYNC_H */

Modified: icecast/branches/kh/icecast/src/source.c
===================================================================
--- icecast/branches/kh/icecast/src/source.c	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/source.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -292,7 +292,7 @@
         source->dumpfile = NULL;
     }
 
-    format_plugin_clear (source->format);
+    format_plugin_clear (source->format, source->client);
 
     /* flush out the stream data, we don't want any left over */
 
@@ -391,13 +391,13 @@
  */
 static void update_source_stats (source_t *source)
 {
-    unsigned long incoming_rate = 8 * rate_avg (source->format->in_bitrate);
+    unsigned long incoming_rate = (long)(8 * rate_avg (source->format->in_bitrate));
     unsigned long kbytes_sent = source->bytes_sent_since_update/1024;
     unsigned long kbytes_read = source->bytes_read_since_update/1024;
 
     source->format->sent_bytes += kbytes_sent*1024;
     stats_event_args (source->mount, "outgoing_kbitrate", "%ld",
-            (8 * rate_avg (source->format->out_bitrate))/1024);
+            (long)(8 * rate_avg (source->format->out_bitrate))/1024);
     stats_event_args (source->mount, "incoming_bitrate", "%ld", incoming_rate);
     stats_event_args (source->mount, "total_bytes_read",
             "%"PRIu64, source->format->read_bytes);
@@ -468,7 +468,10 @@
             if (source->limit_rate < incoming_rate)
             {
                 rate_add (source->format->in_bitrate, 0, current);
-                break;
+                source->skip_duration += 300;
+                client->schedule_ms = client->worker->time_ms + 150;
+                thread_mutex_unlock (&source->lock);
+                return 0;
             }
         }
         fds = util_timed_wait_for_fd (client->connection.sock, 0);
@@ -492,15 +495,14 @@
                 skip = 0;
                 break;
             }
-            if (source->skip_duration < 20)
-                source->skip_duration = 30;
-            else
-                source->skip_duration = (long)(source->skip_duration * 1.8);
-                if (source->skip_duration > 700)
-                    source->skip_duration = 700;
+            source->skip_duration = (long)(source->skip_duration * 1.8);
+            if (source->skip_duration > 700)
+                source->skip_duration = 700;
             break;
         }
         source->skip_duration = (long)(source->skip_duration * 0.9);
+        if (source->skip_duration < 5)
+            source->skip_duration = 5;
 
         skip = 0;
         source->last_read = current;
@@ -742,6 +744,8 @@
         client->check_buffer = http_source_intro;
         return -1;
     }
+    if (source->queue_size == 0)
+        return -1;  /* postpone processing until data on queue */
 
     if (client->respcode == 0)
     {
@@ -787,7 +791,19 @@
 {
     if (client->check_buffer != http_source_listener)
     {
+        refbuf_t *ref = client->refbuf;
+
         client->check_buffer = source->format->write_buf_to_client;
+        if (ref && client->pos < ref->len && ref->flags&SOURCE_QUEUE_BLOCK)
+        {
+            /* make a private copy so that a write can complete */
+            refbuf_t *orig = ref;
+            ref = refbuf_new (ref->len);
+            memcpy (ref->data, orig->data, orig->len);
+            refbuf_release (client->refbuf);
+            client->refbuf = ref;
+            client->flags |= CLIENT_HAS_INTRO_CONTENT;
+        }
         if ((client->flags & CLIENT_HAS_INTRO_CONTENT) == 0)
             client_set_queue (client, NULL);
     }
@@ -819,7 +835,7 @@
     thread_mutex_lock (&source->lock);
     ret = send_listener (source, client);
     if (ret == 1)
-        return 0;
+        return 1; // client moved, and source unlocked
     if (ret < 0)
         ret = source_listener_release (source, client);
     thread_mutex_unlock (&source->lock);
@@ -892,7 +908,28 @@
         if (listener_change_worker (client, source))
             return 1;
 
+    /* progessive slowdown if nearing max bandwidth.  */
     client->schedule_ms = client->worker->time_ms;
+    if (global.max_rate)
+    {
+        if (throttle_sends > 2) /* exceeded limit, skip 30ms */
+        {
+            client->schedule_ms += 30;
+            return 0;
+        }
+        if (throttle_sends > 1) /* slow down any multiple sends */
+        {
+            loop = 2;
+            client->schedule_ms += 50;
+        }
+        if (throttle_sends > 0)
+        {
+            /* make lagging listeners, lag further on high bandwidth use */
+            if (source->client->queue_pos - client->queue_pos > 8192)
+                client->schedule_ms += 150;
+        }
+    }
+
     while (loop)
     {
         /* jump out if client connection has died */
@@ -1603,13 +1640,13 @@
     if (source->format)
         client->connection.sent_bytes = source->format->read_bytes;
 
-    client_destroy (client);
     source_clear_listeners (source);
     thread_mutex_unlock (&source->lock);
 
     source_free_source (source);
     thread_rwlock_unlock (&global.shutdown_lock);
     slave_update_all_mounts();
+    client_destroy (client);
 }
 
 

Modified: icecast/branches/kh/icecast/src/stats.c
===================================================================
--- icecast/branches/kh/icecast/src/stats.c	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/stats.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -123,6 +123,7 @@
 static void stats_listener_send (int flags, const char *fmt, ...);
 static void process_event_unlocked (stats_event_t *event);
 
+unsigned int throttle_sends;
 
 /* simple helper function for creating an event */
 static void build_event (stats_event_t *event, const char *source, const char *name, const char *value)
@@ -686,6 +687,10 @@
     stats_event_flags (NULL, "host", config->hostname, STATS_GENERAL);
     stats_event (NULL, "location", config->location);
     stats_event (NULL, "admin", config->admin);
+    thread_spin_lock (&global.spinlock);
+    global.max_rate = config->max_bandwidth;
+    throttle_sends = 0;
+    thread_spin_unlock (&global.spinlock);
 #if 0
     /* restart a master stats connection */
     config->master = calloc (1, sizeof ice_master_details);

Modified: icecast/branches/kh/icecast/src/util.c
===================================================================
--- icecast/branches/kh/icecast/src/util.c	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/util.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -781,7 +781,7 @@
 /* return the average sample value over all the blocks except the 
  * current one, as that may be incomplete
  */
-long rate_avg (struct rate_calc *calc)
+float rate_avg (struct rate_calc *calc)
 {
     float range;
 
@@ -790,7 +790,7 @@
     range = (calc->current->index - calc->current->next->index) + 1;
     if (range < 1)
         range = 1;
-    return (long)(calc->total / range * calc->ssec);
+    return calc->total / range * calc->ssec;
 }
 
 /* reduce the samples used to calculate average */

Modified: icecast/branches/kh/icecast/src/util.h
===================================================================
--- icecast/branches/kh/icecast/src/util.h	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/util.h	2010-03-29 02:14:55 UTC (rev 17097)
@@ -59,7 +59,7 @@
 
 struct rate_calc *rate_setup (unsigned int samples, unsigned int ssec);
 void rate_add (struct rate_calc *calc, long value, uint64_t t);
-long rate_avg (struct rate_calc *calc);
+float rate_avg (struct rate_calc *calc);
 void rate_free (struct rate_calc *calc);
 void rate_reduce (struct rate_calc *calc, unsigned int range);
 

Modified: icecast/branches/kh/icecast/src/xslt.c
===================================================================
--- icecast/branches/kh/icecast/src/xslt.c	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/src/xslt.c	2010-03-29 02:14:55 UTC (rev 17097)
@@ -203,7 +203,7 @@
 
     res = xsltApplyStylesheet(cur, doc, NULL);
 
-    if (xsltSaveResultToString (&string, &len, res, cur) < 0)
+    if (res == NULL || xsltSaveResultToString (&string, &len, res, cur) < 0)
         problem = 1;
 
     /* lets find out the content type to use */

Modified: icecast/branches/kh/icecast/web/Makefile.am
===================================================================
--- icecast/branches/kh/icecast/web/Makefile.am	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/web/Makefile.am	2010-03-29 02:14:55 UTC (rev 17097)
@@ -9,6 +9,7 @@
                 style.css \
                 auth.xsl \
                 server_version.xsl \
+                7.xsl \
                 adminbar.html \
                 statusbar.html \
                 admin.html \

Modified: icecast/branches/kh/icecast/win32/icecast.dsp
===================================================================
--- icecast/branches/kh/icecast/win32/icecast.dsp	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/win32/icecast.dsp	2010-03-29 02:14:55 UTC (rev 17097)
@@ -86,57 +86,22 @@
 # Begin Source File
 
 SOURCE=..\src\admin.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\auth.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\auth_htpasswd.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\auth_url.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\avl\avl.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
@@ -154,35 +119,14 @@
 # Begin Source File
 
 SOURCE=..\src\client.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\connection.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\event.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
@@ -200,310 +144,118 @@
 # Begin Source File
 
 SOURCE=..\src\format.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\format_flac.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\format_kate.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\format_midi.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\format_mp3.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\format_ogg.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\format_skeleton.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\format_speex.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\format_theora.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\format_vorbis.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\fserve.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\global.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\httpp\httpp.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\log\log.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\logging.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\md5.c
+# End Source File
+# Begin Source File
 
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
+SOURCE=\src\mpeg.c
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\refbuf.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\net\resolver.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\sighandler.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\slave.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\net\sock.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\source.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\stats.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\thread\thread.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\timing\timing.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\util.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\xslt.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # Begin Source File
 
 SOURCE=..\src\yp.c
-
-!IF  "$(CFG)" == "icecast - Win32 Release"
-
-!ELSEIF  "$(CFG)" == "icecast - Win32 Debug"
-
-!ENDIF 
-
 # End Source File
 # End Group
 # Begin Group "Header Files"
@@ -615,6 +367,10 @@
 # End Source File
 # Begin Source File
 
+SOURCE=\src\mpeg.h
+# End Source File
+# Begin Source File
+
 SOURCE=..\src\refbuf.h
 # End Source File
 # Begin Source File

Modified: icecast/branches/kh/icecast/win32/icecast2.iss
===================================================================
--- icecast/branches/kh/icecast/win32/icecast2.iss	2010-03-28 10:18:53 UTC (rev 17096)
+++ icecast/branches/kh/icecast/win32/icecast2.iss	2010-03-29 02:14:55 UTC (rev 17097)
@@ -3,7 +3,7 @@
 
 [Setup]
 AppName=Icecast2-KH
-AppVerName=Icecast v2.3.2-kh21
+AppVerName=Icecast v2.3.2-kh22
 AppPublisherURL=http://www.icecast.org
 AppSupportURL=http://www.icecast.org
 AppUpdatesURL=http://www.icecast.org
@@ -13,7 +13,7 @@
 LicenseFile=..\COPYING
 InfoAfterFile=..\README
 OutputDir=.
-OutputBaseFilename=icecast2_win32_v2.3.2-kh21_setup
+OutputBaseFilename=icecast2_win32_v2.3.2-kh22_setup
 WizardImageFile=icecast2logo2.bmp
 WizardImageStretch=no
 VersionInfoVersion=2.3.2
@@ -69,3 +69,6 @@
 Filename: "{app}\icecastService.exe"; Parameters: "remove"
 
 
+
+
+



More information about the commits mailing list