diff src/audacious/input.c @ 3959:a575c29cee05

- revive on-demand metadata retrieving. in the combination with "Detect file formats on demand", now audacious can load large directory in a few seconds. - revise ext_hash to have lists of input plugins which associated with each extension. - now input_check_file() makes use of ext_hash for file format probing to avoid full scan in the input list. - make "detect file formats on demand" default. - change tooltip text for on demand {detect|metadata}. - move update request for playlist from idle function to event queue.
author Yoshiki Yazawa <yaz@cc.rim.or.jp>
date Sat, 17 Nov 2007 17:07:46 +0900
parents b747ad540903
children 572258c68dfb
line wrap: on
line diff
--- a/src/audacious/input.c	Fri Nov 16 18:55:48 2007 +0100
+++ b/src/audacious/input.c	Sat Nov 17 17:07:46 2007 +0900
@@ -306,6 +306,60 @@
     }
 }
 
+
+/* do actual probing. this function is called from input_check_file() */
+static ProbeResult *
+input_do_check_file(InputPlugin *ip, VFSFile *fd, gchar *filename_proxy, gboolean loading)
+{
+    ProbeResult *pr = NULL;
+    gint result = 0;
+
+    g_return_val_if_fail(fd != NULL, NULL);
+
+    vfs_rewind(fd);
+
+    if (ip->probe_for_tuple &&
+        cfg.use_pl_metadata &&
+        (!loading || (loading && cfg.get_info_on_load)) ) {
+
+        Tuple *tuple = ip->probe_for_tuple(filename_proxy, fd);
+
+        if (tuple != NULL) {
+            pr = g_new0(ProbeResult, 1);
+            pr->ip = ip;
+            pr->tuple = tuple;
+            tuple_associate_int(pr->tuple, FIELD_MTIME, NULL, input_get_mtime(filename_proxy));
+
+            return pr;
+        }
+    }
+
+    else if (ip->is_our_file_from_vfs != NULL) {
+        result = ip->is_our_file_from_vfs(filename_proxy, fd);
+
+        if (result > 0) {
+            pr = g_new0(ProbeResult, 1);
+            pr->ip = ip;
+
+            return pr;
+        }
+    }
+
+    else if (ip->is_our_file != NULL) {
+        result = ip->is_our_file(filename_proxy);
+
+        if (result > 0) {
+            pr = g_new0(ProbeResult, 1);
+            pr->ip = ip;
+
+            return pr;
+        }
+    }
+
+    return NULL;
+}
+
+
 /*
  * input_check_file()
  *
@@ -341,9 +395,15 @@
  * Adapted to return ProbeResult structure.
  *
  * --nenolod, Jul 20 2007
+ *
+ * Make use of ext_hash to avoid full scan in input list.
+ *
+ * --yaz, Nov 16 2007
  */
+
+/* if loading is TRUE, tuple probing can be skipped as regards configuration. */
 ProbeResult *
-input_check_file(const gchar * filename, gboolean show_warning)
+input_check_file(const gchar *filename, gboolean loading)
 {
     VFSFile *fd;
     GList *node;
@@ -351,20 +411,23 @@
     gchar *filename_proxy;
     gint ret = 1;
     gchar *ext, *tmp, *tmp_uri;
-    gboolean use_ext_filter;
+    gboolean use_ext_filter = FALSE;
     gchar *mimetype;
     ProbeResult *pr = NULL;
+    GList **list_hdr = NULL;
+    extern GHashTable *ext_hash;
 
     filename_proxy = g_strdup(filename);
 
+
     /* Some URIs will end in ?<subsong> to determine the subsong requested. */
     tmp_uri = g_strdup(filename);
-
     tmp = strrchr(tmp_uri, '?');
 
     if (tmp != NULL && g_ascii_isdigit(*(tmp + 1)))
         *tmp = '\0';
 
+
     /* Check for plugins with custom URI:// strings */
     /* cue:// cdda:// tone:// tact:// */
     if ((ip = uri_get_plugin(filename)) != NULL && ip->enabled)
@@ -384,6 +447,8 @@
         return NULL;
     }
 
+
+    // open the file with vfs sub-system
     fd = vfs_buffered_file_new_from_uri(tmp_uri);
     g_free(tmp_uri);
 
@@ -393,149 +458,90 @@
         return NULL;
     }
 
-    ext = strrchr(filename_proxy, '.') + 1;
 
-    use_ext_filter =
-        (fd != NULL && (!g_strncasecmp(filename, "/", 1) ||
-                        !g_strncasecmp(filename, "file://", 7))) ? TRUE : FALSE;
-
+    // apply mimetype check. note that stdio does not support mimetype check.
     mimetype = vfs_get_metadata(fd, "content-type");
-    if ((ip = mime_get_plugin(mimetype)) != NULL && ip->enabled)
-    {
-        if (ip->probe_for_tuple != NULL)
-        {
-            Tuple *tuple = ip->probe_for_tuple(filename_proxy, fd);
+    if ((ip = mime_get_plugin(mimetype)) != NULL && ip->enabled) {
+        while(1) {
+            if (!ip || !ip->enabled)
+                continue;
 
-            if (tuple != NULL)
-            {
+            pr = input_do_check_file(ip, fd, filename_proxy, loading);
+
+            if(pr) {
                 g_free(filename_proxy);
                 vfs_fclose(fd);
-
-                pr = g_new0(ProbeResult, 1);
-                pr->ip = ip;
-                pr->tuple = tuple;
-                tuple_associate_int(pr->tuple, FIELD_MTIME, NULL, input_get_mtime(filename_proxy));
-
-                return pr;
-            }
-        }
-        else if (fd && ip->is_our_file_from_vfs != NULL)
-        {
-            ret = ip->is_our_file_from_vfs(filename_proxy, fd);
-
-            if (ret > 0)
-            {
-                g_free(filename_proxy);
-                vfs_fclose(fd);
-
-                pr = g_new0(ProbeResult, 1);
-                pr->ip = ip;
-
-                return pr;
-            }
-        }
-        else if (ip->is_our_file != NULL)
-        {
-            ret = ip->is_our_file(filename_proxy);
-
-            if (ret > 0)
-            {
-                g_free(filename_proxy);
-                vfs_fclose(fd);
-
-                pr = g_new0(ProbeResult, 1);
-                pr->ip = ip;
-
                 return pr;
             }
         }
     }
 
-    for (node = get_input_list(); node != NULL; node = g_list_next(node))
-    {
+
+    // apply ext_hash check
+    if(cfg.use_extension_probing) {
+        use_ext_filter =
+            (fd != NULL && (!g_strncasecmp(filename, "/", 1) ||
+                            !g_strncasecmp(filename, "file://", 7))) ? TRUE : FALSE;
+    }
+
+    if(use_ext_filter) {
+        gchar *base, *lext;
+        gchar *tmp2 = g_filename_from_uri(filename_proxy, NULL, NULL);
+        gchar *realfn = g_strdup(tmp2 ? tmp2 : filename_proxy);
+        g_free(tmp2);
+
+        base = g_path_get_basename(realfn);
+        g_free(realfn);
+        ext = strrchr(base, '.');
+    
+        if(ext) {
+            lext = g_ascii_strdown(ext+1, -1);
+            list_hdr = g_hash_table_lookup(ext_hash, lext);
+            g_free(lext);
+        }
+        g_free(base);
+
+        if(list_hdr) {
+            for(node = *list_hdr; node != NULL; node = g_list_next(node)) {
+                ip = INPUT_PLUGIN(node->data);
+
+                if (!ip || !ip->enabled)
+                    continue;
+
+                pr = input_do_check_file(ip, fd, filename_proxy, loading);
+
+                if(pr) {
+                    g_free(filename_proxy);
+                    vfs_fclose(fd);
+                    return pr;
+                }
+            }
+        }
+
+        return NULL; // no plugin found.
+    }
+
+
+    // do full scan when extension match isn't specified.
+    for (node = get_input_list(); node != NULL; node = g_list_next(node)) {
         ip = INPUT_PLUGIN(node->data);
 
         if (!ip || !ip->enabled)
             continue;
 
-        vfs_rewind(fd);
-
-        if (cfg.use_extension_probing == TRUE && ip->vfs_extensions != NULL &&
-            ext != NULL && ext != (gpointer) 0x1 && use_ext_filter == TRUE)
-        {
-            gint i;
-            gboolean is_our_ext = FALSE;
-
-            for (i = 0; ip->vfs_extensions[i] != NULL; i++)
-            {
-                if (str_has_prefix_nocase(ext, ip->vfs_extensions[i]))
-                {
-                    is_our_ext = TRUE;
-                    break;
-                }
-            }
-
-            /* not a plugin that supports this extension */
-            if (is_our_ext == FALSE) 
-                continue;
-        }
-
-        if (fd && ip->probe_for_tuple != NULL)
-        {
-            Tuple *tuple = ip->probe_for_tuple(filename_proxy, fd);
-
-            if (tuple != NULL)
-            {
-                g_free(filename_proxy);
-                vfs_fclose(fd);
-
-                pr = g_new0(ProbeResult, 1);
-                pr->ip = ip;
-                pr->tuple = tuple;
-                tuple_associate_int(pr->tuple, FIELD_MTIME, NULL, input_get_mtime(filename_proxy));
+        pr = input_do_check_file(ip, fd, filename_proxy, loading);
 
-                return pr;
-            }
-        }
-        else if (fd && ip->is_our_file_from_vfs != NULL)
-        {
-            ret = ip->is_our_file_from_vfs(filename_proxy, fd);
-
-            if (ret > 0)
-            {
-                g_free(filename_proxy);
-                vfs_fclose(fd);
-
-                pr = g_new0(ProbeResult, 1);
-                pr->ip = ip;
-
-                return pr;
-            }
+        if(pr) {
+            g_free(filename_proxy);
+            vfs_fclose(fd);
+            return pr;
         }
-        else if (ip->is_our_file != NULL)
-        {
-            ret = ip->is_our_file(filename_proxy);
-
-            if (ret > 0)
-            {
-                g_free(filename_proxy);
-                vfs_fclose(fd);
-
-                pr = g_new0(ProbeResult, 1);
-                pr->ip = ip;
-
-                return pr;
-            }
-        }
-
-        if (ret <= -1)
-            break;
     }
 
+
+    // all probing failed. return NULL
     g_free(filename_proxy);
-
     vfs_fclose(fd);
-
     return NULL;
 }