Audacious
$Id:Doxyfile42802007-03-2104:39:00Znenolod$
|
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 }