/* filename */
gchar *filename;
- /* is it a local file ? */
- gboolean is_local;
/* uri */
GnomeVFSURI *uri;
/* Seek stuff */
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 */
GnomeVFSFileSize size;
GnomeVFSFileOffset curoffset; /* current offset in file */
gulong bytes_per_read; /* bytes per read */
gboolean new_seek;
+ gboolean in_first_get;
/* icecast/audiocast metadata extraction handling */
gboolean iradio_mode;
- gboolean iradio_callbacks_pushed;
+ gboolean http_callbacks_pushed;
gint icy_metaint;
GnomeVFSFileSize icy_count;
gst_gnomevfssrc_get_formats);
gst_element_add_pad(GST_ELEMENT(gnomevfssrc), gnomevfssrc->srcpad);
- gnomevfssrc->filename = NULL;
- gnomevfssrc->is_local = FALSE;
gnomevfssrc->uri = NULL;
gnomevfssrc->handle = NULL;
- gnomevfssrc->fd = 0;
gnomevfssrc->curoffset = 0;
gnomevfssrc->bytes_per_read = 4096;
gnomevfssrc->new_seek = FALSE;
+ gnomevfssrc->in_first_get = TRUE;
gnomevfssrc->icy_metaint = 0;
gnomevfssrc->iradio_mode = FALSE;
- gnomevfssrc->iradio_callbacks_pushed = FALSE;
+ gnomevfssrc->http_callbacks_pushed = FALSE;
gnomevfssrc->icy_count = 0;
gnomevfssrc->iradio_name = NULL;
gnomevfssrc->iradio_genre = NULL;
GnomeVFSModuleCallbackReceivedHeadersIn *in_args =
(GnomeVFSModuleCallbackReceivedHeadersIn *)in;
+ /* This is only used for internet radio stuff right now */
if (!src->iradio_mode)
return;
for (i = in_args->headers; i; i = i->next) {
char *data = (char *) i->data;
- char *key;
+ char *key = data;
char *value = strchr(data, ':');
if (!value)
continue;
{
sscanf (data + 12, "%d", &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);
continue;
}
static void
gst_gnomevfssrc_push_callbacks (GstGnomeVFSSrc *gnomevfssrc)
{
- if (gnomevfssrc->iradio_callbacks_pushed)
+ if (gnomevfssrc->http_callbacks_pushed)
return;
GST_DEBUG (0,"pushing callbacks");
gnomevfssrc,
NULL);
- gnomevfssrc->iradio_callbacks_pushed = TRUE;
+ gnomevfssrc->http_callbacks_pushed = TRUE;
}
static void
gst_gnomevfssrc_pop_callbacks (GstGnomeVFSSrc *gnomevfssrc)
{
- if (!gnomevfssrc->iradio_callbacks_pushed)
+ if (!gnomevfssrc->http_callbacks_pushed)
return;
GST_DEBUG (0,"popping callbacks");
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)
g_free (src->iradio_title);
GST_DEBUG(0, "sending notification on icecast 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)
g_free (src->iradio_url);
audiocast_do_notifications(src);
- /* read it in from the file */
- 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) {
+ if (src->iradio_mode && src->icy_metaint > 0) {
GST_BUFFER_DATA (buf) = g_malloc0 (src->icy_metaint);
g_return_val_if_fail (GST_BUFFER_DATA (buf) != NULL, NULL);
- result = gnome_vfs_read (src->handle, GST_BUFFER_DATA (buf),
- src->icy_metaint - src->icy_count,
- &readbytes);
-
- /* EOS? */
- if (readbytes == 0) {
- gst_buffer_unref (buf);
- gst_element_set_eos (GST_ELEMENT (src));
-
- 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;
- }
-
+ GST_BUFFER_SIZE (buf) = 0;
+ /* FIXME GROSS HACK: We try to read in at least 8000
+ * bytes of data so that mp3 typefinding will work. */
+ do
+ {
+ GST_DEBUG (0,"doing read: icy_count: %" G_GINT64_FORMAT, src->icy_count);
+ result = gnome_vfs_read (src->handle, GST_BUFFER_DATA (buf),
+ src->icy_metaint - src->icy_count,
+ &readbytes);
+
+ /* 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 {
/* allocate the space for the buffer data */
GST_BUFFER_DATA(buf) = g_malloc(src->bytes_per_read);
}
GST_BUFFER_TIMESTAMP (buf) = -1;
-
+ src->in_first_get = FALSE;
/* we're done, return the buffer */
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)
{
GnomeVFSResult result;
+ GnomeVFSFileInfo *info;
g_return_val_if_fail(!GST_FLAG_IS_SET(src, GST_GNOMEVFSSRC_OPEN),
FALSE);
/* create the uri */
src->uri = gnome_vfs_uri_new(src->filename);
if (!src->uri) {
- gst_element_error(GST_ELEMENT(src),
- "creating uri \"%s\" (%s)",
- src->filename, strerror (errno));
+ gst_element_error(GST_ELEMENT(src), "creating uri \"%s\" (%s)",
+ src->filename, strerror (errno));
return FALSE;
}
- /* open the file using open() if the file is local */
- src->is_local = gnome_vfs_uri_is_local(src->uri);
-
- 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;
+ if (!audiocast_init(src))
+ return FALSE;
- gst_gnomevfssrc_push_callbacks (src);
-
- result =
- gnome_vfs_open_uri(&(src->handle), src->uri,
- GNOME_VFS_OPEN_READ);
- if (result != GNOME_VFS_OK)
- {
- gst_gnomevfssrc_pop_callbacks (src);
- audiocast_thread_kill(src);
- gst_element_error(GST_ELEMENT(src),
+ gst_gnomevfssrc_push_callbacks (src);
+
+ result = gnome_vfs_open_uri(&(src->handle), src->uri,
+ GNOME_VFS_OPEN_READ);
+ if (result != GNOME_VFS_OK)
+ {
+ gst_gnomevfssrc_pop_callbacks (src);
+ audiocast_thread_kill(src);
+ gst_element_error(GST_ELEMENT(src),
"opening vfs file \"%s\" (%s)",
- src->filename,
- gnome_vfs_result_to_string(result));
- return FALSE;
- }
-
- /* find the file length (but skip it in iradio mode,
- * since it will require a separate request, and we
- * know the length is undefined anyways) */
- if (!src->iradio_mode)
+ src->filename,
+ gnome_vfs_result_to_string(result));
+ return FALSE;
+ }
+
+ info = gnome_vfs_file_info_new ();
+ if (gnome_vfs_get_file_info_from_handle (src->handle, info,
+ GNOME_VFS_FILE_INFO_DEFAULT | GNOME_VFS_FILE_INFO_GET_MIME_TYPE)
+ == 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;
- GnomeVFSFileInfo *info;
-
- info = gnome_vfs_file_info_new ();
- 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);
+ GST_DEBUG (0, "got MIME type \"%s\", setting caps",
+ info->mime_type);
+ GstCaps *caps = gst_caps_new ("gnomevfssrc", info->mime_type, NULL);
+ gst_pad_try_set_caps (src->srcpad, caps);
}
else
- src->size = 0;
-
- GST_DEBUG(0, "size %" G_GINT64_FORMAT, src->size);
+ GST_DEBUG (0, "No mime type available");
+ }
+ else
+ GST_DEBUG (0, "getting info failed: %s", gnome_vfs_result_to_string (result));
- audiocast_do_notifications(src);
+ gnome_vfs_file_info_unref(info);
- GST_DEBUG(0, "open %s", gnome_vfs_result_to_string(result));
- }
+ 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);
return TRUE;
}
-/* unmap and close the file */
static void gst_gnomevfssrc_close_file(GstGnomeVFSSrc *src)
{
g_return_if_fail(GST_FLAG_IS_SET(src, GST_GNOMEVFSSRC_OPEN));
gst_gnomevfssrc_pop_callbacks (src);
audiocast_thread_kill(src);
- /* close the file */
- if (src->is_local)
- {
- /* unmap the file from memory */
- munmap (src->map, src->size);
- close(src->fd);
- } else {
- gnome_vfs_close(src->handle);
- }
+ gnome_vfs_close(src->handle);
- /* zero out a lot of our state */
- src->is_local = FALSE;
gnome_vfs_uri_unref(src->uri);
- g_free(src->local_name);
- src->fd = 0;
- src->map = NULL;
src->size = 0;
src->curoffset = 0;
src->new_seek = FALSE;
return FALSE;
break;
}
- if (!src->is_local) {
- GnomeVFSResult result;
-
- result = gnome_vfs_seek(src->handle,
+ GnomeVFSResult result;
+
+ result = gnome_vfs_seek(src->handle,
GNOME_VFS_SEEK_START, desired_offset);
- GST_DEBUG(0, "new_seek: %s",
- gnome_vfs_result_to_string(result));
-
- if (result != GNOME_VFS_OK) {
- gst_event_unref (event);
- return FALSE;
- }
+ GST_DEBUG(0, "new_seek: %s",
+ gnome_vfs_result_to_string(result));
+
+ if (result != GNOME_VFS_OK) {
+ gst_event_unref (event);
+ return FALSE;
}
src->curoffset = desired_offset;
src->new_seek = TRUE;