static struct shortcut* get_shortcut(int index) { int handle_count, handle_index; int current_handle = first_handle; struct shortcut_handle *h = NULL; if (first_handle == 0) { first_handle = core_alloc("shortcuts_head", sizeof(struct shortcut_handle)); if (first_handle <= 0) return NULL; h = core_get_data(first_handle); h->next_handle = 0; current_handle = first_handle; } handle_count = index/SHORTCUTS_PER_HANDLE + 1; handle_index = index%SHORTCUTS_PER_HANDLE; do { h = core_get_data(current_handle); current_handle = h->next_handle; handle_count--; } while (handle_count > 0 && current_handle > 0); if (handle_count > 0 && handle_index == 0) { char buf[32]; snprintf(buf, sizeof buf, "shortcuts_%d", index/SHORTCUTS_PER_HANDLE); h->next_handle = core_alloc(buf, sizeof(struct shortcut_handle)); if (h->next_handle <= 0) return NULL; h = core_get_data(h->next_handle); h->next_handle = 0; } return &h->shortcuts[handle_index]; }
void wps_draw_image(struct gui_wps *gwps, struct gui_img *img, int subimage) { struct screen *display = gwps->display; img->bm.data = core_get_data(img->buflib_handle); display->set_drawmode(DRMODE_SOLID); display->bmp_part(&img->bm, 0, img->subimage_height * subimage, img->x, img->y, img->bm.width, img->subimage_height); }
static void dsp_surround_flush(void) { if (!surround_enabled) return; unsigned int total_len = B0_DLY + B2_DLY + BB_DLY + HH_DLY + CL_DLY; if (handle > 0) memset(core_get_data(handle),0,sizeof(int32_t) * total_len); }
/* Returns a pointer to the mp3 buffer. Playback gets stopped, to avoid conflicts. Talk buffer is stolen as well. */ static void* plugin_get_audio_buffer(size_t *buffer_size) { /* dummy ops with no callbacks, needed because by * default buflib buffers can be moved around which must be avoided */ static struct buflib_callbacks dummy_ops; plugin_buffer_handle = core_alloc_maximum("plugin audio buf", buffer_size, &dummy_ops); return core_get_data(plugin_buffer_handle); }
static void surround_buffer_get_data(void) { if (handle < 0) return; b0 = core_get_data(handle); b2 = b0 + B0_DLY; bb = b2 + B2_DLY; hh = bb + BB_DLY; cl = hh + HH_DLY; }
static inline unsigned long map_sector(unsigned long sector) { /* * Sector mapping: start of CFS + FAT_SECTOR2CFS_SECTOR(sector) + missing part * FAT works with sectors of 0x200 bytes, CFS with sectors of 0x8000 bytes. */ #ifndef BOOTLOADER unsigned long *sectors = core_get_data(sectors_handle); #endif return cfs_start+sectors[sector/64]*64+sector%64; }
static void pbe_buffer_get_data(void) { if (handle < 0) return; b0[0] = core_get_data(handle); b0[1] = b0[0] + B0_SIZE; b2[0] = b0[1] + B0_SIZE; b2[1] = b2[0] + B2_SIZE; b3[0] = b2[1] + B2_SIZE; b3[1] = b3[0] + B3_SIZE; }
void radioart_init(bool entering_screen) { if (entering_screen) { /* grab control over buffering */ size_t bufsize; int handle = core_alloc_maximum("radioart", &bufsize, &radioart_ops); buffering_reset(core_get_data(handle), bufsize); buf = core_get_data(handle); /* one-shot */ add_event(BUFFER_EVENT_BUFFER_RESET, true, buffer_reset_handler); } else /* init at startup */ { for(int i=0;i<MAX_RADIOART_IMAGES;i++) { radioart[i].handle = -1; radioart[i].name[0] = '\0'; } } }
void wps_draw_image(struct gui_wps *gwps, struct gui_img *img, int subimage, struct viewport* vp) { struct screen *display = gwps->display; img->bm.data = core_get_data(img->buflib_handle); display->set_drawmode(DRMODE_SOLID); if (img->is_9_segment) display->nine_segment_bmp(&img->bm, 0, 0, vp->width, vp->height); else display->bmp_part(&img->bm, 0, img->subimage_height * subimage, img->x, img->y, img->bm.width, img->subimage_height); }
static bool nand_read_sector_of_logical_segment(int log_segment, int sector, void* buf) { int page_in_segment = sector / sectors_per_page; int sector_in_page = sector % sectors_per_page; #ifndef BOOTLOADER struct lpt_entry* lpt_lookup = core_get_data(lpt_handle); #endif int bank = lpt_lookup[log_segment].bank; int phys_segment = lpt_lookup[log_segment].phys_segment; /* Check if any of the write caches refer to this segment/page. If present we need to read the cached page instead. */ int cache_num = 0; bool found = false; while (!found && cache_num < write_caches_in_use) { if (write_caches[cache_num].log_segment == log_segment) { if (write_caches[cache_num].page_map[page_in_segment] != -1) { /* data is located in random pages cache */ found = true; bank = write_caches[cache_num].random_bank; phys_segment = write_caches[cache_num].random_phys_segment; page_in_segment = write_caches[cache_num].page_map[page_in_segment]; } else if (write_caches[cache_num].inplace_pages_used != -1 && write_caches[cache_num].inplace_pages_used > page_in_segment) { /* data is located in in-place pages cache */ found = true; bank = write_caches[cache_num].inplace_bank; phys_segment = write_caches[cache_num].inplace_phys_segment; } } cache_num++; } return nand_read_sector_of_phys_segment(bank, phys_segment, page_in_segment, sector_in_page, buf); }
static void surround_buffer_alloc(void) { if (handle > 0) return; /* already-allocated */ unsigned int total_len = B0_DLY + B2_DLY + BB_DLY + HH_DLY + CL_DLY; handle = core_alloc("dsp_surround_buffer",sizeof(int32_t) * total_len); if (handle < 0) { surround_enabled = false; return; } memset(core_get_data(handle),0,sizeof(int32_t) * total_len); }
static void reset_shortcuts(void) { int current_handle = first_handle; struct shortcut_handle *h = NULL; while (current_handle > 0) { int next; h = core_get_data(current_handle); next = h->next_handle; core_free(current_handle); current_handle = next; } first_handle = 0; shortcut_count = 0; }
static void pbe_buffer_alloc(void) { if (handle > 0) return; /* already-allocated */ unsigned int total_len = (B0_SIZE + B2_SIZE + B3_SIZE) * 2; handle = core_alloc("dsp_pbe_buffer",sizeof(int32_t) * total_len); if (handle < 0) { pbe_strength = 0; return; } memset(core_get_data(handle),0,sizeof(int32_t) * total_len); }
static void dsp_pbe_flush(void) { if (pbe_strength == 0) return; /* Not currently enabled */ unsigned int total_len = (B0_SIZE + B2_SIZE + B3_SIZE) * 2; if (handle > 0) memset(core_get_data(handle),0,sizeof(int32_t) * total_len); b0_r[0] = 0; b0_w[0] = 0; b0_r[1] = 0; b0_w[1] = 0; b2_r[0] = 0; b2_w[0] = 0; b2_r[1] = 0; b2_w[1] = 0; b3_r[0] = 0; b3_w[0] = 0; b3_r[1] = 0; b3_w[1] = 0; for (int i = 0; i < 5; i++) filter_flush(&pbe_filter[i]); }
void shortcuts_init(void) { int fd; char buf[512]; struct shortcut *param = NULL; struct shortcut_handle *h; shortcut_count = 0; fd = open_utf8(SHORTCUTS_FILENAME, O_RDONLY); if (fd < 0) return; first_handle = core_alloc("shortcuts_head", sizeof(struct shortcut_handle)); if (first_handle <= 0) return; h = core_get_data(first_handle); h->next_handle = 0; fast_readline(fd, buf, sizeof buf, ¶m, readline_cb); close(fd); if (param && verify_shortcut(param)) shortcut_count++; }
static void cfs_init(void) { struct main_header *hdr; struct cfs_header *cfs; struct cfs_inode *root_inode, *vfat_inode, *inode; struct cfs_direntry *root_direntry, *vfat_direntry; struct cfs_direntry_item *root_direntry_items, *vfat_direntry_items; unsigned int i, j, k, vfat_inode_nr=0, vfat_inodes_nr[10], vfat_sector_count; unsigned char sector[512]; static unsigned int vfat_data[2][0x8000]; static unsigned char sector2[0x8000]; if(cfs_inited) return; /* Read MBLK */ _ata_read_sectors(0, 1, §or); hdr = (struct main_header*)§or; logf("CFS is at 0x%x [0x%x]", CFS_START, CFS_START/512); /* Read CFS header */ _ata_read_sectors(CFS_START/512, 64, §or2); cfs = (struct cfs_header*)§or2; logf("First inode = 0x%x", cfs->first_inode); /* Read root inode */ _ata_read_sectors(CFS_CLUSTER2CLUSTER(cfs->first_inode), 64, §or2); root_inode = (struct cfs_inode*)§or2; logf("Root inode = 0x%x", root_inode); logf("0x%x 0x%x", CFS_CLUSTER2CLUSTER(root_inode->first_class_chain[0]), root_inode->first_class_chain[0]); /* Read root inode's first sector */ _ata_read_sectors(CFS_CLUSTER2CLUSTER(root_inode->first_class_chain[0]), 64, §or2); root_direntry = (struct cfs_direntry*)§or2; root_direntry_items = (struct cfs_direntry_item*)(§or2+sizeof(struct cfs_direntry)); logf("0x%x", root_direntry->identifier); logf("%d", root_direntry->items); /* Search VFAT inode */ for(i=0; i < root_direntry->items; i++) { if(root_direntry_items[i].inode_number != 0) { //logf(" * [%s] at 0x%x", ucs2letostring(&root_direntry_items[i].string[0]), root_direntry_items[i].inode_number); if(strcmp(ucs2letostring(&root_direntry_items[i].string[0]), "VFAT") == 0) vfat_inode_nr = root_direntry_items[i].inode_number; } } logf("VFAT inode = 0x%x", vfat_inode_nr); if(vfat_inode_nr != 0) { /* Read VFAT inode */ _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inode_nr), 64, §or2); vfat_inode = (struct cfs_inode*)§or2; /* Read VFAT inode's first sector */ _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inode->first_class_chain[0]), 64, §or2); vfat_direntry = (struct cfs_direntry*)§or2; vfat_direntry_items = (struct cfs_direntry_item*)(§or2+sizeof(struct cfs_direntry)); /* Search for VFAT's subinodes */ for(i=0; i < vfat_direntry->items; i++) { logf(" * [%s] at 0x%x\n", ucs2letostring(&vfat_direntry_items[i].string[0]), vfat_direntry_items[i].inode_number); if(i > 0) vfat_inodes_nr[i-1] = vfat_direntry_items[i].inode_number; } /* Determine size of VFAT file */ _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inodes_nr[1]), 1, §or); inode = (struct cfs_inode*)§or; #ifndef BOOTLOADER sectors_handle = core_alloc("ata sectors", VFAT_SECTOR_SIZE(inode->filesize)); unsigned long *sectors = core_get_data(sectors_handle); #else static unsigned long _sector[VFAT_SECTOR_SIZE(1024*1024*1024)]; /* 1GB guess */ sectors = _sector; #endif logf("VFAT file size: 0x%x", inode->filesize); /* Clear data sectors */ memset(§ors, 0, VFAT_SECTOR_SIZE(inode->filesize)*sizeof(unsigned long)); /* Read all data sectors' addresses in memory */ vfat_sector_count = 0; for(i=0; vfat_inodes_nr[i] != 0; i++) { _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_inodes_nr[i]), 1, §or); inode = (struct cfs_inode*)§or; /* Read second & third class chain */ _ata_read_sectors(CFS_CLUSTER2CLUSTER(inode->second_class_chain_first_cluster), 64, &vfat_data[0]); _ata_read_sectors(CFS_CLUSTER2CLUSTER(inode->second_class_chain_second_cluster), 64, &vfat_data[1]); /* First class chain */ #ifndef BOOTLOADER sectors = core_get_data(sectors_handle); #endif for(j=0; j<12; j++) { if( (inode->first_class_chain[j] & 0xFFFF) != 0xFFFF && inode->first_class_chain[j] != 0 ) sectors[vfat_sector_count++] = inode->first_class_chain[j]; } /* Second class chain */ #ifndef BOOTLOADER sectors = core_get_data(sectors_handle); #endif for(j=0; j<0x8000/4; j++) { if( (vfat_data[0][j] & 0xFFFF) != 0xFFFF && vfat_data[0][j] != 0 ) sectors[vfat_sector_count++] = vfat_data[0][j]; } /* Third class chain */ for(j=0; j<0x8000/4; j++) { if( (vfat_data[1][j] & 0xFFFF) != 0xFFFF && vfat_data[1][j] != 0 ) { memset(&vfat_data[0], 0, 0x8000*sizeof(unsigned int)); /* Read third class subchain(s) */ _ata_read_sectors(CFS_CLUSTER2CLUSTER(vfat_data[1][j]), 64, &vfat_data[0]); #ifndef BOOTLOADER sectors = core_get_data(sectors_handle); #endif for(k=0; k<0x8000/4; k++) { if( (vfat_data[0][k] & 0xFFFF) != 0xFFFF && vfat_data[0][k] != 0 ) sectors[vfat_sector_count++] = vfat_data[0][k]; } } } } logf("Sector count: %d 0x%x", vfat_sector_count, vfat_sector_count); } else panicf("Cannot find virtual FAT filesystem!"); cfs_inited = true; }
struct entry* tree_get_entries(struct tree_context *t) { return core_get_data(t->cache.entries_handle); }
void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb) { struct screen *display = gwps->display; struct viewport *vp = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->vp); struct wps_state *state = skin_get_global_state(); struct mp3entry *id3 = state->id3; int x = pb->x, y = pb->y, width = pb->width, height = pb->height; unsigned long length, end; int flags = HORIZONTAL; if (height < 0) height = font_get(vp->font)->height; if (y < 0) { int line_height = font_get(vp->font)->height; /* center the pb in the line, but only if the line is higher than the pb */ int center = (line_height-height)/2; /* if Y was not set calculate by font height,Y is -line_number-1 */ y = line*line_height + (0 > center ? 0 : center); } if (pb->type == SKIN_TOKEN_VOLUMEBAR) { int minvol = sound_min(SOUND_VOLUME); int maxvol = sound_max(SOUND_VOLUME); length = maxvol-minvol; end = global_settings.volume-minvol; } else if (pb->type == SKIN_TOKEN_BATTERY_PERCENTBAR) { length = 100; end = battery_level(); } else if (pb->type == SKIN_TOKEN_PEAKMETER_LEFTBAR || pb->type == SKIN_TOKEN_PEAKMETER_RIGHTBAR) { int left, right, val; peak_meter_current_vals(&left, &right); val = pb->type == SKIN_TOKEN_PEAKMETER_LEFTBAR ? left : right; length = MAX_PEAK; end = peak_meter_scale_value(val, length); } else if (pb->type == SKIN_TOKEN_LIST_SCROLLBAR) { int val, min, max; skinlist_get_scrollbar(&val, &min, &max); end = val - min; length = max - min; } #if CONFIG_TUNER else if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF)) { #ifdef HAVE_RADIO_RSSI if (pb->type == SKIN_TOKEN_TUNER_RSSI_BAR) { int val = tuner_get(RADIO_RSSI); int min = tuner_get(RADIO_RSSI_MIN); int max = tuner_get(RADIO_RSSI_MAX); end = val - min; length = max - min; } else #endif { int min = fm_region_data[global_settings.fm_region].freq_min; end = radio_current_frequency() - min; length = fm_region_data[global_settings.fm_region].freq_max - min; } } #endif else if (id3 && id3->length) { length = id3->length; end = id3->elapsed + state->ff_rewind_count; } else { length = 1; end = 0; } if (!pb->horizontal) { /* we want to fill upwards which is technically inverted. */ flags = INVERTFILL; } if (pb->invert_fill_direction) { flags ^= INVERTFILL; } if (pb->nofill) { flags |= INNER_NOFILL; } if (SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->slider)) { struct gui_img *img = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->slider); /* clear the slider */ screen_clear_area(display, x, y, width, height); /* shrink the bar so the slider is inside bounds */ if (flags&HORIZONTAL) { width -= img->bm.width; x += img->bm.width / 2; } else { height -= img->bm.height; y += img->bm.height / 2; } } if (SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->backdrop)) { struct gui_img *img = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->backdrop); img->bm.data = core_get_data(img->buflib_handle); display->bmp_part(&img->bm, 0, 0, x, y, width, height); flags |= DONT_CLEAR_EXCESS; } if (!pb->nobar) { struct gui_img *img = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->image); if (img) { char *img_data = core_get_data(img->buflib_handle); img->bm.data = img_data; gui_bitmap_scrollbar_draw(display, &img->bm, x, y, width, height, length, 0, end, flags); } else gui_scrollbar_draw(display, x, y, width, height, length, 0, end, flags); } if (SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->slider)) { int xoff = 0, yoff = 0; int w = width, h = height; struct gui_img *img = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->slider); img->bm.data = core_get_data(img->buflib_handle); if (flags&HORIZONTAL) { w = img->bm.width; xoff = width * end / length; if (flags&INVERTFILL) xoff = width - xoff; xoff -= w / 2; } else { h = img->bm.height; yoff = height * end / length; if (flags&INVERTFILL) yoff = height - yoff; yoff -= h / 2; } display->bmp_part(&img->bm, 0, 0, x + xoff, y + yoff, w, h); } if (pb->type == SKIN_TOKEN_PROGRESSBAR) { if (id3 && id3->length) { #ifdef AB_REPEAT_ENABLE if (ab_repeat_mode_enabled()) ab_draw_markers(display, id3->length, x, y, width, height); #endif if (id3->cuesheet) cue_draw_markers(display, id3->cuesheet, id3->length, x, y+1, width, height-2); } #if 0 /* disable for now CONFIG_TUNER */ else if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF)) { presets_draw_markers(display, x, y, width, height); } #endif } }
/* 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; }