Audacious $Id:Doxyfile42802007-03-2104:39:00Znenolod$

probe-buffer.c

Go to the documentation of this file.
00001 /*
00002  * probe-buffer.c
00003  * Copyright 2010 John Lindgren
00004  *
00005  * This file is part of Audacious.
00006  *
00007  * Audacious is free software: you can redistribute it and/or modify it under
00008  * the terms of the GNU General Public License as published by the Free Software
00009  * Foundation, version 2 or version 3 of the License.
00010  *
00011  * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
00012  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
00013  * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License along with
00016  * Audacious. If not, see <http://www.gnu.org/licenses/>.
00017  *
00018  * The Audacious team does not consider modular code linking to Audacious or
00019  * using our public API to be a derived work.
00020  */
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <string.h>
00025 
00026 #include "probe-buffer.h"
00027 
00028 typedef struct
00029 {
00030     const gchar * filename, * decoder;
00031     VFSFile * file;
00032     guchar buffer[16384];
00033     gint filled, at;
00034     const gchar * read_warned, * seek_warned;
00035 }
00036 ProbeBuffer;
00037 
00038 static gint probe_buffer_fclose (VFSFile * file)
00039 {
00040     gint ret = vfs_fclose (((ProbeBuffer *) file->handle)->file);
00041     g_free (file->handle);
00042     return ret;
00043 }
00044 
00045 static void increase_buffer (ProbeBuffer * p, gint64 size)
00046 {
00047     size = (size + 0xFF) & ~0xFF;
00048 
00049     if (size > sizeof p->buffer)
00050     {
00051         if (p->read_warned != p->decoder)
00052         {
00053             fprintf (stderr, "%s tried to read past end of buffer while "
00054              "probing %s.\n", p->decoder, p->filename);
00055             p->read_warned = p->decoder;
00056         }
00057 
00058         size = sizeof p->buffer;
00059     }
00060 
00061     if (p->filled < size)
00062         p->filled += vfs_fread (p->buffer + p->filled, 1, size - p->filled,
00063          p->file);
00064 }
00065 
00066 static gint64 probe_buffer_fread (void * buffer, gint64 size, gint64 count,
00067  VFSFile * file)
00068 {
00069     ProbeBuffer * p = file->handle;
00070 
00071     increase_buffer (p, p->at + size * count);
00072     gint readed = (size > 0) ? MIN (count, (p->filled - p->at) / size) : 0;
00073     memcpy (buffer, p->buffer + p->at, size * readed);
00074 
00075     p->at += size * readed;
00076     return readed;
00077 }
00078 
00079 static gint64 probe_buffer_fwrite (const void * data, gint64 size, gint64 count,
00080  VFSFile * file)
00081 {
00082     /* not implemented */
00083     return 0;
00084 }
00085 
00086 static gint probe_buffer_getc (VFSFile * file)
00087 {
00088     guchar c;
00089     return (probe_buffer_fread (& c, 1, 1, file) == 1) ? c : EOF;
00090 }
00091 
00092 static gint probe_buffer_fseek (VFSFile * file, gint64 offset, gint whence)
00093 {
00094     ProbeBuffer * p = file->handle;
00095 
00096     if (whence == SEEK_END)
00097     {
00098         if (p->seek_warned != p->decoder)
00099         {
00100             fprintf (stderr, "%s tried to seek to end of file while probing "
00101              "%s.\n", p->decoder, p->filename);
00102             p->seek_warned = p->decoder;
00103         }
00104 
00105         return -1;
00106     }
00107 
00108     if (whence == SEEK_CUR)
00109         offset += p->at;
00110 
00111     g_return_val_if_fail (offset >= 0, -1);
00112     increase_buffer (p, offset);
00113 
00114     if (offset > p->filled)
00115         return -1;
00116 
00117     p->at = offset;
00118     return 0;
00119 }
00120 
00121 static gint probe_buffer_ungetc (gint c, VFSFile * file)
00122 {
00123     return (! probe_buffer_fseek (file, -1, SEEK_CUR)) ? c : EOF;
00124 }
00125 
00126 static void probe_buffer_rewind (VFSFile * file)
00127 {
00128     probe_buffer_fseek (file, 0, SEEK_SET);
00129 }
00130 
00131 static gint64 probe_buffer_ftell (VFSFile * file)
00132 {
00133     return ((ProbeBuffer *) file->handle)->at;
00134 }
00135 
00136 static gboolean probe_buffer_feof (VFSFile * file)
00137 {
00138     ProbeBuffer * p = file->handle;
00139     return (p->at < p->filled) ? FALSE : vfs_feof (p->file);
00140 }
00141 
00142 static gint probe_buffer_ftruncate (VFSFile * file, gint64 size)
00143 {
00144     /* not implemented */
00145     return -1;
00146 }
00147 
00148 static gint64 probe_buffer_fsize (VFSFile * file)
00149 {
00150     return vfs_fsize (((ProbeBuffer *) file->handle)->file);
00151 }
00152 
00153 static gchar * probe_buffer_get_metadata (VFSFile * file, const gchar * field)
00154 {
00155     return vfs_get_metadata (((ProbeBuffer *) file->handle)->file, field);
00156 }
00157 
00158 static VFSConstructor probe_buffer_table =
00159 {
00160         .uri_id = NULL,
00161         .vfs_fopen_impl = NULL,
00162         .vfs_fclose_impl = probe_buffer_fclose,
00163         .vfs_fread_impl = probe_buffer_fread,
00164         .vfs_fwrite_impl = probe_buffer_fwrite,
00165         .vfs_getc_impl = probe_buffer_getc,
00166         .vfs_ungetc_impl = probe_buffer_ungetc,
00167         .vfs_fseek_impl = probe_buffer_fseek,
00168         .vfs_rewind_impl = probe_buffer_rewind,
00169         .vfs_ftell_impl = probe_buffer_ftell,
00170         .vfs_feof_impl = probe_buffer_feof,
00171         .vfs_ftruncate_impl = probe_buffer_ftruncate,
00172         .vfs_fsize_impl = probe_buffer_fsize,
00173         .vfs_get_metadata_impl = probe_buffer_get_metadata,
00174 };
00175 
00176 VFSFile * probe_buffer_new (const gchar * filename)
00177 {
00178     VFSFile * file = vfs_fopen (filename, "r");
00179 
00180     if (! file)
00181         return NULL;
00182 
00183     ProbeBuffer * p = g_malloc (sizeof (ProbeBuffer));
00184     p->decoder = NULL;
00185     p->filename = filename;
00186     p->file = file;
00187     p->filled = 0;
00188     p->at = 0;
00189     p->read_warned = NULL;
00190     p->seek_warned = NULL;
00191 
00192     VFSFile * file2 = g_malloc (sizeof (VFSFile));
00193     file2->base = & probe_buffer_table;
00194     file2->handle = p;
00195     file2->uri = g_strdup (filename);
00196     file2->ref = 1;
00197 
00198     return file2;
00199 }
00200 
00201 void probe_buffer_set_decoder (VFSFile * file, const gchar * decoder)
00202 {
00203     ProbeBuffer * p = file->handle;
00204     p->decoder = decoder;
00205 }