diff options
Diffstat (limited to 'src/input/input_http.c')
-rw-r--r-- | src/input/input_http.c | 85 |
1 files changed, 63 insertions, 22 deletions
diff --git a/src/input/input_http.c b/src/input/input_http.c index 3adbc836b..5673a74b2 100644 --- a/src/input/input_http.c +++ b/src/input/input_http.c @@ -64,13 +64,13 @@ #define TAG_ICY_NOTICE2 "icy-notice2:" #define TAG_ICY_METAINT "icy-metaint:" #define TAG_CONTENT_TYPE "Content-Type:" +#define TAG_LASTFM_SERVER "Server: last.fm Streaming Server" typedef struct { input_plugin_t input_plugin; xine_stream_t *stream; - int fh; char *mrl; nbc_t *nbc; @@ -84,25 +84,30 @@ typedef struct { char auth[BUFSIZE]; char proxyauth[BUFSIZE]; + char preview[MAX_PREVIEW_SIZE]; + off_t preview_size; + char *proto; char *user; char *password; char *host; - int port; char *uri; - - char preview[MAX_PREVIEW_SIZE]; - off_t preview_size; - + int port; + + int fh; + + /** Set to 1 if the stream is a NSV stream. */ + int is_nsv:1; + /** Set to 1 if the stream comes from last.fm. */ + int is_lastfm:1; + /** Set to 1 if the stream is ShoutCast. */ + int shoutcast_mode:1; + /* ShoutCast */ - int shoutcast_mode; int shoutcast_metaint; off_t shoutcast_pos; char *shoutcast_songtitle; - /* NSV */ - int is_nsv; - /* scratch buffer for forward seeking */ char seek_buf[BUFSIZE]; @@ -117,13 +122,13 @@ typedef struct { config_values_t *config; char *proxyhost; + char *proxyhost_env; int proxyport; + int proxyport_env; + char *proxyuser; char *proxypassword; char *noproxylist; - - char *proxyhost_env; - int proxyport_env; } http_input_class_t; static void proxy_host_change_cb (void *this_gen, xine_cfg_entry_t *cfg) { @@ -181,7 +186,7 @@ static int _x_use_proxy(http_input_class_t *this, const char *host) { /* \177\0\0\1 is the *octal* representation of 127.0.0.1 */ if ( info->h_addrtype == AF_INET && !memcmp(info->h_addr_list[0], "\177\0\0\1", 4) ) { lprintf("host '%s' is localhost\n", host); - return 1; + return 0; } /* TODO: IPv6 check */ } @@ -200,13 +205,13 @@ static int _x_use_proxy(http_input_class_t *this, const char *host) { /* special-case domain beginning with '=' -> is a host name */ if (domain[0] == '=' && strcmp(target, domain + 1) == 0) { lprintf("host '%s' is in no-proxy domain '%s'\n", target, domain); - return 1; + return 0; } noprox_len = strlen(domain); /* special-case host==domain, avoiding dot checks */ if (host_len == noprox_len && strcmp(target, domain) == 0) { lprintf("host '%s' is in no-proxy domain '%s'\n", target, domain); - return 1; + return 0; } /* check for host in domain, and require that (if matched) the domain * name is preceded by a dot, either in the host or domain strings, @@ -216,7 +221,7 @@ static int _x_use_proxy(http_input_class_t *this, const char *host) { && (domain[0] == '.' || target[host_len - noprox_len - 1] == '.') && strcmp(target + host_len - noprox_len, domain) == 0) { lprintf("host '%s' is in no-proxy domain '%s'\n", target, domain); - return 1; + return 0; } lprintf("host '%s' isn't in no-proxy domain '%s'\n", target, domain); } @@ -225,7 +230,7 @@ static int _x_use_proxy(http_input_class_t *this, const char *host) { } free(no_proxy); - return 0; + return 1; } static int http_plugin_basicauth (const char *user, const char *password, char* dest, int len) { @@ -383,6 +388,25 @@ static off_t http_plugin_read_int (http_input_plugin_t *this, if (nlen < 0) goto error; + /* Identify SYNC string for last.fm, this is limited to last.fm + * streaming servers to avoid hitting on tracks metadata for other + * servers. + */ + if ( this->is_lastfm && + memmem(&buf[read_bytes], nlen, "SYNC", 4) != NULL ) { + /* Tell frontend to update the UI */ + const xine_event_t event = { + .type = XINE_EVENT_UI_CHANNELS_CHANGED, + .stream = this->stream, + .data = NULL, + .data_length = 0 + }; + + lprintf("SYNC from last.fm server received\n"); + + xine_event_send(this->stream, &event); + } + this->shoutcast_pos += nlen; } @@ -402,8 +426,9 @@ error: } static off_t http_plugin_read (input_plugin_t *this_gen, - char *buf, off_t nlen) { + void *buf_gen, off_t nlen) { http_input_plugin_t *this = (http_input_plugin_t *) this_gen; + char *buf = (char *)buf_gen; off_t n, num_bytes; num_bytes = 0; @@ -663,9 +688,8 @@ static int http_plugin_open (input_plugin_t *this_gen ) { _x_message(this->stream, XINE_MSG_GENERAL_WARNING, "malformed url", NULL); return 0; } - if (use_proxy && _x_use_proxy(this_class, this->host)) { - use_proxy = 0; - } + use_proxy = use_proxy && _x_use_proxy(this_class, this->host); + if (this->port == 0) this->port = DEFAULT_HTTP_PORT; @@ -830,6 +854,11 @@ static int http_plugin_open (input_plugin_t *this_gen ) { _("input_http: http status not 2xx: >%d %s<\n"), httpcode, httpstatus); return -7; + } else if (httpcode == 401) { + xine_log (this->stream->xine, XINE_LOG_MSG, + _("input_http: http status not 2xx: >%d %s<\n"), + httpcode, httpstatus); + /* don't return - there may be a WWW-Authenticate header... */ } else if (httpcode == 403) { _x_message(this->stream, XINE_MSG_PERMISSION_ERROR, this->mrl, NULL); xine_log (this->stream->xine, XINE_LOG_MSG, @@ -867,6 +896,10 @@ static int http_plugin_open (input_plugin_t *this_gen ) { return http_plugin_open(this_gen); } + if (!strncasecmp (this->buf, "WWW-Authenticate: ", 18)) + strcpy (this->preview, this->buf + 18); + + /* 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, @@ -908,6 +941,10 @@ static int http_plugin_open (input_plugin_t *this_gen ) { this->is_nsv = 1; } } + if ( !strncasecmp(this->buf, TAG_LASTFM_SERVER, sizeof(TAG_LASTFM_SERVER)-1) ) { + lprintf("last.fm streaming server detected\n"); + this->is_lastfm = 1; + } } if (len == -1) @@ -926,6 +963,10 @@ static int http_plugin_open (input_plugin_t *this_gen ) { lprintf ("end of headers\n"); + if (httpcode == 401) + _x_message(this->stream, XINE_MSG_AUTHENTICATION_NEEDED, + this->mrl, *this->preview ? this->preview : NULL, NULL); + /* * fill preview buffer */ |