📄 tree.c
字号:
/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id: tree.c,v 1.227 2004/03/11 10:43:53 linusnielsen Exp $ * * Copyright (C) 2002 Daniel Stenberg * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/#include <stdio.h>#include <string.h>#include <stdlib.h>#include <stdbool.h>#include "applimits.h"#include "dir.h"#include "file.h"#include "lcd.h"#include "font.h"#include "backlight.h"#include "button.h"#include "kernel.h"#include "usb.h"#include "tree.h"#include "main_menu.h"#include "sprintf.h"#include "mpeg.h"#include "playlist.h"#include "menu.h"#include "wps.h"#include "wps-display.h"#include "settings.h"#include "status.h"#include "debug.h"#include "ata.h"#include "rolo.h"#include "icons.h"#include "lang.h"#include "language.h"#include "screens.h"#include "keyboard.h"#include "bookmark.h"#include "onplay.h"#include "buffer.h"#include "plugin.h"#include "power.h"#ifdef HAVE_LCD_BITMAP#include "widgets.h"#define BOOTFILE "ajbrec.ajz"#else#define BOOTFILE "archos.mod"#endif/* a table for the know file types */static struct{ char* extension; /* extension for which the file type is recognized */ int tree_attr; /* which identifier */ int icon; /* the icon which shall be used for it, -1 if unknown */ /* To have it extendable, there could be more useful stuff in here, like handler functions, plugin name, etc. */} filetypes[] = { { ".mp3", TREE_ATTR_MPA, File }, { ".mp2", TREE_ATTR_MPA, File }, { ".mpa", TREE_ATTR_MPA, File }, { ".m3u", TREE_ATTR_M3U, Playlist }, { ".cfg", TREE_ATTR_CFG, Config }, { ".wps", TREE_ATTR_WPS, Wps, }, { ".txt", TREE_ATTR_TXT, Text }, { ".lng", TREE_ATTR_LNG, Language }, { ".rock",TREE_ATTR_ROCK,Plugin },#ifdef HAVE_LCD_BITMAP { ".fnt", TREE_ATTR_FONT,Font }, { ".ch8", TREE_ATTR_CH8, Chip8 }, { ".rvf", TREE_ATTR_RVF, Video }, { ".bmark",TREE_ATTR_BMARK,Bookmark },#else { ".bmark", TREE_ATTR_BMARK, -1 },#endif#ifndef SIMULATOR#ifdef HAVE_LCD_BITMAP { ".ucl", TREE_ATTR_UCL, Flashfile}, { ".ajz", TREE_ATTR_MOD, Mod_Ajz },#else { ".mod", TREE_ATTR_MOD, Mod_Ajz },#endif#endif /* #ifndef SIMULATOR */};/* Boot value of global_settings.max_files_in_dir */static int max_files_in_dir;static char *name_buffer;static int name_buffer_size; /* Size of allocated buffer */static int name_buffer_length; /* Currently used amount */static struct entry *dircache;static int dircursor;static int dirstart;static int dirlevel;static int filesindir;static int dirpos[MAX_DIR_LEVELS];static int cursorpos[MAX_DIR_LEVELS];static char lastdir[MAX_PATH];static char lastfile[MAX_PATH];static char currdir[MAX_PATH];static char currdir_save[MAX_PATH];static bool reload_dir = false;static int boot_size = 0;static int boot_cluster;static bool boot_changed = false;static bool start_wps = false;static bool dirbrowse(char *root, int *dirfilter);void browse_root(void){#ifndef SIMULATOR dirbrowse("/", &global_settings.dirfilter);#else if (!dirbrowse("/", &global_settings.dirfilter)) { DEBUGF("No filesystem found. Have you forgotten to create it?\n"); }#endif}#ifdef HAVE_LCD_BITMAP/* pixel margins */#define MARGIN_X (global_settings.scrollbar && \ filesindir > tree_max_on_screen ? SCROLLBAR_WIDTH : 0) + \ CURSOR_WIDTH + (global_settings.show_icons && ICON_WIDTH > 0 ? ICON_WIDTH :0)#define MARGIN_Y (global_settings.statusbar ? STATUSBAR_HEIGHT : 0)/* position the entry-list starts at */#define LINE_X 0#define LINE_Y (global_settings.statusbar ? 1 : 0)#define CURSOR_X (global_settings.scrollbar && \ filesindir > tree_max_on_screen ? 1 : 0)#define CURSOR_Y 0 /* the cursor is not positioned in regard to the margins, so this is the amount of lines we add to the cursor Y position to position it on a line */#define CURSOR_WIDTH (global_settings.invert_cursor ? 0 : 4)#define ICON_WIDTH 6#define SCROLLBAR_X 0#define SCROLLBAR_Y lcd_getymargin()#define SCROLLBAR_WIDTH 6extern unsigned char bitmap_icons_6x8[LastIcon][6];#else /* HAVE_LCD_BITMAP */#define TREE_MAX_ON_SCREEN 2#define TREE_MAX_LEN_DISPLAY 11 /* max length that fits on screen */#define LINE_X 2 /* X position the entry-list starts at */#define LINE_Y 0 /* Y position the entry-list starts at */#define CURSOR_X 0#define CURSOR_Y 0 /* not really used for players */#endif /* HAVE_LCD_BITMAP */#ifdef HAVE_RECORDER_KEYPAD#define TREE_NEXT BUTTON_DOWN#define TREE_PREV BUTTON_UP#define TREE_EXIT BUTTON_LEFT#define TREE_ENTER BUTTON_RIGHT#define TREE_MENU BUTTON_F1#else#define TREE_NEXT BUTTON_RIGHT#define TREE_PREV BUTTON_LEFT#define TREE_EXIT BUTTON_STOP#define TREE_ENTER BUTTON_PLAY#define TREE_MENU BUTTON_MENU#endif /* HAVE_RECORDER_KEYPAD */static int build_playlist(int start_index){ int i; int start=start_index; for(i = 0;i < filesindir;i++) { if((dircache[i].attr & TREE_ATTR_MASK) == TREE_ATTR_MPA) { DEBUGF("Adding %s\n", dircache[i].name); if (playlist_add(dircache[i].name) < 0) break; } else { /* Adjust the start index when se skip non-MP3 entries */ if(i < start) start_index--; } } return start_index;}static int compare(const void* p1, const void* p2){ struct entry* e1 = (struct entry*)p1; struct entry* e2 = (struct entry*)p2; if (( e1->attr & ATTR_DIRECTORY ) == ( e2->attr & ATTR_DIRECTORY )) if (global_settings.sort_case) return strncmp(e1->name, e2->name, MAX_PATH); else return strncasecmp(e1->name, e2->name, MAX_PATH); else return ( e2->attr & ATTR_DIRECTORY ) - ( e1->attr & ATTR_DIRECTORY );}static void showfileline(int line, int direntry, bool scroll, int *dirfilter){ char* name = dircache[direntry].name; int xpos = LINE_X;#ifdef HAVE_LCD_CHARCELLS if (!global_settings.show_icons) xpos--;#endif /* if any file filter is on, strip the extension */ if (*dirfilter != SHOW_ALL && !(dircache[direntry].attr & ATTR_DIRECTORY)) { char* dotpos = strrchr(name, '.'); char temp=0; if (dotpos) { temp = *dotpos; *dotpos = 0; } if(scroll)#ifdef HAVE_LCD_BITMAP if (global_settings.invert_cursor) lcd_puts_scroll_style(xpos, line, name, STYLE_INVERT); else#endif lcd_puts_scroll(xpos, line, name); else lcd_puts(xpos, line, name); if (temp) *dotpos = temp; } else { if(scroll)#ifdef HAVE_LCD_BITMAP if (global_settings.invert_cursor) lcd_puts_scroll_style(xpos, line, name, STYLE_INVERT); else#endif lcd_puts_scroll(xpos, line, name); else lcd_puts(xpos, line, name); }}/* load sorted directory into dircache. returns NULL on failure. */struct entry* load_and_sort_directory(char *dirname, int *dirfilter, int *num_files, bool *buffer_full){ int i; DIR *dir = opendir(dirname); if(!dir) return NULL; /* not a directory */ name_buffer_length = 0; *buffer_full = false; for ( i=0; i < max_files_in_dir; i++ ) { int len; struct dirent *entry = readdir(dir); struct entry* dptr = &dircache[i]; if (!entry) break; len = strlen(entry->d_name); /* skip directories . and .. */ if ((entry->attribute & ATTR_DIRECTORY) && (((len == 1) && (!strncmp(entry->d_name, ".", 1))) || ((len == 2) && (!strncmp(entry->d_name, "..", 2))))) { i--; continue; } /* Skip FAT volume ID */ if (entry->attribute & ATTR_VOLUME_ID) { i--; continue; } /* filter out dotfiles and hidden files */ if (*dirfilter != SHOW_ALL && ((entry->d_name[0]=='.') || (entry->attribute & ATTR_HIDDEN))) { i--; continue; } dptr->attr = entry->attribute; /* check for known file types */ if ( !(dptr->attr & ATTR_DIRECTORY) && (len > 4) ) { unsigned j; for (j=0; j<sizeof(filetypes)/sizeof(*filetypes); j++) { if (!strcasecmp( &entry->d_name[len-strlen(filetypes[j].extension)], filetypes[j].extension)) { dptr->attr |= filetypes[j].tree_attr; break; } } } /* memorize/compare details about the boot file */ if ((currdir[1] == 0) && !strcasecmp(entry->d_name, BOOTFILE)) { if (boot_size) { if ((entry->size != boot_size) || (entry->startcluster != boot_cluster)) boot_changed = true; } boot_size = entry->size; boot_cluster = entry->startcluster; } /* filter out non-visible files */ if (!(dptr->attr & ATTR_DIRECTORY) && ( (*dirfilter == SHOW_PLAYLIST && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_M3U) || ((*dirfilter == SHOW_MUSIC && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_MPA) && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_M3U) || (*dirfilter == SHOW_SUPPORTED && !(dptr->attr & TREE_ATTR_MASK)) || (*dirfilter == SHOW_WPS && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_WPS) || (*dirfilter == SHOW_CFG && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_CFG) || (*dirfilter == SHOW_LNG && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_LNG) || (*dirfilter == SHOW_MOD && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_MOD) || (*dirfilter == SHOW_FONT && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_FONT) || (*dirfilter == SHOW_PLUGINS && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_ROCK))) { i--; continue; } if (len > name_buffer_size - name_buffer_length - 1) { /* Tell the world that we ran out of buffer space */ *buffer_full = true; break; } dptr->name = &name_buffer[name_buffer_length]; strcpy(dptr->name,entry->d_name); name_buffer_length += len + 1; } *num_files = i; closedir(dir); strncpy(lastdir,dirname,sizeof(lastdir)); lastdir[sizeof(lastdir)-1] = 0; qsort(dircache,i,sizeof(struct entry),compare); return dircache;}static int showdir(char *path, int start, int *dirfilter){ int icon_type = 0; int i; int tree_max_on_screen; bool dir_buffer_full;#ifdef HAVE_LCD_BITMAP int line_height; int fw, fh;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -