📄 cdcache.c
字号:
}
break;
case 202:
// no matches;
break;
case 403:
// database entry corrupt
break;
case 409:
// no handshake (probably won't happen with HTTP)
break;
}
lpq->num = total;
fclose( fp );
}
void GetLineFromBuf( char **src, char *tgt, int len )
{
char *s, *t;
if ( !src || !*src || !tgt )
{
return;
}
ZeroMemory( tgt, len );
s = strstr( *src, "\r\n" );
if ( !s )
{
*src += lstrlen( *src );
return;
}
lstrcpyn( tgt, *src, len-1 );
t = strstr( tgt, "\r\n" );
if ( t && ((t - tgt) < len) )
tgt[t-tgt] = '\0';
*src = s + 2;
}
/*
* extracts the category, cddbid and title(artist/album) from linebuf and
* stores it in lpq
*/
int extractCDDBQueryInfo( LPCDDBQUERYITEM lpq, char *linebuf )
{
int i;
char *p = linebuf;
char *t;
if ( !lpq || !linebuf || !*linebuf )
return 0;
ZeroMemory( lpq, sizeof(CDDBQUERY) );
// extract the category
i = 11;
t = lpq->categ;
while( *p && (*p != ' ') && i )
{
*t++ = *p++;
i--;
}
if ( *p != ' ' )
{
return 0;
}
// extract the cddbid
while ( *p && (*++p == ' ') ); // skip space
i = 8;
t = lpq->cddbId;
while ( *p && ( isxdigit( *p ) ) && i )
{
*t++ = *p++;
i--;
}
if ( *p != ' ' )
{
return 0;
}
// get artist and title
while ( *p && (*++p == ' ') ); // skip space
i = 80;
t = lpq->artist;
t[0] = '\0';
while ( *p && (*p != '/') && i )
{
*t++ = *p++;
i--;
}
i = lstrlen( lpq->artist );
if ( i > 0 )
{
if ( lpq->artist[i-1] == ' ' )
lpq->artist[i-1] = '\0';
}
if ( *p != '/' )
{
return 0;
}
while ( *p && (*++p == ' ') ); // skip space
t = lpq->title;
lstrcpyn( t, p, 80 );
i = lstrlen( lpq->title );
if ( i > 0 )
{
if ( lpq->title[i-1] == '\r' || lpq->title[i-1] == '\n' )
lpq->title[i-1] = '\0';
}
return 1;
}
void SkipHTTPHeaders( char **buf )
{
char *p;
if ( !buf || !*buf || !**buf )
return;
p = *buf;
if ( strncmp( p, "HTTP", 4 ) )
{
return;
}
p = strstr( p, "\r\n\r\n" );
if ( p )
{
p += 4;
*buf = p;
}
}
/*
* Returns the CDDB entry verbatim from the CDDB database. If not large
* enough, no data is copied. Verifies that the return code from CDDB is
* 210 -- CDDB entry follows...
*
* If the use of CDPLAYER.INI is enabled and the category is for the query
* is "cdplayerini", then an attempt is made to read the information from
* CDPLAYER.INI.
*/
DWORD CDDBGetDiskInfo( LPCDDBQUERYITEM lpq, char *szCDDBEntry, int maxLen )
{
char *cmd, *p;
char *retBuf;
DWORD retVal = SS_ERR;
if ( !lpq || !szCDDBEntry )
return retVal;
if ( !lstrcmp( lpq->categ, "cdplayerini" ) )
return getDiskInfoCDPlayerIni( lpq, szCDDBEntry, maxLen );
cmd = (char *)GlobalAlloc( GPTR, 512 );
retBuf = (char *)GlobalAlloc( GPTR, maxLen );
p = cmd;
wsprintf( p, "cmd=cddb+read+%s+%s", lpq->categ, lpq->cddbId );
p += lstrlen( p );
wsprintf( p, "&hello=%s+%s&proto=3", szUser, szAgent );
urlEncodeString( p );
// send the query string
if ( bUseProxy )
CDDBPostCmdProxy( cmd, retBuf, maxLen );
else
CDDBPostCmd( cmd, retBuf, maxLen );
// strip any HTTP headers
p = retBuf;
SkipHTTPHeaders( &p );
if ( !strncmp( p, "210", 3 ) )
{
p = strstr( p, "\n" );
if ( p )
{
p += 1; // skip the '\n'
if ( lstrlen(p) < maxLen )
{
strcpy( szCDDBEntry, p );
retVal = SS_COMP;
// should we add it to cdplayer.ini?
if ( bUseCDPlayerIni && *p )
{
writeCDPlayerIniEntry( lpq, p );
}
}
}
}
GlobalFree( (HGLOBAL)cmd );
GlobalFree( (HGLOBAL)retBuf );
return retVal;
}
DWORD CDDBGetServerList( LPCDDBSITELIST lps )
{
char *cmd, *p;
char *retBuf;
DWORD retVal = SS_ERR;
if ( !lps || !lps->s )
return retVal;
cmd = (char *)GlobalAlloc( GPTR, 512 );
retBuf = (char *)GlobalAlloc( GPTR, 4096 );
p = cmd;
wsprintf( p, "cmd=sites&hello=%s+%s&proto=3", szUser, szAgent );
urlEncodeString( p );
// send the query string
if ( bUseProxy )
CDDBPostCmdProxy( cmd, retBuf, 4096 );
else
CDDBPostCmd( cmd, retBuf, 4096 );
if ( retBuf[0] )
{
// look for the "210 OK, site information..." message
processSites( retBuf, lps );
retVal = SS_COMP;
}
GlobalFree( (HGLOBAL)cmd );
GlobalFree( (HGLOBAL)retBuf );
return retVal;
}
void processSites( char *buf, LPCDDBSITELIST lps )
{
char linebuf[81];
char retCode[4] = "";
char *p;
int total, iRetCode;
int maxLines = 100;
// strip any HTTP headers
p = buf;
SkipHTTPHeaders( &p );
GetLineFromBuf( &p, linebuf, 81 );
strncpy( retCode, linebuf, 3 );
iRetCode = atoi( retCode );
total = 0;
switch( iRetCode )
{
case 210: // normal return code, site list follows
while ( p && lps->num && (maxLines-- > 0) )
{
GetLineFromBuf( &p, linebuf, 81 );
if ( !strcmp( linebuf, "." ) )
break;
if ( extractCDDBSiteInfo( &lps->s[total], linebuf ) )
{
total++;
lps->num--;
}
}
break;
case 401: // no site info available
break;
}
lps->num = total;
}
int extractCDDBSiteInfo( LPCDDBSITE lps, char *linebuf )
{
char *p;
char buf[6];
if ( !lps || !linebuf || !*linebuf )
return 0;
ZeroMemory( lps, sizeof(CDDBSITE) );
p = linebuf;
// extract the server
getWord( &p, lps->szServer, 81 );
if ( *p != ' ' )
return 0;
// extract the protocol
getWord( &p, buf, 6 );
if ( *p != ' ' )
return 0;
if ( !lstrcmpi( buf, "http" ) )
lps->bHTTP = TRUE;
// extract the port number
getWord( &p, buf, 6 );
if ( *p != ' ' )
return 0;
lps->iPort = atoi( buf );
if ( lps->bHTTP && !lps->iPort )
lps->iPort = 80;
// extract the CGI
getWord( &p, lps->szCGI, 81 );
if ( *p != ' ' )
return 0;
// extract north coordinate
getWord( &p, lps->szNorth, 16 );
if ( *p != ' ' )
return 0;
// extract north coordinate
getWord( &p, lps->szSouth, 16 );
if ( *p != ' ' )
return 0;
// extract the location
while( *p && (*p == ' ') ) p++;
lstrcpyn( lps->szLocation, p, 80 );
return -1;
}
void getWord( char **inBuf, char *outBuf, int len )
{
char *p = *inBuf;
ZeroMemory( outBuf, len );
len--;
// skip space
while( *p && (*p == ' ') ) p++;
#if 0
while( TRUE )
{
if ( !*p )
break;
if ( !isalnum( *p ) && (*p != '.') )
break;
if ( !len )
break;
*outBuf++ = *p++;
len--;
}
#else
while( *p &&
( isalnum( *p ) || ( *p == '.') || ( *p == '/' ) || ( *p == '~' ) ) &&
len )
{
*outBuf++ = *p++;
len--;
}
#endif
*inBuf = p;
}
DWORD genCDPlayerIniIndex( HCDROM hCD )
{
DWORD retVal = 0;
BOOL bMSF;
int idx = (int)hCD - 1;
int i;
TOC toc;
DWORD dwAddr;
bMSF = cdHandles[idx].bMSF;
cdHandles[idx].bMSF = TRUE;
memset( &toc, 0, sizeof(toc) );
ReadTOC( hCD, &toc );
for( i = 0; i <= (toc.lastTrack - toc.firstTrack); i++ )
{
MSB2DWORD( &dwAddr, toc.tracks[i].addr );
retVal += dwAddr;
}
return retVal;
}
void MSB2DWORD( DWORD *d, BYTE *b )
{
DWORD retVal;
retVal = (DWORD)b[0];
retVal = (retVal<<8) + (DWORD)b[1];
retVal = (retVal<<8) + (DWORD)b[2];
retVal = (retVal<<8) + (DWORD)b[3];
*d = retVal;
}
DWORD getDiskInfoCDPlayerIni( LPCDDBQUERYITEM lpq, char *szCDDBEntry, int maxLen )
{
UINT i, numRead;
char buf[256];
char idx[5];
char defaultName[13];
char *p;
if ( !lpq || !szCDDBEntry )
return SS_ERR;
numRead = GetPrivateProfileInt( lpq->cddbId, "NUMTRACKS", 0, szCDPlayerIni );
if ( numRead )
{
lstrcpy( lpq->categ, "rock" );
lpq->bExact = TRUE;
GetPrivateProfileString( lpq->cddbId, "ARTIST", "", buf, 256, szCDPlayerIni );
lstrcpyn( lpq->artist, buf, 80 ); lpq->artist[80] = '\0';
GetPrivateProfileString( lpq->cddbId, "TITLE", "", buf, 256, szCDPlayerIni );
lstrcpyn( lpq->title, buf, 80 ); lpq->title[80] = '\0';
p = szCDDBEntry;
wsprintf( buf, "DTITLE=%s / %s\r\n", lpq->artist, lpq->title );
if ( maxLen > lstrlen(buf) )
{
lstrcpy( p, buf );
p += lstrlen( buf );
maxLen -= lstrlen( buf );
}
for( i = 0; i < numRead; i++ )
{
wsprintf( idx, "%d", i );
wsprintf( defaultName, "Track %d", i+1 );
GetPrivateProfileString( lpq->cddbId, idx, defaultName, buf, 256, szCDPlayerIni );
if ( maxLen > (lstrlen( buf )+12) )
{
wsprintf( p, "TTITLE%d=%s\r\n", i, buf );
maxLen -= lstrlen( p );
p += lstrlen( p );
}
else
break;
}
}
if ( numRead )
return SS_COMP;
return SS_ERR;
}
BOOL isCDinCDPlayerIni( char *s )
{
UINT uiVal;
uiVal = GetPrivateProfileInt( s, "NUMTRACKS", 0, "cdplayer.ini" );
return (BOOL)uiVal;
}
void addCDPlayerCDDBIndex( DWORD cdpIdx, DWORD cddbId, DWORD numTracks )
{
if ( iNextIndex == -1 )
ZeroMemory( dwCDDB2CDPlayer, sizeof(dwCDDB2CDPlayer) );
if ( (++iNextIndex % 20) == 0 )
iNextIndex = 0;
dwCDDB2CDPlayer[iNextIndex][0] = cdpIdx; // cdplayer.ini index
dwCDDB2CDPlayer[iNextIndex][1] = cddbId; // cddb id
dwCDDB2CDPlayer[iNextIndex][2] = numTracks; // number of tracks
}
DWORD CDDBIndex2CDPlayerIni( char *szCDDBId, DWORD *dwRetVal, DWORD *numTracks )
{
int i;
DWORD dwIdx = (DWORD)strtoul( szCDDBId, NULL, 16 );
for( i = 0; i < 20; i++ )
{
if ( dwCDDB2CDPlayer[i][1] == dwIdx )
{
*dwRetVal = dwCDDB2CDPlayer[i][0];
*numTracks = dwCDDB2CDPlayer[i][2];
return *dwRetVal;
}
}
return 0;
}
/*
* Stores a CDDB entry in cdplayer.ini. NOTE: the buffer pointed to
* by szCDDBEntry may be modified by this function. Do not count on the
* buffer being unmodified!!!
*/
void writeCDPlayerIniEntry( LPCDDBQUERYITEM lpq, char *szCDDBEntry )
{
DWORD dwCDPlayerIdx, dwNumTracks;
char section[24];
char buf[128];
char *p1, *p2;
CDDBIndex2CDPlayerIni( lpq->cddbId, &dwCDPlayerIdx, &dwNumTracks );
if ( !dwCDPlayerIdx )
{
return;
}
wsprintf( section, "%X", dwCDPlayerIdx );
WritePrivateProfileString( section, "EntryType", "1", szCDPlayerIni );
WritePrivateProfileString( section, "artist", lpq->artist, szCDPlayerIni );
WritePrivateProfileString( section, "title", lpq->title, szCDPlayerIni );
WritePrivateProfileString( section, "genre", lpq->categ, szCDPlayerIni );
wsprintf( buf, "%d", dwNumTracks );
WritePrivateProfileString( section, "numtracks", buf, szCDPlayerIni );
while (*szCDDBEntry)
{
GetLineFromBuf( &szCDDBEntry, buf, 128 );
if ( !szCDDBEntry )
break;
if ( !strncmp( "TTITLE", buf, 6 ) )
{
p1 = buf + 6;
p2 = strstr( buf, "=" );
if ( *p1 && p2 )
{
*p2 = '\0';
p2++;
WritePrivateProfileString( section, p1, p2, szCDPlayerIni );
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -