@ -11,6 +11,9 @@
CardReader : : CardReader ( )
{
# ifdef SDCARD_SORT_ALPHA
sort_count = 0 ;
# endif
filesize = 0 ;
sdpos = 0 ;
sdprinting = false ;
@ -33,19 +36,15 @@ CardReader::CardReader()
autostart_atmillis = millis ( ) + 5000 ;
}
char * createFilename ( char * buffer , const dir_t & p ) //buffer>12characters
char * createFilename ( char * buffer , const dir_t & p ) //buffer>12characters
{
char * pos = buffer ;
for ( uint8_t i = 0 ; i < 11 ; i + + )
{
if ( p . name [ i ] = = ' ' ) continue ;
if ( i = = 8 )
{
* pos + + = ' . ' ;
}
* pos + + = p . name [ i ] ;
for ( uint8_t i = 0 ; i < 11 ; i + + ) {
if ( p . name [ i ] = = ' ' ) continue ;
if ( i = = 8 ) * pos + + = ' . ' ;
* pos + + = p . name [ i ] ;
}
* pos + + = 0 ;
* pos + + = 0 ;
return buffer ;
}
@ -53,15 +52,15 @@ char *createFilename(char *buffer,const dir_t &p) //buffer>12characters
void CardReader : : lsDive ( const char * prepend , SdFile parent )
{
dir_t p ;
uint8_t cnt = 0 ;
uint8_t cnt = 0 ;
while ( parent . readDir ( p , longFilename ) > 0 )
{
if ( DIR_IS_SUBDIR ( & p ) & & lsAction ! = LS_Count & & lsAction ! = LS_GetFilename ) // hence LS_SerialPrint
{
char path [ 13 * 2 ] ;
char lfilename [ 13 ] ;
char path [ FILENAME_LENGTH * 2 ] ;
char lfilename [ FILENAME_LENGTH ] ;
createFilename ( lfilename , p ) ;
path [ 0 ] = 0 ;
@ -87,8 +86,6 @@ void CardReader::lsDive(const char *prepend,SdFile parent)
}
lsDive ( path , dir ) ;
//close done automatically by destructor of SdFile
}
else
{
@ -101,11 +98,10 @@ void CardReader::lsDive(const char *prepend,SdFile parent)
if ( p . name [ 1 ] ! = ' . ' )
continue ;
}
if ( ! DIR_IS_FILE_OR_SUBDIR ( & p ) ) continue ;
filenameIsDir = DIR_IS_SUBDIR ( & p ) ;
if ( ! filenameIsDir )
{
if ( p . name [ 8 ] ! = ' G ' ) continue ;
@ -124,10 +120,8 @@ void CardReader::lsDive(const char *prepend,SdFile parent)
}
else if ( lsAction = = LS_GetFilename )
{
if ( cnt = = nrFiles )
return ;
if ( cnt = = nrFiles ) return ;
cnt + + ;
}
}
}
@ -136,9 +130,6 @@ void CardReader::lsDive(const char *prepend,SdFile parent)
void CardReader : : ls ( )
{
lsAction = LS_SerialPrint ;
if ( lsAction = = LS_Count )
nrFiles = 0 ;
root . rewind ( ) ;
lsDive ( " " , root ) ;
}
@ -177,6 +168,9 @@ void CardReader::initsd()
}
workDir = root ;
curDir = & root ;
# ifdef SDCARD_SORT_ALPHA
presort ( ) ;
# endif
/*
if ( ! workDir . openRoot ( & volume ) )
{
@ -193,8 +187,10 @@ void CardReader::setroot()
SERIAL_ECHOLNPGM ( MSG_SD_WORKDIR_FAIL ) ;
} */
workDir = root ;
curDir = & workDir ;
# ifdef SDCARD_SORT_ALPHA
presort ( ) ;
# endif
}
void CardReader : : release ( )
{
@ -207,6 +203,7 @@ void CardReader::startFileprint()
if ( cardOK )
{
sdprinting = true ;
flush_presort ( ) ;
}
}
@ -235,7 +232,7 @@ void CardReader::getAbsFilename(char *t)
while ( * t ! = 0 & & cnt < MAXPATHNAMELENGTH )
{ t + + ; cnt + + ; } //crawl counter forward.
}
if ( cnt < MAXPATHNAMELENGTH - 13 )
if ( cnt < MAXPATHNAMELENGTH - FILENAME_LENGTH )
file . getFilename ( t ) ;
else
t [ 0 ] = 0 ;
@ -305,7 +302,7 @@ void CardReader::openFile(char* name,bool read, bool replace_current/*=true*/)
//SERIAL_ECHO("end :");SERIAL_ECHOLN((int)(dirname_end-name));
if ( dirname_end > 0 & & dirname_end > dirname_start )
{
char subdirname [ 13 ] ;
char subdirname [ FILENAME_LENGTH ] ;
strncpy ( subdirname , dirname_start , dirname_end - dirname_start ) ;
subdirname [ dirname_end - dirname_start ] = 0 ;
SERIAL_ECHOLN ( subdirname ) ;
@ -401,7 +398,7 @@ void CardReader::removeFile(char* name)
//SERIAL_ECHO("end :");SERIAL_ECHOLN((int)(dirname_end-name));
if ( dirname_end > 0 & & dirname_end > dirname_start )
{
char subdirname [ 13 ] ;
char subdirname [ FILENAME_LENGTH ] ;
strncpy ( subdirname , dirname_start , dirname_end - dirname_start ) ;
subdirname [ dirname_end - dirname_start ] = 0 ;
SERIAL_ECHOLN ( subdirname ) ;
@ -439,6 +436,9 @@ void CardReader::removeFile(char* name)
SERIAL_PROTOCOLPGM ( " File deleted: " ) ;
SERIAL_PROTOCOLLN ( fname ) ;
sdpos = 0 ;
# ifdef SDCARD_SORT_ALPHA
presort ( ) ;
# endif
}
else
{
@ -552,14 +552,21 @@ void CardReader::closefile(bool store_location)
}
void CardReader : : getfilename ( const uint 8 _t nr )
void CardReader : : getfilename ( const uint 16 _t nr )
{
# if defined(SDCARD_SORT_ALPHA) && SORT_USES_RAM && SORT_USES_MORE_RAM
if ( nr < sort_count ) {
strcpy ( filename , sortshort [ nr ] ) ;
strcpy ( longFilename , sortnames [ nr ] ) ;
filenameIsDir = isDir [ nr ] ;
return ;
}
# endif
curDir = & workDir ;
lsAction = LS_GetFilename ;
nrFiles = nr ;
curDir - > rewind ( ) ;
lsDive ( " " , * curDir ) ;
}
uint16_t CardReader : : getnrfilenames ( )
@ -577,7 +584,7 @@ void CardReader::chdir(const char * relpath)
{
SdFile newfile ;
SdFile * parent = & root ;
if ( workDir . isOpen ( ) )
parent = & workDir ;
@ -595,21 +602,167 @@ void CardReader::chdir(const char * relpath)
workDirParents [ 0 ] = * parent ;
}
workDir = newfile ;
# ifdef SDCARD_SORT_ALPHA
presort ( ) ;
# endif
}
}
void CardReader : : updir ( )
{
if ( workDirDepth > 0 )
if ( workDirDepth > 0 )
{
- - workDirDepth ;
workDir = workDirParents [ 0 ] ;
int d ;
for ( int d = 0 ; d < workDirDepth ; d + + )
workDirParents [ d ] = workDirParents [ d + 1 ] ;
# ifdef SDCARD_SORT_ALPHA
presort ( ) ;
# endif
}
}
# ifdef SDCARD_SORT_ALPHA
/**
* Get the name of a file in the current directory by sort - index
*/
void CardReader : : getfilename_sorted ( const uint16_t nr ) {
getfilename ( nr < sort_count ? sort_order [ nr ] : nr ) ;
}
/**
* Read all the files and produce a sort key
*
* We can do this in 3 ways . . .
* - Minimal RAM : Read two filenames at a time sorting along . . .
* - Some RAM : Buffer the directory and return filenames from RAM
* - Some RAM : Buffer the directory just for this sort
*/
void CardReader : : presort ( )
{
flush_presort ( ) ;
uint16_t fileCnt = getnrfilenames ( ) ;
if ( fileCnt > 0 ) {
if ( fileCnt > SORT_LIMIT ) fileCnt = SORT_LIMIT ;
# if SORT_USES_RAM
# if SORT_USES_MORE_RAM
sortshort = ( char * * ) calloc ( fileCnt , sizeof ( char * ) ) ;
sortnames = ( char * * ) calloc ( fileCnt , sizeof ( char * ) ) ;
# else
char * sortnames [ fileCnt ] ;
# endif
# else
char name1 [ LONG_FILENAME_LENGTH + 1 ] ;
# endif
# if FOLDER_SORTING != 0
# if SORT_USES_RAM && SORT_USES_MORE_RAM
isDir = ( uint8_t * ) calloc ( fileCnt , sizeof ( uint8_t ) ) ;
# else
uint8_t isDir [ fileCnt ] ;
# endif
# endif
sort_order = new uint8_t [ fileCnt ] ;
if ( fileCnt > 1 ) {
// Init sort order. If using RAM then read all filenames now.
for ( uint16_t i = 0 ; i < fileCnt ; i + + ) {
sort_order [ i ] = i ;
# if SORT_USES_RAM
getfilename ( i ) ;
sortnames [ i ] = strdup ( longFilename [ 0 ] ? longFilename : filename ) ;
# if SORT_USES_MORE_RAM
sortshort [ i ] = strdup ( filename ) ;
# endif
// char out[30];
// sprintf_P(out, PSTR("---- %i %s %s"), i, filenameIsDir ? "D" : " ", sortnames[i]);
// SERIAL_ECHOLN(out);
# if FOLDER_SORTING != 0
isDir [ i ] = filenameIsDir ;
# endif
# endif
}
// Bubble Sort
for ( uint16_t i = fileCnt ; - - i ; ) {
bool cmp , didSwap = false ;
for ( uint16_t j = 0 ; j < i ; + + j ) {
uint16_t s1 = j , s2 = j + 1 , o1 = sort_order [ s1 ] , o2 = sort_order [ s2 ] ;
# if SORT_USES_RAM
# if FOLDER_SORTING != 0
cmp = ( isDir [ o1 ] = = isDir [ o2 ] ) ? ( strcasecmp ( sortnames [ o1 ] , sortnames [ o2 ] ) > 0 ) : isDir [ FOLDER_SORTING > 0 ? o1 : o2 ] ;
# else
cmp = strcasecmp ( sortnames [ o1 ] , sortnames [ o2 ] ) > 0 ;
# endif
# else
getfilename ( o1 ) ;
strcpy ( name1 , longFilename [ 0 ] ? longFilename : filename ) ;
# if FOLDER_SORTING != 0
bool dir1 = filenameIsDir ;
# endif
getfilename ( o2 ) ;
char * name2 = longFilename [ 0 ] ? longFilename : filename ;
# if FOLDER_SORTING != 0
cmp = ( dir1 = = filenameIsDir ) ? ( strcasecmp ( name1 , name2 ) > 0 ) : ( FOLDER_SORTING > 0 ? dir1 : ! dir1 ) ;
# else
cmp = strcasecmp ( name1 , name2 ) > 0 ;
# endif
# endif
if ( cmp ) {
// char out[LONG_FILENAME_LENGTH*2+20];
// sprintf_P(out, PSTR("Swap %i %s for %i %s"), o1, sortnames[o1], o2, sortnames[o2]);
// SERIAL_ECHOLN(out);
sort_order [ s1 ] = o2 ;
sort_order [ s2 ] = o1 ;
didSwap = true ;
}
}
if ( ! didSwap ) break ;
}
# if SORT_USES_RAM && !SORT_USES_MORE_RAM
for ( uint16_t i = 0 ; i < fileCnt ; + + i ) free ( sortnames [ i ] ) ;
# endif
}
else {
sort_order [ 0 ] = 0 ;
# if SORT_USES_RAM && SORT_USES_MORE_RAM
sortnames = ( char * * ) malloc ( sizeof ( char * ) ) ;
sortshort = ( char * * ) malloc ( sizeof ( char * ) ) ;
isDir = ( uint8_t * ) malloc ( sizeof ( uint8_t ) ) ;
getfilename ( 0 ) ;
sortnames [ 0 ] = strdup ( longFilename [ 0 ] ? longFilename : filename ) ;
sortshort [ 0 ] = strdup ( filename ) ;
isDir [ 0 ] = filenameIsDir ;
# endif
}
sort_count = fileCnt ;
}
}
void CardReader : : flush_presort ( ) {
if ( sort_count > 0 ) {
# if SORT_USES_RAM && SORT_USES_MORE_RAM
for ( uint8_t i = 0 ; i < sort_count ; + + i ) {
free ( sortshort [ i ] ) ;
free ( sortnames [ i ] ) ;
}
free ( sortshort ) ;
free ( sortnames ) ;
# endif
delete sort_order ;
sort_count = 0 ;
}
}
# endif // SDCARD_SORT_ALPHA
void CardReader : : printingHasFinished ( )
{
@ -633,6 +786,9 @@ void CardReader::printingHasFinished()
enquecommand_P ( PSTR ( SD_FINISHED_RELEASECOMMAND ) ) ;
}
autotempShutdown ( ) ;
# ifdef SDCARD_SORT_ALPHA
presort ( ) ;
# endif
}
}
# endif //SDSUPPORT