BlinkenArea - GitList
Repositories
Blog
Wiki
flaneth
Code
Commits
Branches
Tags
Search
Tree:
369747f
Branches
Tags
master
flaneth
firmware
app_bbm.c
iplemented 1st part of BBM player app: finding files and parsing BBM header
Stefan Schuermans
commited
369747f
at 2012-05-06 15:16:58
app_bbm.c
Blame
History
Raw
/* flaneth - flash and ethernet Copyright (C) 2007-2012 Stefan Schuermans <stefan@schuermans.info> Copyleft: GNU public license V2 - http://www.gnu.org/copyleft/gpl.html a BlinkenArea project - http://www.blinkenarea.org/ */ #include <stdio.h> #include <string.h> #include "apps_tools.h" #include "app_bbm.h" #include "debug.h" #include "dosfs.h" #include "nethelp.h" #include "timing.h" ///< BBM file header typedef struct app_bbm_header { uint32_t magic; uint16_t height; uint16_t width; uint16_t channels; uint16_t maxval; uint32_t framecnt; uint32_t duration; uint32_t frameptr; } AppBbmHeader; /** * @brief get name of next file from playlist directory * @param[in,out] state internal state of application * @param[out] filename name of file * @param[in] filename_sz length of filename buffer * @return 0 if success ful, -1 if not */ static char AppBbmNextName(AppBbmState *state, char *filename, unsigned char filename_sz) { // assemble filename of playlist directory char dirname[10]; sprintf(dirname, "bbm%hhu/pl", state->no); // open playlist directory DIRINFO di; di.scratch = *state->sectorBuf; if (DFS_OpenDir(state->vi, (uint8_t *)dirname, &di) != DFS_OK) { // no playlist dir -> deactivate application state->isInit = 0; debug_app_bbm_printf("%hhu: cannot open directory %s", state->no, filename); return -1; } // get file with index idxFile DIRENT de; unsigned short idx; char firstName[11], haveFirst; haveFirst = 0; for (idx = 0; idx <= /* file 0 -> loop once */ state->idxFile; ++idx) { // get next file do { if (DFS_GetNext(state->vi, &di, &de) != 0) { // no files at all -> deactivate application if (!haveFirst) { state->isInit = 0; debug_app_bbm_printf("%hhu: no files in playlist directory", state->no); return -1; } // end of (non-empty) playlist reached -> restart playlist // -> return first file name, next file index 1 snprintf(filename, filename_sz, "bbm%hhu/pl/%-11.11s", state->no, firstName); filename[filename_sz - 1] = 0; state->idxFile = 1; return 0; } } while (de.name[0] == 0 || // ignore deleted de.attr & (ATTR_VOLUME_ID | ATTR_DIRECTORY)); // ignore volumeIDs, // dirs, long names // first file found -> save name (for restarting playlist when end reached) if (!haveFirst) { memcpy(firstName, de.name, sizeof(firstName)); haveFirst = 1; } } // for idx // found name of file with index idxFile // -> return file name, increment file index for next file snprintf(filename, filename_sz, "bbm%hhu/pl/%-11.11s", state->no, de.name); filename[filename_sz - 1] = 0; state->idxFile++; return 0; } /** * @brief parse header of BBM file * @param[in,out] state internal state of application */ static void AppBbmParseHeader(AppBbmState *state) { // read BBM header AppBbmHeader hdr; uint32_t len; if (DFS_ReadFile(&state->fi, *state->sectorBuf, (uint8_t *)&hdr, &len, sizeof(hdr)) != DFS_OK) len = 0; if (len < sizeof(hdr)) { debug_app_bbm_printf("%hhu: truncated BBM file", state->no); return; // retry with next file in next iteration } // check header if (ntohl(hdr.magic) != 0x23542666) { debug_app_bbm_printf("%hhu: invalid magic %lX in BBM file", state->no, hdr.magic); return; // retry with next file in next iteration } state->height = ntohs(hdr.height); state->width = ntohs(hdr.width); state->channels = ntohs(hdr.channels); state->maxval = ntohs(hdr.maxval); if (state->height < 1 || state->height > 1000 || state->width < 1 || state->width > 1000 || state->channels < 1 || state->channels > 3 || state->maxval < 1 || state->maxval > 255) { debug_app_bbm_printf("%hhu: invalid dimensions in BBM file", state->no); return; // retry with next file in next iteration } if (state->height * state->width * state->channels > 1000) { debug_app_bbm_printf("%hhu: BBM frame size too large", state->no); return; // retry with next file in next iteration } uint32_t frameptr = ntohl(hdr.frameptr); if (frameptr < sizeof(hdr)) { debug_app_bbm_printf("%hhu: invalid framepointer in BBM", state->no); return; // retry with next file in next iteration } // seek to start of first frame DFS_Seek(&state->fi, frameptr, *state->sectorBuf); if (state->fi.pointer != frameptr) { debug_app_bbm_printf("%hhu: seek to first frame failed", state->no); return; // retry with next file in next iteration } // a file has been found and opened, header is parsed debug_app_bbm_printf("%hhu: header parsed: %hux%hu-%hu/%hu", state->no, state->width, state->height, state->channels, state->maxval + 1); } /** * @brief open next file from playlist directory * @param[in,out] state internal state of application */ static void AppBbmNextFile(AppBbmState *state) { // get name of next file to open char filename[22]; if (AppBbmNextName(state, filename, sizeof(filename)) != 0) return; // open file if (DFS_OpenFile(state->vi, (uint8_t *)filename, DFS_READ, *state->sectorBuf, &state->fi) != 0) { debug_app_bbm_printf("%hhu: cannot open file %s", state->no, filename); return; // retry with next file in next iteration } debug_app_bbm_printf("%hhu: file %s", state->no, filename); // parse header AppBbmParseHeader(state); } /** * @brief initialize BBM play application * @param[in,out] state internal state of application * * state.sectorBuf, state.vi, state.no have to be initialized before calling */ void AppBbmInit(AppBbmState *state) // (extern) { // default: not initialized state->isInit = 0; // get destination address for MCUF frames char filename[12]; sprintf(filename, "bbm%hhu/addr", state->no); if (AppsToolsReadIp(*state->sectorBuf, state->vi, filename, state->addr) == 0) { state->haveAddr = 1; debug_app_bbm_printf("%hhu: address %hhu.%hhu.%hhu.%hhu", state->no, state->addr[0], state->addr[1], state->addr[2], state->addr[3]); } else { state->haveAddr = 0; debug_app_bbm_printf("%hhu: no address", state->no); } // initialize internal state state->idxFile = 0; state->haveFile = 0; // initialized, start with first action now state->isInit = 1; TimingGetMs(&state->nextActMs); } /** * @brief run BBM play application * @param[in,out] state internal state of application */ void AppBbmRun(AppBbmState *state) // (extern) { // not initialized -> leave if (!state->isInit) return; // time for next action not yet reached -> leave unsigned long ms; TimingGetMs(&ms); if ((long)(state->nextActMs - ms) > 0) return; // no file -> open next one if (!state->haveFile) { AppBbmNextFile(state); return; // do not work too much in one step / app might be deactivated now } // TODO }