Audacious $Id:Doxyfile42802007-03-2104:39:00Znenolod$
|
00001 /* 00002 * Copyright (c) 2006-2007 William Pitcock 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; under version 3 of the License. 00007 * 00008 * This program is distributed in the hope that it will be useful, 00009 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00011 * GNU General Public License for more details. 00012 * 00013 * You should have received a copy of the GNU General Public License 00014 * along with this program. If not, see <http://www.gnu.org/licenses>. 00015 * 00016 * The Audacious team does not consider modular code linking to 00017 * Audacious or using our public API to be a derived work. 00018 */ 00019 00020 #include <glib.h> 00021 #include <string.h> 00022 #include "vfs.h" 00023 #include "vfs_buffer.h" 00024 #include "vfs_buffered_file.h" 00025 00026 VFSFile * 00027 buffered_file_vfs_fopen_impl(const gchar * path, 00028 const gchar * mode) 00029 { 00030 return NULL; 00031 } 00032 00033 gint 00034 buffered_file_vfs_fclose_impl(VFSFile * file) 00035 { 00036 g_return_val_if_fail(file != NULL, -1); 00037 00038 if (file->handle) 00039 { 00040 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle; 00041 00042 if (handle->fd != NULL) 00043 vfs_fclose(handle->fd); 00044 00045 vfs_fclose(handle->buffer); 00046 g_free(handle->mem); 00047 g_free(handle); 00048 } 00049 00050 return 0; 00051 } 00052 00053 gint64 buffered_file_vfs_fread_impl (void * i_ptr, gint64 size, gint64 nmemb, 00054 VFSFile * file) 00055 { 00056 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle; 00057 00058 /* is this request within the buffered area, or should we switch to 00059 * an FD? --nenolod 00060 */ 00061 if (handle->which == FALSE && 00062 (vfs_ftell(handle->buffer)) + (size * nmemb) > 00063 ((VFSBuffer *) handle->buffer->handle)->size) 00064 { 00065 if (vfs_fseek (handle->fd, vfs_ftell (handle->buffer), SEEK_SET)) 00066 return 0; 00067 handle->which = TRUE; 00068 } 00069 00070 return vfs_fread(i_ptr, size, nmemb, handle->which == TRUE ? handle->fd : handle->buffer); 00071 } 00072 00073 gint64 buffered_file_vfs_fwrite_impl (const void * i_ptr, gint64 size, gint64 00074 nmemb, VFSFile * file) 00075 { 00076 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle; 00077 00078 return vfs_fwrite(i_ptr, size, nmemb, handle->fd); 00079 } 00080 00081 gint 00082 buffered_file_vfs_getc_impl(VFSFile *stream) 00083 { 00084 VFSBufferedFile *handle = (VFSBufferedFile *) stream->handle; 00085 00086 /* is this request within the buffered area, or should we switch to 00087 * an FD? --nenolod 00088 */ 00089 if ((vfs_ftell(handle->buffer)) + 1 > 00090 ((VFSBuffer *) handle->buffer->handle)->size) 00091 { 00092 if (vfs_fseek (handle->fd, vfs_ftell (handle->buffer), SEEK_SET)) 00093 return EOF; 00094 handle->which = TRUE; 00095 } 00096 00097 return vfs_getc(handle->which == TRUE ? handle->fd : handle->buffer); 00098 } 00099 00100 gint 00101 buffered_file_vfs_ungetc_impl(gint c, VFSFile *stream) 00102 { 00103 return -1; 00104 } 00105 00106 gint 00107 buffered_file_vfs_fseek_impl(VFSFile * file, 00108 gint64 offset, 00109 gint whence) 00110 { 00111 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle; 00112 00113 if (vfs_fseek (handle->buffer, offset, whence)) 00114 return -1; 00115 00116 switch(whence) 00117 { 00118 case SEEK_END: 00119 handle->which = TRUE; 00120 return vfs_fseek (handle->fd, offset, whence); 00121 case SEEK_CUR: 00122 if (vfs_ftell(handle->buffer) + offset >= ((VFSBuffer *) handle->buffer->handle)->size) 00123 { 00124 handle->which = TRUE; 00125 return vfs_fseek (handle->fd, offset, whence); 00126 } 00127 else 00128 { 00129 gint64 noff; 00130 00131 handle->which = FALSE; 00132 noff = ((VFSBuffer *) handle->buffer->handle)->size - (vfs_ftell(handle->buffer) + offset); 00133 return vfs_fseek (handle->buffer, noff, whence); 00134 } 00135 break; 00136 case SEEK_SET: 00137 default: 00138 if (offset > ((VFSBuffer *) handle->buffer->handle)->size) 00139 { 00140 handle->which = TRUE; 00141 return vfs_fseek (handle->fd, offset, whence); 00142 } 00143 else 00144 { 00145 handle->which = FALSE; 00146 return vfs_fseek (handle->buffer, offset, whence); 00147 } 00148 break; 00149 } 00150 return 0; 00151 } 00152 00153 void 00154 buffered_file_vfs_rewind_impl(VFSFile * file) 00155 { 00156 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle; 00157 00158 vfs_rewind(handle->buffer); 00159 vfs_rewind(handle->fd); 00160 handle->which = FALSE; 00161 } 00162 00163 gint64 00164 buffered_file_vfs_ftell_impl(VFSFile * file) 00165 { 00166 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle; 00167 00168 return vfs_ftell(handle->which == TRUE ? handle->fd : handle->buffer); 00169 } 00170 00171 gboolean 00172 buffered_file_vfs_feof_impl(VFSFile * file) 00173 { 00174 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle; 00175 00176 return vfs_feof(handle->which == TRUE ? handle->fd : handle->buffer); 00177 } 00178 00179 gint 00180 buffered_file_vfs_truncate_impl (VFSFile * file, gint64 size) 00181 { 00182 return 0; 00183 } 00184 00185 gint64 00186 buffered_file_vfs_fsize_impl(VFSFile * file) 00187 { 00188 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle; 00189 00190 return vfs_fsize(handle->fd); 00191 } 00192 00193 gchar * 00194 buffered_file_vfs_metadata_impl(VFSFile * file, const gchar * field) 00195 { 00196 VFSBufferedFile *handle = (VFSBufferedFile *) file->handle; 00197 00198 return vfs_get_metadata(handle->fd, field); 00199 } 00200 00201 VFSConstructor buffered_file_const = { 00202 NULL, // not a normal VFS class 00203 buffered_file_vfs_fopen_impl, 00204 buffered_file_vfs_fclose_impl, 00205 buffered_file_vfs_fread_impl, 00206 buffered_file_vfs_fwrite_impl, 00207 buffered_file_vfs_getc_impl, 00208 buffered_file_vfs_ungetc_impl, 00209 buffered_file_vfs_fseek_impl, 00210 buffered_file_vfs_rewind_impl, 00211 buffered_file_vfs_ftell_impl, 00212 buffered_file_vfs_feof_impl, 00213 buffered_file_vfs_truncate_impl, 00214 buffered_file_vfs_fsize_impl, 00215 buffered_file_vfs_metadata_impl 00216 }; 00217 00224 VFSFile * 00225 vfs_buffered_file_new_from_uri(const gchar *uri) 00226 { 00227 VFSFile *handle; 00228 VFSBufferedFile *fd; 00229 gsize sz; 00230 00231 g_return_val_if_fail(uri != NULL, NULL); 00232 00233 handle = g_new0(VFSFile, 1); 00234 fd = g_new0(VFSBufferedFile, 1); 00235 fd->mem = g_malloc0(128000); 00236 fd->fd = vfs_fopen(uri, "rb"); 00237 00238 if (fd->fd == NULL) 00239 { 00240 g_free(fd->mem); 00241 g_free(fd); 00242 g_free(handle); 00243 00244 return NULL; 00245 } 00246 00247 sz = vfs_fread(fd->mem, 1, 128000, fd->fd); 00248 vfs_rewind(fd->fd); 00249 00250 if (!sz) 00251 { 00252 vfs_fclose(fd->fd); 00253 g_free(fd->mem); 00254 g_free(fd); 00255 g_free(handle); 00256 00257 return NULL; 00258 } 00259 00260 fd->buffer = vfs_buffer_new(fd->mem, sz); 00261 00262 handle->handle = fd; 00263 handle->base = &buffered_file_const; 00264 handle->uri = g_strdup(uri); 00265 handle->ref = 1; 00266 00267 return handle; 00268 } 00269 00274 VFSFile * 00275 vfs_buffered_file_release_live_fd(VFSFile *fd) 00276 { 00277 VFSBufferedFile *file = (VFSBufferedFile *) fd; 00278 VFSFile *out; 00279 00280 g_return_val_if_fail(file != NULL, NULL); 00281 00282 out = file->fd; 00283 file->fd = NULL; 00284 00285 vfs_fclose(fd); 00286 00287 return out; 00288 }