Audacious $Id:Doxyfile42802007-03-2104:39:00Znenolod$
|
00001 /* Audacious 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 <inttypes.h> 00021 00022 #include "vfs.h" 00023 #include "audstrings.h" 00024 #include <stdio.h> 00025 #include <unistd.h> 00026 #include <sys/stat.h> 00027 #include <sys/types.h> 00028 #include <string.h> 00029 00030 #include <mowgli.h> 00031 00032 /* Audacious core provides us with a function that looks up a VFS transport for 00033 * a given URI scheme. Since this function will load plugins as needed, it can 00034 * only be called from the main thread. When VFS is used from parallel threads, 00035 * vfs_prepare must be called from the main thread to look up any needed 00036 * transports beforehand. */ 00037 00038 static VFSConstructor * (* lookup_func) (const gchar * scheme) = NULL; 00039 00040 void vfs_set_lookup_func (VFSConstructor * (* func) (const gchar * scheme)) 00041 { 00042 lookup_func = func; 00043 } 00044 00045 static gboolean verbose = FALSE; 00046 00047 void vfs_set_verbose (gboolean set) 00048 { 00049 verbose = set; 00050 } 00051 00052 static void logger (const gchar * format, ...) 00053 { 00054 static gchar last[256] = ""; 00055 static gint repeated = 0; 00056 00057 gchar buf[256]; 00058 00059 va_list args; 00060 va_start (args, format); 00061 vsnprintf (buf, sizeof buf, format, args); 00062 va_end (args); 00063 00064 if (! strcmp (buf, last)) 00065 repeated ++; 00066 else 00067 { 00068 if (repeated) 00069 { 00070 printf ("VFS: (last message repeated %d times)\n", repeated); 00071 repeated = 0; 00072 } 00073 00074 fputs (buf, stdout); 00075 strcpy (last, buf); 00076 } 00077 } 00078 00087 VFSFile * 00088 vfs_fopen(const gchar * path, 00089 const gchar * mode) 00090 { 00091 g_return_val_if_fail (path && mode, NULL); 00092 g_return_val_if_fail (lookup_func, NULL); 00093 00094 VFSFile *file; 00095 VFSConstructor *vtable = NULL; 00096 00097 const gchar * s = strstr (path, "://"); 00098 g_return_val_if_fail (s, NULL); 00099 gchar scheme[s - path + 1]; 00100 strncpy (scheme, path, s - path); 00101 scheme[s - path] = 0; 00102 00103 vtable = lookup_func (scheme); 00104 if (! vtable) 00105 return NULL; 00106 00107 file = vtable->vfs_fopen_impl(path, mode); 00108 00109 if (verbose) 00110 logger ("VFS: <%p> open (mode %s) %s\n", file, mode, path); 00111 00112 if (file == NULL) 00113 return NULL; 00114 00115 file->uri = g_strdup(path); 00116 file->base = vtable; 00117 file->ref = 1; 00118 file->sig = VFS_SIG; 00119 00120 return file; 00121 } 00122 00129 gint 00130 vfs_fclose(VFSFile * file) 00131 { 00132 g_return_val_if_fail (file && file->sig == VFS_SIG, -1); 00133 00134 if (verbose) 00135 printf ("VFS: <%p> close\n", file); 00136 00137 gint ret = 0; 00138 00139 if (--file->ref > 0) 00140 return -1; 00141 00142 if (file->base->vfs_fclose_impl(file) != 0) 00143 ret = -1; 00144 00145 g_free(file->uri); 00146 00147 memset (file, 0, sizeof (VFSFile)); 00148 g_free (file); 00149 00150 return ret; 00151 } 00152 00162 gint64 vfs_fread (void * ptr, gint64 size, gint64 nmemb, VFSFile * file) 00163 { 00164 g_return_val_if_fail (file && file->sig == VFS_SIG, 0); 00165 00166 gint64 readed = file->base->vfs_fread_impl (ptr, size, nmemb, file); 00167 00168 if (verbose) 00169 logger ("VFS: <%p> read %"PRId64" elements of size %"PRId64" = " 00170 "%"PRId64"\n", file, nmemb, size, readed); 00171 00172 return readed; 00173 } 00174 00184 gint64 vfs_fwrite (const void * ptr, gint64 size, gint64 nmemb, VFSFile * file) 00185 { 00186 g_return_val_if_fail (file && file->sig == VFS_SIG, 0); 00187 00188 gint64 written = file->base->vfs_fwrite_impl (ptr, size, nmemb, file); 00189 00190 if (verbose) 00191 logger ("VFS: <%p> write %"PRId64" elements of size %"PRId64" = " 00192 "%"PRId64"\n", file, nmemb, size, written); 00193 00194 return written; 00195 } 00196 00203 gint 00204 vfs_getc(VFSFile *file) 00205 { 00206 g_return_val_if_fail (file && file->sig == VFS_SIG, EOF); 00207 00208 if (verbose) 00209 logger ("VFS: <%p> getc\n", file); 00210 00211 return file->base->vfs_getc_impl(file); 00212 } 00213 00221 gint 00222 vfs_ungetc(gint c, VFSFile *file) 00223 { 00224 g_return_val_if_fail (file && file->sig == VFS_SIG, EOF); 00225 00226 if (verbose) 00227 logger ("VFS: <%p> ungetc\n", file); 00228 00229 return file->base->vfs_ungetc_impl(c, file); 00230 } 00231 00245 gint 00246 vfs_fseek(VFSFile * file, 00247 gint64 offset, 00248 gint whence) 00249 { 00250 g_return_val_if_fail (file && file->sig == VFS_SIG, -1); 00251 00252 if (verbose) 00253 logger ("VFS: <%p> seek to %"PRId64" from %s\n", file, offset, whence == 00254 SEEK_CUR ? "current" : whence == SEEK_SET ? "beginning" : whence == 00255 SEEK_END ? "end" : "invalid"); 00256 00257 return file->base->vfs_fseek_impl(file, offset, whence); 00258 } 00259 00265 void 00266 vfs_rewind(VFSFile * file) 00267 { 00268 g_return_if_fail (file && file->sig == VFS_SIG); 00269 00270 if (verbose) 00271 logger ("VFS: <%p> rewind\n", file); 00272 00273 file->base->vfs_rewind_impl(file); 00274 } 00275 00282 gint64 00283 vfs_ftell(VFSFile * file) 00284 { 00285 g_return_val_if_fail (file && file->sig == VFS_SIG, -1); 00286 00287 gint64 told = file->base->vfs_ftell_impl (file); 00288 00289 if (verbose) 00290 logger ("VFS: <%p> tell = %"PRId64"\n", file, told); 00291 00292 return told; 00293 } 00294 00301 gboolean 00302 vfs_feof(VFSFile * file) 00303 { 00304 g_return_val_if_fail (file && file->sig == VFS_SIG, TRUE); 00305 00306 gboolean eof = file->base->vfs_feof_impl (file); 00307 00308 if (verbose) 00309 logger ("VFS: <%p> eof = %s\n", file, eof ? "yes" : "no"); 00310 00311 return eof; 00312 } 00313 00321 gint vfs_ftruncate (VFSFile * file, gint64 length) 00322 { 00323 g_return_val_if_fail (file && file->sig == VFS_SIG, -1); 00324 00325 if (verbose) 00326 logger ("VFS: <%p> truncate to %"PRId64"\n", file, length); 00327 00328 return file->base->vfs_ftruncate_impl(file, length); 00329 } 00330 00337 gint64 vfs_fsize (VFSFile * file) 00338 { 00339 g_return_val_if_fail (file && file->sig == VFS_SIG, -1); 00340 00341 gint64 size = file->base->vfs_fsize_impl (file); 00342 00343 if (verbose) 00344 logger ("VFS: <%p> size = %"PRId64"\n", file, size); 00345 00346 return size; 00347 } 00348 00356 gchar * 00357 vfs_get_metadata(VFSFile * file, const gchar * field) 00358 { 00359 if (file == NULL) 00360 return NULL; 00361 00362 if (file->base->vfs_get_metadata_impl) 00363 return file->base->vfs_get_metadata_impl(file, field); 00364 return NULL; 00365 } 00366 00374 gboolean 00375 vfs_file_test(const gchar * path, GFileTest test) 00376 { 00377 if (strncmp (path, "file://", 7)) 00378 return FALSE; /* only local files are handled */ 00379 00380 gchar * path2 = uri_to_filename (path); 00381 00382 if (path2 == NULL) 00383 path2 = g_strdup(path); 00384 00385 gboolean ret = g_file_test (path2, test); 00386 00387 g_free(path2); 00388 00389 return ret; 00390 } 00391 00398 gboolean 00399 vfs_is_writeable(const gchar * path) 00400 { 00401 struct stat info; 00402 gchar * realfn = uri_to_filename (path); 00403 00404 if (stat(realfn, &info) == -1) 00405 return FALSE; 00406 00407 g_free(realfn); 00408 00409 return (info.st_mode & S_IWUSR); 00410 } 00411 00421 VFSFile * 00422 vfs_dup(VFSFile *in) 00423 { 00424 g_return_val_if_fail(in != NULL, NULL); 00425 00426 in->ref++; 00427 00428 return in; 00429 } 00430 00437 gboolean 00438 vfs_is_remote(const gchar * path) 00439 { 00440 return strncasecmp (path, "file://", 7) ? TRUE : FALSE; 00441 } 00442 00449 gboolean 00450 vfs_is_streaming(VFSFile *file) 00451 { 00452 off_t size = 0; 00453 00454 if (file == NULL) 00455 return FALSE; 00456 00457 size = file->base->vfs_fsize_impl(file); 00458 00459 if (size == -1) 00460 return TRUE; 00461 else 00462 return FALSE; 00463 }