int ft_build_playlist(struct tree_context* c, int start_index) { int i; int start=start_index; tree_lock_cache(c); struct entry *entries = tree_get_entries(c); for(i = 0;i < c->filesindir;i++) { if((entries[i].attr & FILE_ATTR_MASK) == FILE_ATTR_AUDIO) { if (playlist_add(entries[i].name) < 0) break; } else { /* Adjust the start index when se skip non-MP3 entries */ if(i < start) start_index--; } } tree_unlock_cache(c); return start_index; }
/* walk a directory and check all entries if a .talk file exists */ static void check_file_thumbnails(struct tree_context* c) { int i; struct dirent *entry; struct entry* entries; DIR *dir; dir = opendir(c->currdir); if(!dir) return; /* mark all files as non talking, except the .talk ones */ entries = tree_get_entries(c); tree_lock_cache(c); for (i=0; i < c->filesindir; i++) { if (entries[i].attr & ATTR_DIRECTORY) continue; /* we're not touching directories */ if (strcasecmp(file_thumbnail_ext, &entries[i].name[strlen(entries[i].name) - strlen(file_thumbnail_ext)])) { /* no .talk file */ entries[i].attr &= ~FILE_ATTR_THUMBNAIL; /* clear */ } else { /* .talk file, we later let them speak themselves */ entries[i].attr |= FILE_ATTR_THUMBNAIL; /* set */ } } while((entry = readdir(dir)) != 0) /* walk directory */ { int ext_pos; struct dirinfo info = dir_get_info(dir, entry); ext_pos = strlen((char *)entry->d_name) - strlen(file_thumbnail_ext); if (ext_pos <= 0 /* too short to carry ".talk" */ || (info.attribute & ATTR_DIRECTORY) /* no file */ || strcasecmp((char *)&entry->d_name[ext_pos], file_thumbnail_ext)) { /* or doesn't end with ".talk", no candidate */ continue; } /* terminate the (disposable) name in dir buffer, this truncates off the ".talk" without needing an extra buffer */ entry->d_name[ext_pos] = '\0'; /* search corresponding file in dir cache */ for (i=0; i < c->filesindir; i++) { if (!strcasecmp(entries[i].name, (char *)entry->d_name)) { /* match */ entries[i].attr |= FILE_ATTR_THUMBNAIL; /* set the flag */ break; /* exit search loop, because we found it */ } } } tree_unlock_cache(c); closedir(dir); }
int plugin_load(const char* plugin, const void* parameter) { struct plugin_header *p_hdr; struct lc_header *hdr; if (current_plugin_handle && pfn_tsr_exit) { /* if we have a resident old plugin and a callback */ if (pfn_tsr_exit(!strcmp(current_plugin, plugin)) == false ) { /* not allowing another plugin to load */ return PLUGIN_OK; } lc_close(current_plugin_handle); current_plugin_handle = pfn_tsr_exit = NULL; if (plugin_buffer_handle > 0) plugin_buffer_handle = core_free(plugin_buffer_handle); } splash(0, ID2P(LANG_WAIT)); strcpy(current_plugin, plugin); current_plugin_handle = lc_open(plugin, pluginbuf, PLUGIN_BUFFER_SIZE); if (current_plugin_handle == NULL) { splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin); return -1; } p_hdr = lc_get_header(current_plugin_handle); hdr = p_hdr ? &p_hdr->lc_hdr : NULL; if (hdr == NULL || hdr->magic != PLUGIN_MAGIC || hdr->target_id != TARGET_ID #if (CONFIG_PLATFORM & PLATFORM_NATIVE) || hdr->load_addr != pluginbuf || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE #endif ) { lc_close(current_plugin_handle); splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); return -1; } if (hdr->api_version > PLUGIN_API_VERSION || hdr->api_version < PLUGIN_MIN_API_VERSION) { lc_close(current_plugin_handle); splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); return -1; } #if (CONFIG_PLATFORM & PLATFORM_NATIVE) plugin_size = hdr->end_addr - pluginbuf; #else plugin_size = 0; #endif *(p_hdr->api) = &rockbox_api; lcd_clear_display(); lcd_update(); #ifdef HAVE_REMOTE_LCD lcd_remote_clear_display(); lcd_remote_update(); #endif push_current_activity(ACTIVITY_PLUGIN); /* some plugins assume the entry cache doesn't move and save pointers to it * they should be fixed properly instead of this lock */ tree_lock_cache(tree_get_context()); FOR_NB_SCREENS(i) viewportmanager_theme_enable(i, false, NULL); #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(TOUCHSCREEN_BUTTON); #endif /* allow voice to back off if the plugin needs lots of memory */ talk_buffer_set_policy(TALK_BUFFER_LOOSE); plugin_check_open_close__enter(); int rc = p_hdr->entry_point(parameter); tree_unlock_cache(tree_get_context()); pop_current_activity(); if (!pfn_tsr_exit) { /* close handle if plugin is no tsr one */ lc_close(current_plugin_handle); current_plugin_handle = NULL; if (plugin_buffer_handle > 0) plugin_buffer_handle = core_free(plugin_buffer_handle); } talk_buffer_set_policy(TALK_BUFFER_DEFAULT); /* Go back to the global setting in case the plugin changed it */ #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(global_settings.touch_mode); #endif #ifdef HAVE_LCD_BITMAP screen_helper_setfont(FONT_UI); #if LCD_DEPTH > 1 #ifdef HAVE_LCD_COLOR lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color, global_settings.bg_color); #else lcd_set_drawinfo(DRMODE_SOLID, LCD_DEFAULT_FG, LCD_DEFAULT_BG); #endif #else /* LCD_DEPTH == 1 */ lcd_set_drawmode(DRMODE_SOLID); #endif /* LCD_DEPTH */ #endif /* HAVE_LCD_BITMAP */ #ifdef HAVE_REMOTE_LCD #if LCD_REMOTE_DEPTH > 1 lcd_remote_set_drawinfo(DRMODE_SOLID, LCD_REMOTE_DEFAULT_FG, LCD_REMOTE_DEFAULT_BG); #else lcd_remote_set_drawmode(DRMODE_SOLID); #endif #endif lcd_clear_display(); #ifdef HAVE_REMOTE_LCD lcd_remote_clear_display(); #endif FOR_NB_SCREENS(i) viewportmanager_theme_undo(i, true); plugin_check_open_close__exit(); if (rc == PLUGIN_ERROR) splash(HZ*2, str(LANG_PLUGIN_ERROR)); return rc; }
int plugin_load(const char* plugin, const void* parameter) { struct plugin_header *p_hdr; struct lc_header *hdr; if (current_plugin_handle && pfn_tsr_exit) { /* if we have a resident old plugin and a callback */ if (pfn_tsr_exit(!strcmp(current_plugin, plugin)) == false ) { /* not allowing another plugin to load */ return PLUGIN_OK; } lc_close(current_plugin_handle); current_plugin_handle = pfn_tsr_exit = NULL; } splash(0, ID2P(LANG_WAIT)); strcpy(current_plugin, plugin); current_plugin_handle = lc_open(plugin, pluginbuf, PLUGIN_BUFFER_SIZE); if (current_plugin_handle == NULL) { splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin); return -1; } p_hdr = lc_get_header(current_plugin_handle); hdr = p_hdr ? &p_hdr->lc_hdr : NULL; if (hdr == NULL || hdr->magic != PLUGIN_MAGIC || hdr->target_id != TARGET_ID #if (CONFIG_PLATFORM & PLATFORM_NATIVE) || hdr->load_addr != pluginbuf || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE #endif ) { lc_close(current_plugin_handle); splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); return -1; } if (hdr->api_version > PLUGIN_API_VERSION || hdr->api_version < PLUGIN_MIN_API_VERSION) { lc_close(current_plugin_handle); splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); return -1; } #if (CONFIG_PLATFORM & PLATFORM_NATIVE) plugin_size = hdr->end_addr - pluginbuf; #else plugin_size = 0; #endif *(p_hdr->api) = &rockbox_api; lcd_clear_display(); lcd_update(); #ifdef HAVE_REMOTE_LCD lcd_remote_clear_display(); lcd_remote_update(); #endif push_current_activity(ACTIVITY_PLUGIN); /* some plugins assume the entry cache doesn't move and save pointers to it * they should be fixed properly instead of this lock */ tree_lock_cache(tree_get_context()); FOR_NB_SCREENS(i) viewportmanager_theme_enable(i, false, NULL); #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(TOUCHSCREEN_BUTTON); #endif #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE open_files = 0; #endif int rc = p_hdr->entry_point(parameter); tree_unlock_cache(tree_get_context()); pop_current_activity(); if (!pfn_tsr_exit) { /* close handle if plugin is no tsr one */ lc_close(current_plugin_handle); current_plugin_handle = NULL; } /* Go back to the global setting in case the plugin changed it */ #ifdef HAVE_TOUCHSCREEN touchscreen_set_mode(global_settings.touch_mode); #endif #ifdef HAVE_LCD_BITMAP screen_helper_setfont(FONT_UI); #if LCD_DEPTH > 1 #ifdef HAVE_LCD_COLOR lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color, global_settings.bg_color); #else lcd_set_drawinfo(DRMODE_SOLID, LCD_DEFAULT_FG, LCD_DEFAULT_BG); #endif #else /* LCD_DEPTH == 1 */ lcd_set_drawmode(DRMODE_SOLID); #endif /* LCD_DEPTH */ #endif /* HAVE_LCD_BITMAP */ #ifdef HAVE_REMOTE_LCD #if LCD_REMOTE_DEPTH > 1 lcd_remote_set_drawinfo(DRMODE_SOLID, LCD_REMOTE_DEFAULT_FG, LCD_REMOTE_DEFAULT_BG); #else lcd_remote_set_drawmode(DRMODE_SOLID); #endif #endif lcd_clear_display(); #ifdef HAVE_REMOTE_LCD lcd_remote_clear_display(); #endif FOR_NB_SCREENS(i) viewportmanager_theme_undo(i, true); #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE if(open_files != 0 && !current_plugin_handle) { int fd; logf("Plugin '%s' leaks file handles", plugin); static const char *lines[] = { ID2P(LANG_PLUGIN_ERROR), "#leak-file-handles" }; static const struct text_message message={ lines, 2 }; button_clear_queue(); /* Empty the keyboard buffer */ gui_syncyesno_run(&message, NULL, NULL); for(fd=0; fd < MAX_OPEN_FILES; fd++) if(open_files & (1<<fd)) close_wrapper(fd); } #endif if (rc == PLUGIN_ERROR) splash(HZ*2, str(LANG_PLUGIN_ERROR)); return rc; }
/* load and sort directory into the tree's cache. returns NULL on failure. */ int ft_load(struct tree_context* c, const char* tempdir) { int files_in_dir = 0; int name_buffer_used = 0; struct dirent *entry; bool (*callback_show_item)(char *, int, struct tree_context *) = NULL; DIR *dir; if (tempdir) dir = opendir(tempdir); else { dir = opendir(c->currdir); callback_show_item = c->browse? c->browse->callback_show_item: NULL; } if(!dir) return -1; /* not a directory */ c->dirsindir = 0; c->dirfull = false; tree_lock_cache(c); while ((entry = readdir(dir))) { int len; struct dirinfo info; struct entry* dptr = tree_get_entry_at(c, files_in_dir); if (!entry) break; info = dir_get_info(dir, entry); len = strlen((char *)entry->d_name); /* skip directories . and .. */ if ((info.attribute & ATTR_DIRECTORY) && (((len == 1) && (!strncmp((char *)entry->d_name, ".", 1))) || ((len == 2) && (!strncmp((char *)entry->d_name, "..", 2))))) { continue; } /* Skip FAT volume ID */ if (info.attribute & ATTR_VOLUME_ID) { continue; } /* filter out dotfiles and hidden files */ if (*c->dirfilter != SHOW_ALL && ((entry->d_name[0]=='.') || (info.attribute & ATTR_HIDDEN))) { continue; } dptr->attr = info.attribute; /* check for known file types */ if ( !(dptr->attr & ATTR_DIRECTORY) ) dptr->attr |= filetype_get_attr((char *)entry->d_name); /* filter out non-visible files */ if ((!(dptr->attr & ATTR_DIRECTORY) && ( (*c->dirfilter == SHOW_PLAYLIST && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_M3U) || ((*c->dirfilter == SHOW_MUSIC && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_AUDIO) && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_M3U) || (*c->dirfilter == SHOW_SUPPORTED && !filetype_supported(dptr->attr)))) || (*c->dirfilter == SHOW_WPS && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_WPS) || #ifdef HAVE_LCD_BITMAP (*c->dirfilter == SHOW_FONT && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_FONT) || (*c->dirfilter == SHOW_SBS && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_SBS) || #if CONFIG_TUNER (*c->dirfilter == SHOW_FMS && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_FMS) || #endif #endif #ifdef HAVE_REMOTE_LCD (*c->dirfilter == SHOW_RWPS && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_RWPS) || (*c->dirfilter == SHOW_RSBS && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_RSBS) || #if CONFIG_TUNER (*c->dirfilter == SHOW_RFMS && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_RFMS) || #endif #endif #if CONFIG_TUNER (*c->dirfilter == SHOW_FMR && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_FMR) || #endif (*c->dirfilter == SHOW_M3U && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_M3U) || (*c->dirfilter == SHOW_CFG && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_CFG) || (*c->dirfilter == SHOW_LNG && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_LNG) || (*c->dirfilter == SHOW_MOD && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_MOD) || (*c->dirfilter == SHOW_PLUGINS && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_ROCK && (dptr->attr & FILE_ATTR_MASK) != FILE_ATTR_LUA) || (callback_show_item && !callback_show_item(entry->d_name, dptr->attr, c))) { continue; } if ((len > c->cache.name_buffer_size - name_buffer_used - 1) || (files_in_dir >= c->cache.max_entries)) { /* Tell the world that we ran out of buffer space */ c->dirfull = true; break; } ++files_in_dir; dptr->name = core_get_data(c->cache.name_buffer_handle)+name_buffer_used; dptr->time_write = (long)info.wrtdate<<16 | (long)info.wrttime; /* in one # */ strcpy(dptr->name, (char *)entry->d_name); name_buffer_used += len + 1; if (dptr->attr & ATTR_DIRECTORY) /* count the remaining dirs */ c->dirsindir++; } c->filesindir = files_in_dir; c->dirlength = files_in_dir; closedir(dir); compare_sort_dir = c->sort_dir; qsort(tree_get_entries(c), files_in_dir, sizeof(struct entry), compare); /* If thumbnail talking is enabled, make an extra run to mark files with associated thumbnails, so we don't do unsuccessful spinups later. */ if (global_settings.talk_file_clip) check_file_thumbnails(c); /* map .talk to ours */ tree_unlock_cache(c); return 0; }