📄 app.cpp
字号:
///////////////////////////////////////////////////////////////////////////////
//
// app.cpp
//
// see RIO.CPP for version history
//
///////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/stat.h>
#include "std.h"
#include "rio.h"
// output
#define INFOSTR printf
#define ERRORSTR INFOSTR
// platform dependencies
#if defined(_WINNT)
// MS VC++ v5.0 for WinNT v4
#include <stdlib.h>
#define SIZE_MAXPATH _MAX_PATH
#define DELETEARRAY delete[]
#elif defined(_WIN32)
// MS VC++ v5.0 for Win9x
#include <stdlib.h>
#define SIZE_MAXPATH _MAX_PATH
#define DELETEARRAY delete[]
#elif defined(__linux__)
// linux g++
#include <unistd.h>
#include <values.h>
#include <linux/limits.h>
#if defined(PATH_MAX)
#define SIZE_MAXPATH PATH_MAX
#else
#define SIZE_MAXPATH 256
#endif
#define DELETEARRAY delete[]
#elif defined(__FreeBSD__)
// FreeBSD g++
#include <unistd.h>
#include <sys/syslimits.h>
#define SIZE_MAXPATH PATH_MAX
#define DELETEARRAY delete[]
#elif defined(__bsdi__)
// BSD/OS g++
#include <unistd.h>
#include <limits.h>
#define SIZE_MAXPATH PATH_MAX
#define DELETEARRAY delete[]
#elif defined(__OS2__)
// OS/2 VisualAge C++ v. 3
#include <stdlib.h>
#elif defined(__TURBOC__)
// turboc v1.01
#include <dir.h>
#define SIZE_MAXPATH MAXPATH
#define DELETEARRAY delete
#else
// not supported
#error ! ! compiler/platform not supported ! !
#endif
// default port base
#if defined(__alpha)
#define PORT_BASE_DEFAULT 0x3bc
#else
#define PORT_BASE_DEFAULT 0x378
#endif
// return code
#define CLEANUP_RETURN( ret ) \
{ \
if ( pRio ) \
{ \
delete pRio; \
pRio = NULL; \
} \
if ( pszFilePlaylistTemp ) \
{ \
unlink( pszFilePlaylistTemp ); \
pszFilePlaylistTemp = NULL; \
} \
return ret; \
}
///////////////////////////////////////////////////////////////////////////////
// return pointer to static string containing datetime
static char* TimeStr( long lValue )
{
static char szBuf[ 64 ];
struct tm* psDateTime;
psDateTime = localtime( &lValue );
if ( !psDateTime )
strcpy( szBuf, "INVALID DATE/TIME" );
else
{
sprintf(
szBuf,
"%02u/%02u/%02u %02u:%02u:%02u",
(UINT)psDateTime->tm_mday % 100,
(UINT)psDateTime->tm_mon+1 % 100,
(UINT)psDateTime->tm_year % 100,
(UINT)psDateTime->tm_hour % 100,
(UINT)psDateTime->tm_min % 100,
(UINT)psDateTime->tm_sec % 100
);
}
return szBuf;
}
///////////////////////////////////////////////////////////////////////////////
// return maxpath
static int GetMaxPathSize( void )
{
#if defined(__OS2__)
ULONG ulSize;
DosQuerySysInfo( QSV_MAX_PATH_LENGTH, QSV_MAX_PATH_LENGTH, &ulSize, sizeof(ulSize) );
return ulSize;
#endif
return SIZE_MAXPATH;
}
///////////////////////////////////////////////////////////////////////////////
// return file size
static long GetFileSize( char* pszPathFile )
{
long lReturn = 0;
FILE* fpFile = fopen( pszPathFile, "rb" );
if ( fpFile )
{
struct stat sStat;
if ( !stat(pszPathFile, &sStat) )
lReturn = sStat.st_size;
fclose( fpFile );
}
return lReturn;
}
///////////////////////////////////////////////////////////////////////////////
// progress callback
static BOOL ProgressCallback( int iPos, int iCount )
{
INFOSTR( "blocks %-5hd\r", iCount-iPos );
fflush( stdout );
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////
// compute sample frequency
static UINT GetSampleFreq( UCHAR* paucProp )
{
int iVersion, iFreq;
UINT auiFreq[3][4] =
{
{ 44100, 48000, 32000, 0 },
{ 22050, 24000, 16000, 0 },
{ 11025, 8000, 8000, 0 }
};
switch( (paucProp[2] >> 3 & 0x3) )
{
case 3: iVersion = 0; break;
case 2: iVersion = 1; break;
case 0: iVersion = 2; break;
default: return 0;
}
iFreq = (paucProp[1] >> 2) & 0x03;
return auiFreq[ iVersion ][ iFreq ];
}
///////////////////////////////////////////////////////////////////////////////
// compute bit rate
static int GetBitRate( UCHAR* paucProp )
{
int iVersion, iLay, iPosBitrate;
int aBitrate[3][3][15] =
{
{
{ 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 },
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 },
{ 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 }
},
{
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 },
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 },
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 }
},
{
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 },
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 },
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 }
}
};
iLay = 4 - ((paucProp[2] >> 1) & 0x03);
iPosBitrate = (paucProp[1] >> 4) & 0x0f;
switch( (paucProp[2]>>3 & 0x03) )
{
case 3: iVersion = 0; break;
case 2: iVersion = 1; break;
case 0: iVersion = 2; break;
default: return 0;
}
return aBitrate[ iVersion][iLay - 1 ][ iPosBitrate ];
}
///////////////////////////////////////////////////////////////////////////////
// display directory
static void DisplayDirectory( CRio& cRio, BOOL bVerbose )
{
CDirBlock& cDirBlock = cRio.GetDirectoryBlock();
CDirHeader& cDirHeader = cDirBlock.m_cDirHeader;
INFOSTR( "\n" );
INFOSTR( " entry count: %hu\n", cDirHeader.m_usCountEntry );
INFOSTR( " total memory: %ld KB\n", ((long)cDirHeader.m_usCount32KBlockAvailable * CRIO_SIZE_32KBLOCK) / 1024 );
INFOSTR( " used memory: %ld KB\n", ((long)cDirHeader.m_usCount32KBlockUsed * CRIO_SIZE_32KBLOCK) / 1024 );
INFOSTR( " unused memory: %ld KB\n", ((long)cDirHeader.m_usCount32KBlockRemaining * CRIO_SIZE_32KBLOCK) / 1024 );
INFOSTR( "flash ram type: %s\n", cRio.GetUseExternalFlashStatus() ? "external" : "internal" );
if ( bVerbose )
{
INFOSTR( "bad 32K blocks: %hu\n", cDirHeader.m_usCount32KBlockBad );
INFOSTR( " last update: %s\n", TimeStr(cDirHeader.m_lTimeLastUpdate) );
INFOSTR( " checksum1: 0x%04hx\n", cDirHeader.m_usChecksum1 );
INFOSTR( " checksum2: 0x%04hx\n", cDirHeader.m_usChecksum2 );
INFOSTR( " host version: 0x%04hx\n", cDirHeader.m_usVersion );
}
UINT uiCountEntry = cDirHeader.m_usCountEntry;
if ( uiCountEntry )
{
CDirEntry* pDirEntry = cDirBlock.m_acDirEntry;
if ( uiCountEntry > CRIO_MAX_DIRENTRY )
uiCountEntry = CRIO_MAX_DIRENTRY;
// extended output
if ( bVerbose )
{
INFOSTR( "\n" );
INFOSTR( "No 32KPos 32KCount Mod32K Size Upload Date/Time Title\n" );
INFOSTR( "-----------------------------------------------------------------------------\n" );
for( UINT uiA=0; uiA<uiCountEntry; ++uiA, ++pDirEntry )
{
INFOSTR( "%02u 0x%04hx %-4hu 0x%04hx %-8ld %s %-24.24s\n",
uiA+1,
pDirEntry->m_usPos32KBlock,
pDirEntry->m_usCount32KBlock,
pDirEntry->m_usSize32KMod,
pDirEntry->m_lSize,
TimeStr(pDirEntry->m_lTimeUpload),
pDirEntry->m_szName
);
}
}
// normal output
else
{
INFOSTR( "\n" );
INFOSTR( "No Size K/s SFreq Upload Date/Time Title\n" );
INFOSTR( "----------------------------------------------------------------------------\n" );
for( UINT uiA=0; uiA<uiCountEntry; ++uiA, ++pDirEntry )
{
INFOSTR( "%02u %-8ld %-3d %-5u %s %-36.36s\n",
uiA+1,
pDirEntry->m_lSize,
GetBitRate(pDirEntry->m_aucProperty),
GetSampleFreq(pDirEntry->m_aucProperty),
TimeStr(pDirEntry->m_lTimeUpload),
pDirEntry->m_szName
);
}
}
}
}
///////////////////////////////////////////////////////////////////////////////
// hex dump directory block
static void DumpDirectory( CRio& cRio, int iPos, int iSize )
{
int iA, iB;
CDirBlock& cDirBlock = cRio.GetDirectoryBlock();
UCHAR* pucS = ((UCHAR*)&cDirBlock) + iPos;
if ( iSize % 16 )
iSize = ((iSize / 16)+1) * 16;
for( iA=0; iA<(iSize/16); ++iA, pucS+=16 )
{
INFOSTR( "%08lx ", iA*16 );
for( iB=0; iB<16; ++iB )
{
int iC = *(pucS+iB);
INFOSTR( "%02x ", iC );
if ( (iB%8) == 7 )
INFOSTR( " " );
}
for( iB=0; iB<16; ++iB )
{
int iC = *(pucS+iB);
INFOSTR( "%c", iC > 32 ? iC : '.' );
if ( (iB%8) == 7 )
INFOSTR( " " );
}
INFOSTR( "\n" );
if ( (iA%8) == 7 )
INFOSTR( "\n" );
}
}
///////////////////////////////////////////////////////////////////////////////
// process playlist file
static BOOL ProcessPlaylist( CRio& cRio, char* pszFile, BOOL bVerbose )
{
// open playlist for read
FILE* fpFile = fopen( pszFile, "r" );
if ( !fpFile )
{
ERRORSTR( "unable to open '%s' for read\n", pszFile );
return FALSE;
}
// create buffer
int iSizeMaxPath = GetMaxPathSize();
char* pszBuf = new char[ iSizeMaxPath ];
// check if device can accommodate all files in playlist
CDirBlock& cDirBlock = cRio.GetDirectoryBlock();
CDirHeader& cDirHeader = cDirBlock.m_cDirHeader;
long lSizeAvailable = (long)cDirHeader.m_usCount32KBlockAvailable * CRIO_SIZE_32KBLOCK;
long lSizeCurrent = (long)cDirHeader.m_usCount32KBlockUsed * CRIO_SIZE_32KBLOCK;
int iCountEntryCurrent = cDirHeader.m_usCountEntry;
while( fgets(pszBuf, iSizeMaxPath, fpFile) )
{
// strip 'new line' char
int iLength = strlen( pszBuf );
pszBuf[ --iLength ] = 0;
// if blank line or comment
if ( !iLength || pszBuf[0] == '#' || pszBuf[0] == ';' )
continue;
// get file size
long lSize = GetFileSize( pszBuf );
if ( !lSize )
{
ERRORSTR( "unable to open '%s' for read\n", pszBuf );
fclose( fpFile );
DELETEARRAY pszBuf;
return FALSE;
}
// check space
lSizeCurrent += lSize;
if ( lSizeCurrent > lSizeAvailable )
{
ERRORSTR( "entry '%s' exceed's memory capacity of device\n", pszBuf );
fclose( fpFile );
DELETEARRAY pszBuf;
return FALSE;
}
// check enough entries
++iCountEntryCurrent;
if ( iCountEntryCurrent > CRIO_MAX_DIRENTRY )
{
ERRORSTR( "entry '%s' exceed's maximum directory entry count for device\n", pszBuf );
fclose( fpFile );
DELETEARRAY pszBuf;
return FALSE;
}
}
// rewind playlist
rewind( fpFile );
// process entries
while( fgets(pszBuf, iSizeMaxPath, fpFile) )
{
// strip 'new line' char
int iLength = strlen( pszBuf );
pszBuf[ --iLength ] = 0;
// if blank line or comment
if ( !iLength || pszBuf[0] == '#' || pszBuf[0] == ';' )
continue;
// upload
if ( bVerbose )
INFOSTR( "uploading %s\n", pszBuf );
if ( !cRio.TxFile(pszBuf, bVerbose ? ProgressCallback : NULL) )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -