The "GR-PEACH_Audio_Playback_7InchLCD_Sample" is a sample code that can provides high-resolution audio playback of FLAC format files. It also allows the user to audio-playback control functions such as play, pause, and stop by manipulating key switches.

Dependencies:   GR-PEACH_video R_BSP TLV320_RBSP USBHost_custom

Fork of GR-PEACH_Audio_Playback_Sample by Renesas

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sys_scan_folder.cpp Source File

sys_scan_folder.cpp

00001 /*******************************************************************************
00002 * DISCLAIMER
00003 * This software is supplied by Renesas Electronics Corporation and is only
00004 * intended for use with Renesas products. No other uses are authorized. This
00005 * software is owned by Renesas Electronics Corporation and is protected under
00006 * all applicable laws, including copyright laws.
00007 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
00008 * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
00009 * LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
00010 * AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
00011 * TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
00012 * ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
00013 * FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
00014 * ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
00015 * BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
00016 * Renesas reserves the right, without notice, to make changes to this software
00017 * and to discontinue the availability of this software. By using this software,
00018 * you agree to the additional terms and conditions found by accessing the
00019 * following link:
00020 * http://www.renesas.com/disclaimer*
00021 * Copyright (C) 2015 Renesas Electronics Corporation. All rights reserved.
00022 *******************************************************************************/
00023 
00024 #include "mbed.h"
00025 #include "rtos.h"
00026 #include "FATFileSystem.h"
00027 #include "USBHostMSD.h"
00028 #include "sys_scan_folder.h"
00029 
00030 /*--- Macro definition of folder structure scan. ---*/
00031 /* The character string to identify root directory. */
00032 #define STR_ROOT_FOR_F_OPENDIR  ""                      /* to use f_opendir() */
00033 #define STR_ROOT_FOR_FOPEN      "/" SYS_USB_MOUNT_NAME  /* to use fopen()  */
00034 
00035 /* The file extension of FLAC. */
00036 #define FILE_EXT_FLAC           ".flac"
00037 #define FILE_EXT_FLA            ".fla"
00038 
00039 #define CHR_FULL_STOP           '.'         /* 0x2E: FULL STOP */
00040 #define CHR_SOLIDUS             '/'         /* 0x2F: SOLIDUS */
00041 #define FOLD_ID_NOT_EXIST       (0xFFFFFFFFu)
00042 #define OPEN_MODE_READ_ONLY     "r"
00043 
00044 /* File path maximum size including the usb mount name size */
00045 #define USB_MOUNT_NAME_SIZE     (sizeof(STR_ROOT_FOR_FOPEN "/"))
00046 #define FILE_PATH_MAX_LEN       (60u)
00047 #define FILE_PATH_MAX_SIZE      (USB_MOUNT_NAME_SIZE + FILE_PATH_MAX_LEN)
00048 
00049 #define SCAN_WAIT_TIME_MS       (1)
00050 
00051 static const char_t *get_full_path(fid_scan_folder_t * const p_info, 
00052                                                 const item_t * const p_item);
00053 static bool open_dir(fid_scan_folder_t * const p_info, 
00054                         const item_t * const p_item, FATFS_DIR * const p_fdir);
00055 static bool read_dir(fid_scan_folder_t * const p_info, FATFS_DIR * const p_fdir, 
00056                             const char_t ** const p_name, bool * const p_flag_dir);
00057 static bool regist_item(item_t * const p_item, 
00058                             const char_t * const p_name, const uint32_t parent);
00059 static bool check_extension(const char_t * const p_name);
00060 
00061 static bool check_folder_depth(const fid_scan_folder_t * const p_info, 
00062                                                     const uint32_t folder_id);
00063 
00064 void fid_init(fid_scan_folder_t * const p_info)
00065 {
00066     if (p_info != NULL) {
00067         p_info->total_folder = 0u;
00068         p_info->total_track = 0u;
00069     }
00070 }
00071 
00072 bool fid_scan_folder_struct(fid_scan_folder_t * const p_info)
00073 {
00074     bool            ret = false;
00075     bool            result;
00076     bool            chk;
00077     uint32_t        i;
00078     item_t          *p_item;
00079     FATFS_DIR       fdir;
00080     const char_t    *p_name;
00081     bool            flg_dir;
00082     bool            chk_dep;
00083     
00084     if (p_info != NULL) {
00085         /* Initializes the scan data. */
00086         p_info->total_track = 0u;
00087         p_info->total_folder = 0u;
00088 
00089         /* Registers the identifier of the root directory to use f_opendir(). */
00090         (void) regist_item(&p_info->folder_list[0], STR_ROOT_FOR_F_OPENDIR, FOLD_ID_NOT_EXIST);
00091         p_info->total_folder++;
00092 
00093         /* Checks the item in all registered directory. */
00094         for (i = 0; i < p_info->total_folder; i++) {
00095             chk_dep = check_folder_depth(p_info, i);
00096             result = open_dir(p_info, &p_info->folder_list[i], &fdir);
00097             while (result == true) {
00098                 result = read_dir(p_info, &fdir, &p_name, &flg_dir);
00099                 if (result == true) {
00100                     /* Checks the attribute of this item. */
00101                     if (flg_dir == true) {
00102                         /* This item is directory. */
00103                         if ((chk_dep == true) && (p_info->total_folder < SYS_MAX_FOLDER_NUM)) {
00104                             p_item = &p_info->folder_list[p_info->total_folder];
00105                             chk = regist_item(p_item, p_name, i);
00106                             if (chk == true) {
00107                                 /* Register of directory item was success. */
00108                                 p_info->total_folder++;
00109                             }
00110                         }
00111                     } else {
00112                         /* This item is file. */
00113                         chk = check_extension(p_name);
00114                         if ((chk == true) && (p_info->total_track < SYS_MAX_TRACK_NUM)) {
00115                             /* This item is FLAC file. */
00116                             p_item = &p_info->track_list[p_info->total_track];
00117                             chk = regist_item(p_item, p_name, i);
00118                             if (chk == true) {
00119                                 /* Register of file item was success. */
00120                                 p_info->total_track++;
00121                             }
00122                         }
00123                     }
00124                     Thread::wait(SCAN_WAIT_TIME_MS);
00125                 }
00126             }
00127         }
00128         /* Changes the identifier of the root directory to use fopen(). */
00129         (void) regist_item(&p_info->folder_list[0], STR_ROOT_FOR_FOPEN, FOLD_ID_NOT_EXIST);
00130 
00131         if (p_info->total_track > 0u) {
00132             ret = true;
00133         }
00134     }
00135 
00136     return ret;
00137 }
00138 
00139 FILE *fid_open_track(fid_scan_folder_t * const p_info, const uint32_t track_id)
00140 {
00141     FILE            *fp = NULL;
00142     const char_t    *p_path;
00143     size_t          path_len;
00144 
00145     if (p_info != NULL) {
00146         if (track_id < p_info->total_track) {
00147             p_path = get_full_path(p_info, &p_info->track_list[track_id]);
00148             if (p_path != NULL) {
00149                 path_len = strlen(p_path); 
00150                 /* File path maximum length is limited by the specification of "fopen". */
00151                 if (path_len < FILE_PATH_MAX_SIZE) {
00152                     fp = fopen(p_path, OPEN_MODE_READ_ONLY);
00153                 }
00154             }
00155         }
00156     }
00157     return fp;
00158 }
00159 
00160 void fid_close_track(FILE * const fp)
00161 {
00162     if (fp != NULL) {
00163         (void) fclose(fp);
00164     }
00165 }
00166 
00167 const char_t *fid_get_track_name(const fid_scan_folder_t * const p_info, 
00168                                                 const uint32_t track_id)
00169 {
00170     const char_t    *p_name = NULL;
00171 
00172     if (p_info != NULL) {
00173         if (track_id < p_info->total_track) {
00174             p_name = &p_info->track_list[track_id].name[0];
00175         }
00176     }
00177     return p_name;
00178 }
00179 
00180 uint32_t fid_get_total_track(const fid_scan_folder_t * const p_info)
00181 {
00182     uint32_t        ret = 0u;
00183 
00184     if (p_info != NULL) {
00185         ret = p_info->total_track;
00186     }
00187     return ret;
00188 }
00189 
00190 /** Gets the full path
00191  *
00192  *  @param p_info Pointer to the control data of folder scan module.
00193  *  @param p_item Pointer to the item structure of the folder / track.
00194  *
00195  *  @returns 
00196  *    Pointer to the full path.
00197  */
00198 static const char_t *get_full_path(fid_scan_folder_t * const p_info, 
00199                                         const item_t * const p_item)
00200 {
00201     const char_t    *p_path = NULL;
00202     const item_t    *p;
00203     const item_t    *item_list[SYS_MAX_FOLDER_DEPTH];
00204     uint32_t        i;
00205     uint32_t        item_cnt;
00206     uint32_t        buf_cnt;
00207     uint32_t        len;
00208     bool            err;
00209 
00210     if ((p_info != NULL) && (p_item != NULL)) {
00211         for (i = 0; i < SYS_MAX_FOLDER_DEPTH; i++) {
00212             item_list[i] = NULL;
00213         }
00214         p_info->work_buf[0] = '\0';
00215 
00216         /* Stores the item name until the root folder. */
00217         p = p_item;
00218         item_cnt = 0;
00219         while ((item_cnt < SYS_MAX_FOLDER_DEPTH) && 
00220                (p->parent_number < p_info->total_folder)) {
00221             item_list[item_cnt] = p;
00222             item_cnt++;
00223             p = &p_info->folder_list[p->parent_number];
00224         } 
00225         if (p->parent_number == FOLD_ID_NOT_EXIST) {
00226             buf_cnt = strlen(p->name);
00227             (void) strncpy(&p_info->work_buf[0], p->name, sizeof(p_info->work_buf));
00228             err = false;
00229             while ((item_cnt > 0u) && (err != true)) {
00230                 item_cnt--;
00231                 p = item_list[item_cnt];
00232                 /* Concatenates SOLIDUS character to the "work_buf" variable. */
00233                 if ((buf_cnt + 1u) < sizeof(p_info->work_buf)) {
00234                     p_info->work_buf[buf_cnt] = CHR_SOLIDUS;
00235                     buf_cnt++;
00236                 } else {
00237                     err = true;
00238                 }
00239                 /* Concatenates the item name to the "work_buf" variable. */
00240                 if (p != NULL) {
00241                     len = strlen(p->name);
00242                     if ((buf_cnt + len) < sizeof(p_info->work_buf)) {
00243                         (void) strncpy(&p_info->work_buf[buf_cnt], p->name, len);
00244                         buf_cnt += len;
00245                     } else {
00246                         err = true;
00247                     }
00248                 }
00249             }
00250             if (err != true) {
00251                 p_info->work_buf[buf_cnt] = '\0';
00252                 p_path = &p_info->work_buf[0];
00253             }
00254         }
00255     }
00256     return p_path;
00257 }
00258 
00259 /** Opens the directory
00260  *
00261  *  @param p_info Pointer to the control data of folder scan module.
00262  *  @param p_item Pointer to the item structure of the folder / track.
00263  *  @param p_fdir Pointer to the structure to store the directory object.
00264  *
00265  *  @returns 
00266  *    Results of process. true is success. false is failure.
00267  */
00268 static bool open_dir(fid_scan_folder_t * const p_info, 
00269                         const item_t * const p_item, FATFS_DIR * const p_fdir)
00270 {
00271     bool            ret = false;
00272     const char_t    *p_path;
00273     FRESULT         ferr;
00274 
00275     if ((p_info != NULL) && (p_item != NULL) && (p_fdir != NULL)) {
00276         p_path = get_full_path(p_info, p_item);
00277         if (p_path != NULL) {
00278             ferr = f_opendir(p_fdir, p_path);
00279             if (ferr == FR_OK) {
00280                 ret = true;
00281             }
00282         }
00283     }
00284     return ret;
00285 }
00286 
00287 /** Reads the directory
00288  *
00289  *  @param p_info Pointer to the control data of folder scan module.
00290  *  @param p_fdir Pointer to the structure of the directory object.
00291  *  @param p_flag_dir Pointer to the variable to store the directory flag.
00292  *
00293  *  @returns 
00294  *    Pointer to the name.
00295  */
00296 static bool read_dir(fid_scan_folder_t * const p_info, FATFS_DIR * const p_fdir, 
00297                             const char_t ** const p_name, bool * const p_flag_dir)
00298 {
00299     bool            ret = false;
00300     FRESULT         ferr;
00301     FILINFO         finfo;
00302 
00303     if ((p_info != NULL) && (p_fdir != NULL) && 
00304         (p_name != NULL) && (p_flag_dir != NULL)) {
00305         /* Sets the buffer to store the long file name. */
00306         finfo.lfname = &p_info->work_buf[0];
00307         finfo.lfsize = sizeof(p_info->work_buf);
00308         ferr = f_readdir(p_fdir, &finfo);
00309         if ((ferr == FR_OK) && ((int32_t)finfo.fname[0] != '\0')) {
00310             if (finfo.lfname != NULL) {
00311                 if ((int32_t)finfo.lfname[0] == '\0') {
00312                     /* Long file name does not exist. */
00313                     (void) strncpy(finfo.lfname, finfo.fname, finfo.lfsize);
00314                 }
00315                 /* Adds the NULL terminal character. */
00316                 /* This is fail-safe processing. */
00317                 finfo.lfname[finfo.lfsize - 1u] = '\0';
00318 
00319                 ret = true;
00320                 *p_name = finfo.lfname;
00321                 if ((finfo.fattrib & AM_DIR) != 0) {
00322                     /* This item is directory. */
00323                     *p_flag_dir = true;
00324                 } else {
00325                     /* This item is file. */
00326                     *p_flag_dir = false;
00327                 }
00328             }
00329         }
00330     }
00331     return ret;
00332 }
00333 
00334 /** Registers the item of the folder / track
00335  *
00336  *  @param p_item Pointer to the structure to store the item of the folder / track.
00337  *  @param p_name Pointer to the name of the item.
00338  *  @param parent Number of the parent folder of the item.
00339  *
00340  *  @returns 
00341  *    Results of process. true is success. false is failure.
00342  */
00343 static bool regist_item(item_t * const p_item, 
00344                             const char_t * const p_name, const uint32_t parent)
00345 {
00346     bool        ret = false;
00347     uint32_t    len;
00348 
00349     if ((p_item != NULL) && (p_name != NULL)) {
00350         len = strlen(p_name);
00351         if ((len + 1u) < sizeof(p_item->name)) {
00352             (void) strncpy(p_item->name, p_name, sizeof(p_item->name));
00353             p_item->name[sizeof(p_item->name) - 1u] = '\0';
00354             p_item->parent_number = parent;
00355             ret = true;
00356         }
00357     }
00358     return ret;
00359 }
00360 
00361 /** Checks the extension of the track name
00362  *
00363  *  @param p_name Pointer to the name of the track.
00364  *
00365  *  @returns 
00366  *    Results of the checking. true is FLAC file. false is other file.
00367  */
00368 static bool check_extension(const char_t * const p_name)
00369 {
00370     bool            ret = false;
00371     const char_t    *p;
00372 
00373     if (p_name != NULL) {
00374         p = strrchr(p_name, CHR_FULL_STOP);
00375         if (p != NULL) {
00376             if (strncasecmp(p, FILE_EXT_FLAC, sizeof(FILE_EXT_FLAC)) == 0) {
00377                 ret = true;
00378             } else if (strncasecmp(p, FILE_EXT_FLA, sizeof(FILE_EXT_FLA)) == 0) {
00379                 ret = true;
00380             } else {
00381                 /* DO NOTHING */
00382             }
00383         }
00384     }
00385     return ret;
00386 }
00387 
00388 /** Checks the folder depth in the scan range
00389  *
00390  *  @param p_info Pointer to the control data of folder scan module.
00391  *  @param folder_id Folder ID [0 - (total folder - 1)]
00392  *
00393  *  @returns 
00394  *    Results of the checking. true is the scan range. false is out of a scan range.
00395  */
00396 static bool check_folder_depth(const fid_scan_folder_t * const p_info, 
00397                                                     const uint32_t folder_id)
00398 {
00399     bool            ret = false;
00400     uint32_t        depth;
00401     uint32_t        parent_id;
00402 
00403     if (p_info != NULL) {
00404         /* Counts the folder depth. */
00405         parent_id = folder_id;
00406         depth = 0u;
00407         while ((depth < SYS_MAX_FOLDER_DEPTH) && 
00408                (parent_id < p_info->total_folder)) {
00409             depth++;
00410             parent_id = p_info->folder_list[parent_id].parent_number;
00411         } 
00412         if (parent_id == FOLD_ID_NOT_EXIST) {
00413             /* Found the root folder. */
00414             if (depth < SYS_MAX_FOLDER_DEPTH) {
00415                 ret = true;
00416             }
00417         }
00418     }
00419     return ret;
00420 }