00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdio.h>
00023 #include <string.h>
00024
00025 #include <libaudcore/audstrings.h>
00026
00027 #include "debug.h"
00028 #include "misc.h"
00029 #include "playlist.h"
00030 #include "plugin.h"
00031 #include "plugins.h"
00032 #include "probe-buffer.h"
00033
00034 typedef struct
00035 {
00036 gchar * filename;
00037 VFSFile * handle;
00038 gboolean buffered;
00039 PluginHandle * plugin;
00040 }
00041 ProbeState;
00042
00043 static gboolean check_opened (ProbeState * state)
00044 {
00045 if (state->handle != NULL)
00046 return TRUE;
00047
00048 AUDDBG ("Opening %s.\n", state->filename);
00049 if ((state->buffered = vfs_is_remote (state->filename)))
00050 state->handle = probe_buffer_new (state->filename);
00051 else
00052 state->handle = vfs_fopen (state->filename, "r");
00053
00054 if (state->handle != NULL)
00055 return TRUE;
00056
00057 AUDDBG ("FAILED.\n");
00058 return FALSE;
00059 }
00060
00061 static gboolean probe_func (PluginHandle * plugin, ProbeState * state)
00062 {
00063 AUDDBG ("Trying %s.\n", plugin_get_name (plugin));
00064 InputPlugin * decoder = plugin_get_header (plugin);
00065 if (decoder == NULL)
00066 return TRUE;
00067
00068 if (decoder->is_our_file_from_vfs != NULL)
00069 {
00070 if (! check_opened (state))
00071 return FALSE;
00072
00073 if (state->buffered)
00074 probe_buffer_set_decoder (state->handle, plugin_get_name (plugin));
00075
00076 if (decoder->is_our_file_from_vfs (state->filename, state->handle))
00077 {
00078 state->plugin = plugin;
00079 return FALSE;
00080 }
00081
00082 if (vfs_fseek (state->handle, 0, SEEK_SET) < 0)
00083 return FALSE;
00084 }
00085
00086 return TRUE;
00087 }
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 static gboolean probe_func_fast (PluginHandle * plugin, ProbeState * state)
00102 {
00103 if (state->plugin != NULL)
00104 {
00105 PluginHandle * prev = state->plugin;
00106 state->plugin = NULL;
00107
00108 if (prev != NULL && ! probe_func (prev, state))
00109 return FALSE;
00110 }
00111
00112 AUDDBG ("Guessing %s.\n", plugin_get_name (plugin));
00113 state->plugin = plugin;
00114 return TRUE;
00115 }
00116
00117 static void probe_by_scheme (ProbeState * state)
00118 {
00119 gchar * s = strstr (state->filename, "://");
00120 gchar c;
00121
00122 if (s == NULL)
00123 return;
00124
00125 AUDDBG ("Probing by scheme.\n");
00126 c = s[3];
00127 s[3] = 0;
00128 input_plugin_for_key (INPUT_KEY_SCHEME, state->filename, (PluginForEachFunc)
00129 probe_func_fast, state);
00130 s[3] = c;
00131 }
00132
00133 static void probe_by_extension (ProbeState * state)
00134 {
00135 gchar * s = strrchr (state->filename, '.');
00136
00137 if (s == NULL)
00138 return;
00139
00140 AUDDBG ("Probing by extension.\n");
00141 s = g_ascii_strdown (s + 1, -1);
00142
00143 gchar * q = strrchr (s, '?');
00144 if (q != NULL)
00145 * q = 0;
00146
00147 input_plugin_for_key (INPUT_KEY_EXTENSION, s, (PluginForEachFunc)
00148 probe_func_fast, state);
00149 g_free (s);
00150 }
00151
00152 static void probe_by_mime (ProbeState * state)
00153 {
00154 gchar * mime;
00155
00156 if (! check_opened (state))
00157 return;
00158
00159 if ((mime = vfs_get_metadata (state->handle, "content-type")) == NULL)
00160 return;
00161
00162 AUDDBG ("Probing by MIME type.\n");
00163 input_plugin_for_key (INPUT_KEY_MIME, mime, (PluginForEachFunc)
00164 probe_func_fast, state);
00165 g_free (mime);
00166 }
00167
00168 static void probe_by_content (ProbeState * state)
00169 {
00170 AUDDBG ("Probing by content.\n");
00171 plugin_for_enabled (PLUGIN_TYPE_INPUT, (PluginForEachFunc) probe_func, state);
00172 }
00173
00174 PluginHandle * file_find_decoder (const gchar * filename, gboolean fast)
00175 {
00176 ProbeState state;
00177
00178 AUDDBG ("Probing %s.\n", filename);
00179 state.plugin = NULL;
00180 state.filename = filename_split_subtune (filename, NULL);
00181 state.handle = NULL;
00182
00183 probe_by_scheme (& state);
00184
00185 if (state.plugin != NULL)
00186 goto DONE;
00187
00188 probe_by_extension (& state);
00189
00190 if (state.plugin != NULL || fast)
00191 goto DONE;
00192
00193 probe_by_mime (& state);
00194
00195 if (state.plugin != NULL)
00196 goto DONE;
00197
00198 probe_by_content (& state);
00199
00200 DONE:
00201 g_free (state.filename);
00202
00203 if (state.handle != NULL)
00204 vfs_fclose (state.handle);
00205
00206 return state.plugin;
00207 }
00208
00209 Tuple * file_read_tuple (const gchar * filename, PluginHandle * decoder)
00210 {
00211 InputPlugin * ip = plugin_get_header (decoder);
00212 g_return_val_if_fail (ip, NULL);
00213 g_return_val_if_fail (ip->probe_for_tuple, NULL);
00214
00215 gchar * real = filename_split_subtune (filename, NULL);
00216 VFSFile * handle = vfs_fopen (real, "r");
00217 g_free (real);
00218
00219 Tuple * tuple = ip->probe_for_tuple (filename, handle);
00220
00221 if (handle)
00222 vfs_fclose (handle);
00223
00224 return tuple;
00225 }
00226
00227 gboolean file_read_image (const gchar * filename, PluginHandle * decoder,
00228 void * * data, gint * size)
00229 {
00230 if (! input_plugin_has_images (decoder))
00231 return FALSE;
00232
00233 InputPlugin * ip = plugin_get_header (decoder);
00234 g_return_val_if_fail (ip, FALSE);
00235 g_return_val_if_fail (ip->get_song_image, FALSE);
00236
00237 gchar * real = filename_split_subtune (filename, NULL);
00238 VFSFile * handle = vfs_fopen (real, "r");
00239 g_free (real);
00240
00241 gboolean success = ip->get_song_image (filename, handle, data, size);
00242
00243 if (handle)
00244 vfs_fclose (handle);
00245
00246 return success;
00247 }
00248
00249 gboolean file_can_write_tuple (const gchar * filename, PluginHandle * decoder)
00250 {
00251 return input_plugin_can_write_tuple (decoder);
00252 }
00253
00254 gboolean file_write_tuple (const gchar * filename, PluginHandle * decoder,
00255 const Tuple * tuple)
00256 {
00257 InputPlugin * ip = plugin_get_header (decoder);
00258 g_return_val_if_fail (ip, FALSE);
00259 g_return_val_if_fail (ip->update_song_tuple, FALSE);
00260
00261 gchar * real = filename_split_subtune (filename, NULL);
00262 VFSFile * handle = vfs_fopen (real, "r+");
00263 g_free (real);
00264
00265 if (! handle)
00266 return FALSE;
00267
00268 gboolean success = ip->update_song_tuple (tuple, handle);
00269
00270 if (handle)
00271 vfs_fclose (handle);
00272
00273 if (success)
00274 playlist_rescan_file (filename);
00275
00276 return success;
00277 }
00278
00279 gboolean custom_infowin (const gchar * filename, PluginHandle * decoder)
00280 {
00281 if (! input_plugin_has_infowin (decoder))
00282 return FALSE;
00283
00284 InputPlugin * ip = plugin_get_header (decoder);
00285 g_return_val_if_fail (ip, FALSE);
00286 g_return_val_if_fail (ip->file_info_box, FALSE);
00287
00288 ip->file_info_box (filename);
00289 return TRUE;
00290 }