Library for Skeleton of SD card player. SD カードプレーヤのための骨組みとして使うためのライブラリ.このライブラリを登録した際のプログラム:「F746_SD_Player_Demo」

Dependencies:   SDFileSystem_Warning_Fixed

Dependents:   F746_SD_Player_Demo F746_SD_VarableFilter F746_SD_GraphicEqualizer F746_MySoundMachine ... more

FileSelectorWav.cpp

Committer:
MikamiUitOpen
Date:
2017-03-23
Revision:
17:abfd6af9a236
Parent:
12:f73e11831c1c

File content as of revision 17:abfd6af9a236:

//--------------------------------------------------------------
//  FileSelector class
//      SD カード内のファイル名の一覧を表示し,ファイルを選択する
//
//  2017/03/23, Copyright (c) 2017 MIKAMI, Naoki
//--------------------------------------------------------------

#include "FileSelectorWav.hpp"

namespace Mikami
{
    FileSelector::FileSelector(uint8_t x0, uint8_t y0, int maxFiles,
                               int maxNameLength, SD_WavReader &reader)
        : X_(x0), Y_(y0),
          MAX_FILES_(maxFiles), MAX_NAME_LENGTH_(maxNameLength),
          fileNames_(maxFiles), fileNameLabels_(MAX_LIST_PAGE_),
          next_(50, 238, 64, 36, 2, (string[]){"<", ">"}, 10, 0, 2, -1, Font24),
          pageLabel_(210, 250, Label::LEFT, Font16),
          lcd_(GuiBase::GetLcd()), sdReader_(reader), page_(1),
          nOld_(-1), kOld_(-1)
    {
        Array<string> nonString(MAX_LIST_PAGE_, "");
        rect_ = new ButtonGroup(X_, Y_, W_H_, W_H_, MAX_LIST_PAGE_,
                                nonString, 0, V_L_-W_H_, 1,
                                -1, Font12, 0, GuiBase::ENUM_BACK,
                                BASE_COLOR_, TOUCHED_COLOR_);
        rect_->EraseAll();
        next_.EraseAll();

        // Label を生成
        for (int n=0; n<MAX_LIST_PAGE_; n++)
            fileNameLabels_[n] = new Label(X_+30, Y_+5+V_L_*n, "",
                                           Label::LEFT, Font16, BASE_COLOR_);
    }

    FileSelector::~FileSelector()
    {   
        delete rect_;
        for (int n=0; n<MAX_LIST_PAGE_; n++) delete fileNameLabels_[n];
    }

    // ファイルの一覧表を作る.WAV ファイルが存在しない場合は false を返す
    bool FileSelector::CreateTable()
    {
        DIR* dp = opendir("/sd");
        fileCount_ = 0; 
        if (dp != NULL)
        {
            dirent* entry;
            for (int n=0; n<256; n++)
            {
                entry = readdir(dp);
                if (entry == NULL) break;

                string strName = entry->d_name;
                if ( (strName.find(".wav") != string::npos) ||
                     (strName.find(".WAV") != string::npos) )
                {
                    sdReader_.Open(strName);        // ファイルオープン

                    // PCM,16 ビットステレオ,標本化周波数 44.1 kHz 以外のファイルは除外
                    if (sdReader_.IsWavFile())
                        fileNames_[fileCount_++] = strName;
                    sdReader_.Close();
                }
                if (fileCount_ >= MAX_FILES_) break;
            }
            closedir(dp);
        }
        else
            return false;                   // SD カードが装着されていない場合
        if (fileCount_ == 0) return false;  // 該当する WAV ファイルが存在しない場合

        div_t m = div(fileCount_, MAX_LIST_PAGE_);
        maxPage_ = (m.rem == 0) ? m.quot : m.quot+1;
        return true;                        // 該当する WAV ファイルが存在する場合
    }

    // ファイルを選択する
    bool FileSelector::Select(string &fileName)
    {
        int m;
        if (next_.GetTouchedNumber(m))
        {
            if (m==0) page_--;
            else      page_++;
            DisplayFileList(false);
            nOld_ = -1;
            wait_ms(300);
        }
        
        int n;
        if (rect_->GetTouchedNumber(n))
        {
            int k = (page_ - 1)*MAX_LIST_PAGE_ + n;
            fileNameLabels_[n]->Draw(GetFileNameNoExt(k),
                                     TOUCHED_COLOR_);
            fileName = fileNames_[k];
            // 同じページで以前に選択されているファイル名の色を戻す
            if (nOld_ != -1)
                fileNameLabels_[nOld_]->Draw(GetFileNameNoExt(kOld_),
                                             BASE_COLOR_);
            if (page_ == maxPage_)      // 最後のページで余分な四角形を消去
                for (int j=fileCount_ % MAX_LIST_PAGE_ + 1;
                     j < MAX_LIST_PAGE_; j++) rect_->Erase(j);
            nOld_ = n;
            kOld_ = k;
            wait_ms(300);
            return true;
        }
        else
            return false;
    }

    // ファイルの一覧の表示
    void FileSelector::DisplayFileList(bool sortEnable)
    {
        if (sortEnable)
            std::sort((string *)fileNames_,
                      (string *)fileNames_+fileCount_); 
        
        Erase(X_, Y_, MAX_NAME_LENGTH_*((sFONT *)(&Font16))->Width, 272-Y_);

        div_t m = div(fileCount_, MAX_LIST_PAGE_);
        int count = (m.quot >= page_) ? MAX_LIST_PAGE_ : m.rem;
        for (int n=0; n<count; n++) rect_->Draw(n);
        for (int n=0; n<count; n++)
            fileNameLabels_[n]->Draw(GetFileNameNoExt(n+(page_-1)*MAX_LIST_PAGE_));

        // 前のページ,次のページの選択ボタンなどを表示する
        next_.InactivateAll();
        if (page_ > 1) next_.Activate(0);           // "<" 有効
        if (page_ < maxPage_) next_.Activate(1);    // ">" 有効
        char page[6];
        sprintf(page, "%d/%d", page_, maxPage_);
        pageLabel_.Draw(page);
    }

    // ファイルの一覧の消去
    void FileSelector::Erase(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
                             uint32_t color)
    {
        lcd_.SetTextColor(color);
        lcd_.FillRect(x, y, width, height);
    }

    // 拡張子を削除したファイル名を取得
    string FileSelector::GetFileNameNoExt(int n)
    {
        string name = fileNames_[n];
        int k = name.rfind(".");
        if (k != string::npos)
            return name.erase(k);
        else
            return name;
    }
}