# HG changeset patch # User Yoshiki Yazawa # Date 1195286866 -32400 # Node ID a575c29cee05746e2760d03d2adbfb15eaedd10f # Parent ad14a25a31fac5ec2218aa3b530b14805fb6fac9 - 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. diff -r ad14a25a31fa -r a575c29cee05 src/audacious/glade/prefswin.glade --- a/src/audacious/glade/prefswin.glade Fri Nov 16 18:55:48 2007 +0100 +++ b/src/audacious/glade/prefswin.glade Sat Nov 17 17:07:46 2007 +0900 @@ -1990,7 +1990,7 @@ True - Load metadata on demand when displaying the file in the playlist + Load metadata on demand when displaying the file in the playlist. You may need to set "Detect file formats on demand" in Audio page for full benefit. True On display True @@ -3968,7 +3968,7 @@ True - When checked, Audacious will detect file formats based by extension. This is slightly slower than detection on demand, but still provides a minimal level of format detection. + When checked, Audacious will detect file formats based by extension. Only files with extensions of supported formats will be loaded. True Detect file formats by extension. True diff -r ad14a25a31fa -r a575c29cee05 src/audacious/input.c --- 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 ? 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; } diff -r ad14a25a31fa -r a575c29cee05 src/audacious/input.h --- a/src/audacious/input.h Fri Nov 16 18:55:48 2007 +0100 +++ b/src/audacious/input.h Sat Nov 17 17:07:46 2007 +0900 @@ -47,7 +47,7 @@ InputVisType input_get_vis_type(); void free_vis_data(void); -ProbeResult *input_check_file(const gchar * filename, gboolean show_warning); +ProbeResult *input_check_file(const gchar * filename, gboolean loading); Tuple *input_get_song_tuple(const gchar * filename); void input_play(gchar * filename); diff -r ad14a25a31fa -r a575c29cee05 src/audacious/main.c --- a/src/audacious/main.c Fri Nov 16 18:55:48 2007 +0100 +++ b/src/audacious/main.c Sat Nov 17 17:07:46 2007 +0900 @@ -207,8 +207,8 @@ TRUE, /* show seperators in pl */ NULL, /* chardet_detector */ NULL, /* chardet_fallback */ - 500, /* audio buffer size */ - FALSE, /* whether or not to postpone format detection on initial add */ + 500, /* audio buffer size */ + TRUE, /* whether or not to postpone format detection on initial add */ TRUE, /* show filepopup for tuple */ NULL, /* words identifying covers */ NULL, /* words that might not show up in cover names */ diff -r ad14a25a31fa -r a575c29cee05 src/audacious/playlist.c --- a/src/audacious/playlist.c Fri Nov 16 18:55:48 2007 +0100 +++ b/src/audacious/playlist.c Sat Nov 17 17:07:46 2007 +0900 @@ -777,6 +777,7 @@ g_return_val_if_fail(playlist != NULL, FALSE); g_return_val_if_fail(filename != NULL, FALSE); + /* load playlist */ if (is_playlist_name(filename)) { playlist->loading_playlist = TRUE; playlist_load_ins(playlist, filename, pos); @@ -784,13 +785,20 @@ return TRUE; } - if (playlist->loading_playlist == TRUE || cfg.playlist_detect == TRUE) { + /* audio file or uri */ + if (playlist->loading_playlist == TRUE) dec = NULL; - if(!filter_by_extension(filename)) + + /* on demand probing is on */ + if (cfg.playlist_detect == TRUE) { + dec = NULL; + if(cfg.use_extension_probing && !filter_by_extension(filename)) return FALSE; } + /* find decorder for non-remote uri i.e. local file */ else if (!str_has_prefix_nocase(filename, "http://") && - !str_has_prefix_nocase(filename, "https://")) { + !str_has_prefix_nocase(filename, "https://")) { + pr = input_check_file(filename, TRUE); if (pr) { @@ -800,13 +808,15 @@ g_free(pr); } - if (cfg.playlist_detect == TRUE || playlist->loading_playlist == TRUE || + /* add filename to playlist */ + if (cfg.playlist_detect == TRUE || + playlist->loading_playlist == TRUE || (playlist->loading_playlist == FALSE && dec != NULL) || (playlist->loading_playlist == FALSE && !is_playlist_name(filename) && str_has_prefix_nocase(filename, "http"))) { - if(!filter_by_extension(filename)) - return FALSE; + __playlist_ins_with_info_tuple(playlist, filename, pos, tuple, dec); + playlist_generate_shuffle_list(playlist); playlistwin_update_list(playlist); playlist_manager_update(); @@ -957,7 +967,7 @@ filename = g_filename_to_uri(tmp, NULL, NULL); g_free(tmp); - if (vfs_file_test(filename, G_FILE_TEST_IS_DIR)) { + if (vfs_file_test(filename, G_FILE_TEST_IS_DIR)) { /* directory */ GList *sub; gchar *dirfilename = g_filename_from_uri(filename, NULL, NULL); sub = playlist_dir_find_files(dirfilename, background, htab); @@ -965,10 +975,13 @@ g_free(filename); list = g_list_concat(list, sub); } - else if (cfg.playlist_detect == TRUE) { - if(filter_by_extension(filename)) { + else if (cfg.playlist_detect) { /* local file, no probing */ + if(cfg.use_extension_probing) { + if(filter_by_extension(filename)) + list = g_list_prepend(list, filename); + } + else list = g_list_prepend(list, filename); - } } else if ((pr = input_check_file(filename, TRUE)) != NULL) { @@ -1725,16 +1738,16 @@ if ((tmp = strrchr(path, '/'))) *tmp = '\0'; else { - if ((playlist->loading_playlist == TRUE || - cfg.playlist_detect == TRUE)) { + if ((playlist->loading_playlist == TRUE || + cfg.playlist_detect == TRUE)) { pr = NULL; if(!filter_by_extension(filename)) return; - } - else if (!str_has_prefix_nocase(filename, "http://") && - !str_has_prefix_nocase(filename, "https://")) - pr = input_check_file(filename, FALSE); - + } + else if (!str_has_prefix_nocase(filename, "http://") && + !str_has_prefix_nocase(filename, "https://")) { + pr = input_check_file(filename, TRUE); + } __playlist_ins_with_info(playlist, filename, pos, title, len, pr ? pr->ip : NULL); g_free(pr); return; @@ -1746,9 +1759,10 @@ if(!filter_by_extension(filename)) return; } - else if (!str_has_prefix_nocase(tmp, "http://") && - !str_has_prefix_nocase(tmp, "https://")) - pr = input_check_file(tmp, FALSE); + else if (!str_has_prefix_nocase(tmp, "http://") && + !str_has_prefix_nocase(tmp, "https://")) { + pr = input_check_file(tmp, TRUE); + } __playlist_ins_with_info(playlist, tmp, pos, title, len, pr ? pr->ip : NULL); g_free(tmp); @@ -1760,13 +1774,13 @@ if ((playlist->loading_playlist == TRUE || cfg.playlist_detect == TRUE)) { pr = NULL; - if(!filter_by_extension(filename)) - return; + if(!filter_by_extension(filename)) + return; } - else if (!str_has_prefix_nocase(filename, "http://") && - !str_has_prefix_nocase(filename, "https://")) - pr = input_check_file(filename, FALSE); - + else if (!str_has_prefix_nocase(filename, "http://") && + !str_has_prefix_nocase(filename, "https://")) { + pr = input_check_file(filename, TRUE); + } __playlist_ins_with_info(playlist, filename, pos, title, len, pr ? pr->ip : NULL); g_free(pr); } @@ -1808,7 +1822,7 @@ } else if (!str_has_prefix_nocase(filename, "http://") && !str_has_prefix_nocase(filename, "https://")) - pr = input_check_file(filename, FALSE); + pr = input_check_file(filename, TRUE); __playlist_ins_with_info_tuple(playlist, filename, pos, tuple, pr ? pr->ip : NULL); g_free(pr); @@ -1824,7 +1838,7 @@ } else if (!str_has_prefix_nocase(filename, "http://") && !str_has_prefix_nocase(filename, "https://")) - pr = input_check_file(filename, FALSE); //here! --yaz + pr = input_check_file(filename, TRUE); __playlist_ins_with_info_tuple(playlist, tmp, pos, tuple, pr ? pr->ip : NULL); g_free(tmp); @@ -1841,7 +1855,7 @@ } else if (!str_has_prefix_nocase(filename, "http://") && !str_has_prefix_nocase(filename, "https://")) - pr = input_check_file(filename, FALSE); + pr = input_check_file(filename, TRUE); __playlist_ins_with_info_tuple(playlist, filename, pos, tuple, pr ? pr->ip : NULL); g_free(pr); @@ -2611,28 +2625,6 @@ } -static gboolean -playlist_get_info_scanning(void) -{ - gboolean result; - - g_mutex_lock(mutex_scan); - result = playlist_get_info_scan_active; - g_mutex_unlock(mutex_scan); - - return result; -} - - -static gboolean -playlist_request_win_update(gpointer unused) -{ - Playlist *playlist = playlist_get_active(); - playlistwin_update_list(playlist); - return FALSE; /* to be called only once */ -} - - static gpointer playlist_get_info_func(gpointer arg) { @@ -2645,7 +2637,7 @@ // on_load if (cfg.use_pl_metadata && cfg.get_info_on_load && - playlist_get_info_scanning()) { + playlist_get_info_scan_active) { for (node = playlist->entries; node; node = g_list_next(node)) { entry = node->data; @@ -2695,7 +2687,7 @@ entry = node->data; - if(playlist->attribute & PLAYLIST_STATIC || // live lock fix + if(playlist->attribute & PLAYLIST_STATIC || (entry->tuple && tuple_get_int(entry->tuple, FIELD_LENGTH, NULL) > -1 && tuple_get_int(entry->tuple, FIELD_MTIME, NULL) != -1)) { update_playlistwin = TRUE; @@ -2713,7 +2705,6 @@ tuple_get_int(entry->tuple, FIELD_LENGTH, NULL) > -1 && tuple_get_int(entry->tuple, FIELD_MTIME, NULL) != -1) { update_playlistwin = TRUE; - break; } } } // on_demand @@ -2733,13 +2724,11 @@ } if (update_playlistwin) { - /* we are in a different thread, so we can't do UI updates directly; - instead, schedule a playlist update in the main loop --giacomo */ - g_idle_add_full(G_PRIORITY_HIGH_IDLE, playlist_request_win_update, NULL, NULL); + event_queue("playlistwin update list", playlist_get_active()); update_playlistwin = FALSE; } - if (playlist_get_info_scanning()) { + if (playlist_get_info_scan_active) { continue; } @@ -3479,14 +3468,15 @@ g_free(tmp); base = g_path_get_basename(filename); - ext = g_strrstr(base, "."); + ext = strrchr(base, '.'); if(!ext) { g_free(base); return FALSE; } - lext = g_utf8_strdown(ext+1, -1); + lext = g_ascii_strdown(ext+1, -1); + g_free(base); if(g_hash_table_lookup(ext_hash, lext)) rv = TRUE; @@ -3494,6 +3484,5 @@ rv = FALSE; g_free(lext); - g_free(base); return rv; } diff -r ad14a25a31fa -r a575c29cee05 src/audacious/playlist_evlisteners.c --- a/src/audacious/playlist_evlisteners.c Fri Nov 16 18:55:48 2007 +0100 +++ b/src/audacious/playlist_evlisteners.c Sat Nov 17 17:07:46 2007 +0900 @@ -26,6 +26,7 @@ #include "playlist_evlisteners.h" #include "ui_main.h" +#include "ui_playlist.h" static void playlist_evlistener_playlist_info_change(gpointer hook_data, gpointer user_data) @@ -37,8 +38,16 @@ g_free(msg); } +static void +playlist_evlistener_playlistwin_update_list(gpointer hook_data, gpointer user_data) +{ + Playlist *playlist = (Playlist *) hook_data; + + playlistwin_update_list(playlist); +} + void playlist_evlistener_init(void) { hook_associate("playlist info change", playlist_evlistener_playlist_info_change, NULL); + hook_associate("playlistwin update list", playlist_evlistener_playlistwin_update_list, NULL); } - diff -r ad14a25a31fa -r a575c29cee05 src/audacious/pluginenum.c --- a/src/audacious/pluginenum.c Fri Nov 16 18:55:48 2007 +0100 +++ b/src/audacious/pluginenum.c Sat Nov 17 17:07:46 2007 +0900 @@ -524,7 +524,16 @@ gint i; if(p->vfs_extensions) { for(i = 0; p->vfs_extensions[i] != NULL; i++) { - g_hash_table_replace(ext_hash, g_strdup(p->vfs_extensions[i]), g_strdup(p->description)); + GList *hdr = NULL; + GList **handle = NULL; //allocated as auto in stack. + GList **handle2 = g_malloc(sizeof(GList **)); + + handle = g_hash_table_lookup(ext_hash, p->vfs_extensions[i]); + if(handle) + hdr = *handle; + hdr = g_list_append(hdr, p); //returned hdr is non-volatile + *handle2 = hdr; + g_hash_table_replace(ext_hash, g_strdup(p->vfs_extensions[i]), handle2); } } } diff -r ad14a25a31fa -r a575c29cee05 src/audacious/ui_playlist.c --- a/src/audacious/ui_playlist.c Fri Nov 16 18:55:48 2007 +0100 +++ b/src/audacious/ui_playlist.c Sat Nov 17 17:07:46 2007 +0900 @@ -225,10 +225,10 @@ gboolean playlistwin_item_visible(gint index) { - if (index >= UI_SKINNED_PLAYLIST(playlistwin_list)->first - && index < - (UI_SKINNED_PLAYLIST(playlistwin_list)->first + UI_SKINNED_PLAYLIST(playlistwin_list)->num_visible)) + if (index >= UI_SKINNED_PLAYLIST(playlistwin_list)->first && + index < (UI_SKINNED_PLAYLIST(playlistwin_list)->first + UI_SKINNED_PLAYLIST(playlistwin_list)->num_visible) ) { return TRUE; + } return FALSE; } @@ -996,7 +996,7 @@ playlistwin_scroll(-cfg.scroll_pl_by); // deactivating this fixed a gui freeze when scrolling. -- mf0102 - //g_cond_signal(cond_scan); + g_cond_signal(cond_scan); } @@ -1269,7 +1269,7 @@ if (refresh) { // fixes keyboard scrolling gui freeze for me. -- mf0102 - //g_cond_signal(cond_scan); + g_cond_signal(cond_scan); playlistwin_update_list(playlist_get_active()); }