Port all the fixes from BRANCH-GSTREAMER-0_6.

Original commit message from CVS:
Port all the fixes from BRANCH-GSTREAMER-0_6.
This commit is contained in:
Colin Walters 2003-02-07 01:47:58 +00:00
parent bcea95f6cb
commit 44f96d01be

View file

@ -77,8 +77,6 @@ struct _GstGnomeVFSSrc {
/* filename */ /* filename */
gchar *filename; gchar *filename;
/* is it a local file ? */
gboolean is_local;
/* uri */ /* uri */
GnomeVFSURI *uri; GnomeVFSURI *uri;
@ -87,22 +85,16 @@ struct _GstGnomeVFSSrc {
/* Seek stuff */ /* Seek stuff */
gboolean need_flush; gboolean need_flush;
/* local filename */
gchar *local_name;
/* fd for local file fallback */
gint fd;
/* mmap */
guchar *map; /* where the file is mapped to */
/* details for fallback synchronous read */ /* details for fallback synchronous read */
GnomeVFSFileSize size; GnomeVFSFileSize size;
GnomeVFSFileOffset curoffset; /* current offset in file */ GnomeVFSFileOffset curoffset; /* current offset in file */
gulong bytes_per_read; /* bytes per read */ gulong bytes_per_read; /* bytes per read */
gboolean new_seek; gboolean new_seek;
gboolean in_first_get;
/* icecast/audiocast metadata extraction handling */ /* icecast/audiocast metadata extraction handling */
gboolean iradio_mode; gboolean iradio_mode;
gboolean iradio_callbacks_pushed; gboolean http_callbacks_pushed;
gint icy_metaint; gint icy_metaint;
GnomeVFSFileSize icy_count; GnomeVFSFileSize icy_count;
@ -303,19 +295,17 @@ static void gst_gnomevfssrc_init(GstGnomeVFSSrc *gnomevfssrc)
gst_gnomevfssrc_get_formats); gst_gnomevfssrc_get_formats);
gst_element_add_pad(GST_ELEMENT(gnomevfssrc), gnomevfssrc->srcpad); gst_element_add_pad(GST_ELEMENT(gnomevfssrc), gnomevfssrc->srcpad);
gnomevfssrc->filename = NULL;
gnomevfssrc->is_local = FALSE;
gnomevfssrc->uri = NULL; gnomevfssrc->uri = NULL;
gnomevfssrc->handle = NULL; gnomevfssrc->handle = NULL;
gnomevfssrc->fd = 0;
gnomevfssrc->curoffset = 0; gnomevfssrc->curoffset = 0;
gnomevfssrc->bytes_per_read = 4096; gnomevfssrc->bytes_per_read = 4096;
gnomevfssrc->new_seek = FALSE; gnomevfssrc->new_seek = FALSE;
gnomevfssrc->in_first_get = TRUE;
gnomevfssrc->icy_metaint = 0; gnomevfssrc->icy_metaint = 0;
gnomevfssrc->iradio_mode = FALSE; gnomevfssrc->iradio_mode = FALSE;
gnomevfssrc->iradio_callbacks_pushed = FALSE; gnomevfssrc->http_callbacks_pushed = FALSE;
gnomevfssrc->icy_count = 0; gnomevfssrc->icy_count = 0;
gnomevfssrc->iradio_name = NULL; gnomevfssrc->iradio_name = NULL;
gnomevfssrc->iradio_genre = NULL; gnomevfssrc->iradio_genre = NULL;
@ -691,12 +681,13 @@ gst_gnomevfssrc_received_headers_callback (gconstpointer in,
GnomeVFSModuleCallbackReceivedHeadersIn *in_args = GnomeVFSModuleCallbackReceivedHeadersIn *in_args =
(GnomeVFSModuleCallbackReceivedHeadersIn *)in; (GnomeVFSModuleCallbackReceivedHeadersIn *)in;
/* This is only used for internet radio stuff right now */
if (!src->iradio_mode) if (!src->iradio_mode)
return; return;
for (i = in_args->headers; i; i = i->next) { for (i = in_args->headers; i; i = i->next) {
char *data = (char *) i->data; char *data = (char *) i->data;
char *key; char *key = data;
char *value = strchr(data, ':'); char *value = strchr(data, ':');
if (!value) if (!value)
continue; continue;
@ -711,7 +702,8 @@ gst_gnomevfssrc_received_headers_callback (gconstpointer in,
{ {
sscanf (data + 12, "%d", &icy_metaint); sscanf (data + 12, "%d", &icy_metaint);
src->icy_metaint = icy_metaint; src->icy_metaint = icy_metaint;
GST_DEBUG (0,"got icy-metaint, killing audiocast thread"); GST_DEBUG (0,"got icy-metaint %d, killing audiocast thread",
src->icy_metaint);
audiocast_thread_kill(src); audiocast_thread_kill(src);
continue; continue;
} }
@ -746,7 +738,7 @@ gst_gnomevfssrc_received_headers_callback (gconstpointer in,
static void static void
gst_gnomevfssrc_push_callbacks (GstGnomeVFSSrc *gnomevfssrc) gst_gnomevfssrc_push_callbacks (GstGnomeVFSSrc *gnomevfssrc)
{ {
if (gnomevfssrc->iradio_callbacks_pushed) if (gnomevfssrc->http_callbacks_pushed)
return; return;
GST_DEBUG (0,"pushing callbacks"); GST_DEBUG (0,"pushing callbacks");
@ -759,13 +751,13 @@ gst_gnomevfssrc_push_callbacks (GstGnomeVFSSrc *gnomevfssrc)
gnomevfssrc, gnomevfssrc,
NULL); NULL);
gnomevfssrc->iradio_callbacks_pushed = TRUE; gnomevfssrc->http_callbacks_pushed = TRUE;
} }
static void static void
gst_gnomevfssrc_pop_callbacks (GstGnomeVFSSrc *gnomevfssrc) gst_gnomevfssrc_pop_callbacks (GstGnomeVFSSrc *gnomevfssrc)
{ {
if (!gnomevfssrc->iradio_callbacks_pushed) if (!gnomevfssrc->http_callbacks_pushed)
return; return;
GST_DEBUG (0,"popping callbacks"); GST_DEBUG (0,"popping callbacks");
@ -819,7 +811,7 @@ gst_gnomevfssrc_get_icy_metadata (GstGnomeVFSSrc *src)
for (i = 0; tags[i]; i++) for (i = 0; tags[i]; i++)
{ {
if (!g_strncasecmp(tags[i], "StreamTitle=", 12)) if (!g_ascii_strncasecmp(tags[i], "StreamTitle=", 12))
{ {
if (src->iradio_title) if (src->iradio_title)
g_free (src->iradio_title); g_free (src->iradio_title);
@ -827,7 +819,7 @@ gst_gnomevfssrc_get_icy_metadata (GstGnomeVFSSrc *src)
GST_DEBUG(0, "sending notification on icecast title"); GST_DEBUG(0, "sending notification on icecast title");
g_object_notify (G_OBJECT (src), "iradio-title"); g_object_notify (G_OBJECT (src), "iradio-title");
} }
if (!g_strncasecmp(tags[i], "StreamUrl=", 10)) if (!g_ascii_strncasecmp(tags[i], "StreamUrl=", 10))
{ {
if (src->iradio_url) if (src->iradio_url)
g_free (src->iradio_url); g_free (src->iradio_url);
@ -874,65 +866,40 @@ static GstBuffer *gst_gnomevfssrc_get(GstPad *pad)
audiocast_do_notifications(src); audiocast_do_notifications(src);
/* read it in from the file */ if (src->iradio_mode && src->icy_metaint > 0) {
if (src->is_local)
{
/* simply set the buffer to point to the correct region of the
* file */
GST_BUFFER_DATA (buf) = src->map + src->curoffset;
GST_BUFFER_OFFSET (buf) = src->curoffset;
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE);
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_READONLY);
if ((src->curoffset + src->bytes_per_read) > src->size)
{
GST_BUFFER_SIZE (buf) = src->size - src->curoffset;
} else {
GST_BUFFER_SIZE (buf) = src->bytes_per_read;
}
if (src->new_seek)
{
GstEvent *event;
gst_buffer_unref (buf);
GST_DEBUG (0,"new seek %" G_GINT64_FORMAT, src->curoffset);
src->new_seek = FALSE;
GST_DEBUG (GST_CAT_EVENT, "gnomevfssrc sending discont");
event = gst_event_new_discontinuous (FALSE, GST_FORMAT_BYTES, src->curoffset, NULL);
src->need_flush = FALSE;
return GST_BUFFER (event);
}
src->curoffset += GST_BUFFER_SIZE (buf);
} else if (src->iradio_mode && src->icy_metaint > 0) {
GST_BUFFER_DATA (buf) = g_malloc0 (src->icy_metaint); GST_BUFFER_DATA (buf) = g_malloc0 (src->icy_metaint);
g_return_val_if_fail (GST_BUFFER_DATA (buf) != NULL, NULL); g_return_val_if_fail (GST_BUFFER_DATA (buf) != NULL, NULL);
result = gnome_vfs_read (src->handle, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf) = 0;
src->icy_metaint - src->icy_count, /* FIXME GROSS HACK: We try to read in at least 8000
&readbytes); * bytes of data so that mp3 typefinding will work. */
do
/* EOS? */ {
if (readbytes == 0) { GST_DEBUG (0,"doing read: icy_count: %" G_GINT64_FORMAT, src->icy_count);
gst_buffer_unref (buf); result = gnome_vfs_read (src->handle, GST_BUFFER_DATA (buf),
gst_element_set_eos (GST_ELEMENT (src)); src->icy_metaint - src->icy_count,
&readbytes);
return GST_BUFFER (gst_event_new (GST_EVENT_EOS));
}
src->icy_count += readbytes;
GST_BUFFER_OFFSET (buf) = src->curoffset;
GST_BUFFER_SIZE (buf) = readbytes;
src->curoffset += readbytes;
if (src->icy_count == src->icy_metaint) {
gst_gnomevfssrc_get_icy_metadata (src);
src->icy_count = 0;
}
/* EOS? */
if (readbytes == 0) {
gst_buffer_unref (buf);
gst_element_set_eos (GST_ELEMENT (src));
src->in_first_get = FALSE;
return GST_BUFFER (gst_event_new (GST_EVENT_EOS));
}
src->icy_count += readbytes;
GST_BUFFER_OFFSET (buf) = src->curoffset;
GST_BUFFER_SIZE (buf) += readbytes;
src->curoffset += readbytes;
if (src->icy_count == src->icy_metaint) {
gst_gnomevfssrc_get_icy_metadata (src);
src->icy_count = 0;
}
} while (src->in_first_get
&& GST_BUFFER_OFFSET (buf) < 8000 &&
src->icy_metaint - src->icy_count >= 8000);
} else { } else {
/* allocate the space for the buffer data */ /* allocate the space for the buffer data */
GST_BUFFER_DATA(buf) = g_malloc(src->bytes_per_read); GST_BUFFER_DATA(buf) = g_malloc(src->bytes_per_read);
@ -974,15 +941,16 @@ static GstBuffer *gst_gnomevfssrc_get(GstPad *pad)
} }
GST_BUFFER_TIMESTAMP (buf) = -1; GST_BUFFER_TIMESTAMP (buf) = -1;
src->in_first_get = FALSE;
/* we're done, return the buffer */ /* we're done, return the buffer */
return buf; return buf;
} }
/* open the file and mmap it, necessary to go to READY state */ /* open the file, do stuff necessary to go to READY state */
static gboolean gst_gnomevfssrc_open_file(GstGnomeVFSSrc *src) static gboolean gst_gnomevfssrc_open_file(GstGnomeVFSSrc *src)
{ {
GnomeVFSResult result; GnomeVFSResult result;
GnomeVFSFileInfo *info;
g_return_val_if_fail(!GST_FLAG_IS_SET(src, GST_GNOMEVFSSRC_OPEN), g_return_val_if_fail(!GST_FLAG_IS_SET(src, GST_GNOMEVFSSRC_OPEN),
FALSE); FALSE);
@ -990,98 +958,62 @@ static gboolean gst_gnomevfssrc_open_file(GstGnomeVFSSrc *src)
/* create the uri */ /* create the uri */
src->uri = gnome_vfs_uri_new(src->filename); src->uri = gnome_vfs_uri_new(src->filename);
if (!src->uri) { if (!src->uri) {
gst_element_error(GST_ELEMENT(src), gst_element_error(GST_ELEMENT(src), "creating uri \"%s\" (%s)",
"creating uri \"%s\" (%s)", src->filename, strerror (errno));
src->filename, strerror (errno));
return FALSE; return FALSE;
} }
/* open the file using open() if the file is local */ if (!audiocast_init(src))
src->is_local = gnome_vfs_uri_is_local(src->uri); return FALSE;
if (src->is_local) {
src->local_name =
gnome_vfs_get_local_path_from_uri(src->filename);
src->fd = open(src->local_name, O_RDONLY);
if (src->fd < 0)
{
gst_element_error(GST_ELEMENT(src),
"opening local file \"%s\" (%s)",
src->filename, strerror (errno));
return FALSE;
}
/* find the file length */
src->size = lseek (src->fd, 0, SEEK_END);
lseek (src->fd, 0, SEEK_SET);
src->map = mmap (NULL, src->size, PROT_READ, MAP_SHARED,
src->fd, 0);
madvise (src->map,src->size, 2);
/* collapse state if that failed */
if (src->map == NULL)
{
gst_gnomevfssrc_close_file(src);
gst_element_error (GST_ELEMENT (src),"mmapping file");
return FALSE;
}
src->new_seek = TRUE;
} else {
if (!audiocast_init(src))
return FALSE;
gst_gnomevfssrc_push_callbacks (src); gst_gnomevfssrc_push_callbacks (src);
result = result = gnome_vfs_open_uri(&(src->handle), src->uri,
gnome_vfs_open_uri(&(src->handle), src->uri, GNOME_VFS_OPEN_READ);
GNOME_VFS_OPEN_READ); if (result != GNOME_VFS_OK)
if (result != GNOME_VFS_OK) {
{ gst_gnomevfssrc_pop_callbacks (src);
gst_gnomevfssrc_pop_callbacks (src); audiocast_thread_kill(src);
audiocast_thread_kill(src); gst_element_error(GST_ELEMENT(src),
gst_element_error(GST_ELEMENT(src),
"opening vfs file \"%s\" (%s)", "opening vfs file \"%s\" (%s)",
src->filename, src->filename,
gnome_vfs_result_to_string(result)); gnome_vfs_result_to_string(result));
return FALSE; return FALSE;
} }
/* find the file length (but skip it in iradio mode, info = gnome_vfs_file_info_new ();
* since it will require a separate request, and we if (gnome_vfs_get_file_info_from_handle (src->handle, info,
* know the length is undefined anyways) */ GNOME_VFS_FILE_INFO_DEFAULT | GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
if (!src->iradio_mode) == GNOME_VFS_OK)
{
if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE)
src->size = info->size;
if (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE)
{ {
GnomeVFSResult size_result; GST_DEBUG (0, "got MIME type \"%s\", setting caps",
GnomeVFSFileInfo *info; info->mime_type);
GstCaps *caps = gst_caps_new ("gnomevfssrc", info->mime_type, NULL);
info = gnome_vfs_file_info_new (); gst_pad_try_set_caps (src->srcpad, caps);
size_result = gnome_vfs_get_file_info_uri(src->uri,
info, GNOME_VFS_FILE_INFO_DEFAULT);
if (size_result != GNOME_VFS_OK)
src->size = 0;
else
src->size = info->size;
gnome_vfs_file_info_unref(info);
} }
else else
src->size = 0; GST_DEBUG (0, "No mime type available");
GST_DEBUG(0, "size %" G_GINT64_FORMAT, src->size);
audiocast_do_notifications(src);
GST_DEBUG(0, "open %s", gnome_vfs_result_to_string(result));
} }
else
GST_DEBUG (0, "getting info failed: %s", gnome_vfs_result_to_string (result));
gnome_vfs_file_info_unref(info);
GST_DEBUG(0, "size %" G_GINT64_FORMAT, src->size);
audiocast_do_notifications(src);
GST_DEBUG(0, "open result: %s", gnome_vfs_result_to_string (result));
GST_FLAG_SET(src, GST_GNOMEVFSSRC_OPEN); GST_FLAG_SET(src, GST_GNOMEVFSSRC_OPEN);
return TRUE; return TRUE;
} }
/* unmap and close the file */
static void gst_gnomevfssrc_close_file(GstGnomeVFSSrc *src) static void gst_gnomevfssrc_close_file(GstGnomeVFSSrc *src)
{ {
g_return_if_fail(GST_FLAG_IS_SET(src, GST_GNOMEVFSSRC_OPEN)); g_return_if_fail(GST_FLAG_IS_SET(src, GST_GNOMEVFSSRC_OPEN));
@ -1089,22 +1021,9 @@ static void gst_gnomevfssrc_close_file(GstGnomeVFSSrc *src)
gst_gnomevfssrc_pop_callbacks (src); gst_gnomevfssrc_pop_callbacks (src);
audiocast_thread_kill(src); audiocast_thread_kill(src);
/* close the file */ gnome_vfs_close(src->handle);
if (src->is_local)
{
/* unmap the file from memory */
munmap (src->map, src->size);
close(src->fd);
} else {
gnome_vfs_close(src->handle);
}
/* zero out a lot of our state */
src->is_local = FALSE;
gnome_vfs_uri_unref(src->uri); gnome_vfs_uri_unref(src->uri);
g_free(src->local_name);
src->fd = 0;
src->map = NULL;
src->size = 0; src->size = 0;
src->curoffset = 0; src->curoffset = 0;
src->new_seek = FALSE; src->new_seek = FALSE;
@ -1214,18 +1133,16 @@ gst_gnomevfssrc_srcpad_event (GstPad *pad, GstEvent *event)
return FALSE; return FALSE;
break; break;
} }
if (!src->is_local) { GnomeVFSResult result;
GnomeVFSResult result;
result = gnome_vfs_seek(src->handle,
result = gnome_vfs_seek(src->handle,
GNOME_VFS_SEEK_START, desired_offset); GNOME_VFS_SEEK_START, desired_offset);
GST_DEBUG(0, "new_seek: %s", GST_DEBUG(0, "new_seek: %s",
gnome_vfs_result_to_string(result)); gnome_vfs_result_to_string(result));
if (result != GNOME_VFS_OK) { if (result != GNOME_VFS_OK) {
gst_event_unref (event); gst_event_unref (event);
return FALSE; return FALSE;
}
} }
src->curoffset = desired_offset; src->curoffset = desired_offset;
src->new_seek = TRUE; src->new_seek = TRUE;