cdcache.c
资源名称:xtractor.zip [点击查看]
上传用户:xmgzy123
上传日期:2007-01-07
资源大小:373k
文件大小:25k
源码类别:
SCSI/ASPI
开发平台:
WINDOWS
- /*
- * cdcache.c - Copyright (C) 1999 Jay A. Key
- *
- * Interface to CD title/artist/track names cache, and cddb. Can optionally
- * use cdplayer.ini when internet access is not available.
- *
- * The code to access CDPLAYER.INI was adapted from code submitted by
- * Blair Thompson
- *
- **********************************************************************
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published
- * by the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- **********************************************************************
- *
- * $Id: cdcache.c,v 1.2 2000/02/25 10:47:37 akey Exp $
- * $Date: 2000/02/25 10:47:37 $
- * $Locker: $
- * $Log: cdcache.c,v $
- * Revision 1.2 2000/02/25 10:47:37 akey
- * sync'ed with akrip32.dll v0.94
- *
- * Revision 1.6 2000/02/14 09:56:25 akey
- * cleaned up #ifdef _DEBUG code considerably
- *
- * Revision 1.5 2000/02/11 10:00:35 akey
- * added access to cdplayer.ini
- *
- * Revision 1.4 2000/01/31 15:35:40 akey
- * v0.93: added CDDBGetServerList and fixed problem with Win2000 scsi pass through code
- *
- * Revision 1.3 2000/01/06 16:38:35 akey
- * Added missing CDDB_OPT_HTTPPORT
- *
- * Revision 1.2 2000/01/03 12:29:43 akey
- * v0.91 release -- added CDDB and bug fixes
- *
- *
- */
- #include <windows.h>
- #include <stdio.h>
- #include <time.h>
- #include <string.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <winsock.h>
- #include "aspilib.h"
- #include "cdcache.h"
- DWORD CDDBPostCmd( char *cmd, char *retBuf, int retLen );
- DWORD CDDBPostCmdProxy( char *cmd, char *retBuf, int retLen );
- void urlEncodeString( char *s );
- void GetLineFromBuf( char **src, char *tgt, int len );
- void processCDDBQuery( char *buf, LPCDDBQUERY lpq );
- void SkipHTTPHeaders( char **buf );
- int extractCDDBQueryInfo( LPCDDBQUERYITEM lpq, char *linebuf );
- void processSites( char *buf, LPCDDBSITELIST lps );
- int extractCDDBSiteInfo( LPCDDBSITE s, char *buf );
- void getWord( char **inBuf, char *outBuf, int len );
- DWORD genCDPlayerIniIndex( HCDROM hCD );
- void MSB2DWORD( DWORD *d, BYTE *b );
- DWORD getDiskInfoCDPlayerIni( LPCDDBQUERYITEM lpq, char *szCDDBEntry, int maxLen );
- BOOL isCDinCDPlayerIni( char *s );
- void addCDPlayerCDDBIndex( DWORD cdpIdx, DWORD cddbId, DWORD numTracks );
- void writeCDPlayerIniEntry( LPCDDBQUERYITEM lpq, char *szCDDBEntry );
- extern CDHANDLEREC *cdHandles;
- extern HANDLE *cdMutexes;
- extern HANDLE hCacheMutex;
- extern CRITICAL_SECTION csCache;
- extern CRITICAL_SECTION getHandle;
- extern int alErrCode;
- extern BYTE alAspiErr;
- extern DWORD (*pfnSendASPI32Command)(LPSRB);
- //static BOOL bCacheInitMutex = FALSE;
- static BOOL bCacheInit = FALSE;
- static char szCacheDir[MAX_PATH+1];
- //static HANDLE hCacheMutex = NULL;
- //static CRITICAL_SECTION csCache;
- static char szCDPlayerIni[] = "cdplayer.ini";
- static char szProxyAddr[256] = "";
- static int iProxyPort = 0;
- static char szCDDBServer[256] = "www.freedb.org";
- static BOOL bUseProxy = FALSE;
- static char szAgent[61] = "akrip32dll 0.91";
- static char szUser[65] = "user@akrip.sourceforge.net";
- static char szCGI[81] = "/~cddb/cddb.cgi";
- static int iHTTPPort = 80;
- static BOOL bUseCDPlayerIni = TRUE;
- static DWORD dwCDDB2CDPlayer[20][3];
- static int iNextIndex = -1;
- DWORD CDDBSum( DWORD n )
- {
- DWORD retVal = 0;
- while( n > 0 )
- {
- retVal += ( n % 10 );
- n /= 10;
- }
- return retVal;
- }
- /*
- * Computes the CDDBID for the CD in the drive represented by hCD.
- * Data which can be used to construct a CDDB query is stored in the
- * array pID.
- * pID[0] = CDDBID
- * pID[1] = number of tracks
- * pID[2..(2+n)] = starting MSF offset of tracks on CD
- * pID will need to have (at least) n+3 entries, where n is the number
- * of tracks on the CD. 102 should always be enough. Note that the lead-out
- * track is included.
- */
- DWORD GetCDDBDiskID( HCDROM hCD, DWORD *pID, int numEntries )
- {
- TOC toc;
- TOCTRACK *t1, *t2;
- int idx = (int)hCD - 1;
- DWORD t;
- DWORD n;
- int i;
- int j;
- BOOL bMSF;
- *pID = 0;
- if ( (idx<0) || (idx>=MAXCDHAND) || !cdHandles[idx].used )
- {
- alErrCode = ALERR_INVHANDLE;
- return SS_ERR;
- }
- if ( WaitForSingleObject( cdMutexes[idx], TIMEOUT ) != WAIT_OBJECT_0 )
- {
- alErrCode = ALERR_LOCK;
- return SS_ERR;
- }
- bMSF = cdHandles[idx].bMSF;
- cdHandles[idx].bMSF = TRUE;
- memset( &toc, 0, sizeof(toc) );
- ReadTOC( hCD, &toc );
- n = t = 0;
- for( j = 2, i = toc.firstTrack - 1; i < toc.lastTrack; i++, j++ )
- {
- t1 = &(toc.tracks[i]);
- pID[j] = (((t1->addr[1]*60)+t1->addr[2])*75)+t1->addr[3];
- n += CDDBSum( 60 * toc.tracks[i].addr[1] + toc.tracks[i].addr[2] );
- }
- t2 = &(toc.tracks[toc.lastTrack-toc.firstTrack+1]);
- t = 60 * t2->addr[1] + t2->addr[2];
- t2 = &(toc.tracks[0]);
- t -= ( 60 * t2->addr[1] + t2->addr[2] );
- pID[toc.lastTrack+2] = t;
- #if 0
- // fudge the total time to generate inexact matches for testing
- t += 2;
- #endif
- pID[1] = toc.lastTrack - toc.firstTrack + 1;
- *pID = ((n%0xFF) << 24) | (t << 8) | (toc.lastTrack - toc.firstTrack + 1);
- cdHandles[idx].bMSF = bMSF;
- n = genCDPlayerIniIndex( hCD );
- addCDPlayerCDDBIndex( n, pID[0], pID[1] );
- ReleaseMutex( cdMutexes[idx] );
- return SS_COMP;
- }
- BOOL InitCache( LPCTSTR lpszDir )
- {
- if ( bCacheInit )
- return FALSE;
- if ( !lpszDir )
- lpszDir = "";
- strncpy( szCacheDir, lpszDir, MAX_PATH+1 );
- bCacheInit = TRUE;
- return TRUE;
- }
- /*
- * Sends an HTTP POST command and waits for a response. The response is
- * copied to retBuf. Uses a proxy. Returns the number of bytes copied to
- * retBuf. Before returning, it should strip the HTTP header from the info
- * if present.
- */
- DWORD CDDBPostCmdProxy( char *cmd, char *retBuf, int retLen )
- {
- WSADATA wsaData;
- SOCKET s;
- struct hostent *h;
- struct sockaddr_in sin;
- int i;
- char *postcmd, *p;
- DWORD retVal = 0;
- p = retBuf;
- ZeroMemory( p, retLen );
- retLen--; // reserve room for the terminating NULL
- WSAStartup( MAKEWORD(1,1), &wsaData );
- s = socket( AF_INET, SOCK_STREAM, 0 );
- h = gethostbyname( szProxyAddr );
- if ( !h )
- {
- #ifdef _DEBUG
- dbprintf( "akrip32: CDDBPostCmdProxy: unable to resolve hostname" );
- #endif
- return 0;
- }
- sin.sin_family = AF_INET;
- sin.sin_port = htons( iProxyPort );
- memcpy( &sin.sin_addr, h->h_addr, h->h_length );
- i = connect( s, (struct sockaddr *)&sin, sizeof(sin) );
- p = postcmd = (char *)GlobalAlloc( GPTR, lstrlen(cmd) + 512 );
- wsprintf( postcmd, "POST http://%s%s HTTP/1.0rnContent-Type: application/x-www-form-urlencodedrnUser-Agent: AKRip090rn", szCDDBServer, szCGI );
- p += lstrlen( postcmd );
- wsprintf( p, "Content-Length: %drnrn", lstrlen( cmd ) + 2 );
- strcat( p, cmd );
- strcat( p, "rn" );
- #if 0
- i = 120;
- i = setsockopt( s, IPPROTO_TCP, SO_SNDTIMEO, &i, sizeof(int) );
- if ( i == SOCKET_ERROR )
- dbprintf( "Error setting rcv timeout on socket" );
- else
- dbprintf( "Receive socket timeout set" );
- #endif
- send( s, postcmd, lstrlen( postcmd ), 0 );
- p = retBuf;
- ZeroMemory( p, retLen );
- i = -1;
- while( (i != 0) && (retLen >= 128) )
- {
- i = recv( s, p, 128, 0 );
- p += i;
- retLen -= i;
- retVal += (DWORD)i;
- if ( i < 0 )
- i = 0;
- }
- closesocket( s );
- GlobalFree( (HGLOBAL)postcmd );
- WSACleanup();
- return retVal;
- }
- /*
- * Sends an HTTP POST command and waits for a response. The response is
- * copied to retBuf. Returns the number of bytes copied to retBuf.
- */
- DWORD CDDBPostCmd( char *cmd, char *retBuf, int retLen )
- {
- WSADATA wsaData;
- SOCKET s;
- struct hostent *h;
- struct sockaddr_in sin;
- int i;
- char *postcmd, *p;
- DWORD retVal = 0;
- p = retBuf;
- ZeroMemory( p, retLen );
- retLen--; // reserve room for the terminating NULL
- WSAStartup( MAKEWORD(1,1), &wsaData );
- s = socket( AF_INET, SOCK_STREAM, 0 );
- h = gethostbyname( szCDDBServer );
- if ( !h )
- return 0;
- sin.sin_family = AF_INET;
- sin.sin_port = htons( iHTTPPort );
- memcpy( &sin.sin_addr, h->h_addr, h->h_length );
- i = connect( s, (struct sockaddr *)&sin, sizeof(sin) );
- p = postcmd = (char *)GlobalAlloc( GPTR, lstrlen(cmd) + 512 );
- wsprintf( p, "GET %s?", szCGI );
- strcat( p, cmd );
- strcat( p, "rn" );
- send( s, postcmd, lstrlen( postcmd ), 0 );
- p = retBuf;
- ZeroMemory( p, retLen );
- i = -1;
- while( (i != 0) && (retLen >= 128) )
- {
- i = recv( s, p, 128, 0 );
- p += i;
- retLen -= i;
- retVal += (DWORD)i;
- if ( i < 0 )
- i = 0;
- }
- closesocket( s );
- GlobalFree( (HGLOBAL)postcmd );
- WSACleanup();
- return retVal;
- }
- /*
- * Queries the CDDB for a given disk.
- * Returns SS_COMP on success, SS_ERR on error. numEntries on entry contains
- * the number of elements in the lpq array, and on return is set to the
- * number of entries returned.
- *
- * If the no items are returned, or if no network connection is available,
- * returns one item with category "cdplayerini" and the index stored in
- * cddbId;
- */
- DWORD CDDBQuery( HCDROM hCD, LPCDDBQUERY lpq )
- {
- //int numRead = 0;
- LPDWORD pdwId;
- char *cmd, *p, *retBuf;
- int i;
- if ( !lpq )
- {
- return SS_ERR;
- }
- pdwId = GlobalAlloc( GPTR, 103 * sizeof(DWORD) );
- cmd = GlobalAlloc( GPTR, 1024 );
- retBuf = GlobalAlloc( GPTR, 2048 );
- if ( !cmd || !pdwId || !retBuf )
- {
- if ( cmd ) GlobalFree( (HGLOBAL)cmd );
- if ( pdwId ) GlobalFree( (HGLOBAL)pdwId );
- if ( retBuf ) GlobalFree( (HGLOBAL)retBuf );
- lpq->num = 0;
- return SS_ERR;
- }
- // Generate the cddb ID for the disc
- if ( GetCDDBDiskID( hCD, pdwId, 102 ) == SS_COMP )
- {
- // Generate a query string
- p = cmd;
- wsprintf( p, "cmd=cddb+query+%08x+%d+", pdwId[0], pdwId[1] );
- p += lstrlen( p );
- for( i = 0; i < pdwId[1]; i++ )
- {
- wsprintf( p, "%d+", pdwId[i+2] );
- p += lstrlen(p);
- }
- wsprintf( p, "%d&hello=%s+%s&proto=3",
- pdwId[pdwId[1]+2], szUser, szAgent );
- urlEncodeString( p );
- // send the query string
- if ( bUseProxy )
- CDDBPostCmdProxy( cmd, retBuf, 2048 );
- else
- CDDBPostCmd( cmd, retBuf, 2048 );
- // process the returned data (if any)
- processCDDBQuery( retBuf, lpq );
- // fall back to cdplayer.ini if no items matched
- if ( (lpq->num == 0) && bUseCDPlayerIni )
- {
- pdwId[0] = genCDPlayerIniIndex( hCD );
- wsprintf( retBuf, "%X", pdwId[0] );
- if ( isCDinCDPlayerIni( retBuf ) )
- {
- wsprintf( lpq->q[0].cddbId, "%X", pdwId[0] );
- lstrcpy( lpq->q[0].categ, "cdplayerini" );
- lpq->q[0].bExact = TRUE;
- lpq->num = 1;
- }
- }
- // else if we have multiple/partial matches from CDDB, we need to
- // associate all of the cddbId values with the cdPlayer.ini index
- else if ( (lpq->num > 1) && bUseCDPlayerIni )
- {
- pdwId[2] = genCDPlayerIniIndex( hCD );
- for( i = 0; i < lpq->num; i++ )
- {
- pdwId[0] = (DWORD)strtoul( lpq->q[i].cddbId, NULL, 16 );
- addCDPlayerCDDBIndex( pdwId[2], pdwId[0], pdwId[1] );
- }
- }
- }
- GlobalFree( (HGLOBAL)pdwId );
- GlobalFree( (HGLOBAL)cmd );
- GlobalFree( (HGLOBAL)retBuf );
- return SS_COMP;
- }
- void CDDBSetOption( int what, char *szVal, int iVal )
- {
- switch( what )
- {
- case CDDB_OPT_PROXY:
- if ( szVal )
- lstrcpyn( szProxyAddr, szVal, 255 );
- szProxyAddr[255] = 0;
- break;
- case CDDB_OPT_SERVER:
- if ( szVal )
- lstrcpyn( szCDDBServer, szVal, 255 );
- szCDDBServer[255] = 0;
- break;
- case CDDB_OPT_CGI:
- if ( szVal )
- lstrcpyn( szCGI, szVal, 80 );
- szCGI[80] = 0;
- break;
- case CDDB_OPT_PROXYPORT:
- iProxyPort = iVal;
- break;
- case CDDB_OPT_AGENT:
- if ( szVal )
- lstrcpyn( szAgent, szVal, 60 );
- szAgent[60] = 0;
- urlEncodeString( szAgent );
- break;
- case CDDB_OPT_USER:
- if ( szVal )
- lstrcpyn( szUser, szVal, 64 );
- szUser[64] = 0;
- urlEncodeString( szUser );
- break;
- case CDDB_OPT_USEPROXY:
- bUseProxy = (BOOL)iVal;
- break;
- case CDDB_OPT_HTTPPORT:
- iHTTPPort = iVal;
- break;
- case CDDB_OPT_USECDPLAYERINI:
- bUseCDPlayerIni = (BOOL)iVal;
- break;
- }
- }
- void urlEncodeString( char *s )
- {
- if ( !s || !*s )
- return;
- while( *++s )
- {
- if ( (*s == '@') || (*s == ' ') )
- *s = '+';
- }
- }
- /*
- * Process the return buffer from a cddb query. Verify that the return code
- * is one that we expect (200, 211, 202, 403, 409).
- */
- void processCDDBQuery( char *buf, LPCDDBQUERY lpq )
- {
- int total = 0;
- int iRetCode, i;
- int maxLines = 100;
- char retCode[4] = "100";
- char linebuf[81];
- char *p = buf;
- FILE *fp;
- fp = fopen( "retbuf.txt", "wb" );
- fwrite( p, 1, lstrlen( p ), fp );
- SkipHTTPHeaders( &p );
- GetLineFromBuf( &p, linebuf, 81 );
- strncpy( retCode, linebuf, 3 );
- iRetCode = atoi( retCode );
- switch( iRetCode )
- {
- case 200:
- // one exact match
- if ( extractCDDBQueryInfo( &lpq->q[0], linebuf+4 ) )
- {
- lpq->q[0].bExact = TRUE;
- total++;
- }
- break;
- case 211:
- // inexact match(es)
- i = 0;
- while ( p && lpq->num && (maxLines-- > 0) )
- {
- GetLineFromBuf( &p, linebuf, 81 );
- if ( !strcmp( linebuf, "." ) )
- break;
- if ( extractCDDBQueryInfo( &lpq->q[i], linebuf ) )
- {
- lpq->q[i].bExact = FALSE;
- total++;
- i++;
- lpq->num--;
- }
- }
- 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, "rn" );
- if ( !s )
- {
- *src += lstrlen( *src );
- return;
- }
- lstrcpyn( tgt, *src, len-1 );
- t = strstr( tgt, "rn" );
- if ( t && ((t - tgt) < len) )
- tgt[t-tgt] = ' ';
- *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] = ' ';
- while ( *p && (*p != '/') && i )
- {
- *t++ = *p++;
- i--;
- }
- i = lstrlen( lpq->artist );
- if ( i > 0 )
- {
- if ( lpq->artist[i-1] == ' ' )
- lpq->artist[i-1] = ' ';
- }
- 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] = ' ';
- }
- return 1;
- }
- void SkipHTTPHeaders( char **buf )
- {
- char *p;
- if ( !buf || !*buf || !**buf )
- return;
- p = *buf;
- if ( strncmp( p, "HTTP", 4 ) )
- {
- return;
- }
- p = strstr( p, "rnrn" );
- 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] = ' ';
- GetPrivateProfileString( lpq->cddbId, "TITLE", "", buf, 256, szCDPlayerIni );
- lstrcpyn( lpq->title, buf, 80 ); lpq->title[80] = ' ';
- p = szCDDBEntry;
- wsprintf( buf, "DTITLE=%s / %srn", 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=%srn", 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 = ' ';
- p2++;
- WritePrivateProfileString( section, p1, p2, szCDPlayerIni );
- }
- }
- }
- }