Audacious  $Id:Doxyfile42802007-03-2104:39:00Znenolod$
probe.c
Go to the documentation of this file.
1 /*
2  * probe.c
3  * Copyright 2009-2010 John Lindgren
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions, and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions, and the following disclaimer in the documentation
13  * provided with the distribution.
14  *
15  * This software is provided "as is" and without any warranty, express or
16  * implied. In no event shall the authors be liable for any damages arising from
17  * the use of this software.
18  */
19 
20 #include <glib.h>
21 #include <stdio.h>
22 #include <string.h>
23 
24 #include <libaudcore/audstrings.h>
25 
26 #include "debug.h"
27 #include "misc.h"
28 #include "playlist.h"
29 #include "plugin.h"
30 #include "plugins.h"
31 #include "probe-buffer.h"
32 
33 typedef struct
34 {
35  const char * filename;
39 }
41 
42 static bool_t check_opened (ProbeState * state)
43 {
44  if (state->handle != NULL)
45  return TRUE;
46  if (state->failed)
47  return FALSE;
48 
49  AUDDBG ("Opening %s.\n", state->filename);
50  state->handle = probe_buffer_new (state->filename);
51 
52  if (state->handle != NULL)
53  return TRUE;
54 
55  AUDDBG ("FAILED.\n");
56  state->failed = TRUE;
57  return FALSE;
58 }
59 
61 {
62  AUDDBG ("Trying %s.\n", plugin_get_name (plugin));
63  InputPlugin * decoder = plugin_get_header (plugin);
64  if (decoder == NULL)
65  return TRUE;
66 
67  if (decoder->is_our_file_from_vfs != NULL)
68  {
69  if (! check_opened (state))
70  return FALSE;
71 
72  if (decoder->is_our_file_from_vfs (state->filename, state->handle))
73  {
74  state->plugin = plugin;
75  return FALSE;
76  }
77 
78  if (vfs_fseek (state->handle, 0, SEEK_SET) < 0)
79  return FALSE;
80  }
81 
82  return TRUE;
83 }
84 
85 /* Optimization: If we have found plugins with a key match, assume that at least
86  * one of them will succeed. This means that we need not check the very last
87  * plugin. (If there is only one, we do not need to check it at all.) This is
88  * implemented as follows:
89  *
90  * 1. On the first call, assume until further notice the plugin passed is the
91  * last one and will therefore succeed.
92  * 2. On a subsequent call, think twice and probe the plugin we assumed would
93  * succeed. If it does in fact succeed, then we are done. If not, assume
94  * similarly that the plugin passed in this call is the last one.
95  */
96 
98 {
99  if (state->plugin != NULL)
100  {
101  PluginHandle * prev = state->plugin;
102  state->plugin = NULL;
103 
104  if (prev != NULL && ! probe_func (prev, state))
105  return FALSE;
106  }
107 
108  AUDDBG ("Guessing %s.\n", plugin_get_name (plugin));
109  state->plugin = plugin;
110  return TRUE;
111 }
112 
113 static void probe_by_scheme (ProbeState * state)
114 {
115  const char * s = strstr (state->filename, "://");
116 
117  if (s == NULL)
118  return;
119 
120  AUDDBG ("Probing by scheme.\n");
121  char buf[s - state->filename + 1];
122  memcpy (buf, state->filename, s - state->filename);
123  buf[s - state->filename] = 0;
124 
125  input_plugin_for_key (INPUT_KEY_SCHEME, buf, (PluginForEachFunc) probe_func_fast, state);
126 }
127 
128 static void probe_by_extension (ProbeState * state)
129 {
130  char buf[32];
131  if (! uri_get_extension (state->filename, buf, sizeof buf))
132  return;
133 
134  AUDDBG ("Probing by extension.\n");
135  input_plugin_for_key (INPUT_KEY_EXTENSION, buf, (PluginForEachFunc) probe_func_fast, state);
136 }
137 
138 static void probe_by_mime (ProbeState * state)
139 {
140  char * mime;
141 
142  if (! check_opened (state))
143  return;
144 
145  if ((mime = vfs_get_metadata (state->handle, "content-type")) == NULL)
146  return;
147 
148  AUDDBG ("Probing by MIME type.\n");
149  input_plugin_for_key (INPUT_KEY_MIME, mime, (PluginForEachFunc)
150  probe_func_fast, state);
151  g_free (mime);
152 }
153 
154 static void probe_by_content (ProbeState * state)
155 {
156  AUDDBG ("Probing by content.\n");
158 }
159 
161 {
162  ProbeState state;
163 
164  AUDDBG ("Probing %s.\n", filename);
165  state.plugin = NULL;
166  state.filename = filename;
167  state.handle = NULL;
168  state.failed = FALSE;
169 
170  probe_by_scheme (& state);
171 
172  if (state.plugin != NULL)
173  goto DONE;
174 
175  probe_by_extension (& state);
176 
177  if (state.plugin != NULL || fast)
178  goto DONE;
179 
180  probe_by_mime (& state);
181 
182  if (state.plugin != NULL)
183  goto DONE;
184 
185  probe_by_content (& state);
186 
187 DONE:
188  if (state.handle != NULL)
189  vfs_fclose (state.handle);
190 
191  if (state.plugin != NULL)
192  AUDDBG ("Probe succeeded: %s\n", plugin_get_name (state.plugin));
193  else
194  AUDDBG ("Probe failed.\n");
195 
196  return state.plugin;
197 }
198 
199 Tuple * file_read_tuple (const char * filename, PluginHandle * decoder)
200 {
201  InputPlugin * ip = plugin_get_header (decoder);
202  g_return_val_if_fail (ip, NULL);
203  g_return_val_if_fail (ip->probe_for_tuple, NULL);
204 
205  VFSFile * handle = vfs_fopen (filename, "r");
206  Tuple * tuple = ip->probe_for_tuple (filename, handle);
207 
208  if (handle)
209  vfs_fclose (handle);
210 
211  return tuple;
212 }
213 
214 bool_t file_read_image (const char * filename, PluginHandle * decoder,
215  void * * data, int64_t * size)
216 {
217  if (! input_plugin_has_images (decoder))
218  return FALSE;
219 
220  InputPlugin * ip = plugin_get_header (decoder);
221  g_return_val_if_fail (ip, FALSE);
222  g_return_val_if_fail (ip->get_song_image, FALSE);
223 
224  VFSFile * handle = vfs_fopen (filename, "r");
225  bool_t success = ip->get_song_image (filename, handle, data, size);
226 
227  if (handle)
228  vfs_fclose (handle);
229 
230  if (! success)
231  {
232  * data = NULL;
233  * size = 0;
234  }
235 
236  return success;
237 }
238 
240 {
241  return input_plugin_can_write_tuple (decoder);
242 }
243 
244 bool_t file_write_tuple (const char * filename, PluginHandle * decoder,
245  const Tuple * tuple)
246 {
247  InputPlugin * ip = plugin_get_header (decoder);
248  g_return_val_if_fail (ip, FALSE);
249  g_return_val_if_fail (ip->update_song_tuple, FALSE);
250 
251  VFSFile * handle = vfs_fopen (filename, "r+");
252 
253  if (! handle)
254  return FALSE;
255 
256  bool_t success = ip->update_song_tuple (tuple, handle);
257 
258  if (handle)
259  vfs_fclose (handle);
260 
261  if (success)
262  playlist_rescan_file (filename);
263 
264  return success;
265 }
266 
267 bool_t custom_infowin (const char * filename, PluginHandle * decoder)
268 {
269  if (! input_plugin_has_infowin (decoder))
270  return FALSE;
271 
272  InputPlugin * ip = plugin_get_header (decoder);
273  g_return_val_if_fail (ip, FALSE);
274  g_return_val_if_fail (ip->file_info_box, FALSE);
275 
276  ip->file_info_box (filename);
277  return TRUE;
278 }
const char * filename
Definition: probe.c:35
VFSFile * handle
Definition: probe.c:36
bool_t input_plugin_has_images(PluginHandle *plugin)
const char filename
Definition: misc-api.h:85
bool_t custom_infowin(const char *filename, PluginHandle *decoder)
Definition: probe.c:267
static void probe_by_mime(ProbeState *state)
Definition: probe.c:138
EXPORT int vfs_fclose(VFSFile *file)
Closes a VFS stream and destroys a VFSFile object.
Definition: vfs.c:164
PluginHandle * file_find_decoder(const char *filename, bool_t fast)
Definition: probe.c:160
void input_plugin_for_key(int key, const char *value, PluginForEachFunc func, void *data)
bool_t file_read_image(const char *filename, PluginHandle *decoder, void **data, int64_t *size)
Definition: probe.c:214
bool_t input_plugin_can_write_tuple(PluginHandle *plugin)
static bool_t check_opened(ProbeState *state)
Definition: probe.c:42
bool_t failed
Definition: probe.c:37
#define FALSE
Definition: core.h:35
bool_t file_write_tuple(const char *filename, PluginHandle *decoder, const Tuple *tuple)
Definition: probe.c:244
Index Index bool_t
Definition: playlist-api.h:122
#define AUDDBG(...)
Definition: debug.h:30
EXPORT int vfs_fseek(VFSFile *file, int64_t offset, int whence)
Performs a seek in given VFS stream.
Definition: vfs.c:277
static void probe_by_scheme(ProbeState *state)
Definition: probe.c:113
static void probe_by_extension(ProbeState *state)
Definition: probe.c:128
void playlist_rescan_file(const char *filename)
const void * plugin_get_header(PluginHandle *plugin)
#define NULL
Definition: core.h:27
bool_t input_plugin_has_infowin(PluginHandle *plugin)
bool_t file_can_write_tuple(const char *filename, PluginHandle *decoder)
Definition: probe.c:239
Tuple * file_read_tuple(const char *filename, PluginHandle *decoder)
Definition: probe.c:199
PluginHandle * plugin
Definition: probe.c:38
static bool_t probe_func(PluginHandle *plugin, ProbeState *state)
Definition: probe.c:60
bool_t(* PluginForEachFunc)(PluginHandle *plugin, void *data)
Definition: plugins.h:27
static void probe_by_content(ProbeState *state)
Definition: probe.c:154
#define TRUE
Definition: core.h:37
EXPORT VFSFile * vfs_fopen(const char *path, const char *mode)
Opens a stream from a VFS transport using one of the registered VFSConstructor handlers.
Definition: vfs.c:122
VFSFile * probe_buffer_new(const char *filename)
Definition: probe-buffer.c:166
static bool_t probe_func_fast(PluginHandle *plugin, ProbeState *state)
Definition: probe.c:97
EXPORT bool_t uri_get_extension(const char *uri, char *buf, int buflen)
Definition: audstrings.c:260
EXPORT char * vfs_get_metadata(VFSFile *file, const char *field)
Returns metadata about the stream.
Definition: vfs.c:388
bool_t(* update_song_tuple)(const Tuple *tuple, VFSFile *file)
Definition: plugin.h:381
bool_t(* get_song_image)(const char *filename, VFSFile *file, void **data, int64_t *size)
Definition: plugin.h:395
void plugin_for_enabled(int type, PluginForEachFunc func, void *data)
void(* file_info_box)(const char *filename)
Definition: plugin.h:387
bool_t(* is_our_file_from_vfs)(const char *filename, VFSFile *file)
Definition: plugin.h:370
void data PluginHandle plugin
Definition: plugins-api.h:54
Tuple *(* probe_for_tuple)(const char *filename, VFSFile *file)
Definition: plugin.h:375
struct @17::@18::@20 s
const char * plugin_get_name(PluginHandle *plugin)