[MPlayer-dev-eng] [PATCH] Displaying SHOUTcast title

Reimar Döffinger Reimar.Doeffinger at stud.uni-karlsruhe.de
Thu Jun 16 20:58:37 CEST 2005


Hi,
the attached patch is a very first, hackish version of support for
Metadata in SHOUTcast streams.
I lost interest and probably won't improve it to a point where it can go
into CVS.
I post it here anyway, maybe someone else wants to work on it.

Greetings,
Reimar Döffinger
-------------- next part --------------
--- libmpdemux/network.c	2005-05-29 19:17:13.000000000 +0200
+++ libmpdemux/network.c	2005-06-15 17:23:23.000000000 +0200
@@ -400,6 +400,8 @@
 	else
 	    http_set_field( http_hdr, "User-Agent: MPlayer/"VERSION);
 
+	http_set_field(http_hdr, "Icy-MetaData: 1");
+
 	if(pos>0) { 
 	// Extend http_send_request with possibility to do partial content retrieval
 	    snprintf(str, 256, "Range: bytes=%d-", pos);
--- libmpdemux/http.c	2005-06-03 21:33:16.000000000 +0200
+++ libmpdemux/http.c	2005-06-15 20:58:46.000000000 +0200
@@ -34,6 +34,104 @@
 
 extern int http_seek(stream_t *stream, off_t pos);
 
+static unsigned my_recv(int fd, char *buffer, int len) {
+  unsigned pos = 0;
+  while (pos < len) {
+    int ret = read(fd, &buffer[pos], len - pos);
+    if (ret <= 0)
+      break;
+    pos += ret;
+  }
+  return pos;
+}
+
+static int scast_recv(int fd, char *buffer, int metaint) {
+  unsigned char tmp = 0;
+  unsigned metalen;
+  unsigned ret = my_recv(fd, buffer, metaint);
+  read(fd, &tmp, 1);
+  metalen = tmp * 16;
+  if (metalen > 0) {
+    char *info = (char *)malloc(metalen + 1);
+    unsigned nlen = my_recv(fd, info, metalen);
+    info[nlen] = 0;
+    mp_msg(MSGT_DEMUXER, MSGL_INFO, "\nICY Info: %s\n", info);
+    free(info);
+  }
+  return ret;
+}
+
+static int scast_streaming_read(int fd, char *buffer, int size,
+                                streaming_ctrl_t *stream_ctrl) {
+  unsigned metaint = stream_ctrl->buffer_size;
+  unsigned block;
+  unsigned done = 0;
+
+  // first read data from buffer
+  block = metaint - stream_ctrl->buffer_pos;
+  if (block > size)
+    block = size;
+  memcpy(buffer, &stream_ctrl->buffer[stream_ctrl->buffer_pos], block);
+  stream_ctrl->buffer_pos += block;
+  done += block;
+
+  if (done < size) { // buffer is empty now
+    // read big blocks directly from stream
+    while (size - done > metaint) {
+      unsigned ret = scast_recv(fd, &buffer[done], metaint);
+      done += ret;
+      if (ret != metaint) // read problems or eof
+        size = done;
+    }
+
+    if (done < size) {
+      int len = scast_recv(fd, stream_ctrl->buffer, metaint);
+      block = size - done;
+      if (len < block) // read problems or eof
+        block = len;
+      memcpy(&buffer[done], stream_ctrl->buffer, block);
+      stream_ctrl->buffer_pos = block;
+      if (len < metaint) {
+        memmove(&stream_ctrl->buffer[block + metaint - len],
+                &stream_ctrl->buffer[block], len - block);
+        stream_ctrl->buffer_pos = block + metaint - len;
+      }
+      done += block;
+    }
+  }
+  return done;
+}
+
+static int scast_streaming_start(stream_t *stream) {
+  int metaint;
+  int fromhdr;
+  HTTP_header_t *http_hdr = stream->streaming_ctrl->data;
+  if (!stream || stream->fd < 0 || !http_hdr)
+    return -1;
+  metaint = atoi(http_get_field(http_hdr, "Icy-MetaInt"));
+  if (metaint <= 0)
+    return -1;
+  fromhdr = http_hdr->buffer_size - http_hdr->body_size;
+  if (http_hdr->body_size > metaint) {
+    mp_msg(MSGT_DEMUXER, MSGL_ERR, "http_hdr->body_size too big\n");
+    return -1;
+  }
+  stream->streaming_ctrl->buffer = malloc(metaint);
+  stream->streaming_ctrl->buffer_size = metaint;
+  stream->streaming_ctrl->buffer_pos = 0;
+  memcpy(stream->streaming_ctrl->buffer, http_hdr->body, http_hdr->body_size);
+  scast_recv(stream->fd, &stream->streaming_ctrl->buffer[http_hdr->body_size],
+             metaint - http_hdr->body_size);
+  http_free(http_hdr);
+  stream->streaming_ctrl->data = NULL;
+  stream->streaming_ctrl->streaming_read = scast_streaming_read;
+  stream->streaming_ctrl->streaming_seek = NULL;
+  stream->streaming_ctrl->prebuffer_size = 64*1024; // 64 KBytes
+  stream->streaming_ctrl->buffering = 1;
+  stream->streaming_ctrl->status = streaming_playing_e;
+  return 0;
+}
+
 static int nop_streaming_start( stream_t *stream ) {
 	HTTP_header_t *http_hdr = NULL;
 	char *next_url=NULL;
@@ -677,14 +775,17 @@
 }
 
 static int fixup_open(stream_t *stream,int seekable) {
+	HTTP_header_t *http_hdr = stream->streaming_ctrl->data;
+	int is_icy = http_hdr && strcasecmp(http_hdr->protocol, "ICY") == 0;
 
 	stream->type = STREAMTYPE_STREAM;
-	if(seekable)
+	if(is_icy && seekable)
 	{
 		stream->flags |= STREAM_SEEK;
 		stream->seek = http_seek;
 	}
 	stream->streaming_ctrl->bandwidth = network_bandwidth;
+	if (!is_icy || scast_streaming_start(stream))
 	if(nop_streaming_start( stream )) {
 		mp_msg(MSGT_NETWORK,MSGL_ERR,"nop_streaming_start failed\n");
 		streaming_ctrl_free(stream->streaming_ctrl);


More information about the MPlayer-dev-eng mailing list