Mercurial > audlegacy
changeset 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 | ad14a25a31fa |
children | cef19abfbbc9 572258c68dfb |
files | src/audacious/glade/prefswin.glade src/audacious/input.c src/audacious/input.h src/audacious/main.c src/audacious/playlist.c src/audacious/playlist_evlisteners.c src/audacious/pluginenum.c src/audacious/ui_playlist.c |
diffstat | 8 files changed, 211 insertions(+), 198 deletions(-) [+] |
line wrap: on
line diff
--- 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 @@ <child> <widget class="GtkRadioButton" id="playlist_metadata_on_display"> <property name="visible">True</property> - <property name="tooltip" translatable="yes">Load metadata on demand when displaying the file in the playlist</property> + <property name="tooltip" translatable="yes">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.</property> <property name="can_focus">True</property> <property name="label" translatable="yes">On display</property> <property name="use_underline">True</property> @@ -3968,7 +3968,7 @@ <child> <widget class="GtkCheckButton" id="detect_by_extension_cb"> <property name="visible">True</property> - <property name="tooltip" translatable="yes">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.</property> + <property name="tooltip" translatable="yes">When checked, Audacious will detect file formats based by extension. Only files with extensions of supported formats will be loaded.</property> <property name="can_focus">True</property> <property name="label" translatable="yes">Detect file formats by extension.</property> <property name="use_underline">True</property>
--- 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; }
--- 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);
--- 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 */
--- 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; }
--- 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); } -
--- 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); } } }
--- 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()); }