From 57226d0ebeef4e865c4e25f205d4e734b56640b4 Mon Sep 17 00:00:00 2001 From: Thibaut Mattern Date: Mon, 17 Jan 2005 19:27:51 +0000 Subject: Merge shoutcast/icecast header parsing with http header parsing. Fixed bug: http://sourceforge.net/tracker/index.php?func=detail&aid=1098490&group_id=9655&atid=109655 CVS patchset: 7356 CVS date: 2005/01/17 19:27:51 --- src/input/input_http.c | 213 +++++++++++++++++++------------------------------ 1 file changed, 81 insertions(+), 132 deletions(-) diff --git a/src/input/input_http.c b/src/input/input_http.c index fe9514e9b..77967a774 100644 --- a/src/input/input_http.c +++ b/src/input/input_http.c @@ -19,7 +19,7 @@ * * input plugin for http network streams * - * $Id: input_http.c,v 1.105 2005/01/13 19:37:15 tmattern Exp $ + * $Id: input_http.c,v 1.106 2005/01/17 19:27:51 tmattern Exp $ */ #ifdef HAVE_CONFIG_H @@ -426,124 +426,49 @@ static off_t http_plugin_read (input_plugin_t *this_gen, return num_bytes; } -static int read_shoutcast_header(http_input_plugin_t *this) { - int done, len, linenum; - - done = 0; len = 0; linenum = 0; - while (!done) { - - if (_x_io_tcp_read (this->stream, this->fh, &this->buf[len], 1) != 1) { - return 0; - } - - if (this->buf[len] == '\012') { - - this->buf[len] = '\0'; - len--; - - if (len >= 0 && this->buf[len] == '\015') { - this->buf[len] = '\0'; - len--; - } - - linenum++; - - lprintf ("shoutcast answer: >%s<\n", this->buf); - - if (!strncasecmp(this->buf, TAG_ICY_NAME, sizeof(TAG_ICY_NAME) - 1)) { - _x_meta_info_set(this->stream, XINE_META_INFO_ALBUM, - (this->buf + sizeof(TAG_ICY_NAME) - 1 + - (*(this->buf + sizeof(TAG_ICY_NAME)) == ' '))); - _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, - (this->buf + sizeof(TAG_ICY_NAME) - 1 + - (*(this->buf + sizeof(TAG_ICY_NAME)) == ' '))); - } - - if (!strncasecmp(this->buf, TAG_ICY_GENRE, sizeof(TAG_ICY_GENRE) - 1)) { - _x_meta_info_set(this->stream, XINE_META_INFO_GENRE, - (this->buf + sizeof(TAG_ICY_GENRE) - 1 + - (*(this->buf + sizeof(TAG_ICY_GENRE)) == ' '))); - } - - /* icy-notice1 is always the same */ - if (!strncasecmp(this->buf, TAG_ICY_NOTICE2, sizeof(TAG_ICY_NOTICE2) - 1)) { - _x_meta_info_set(this->stream, XINE_META_INFO_COMMENT, - (this->buf + sizeof(TAG_ICY_NOTICE2) - 1 + - (*(this->buf + sizeof(TAG_ICY_NOTICE2)) == ' '))); - } - - /* metadata interval (in byte) */ - if (sscanf(this->buf, "icy-metaint:%d", &this->shoutcast_metaint) == 1) { - lprintf("shoutcast_metaint: %d\n", this->shoutcast_metaint); - this->shoutcast_mode = 1; - } - - /* content type */ - if (!strncasecmp(this->buf, TAG_CONTENT_TYPE, sizeof(TAG_CONTENT_TYPE) - 1)) { - if (!strncasecmp(this->buf + sizeof(TAG_CONTENT_TYPE) - 1, "video/nsv", 9)) { - lprintf("shoutcast nsv detected\n"); - this->is_nsv = 1; - } else { - lprintf("shoutcast mp3 detected\n"); - } - } +static int resync_nsv(http_input_plugin_t *this) { + uint8_t c; + int pos = 0; + int read_bytes = 0; - if (len == -1) - done = 1; - else - len = 0; - } else - len ++; - } - - this->shoutcast_pos = 0; - - /* NSV resync */ - if (this->is_nsv) { - uint8_t c; - int pos = 0; - int read_bytes = 0; + lprintf("resyncing NSV stream\n"); + while ((pos < 3) && (read_bytes < (1024*1024))) { - lprintf("resyncing NSV stream\n"); - while ((pos < 3) && (read_bytes < (1024*1024))) { - - if (http_plugin_read_int(this, &c, 1) != 1) - return 1; - - this->preview[pos] = c; - switch (pos) { - case 0: + if (http_plugin_read_int(this, &c, 1) != 1) + return 1; + + this->preview[pos] = c; + switch (pos) { + case 0: + if (c == 'N') + pos++; + break; + case 1: + if (c == 'S') + pos++; + else + if (c != 'N') + pos = 0; + break; + case 2: + if (c == 'V') + pos++; + else if (c == 'N') - pos++; - break; - case 1: - if (c == 'S') - pos++; + pos = 1; else - if (c != 'N') - pos = 0; - break; - case 2: - if (c == 'V') - pos++; - else - if (c == 'N') - pos = 1; - else - pos = 0; - break; - } - read_bytes++; - } - if (pos == 3) { - lprintf("NSV stream resynced\n"); - } else { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "http: cannot resync NSV stream!\n"); - return 0; + pos = 0; + break; } + read_bytes++; + } + if (pos == 3) { + lprintf("NSV stream resynced\n"); + } else { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "http: cannot resync NSV stream!\n"); + return 0; } - lprintf ("end of the shoutcast header\n"); return 1; } @@ -701,7 +626,7 @@ static int http_plugin_open (input_plugin_t *this_gen ) { http_input_plugin_t *this = (http_input_plugin_t *) this_gen; http_input_class_t *this_class = (http_input_class_t *) this->input_plugin.input_class; int done, len, linenum; - int shoutcast = 0, httpcode; + int httpcode; int res, progress; int buflen; int use_proxy; @@ -865,15 +790,12 @@ static int http_plugin_open (input_plugin_t *this_gen ) { if (sscanf(this->buf, "HTTP/%d.%d %d %50[^\015\012]", &httpver, &httpsub, &httpcode, httpstatus) != 4) { - /* icecast ? */ + /* icecast 1 ? */ if (sscanf(this->buf, "ICY %d %50[^\015\012]", &httpcode, httpstatus) != 2) { _x_message(this->stream, XINE_MSG_CONNECTION_REFUSED, "invalid http answer", NULL); xine_log (this->stream->xine, XINE_LOG_MSG, _("input_http: invalid http answer\n")); return 0; - } else { - shoutcast = 1; - done = 1; } } @@ -923,6 +845,44 @@ static int http_plugin_open (input_plugin_t *this_gen ) { this->mrl = href; return http_plugin_open(this_gen); } + + /* Icecast / ShoutCast Stuff */ + if (!strncasecmp(this->buf, TAG_ICY_NAME, sizeof(TAG_ICY_NAME) - 1)) { + _x_meta_info_set(this->stream, XINE_META_INFO_ALBUM, + (this->buf + sizeof(TAG_ICY_NAME) - 1 + + (*(this->buf + sizeof(TAG_ICY_NAME)) == ' '))); + _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, + (this->buf + sizeof(TAG_ICY_NAME) - 1 + + (*(this->buf + sizeof(TAG_ICY_NAME)) == ' '))); + } + + if (!strncasecmp(this->buf, TAG_ICY_GENRE, sizeof(TAG_ICY_GENRE) - 1)) { + _x_meta_info_set(this->stream, XINE_META_INFO_GENRE, + (this->buf + sizeof(TAG_ICY_GENRE) - 1 + + (*(this->buf + sizeof(TAG_ICY_GENRE)) == ' '))); + } + + /* icy-notice1 is always the same */ + if (!strncasecmp(this->buf, TAG_ICY_NOTICE2, sizeof(TAG_ICY_NOTICE2) - 1)) { + _x_meta_info_set(this->stream, XINE_META_INFO_COMMENT, + (this->buf + sizeof(TAG_ICY_NOTICE2) - 1 + + (*(this->buf + sizeof(TAG_ICY_NOTICE2)) == ' '))); + } + + /* metadata interval (in byte) */ + if (sscanf(this->buf, TAG_ICY_METAINT"%d", &this->shoutcast_metaint) == 1) { + lprintf("shoutcast_metaint: %d\n", this->shoutcast_metaint); + this->shoutcast_mode = 1; + this->shoutcast_pos = 0; + } + + /* content type */ + if (!strncasecmp(this->buf, TAG_CONTENT_TYPE, sizeof(TAG_CONTENT_TYPE) - 1)) { + if (!strncasecmp(this->buf + sizeof(TAG_CONTENT_TYPE) - 1, "video/nsv", 9)) { + lprintf("shoutcast nsv detected\n"); + this->is_nsv = 1; + } + } } if (len == -1) @@ -935,25 +895,14 @@ static int http_plugin_open (input_plugin_t *this_gen ) { lprintf ("end of headers\n"); - - /* Trivial shoutcast detection */ - this->shoutcast_metaint = 0; - this->shoutcast_songtitle = NULL; - this->shoutcast_mode = 0; - if (shoutcast) { - if (!read_shoutcast_header(this)) { - /* problem when reading shoutcast header */ - _x_message(this->stream, XINE_MSG_CONNECTION_REFUSED, "can't read shoutcast header", NULL); - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "can't read shoutcast header\n"); - return 0; - } - } - /* * fill preview buffer */ this->preview_size = MAX_PREVIEW_SIZE; if (this->is_nsv) { + if (!resync_nsv(this)) + return 0; + /* the first 3 chars are "NSV" */ this->preview_size = http_plugin_read_int (this, this->preview + 3, MAX_PREVIEW_SIZE - 3); } else { -- cgit v1.2.3