Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1282 lines
29 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: database.c
  3. *
  4. * This module implements the database routines for the CD Audio app.
  5. * The information is stored in the ini file "cdaudio.ini" which should
  6. * be located in the nt\windows directory.
  7. *
  8. * Warning:
  9. * These functions ARE NOT THREAD safe.
  10. * The functions in this file MUST only be called on the UI thread. Before
  11. * calling any of the functions the CALLER MUST call LockTableOfContents
  12. * for the specified cdrom device.
  13. *
  14. * Author:
  15. * Rick Turner (ricktu) 31-Jan-1992
  16. *
  17. *
  18. * Revision History:
  19. *
  20. * 04-Aug-1992 (ricktu) Incorperated routines from old cdaudio.c,
  21. * and made work w/new child window framework.
  22. *
  23. *
  24. * Copyright (c) 1993 - 1995 Microsoft Corporation. All rights reserved.
  25. \**************************************************************************/
  26. #pragma warning( once : 4201 4214 )
  27. #define NOOLE
  28. #include <windows.h>
  29. #include "resource.h"
  30. #include "cdapi.h"
  31. #include "cdplayer.h"
  32. #include "database.h"
  33. #include "literals.h"
  34. #include <string.h>
  35. #include <stdio.h>
  36. #include <tchar.h>
  37. /* -------------------------------------------------------------------------
  38. ** Private entry points
  39. ** -------------------------------------------------------------------------
  40. */
  41. DWORD
  42. ComputeOldDiscId(
  43. int cdrom
  44. );
  45. BOOL
  46. DeleteEntry(
  47. DWORD Id
  48. );
  49. BOOL
  50. WriteEntry(
  51. int cdrom
  52. );
  53. BOOL
  54. ReadEntry(
  55. int cdrom,
  56. DWORD dwId
  57. );
  58. BOOL
  59. ReadMusicBoxEntry(
  60. int cdrom,
  61. DWORD dwId
  62. );
  63. /*****************************Private*Routine******************************\
  64. * ComputeOldDiscId
  65. *
  66. * This routine computes a unique ID based on the information
  67. * in the table of contexts a given disc.
  68. *
  69. *
  70. * History:
  71. * 18-11-93 - ricktu - Created
  72. *
  73. \**************************************************************************/
  74. DWORD
  75. ComputeOldDiscId(
  76. int cdrom
  77. )
  78. {
  79. int NumTracks,i;
  80. DWORD DiscId = 0;
  81. NumTracks = g_Devices[ cdrom ]->toc.LastTrack -
  82. g_Devices[ cdrom ]->toc.FirstTrack;
  83. for ( i = 0; i < NumTracks; i++ ) {
  84. DiscId += ( (TRACK_M(cdrom,i) << 16) +
  85. (TRACK_S(cdrom,i) << 8) +
  86. TRACK_F(cdrom,i) );
  87. }
  88. return DiscId;
  89. }
  90. /******************************Public*Routine******************************\
  91. * ComputeNewDiscId
  92. *
  93. * Just call mci to get the product ID.
  94. *
  95. * History:
  96. * dd-mm-94 - StephenE - Created
  97. *
  98. \**************************************************************************/
  99. DWORD
  100. ComputeNewDiscId(
  101. int cdrom
  102. )
  103. {
  104. #ifdef USE_IOCTLS
  105. return ComputeOrgDiscId( cdrom );
  106. #else
  107. MCI_INFO_PARMS mciInfo;
  108. TCHAR szBuffer[32];
  109. DWORD dwRet;
  110. mciInfo.lpstrReturn = szBuffer;
  111. mciInfo.dwRetSize = sizeof(szBuffer)/sizeof(TCHAR);
  112. dwRet = mciSendCommand( g_Devices[cdrom]->hCd, MCI_INFO,
  113. MCI_INFO_MEDIA_IDENTITY,
  114. (DWORD)(LPVOID)&mciInfo );
  115. if ( dwRet != MMSYSERR_NOERROR ) {
  116. return 0L;
  117. }
  118. _stscanf(szBuffer, TEXT("%ld"), &dwRet );
  119. return dwRet;
  120. #endif
  121. }
  122. /*****************************Private*Routine******************************\
  123. * ComputeOrgDiscId
  124. *
  125. * This routine computes a unique ID based on the information
  126. * in the table of contexts a given disc. This is done by taking
  127. * the TMSF value for each track and XOR'ing it with the previous
  128. * quantity shifted left one bit.
  129. *
  130. *
  131. * History:
  132. * 18-11-93 - ricktu - Created
  133. *
  134. \**************************************************************************/
  135. DWORD
  136. ComputeOrgDiscId(
  137. int cdrom
  138. )
  139. {
  140. int NumTracks,i;
  141. DWORD DiscId = 0;
  142. NumTracks = g_Devices[ cdrom ]->toc.LastTrack -
  143. g_Devices[ cdrom ]->toc.FirstTrack + 1;
  144. for ( i = 0; i < NumTracks; i++ ) {
  145. DiscId = (DiscId << 1) ^
  146. ((i<<24) +
  147. (TRACK_M(cdrom,i) << 16) +
  148. (TRACK_S(cdrom,i) << 8) +
  149. TRACK_F(cdrom,i) );
  150. }
  151. return DiscId;
  152. }
  153. /*****************************Private*Routine******************************\
  154. * ErasePlayList
  155. *
  156. * Erases the current play list. This includes freeing the memory
  157. * for the nodes in the play list, and resetting the current track
  158. * pointer to NULL.
  159. *
  160. *
  161. * History:
  162. * 18-11-93 - ricktu - Created
  163. *
  164. \**************************************************************************/
  165. VOID
  166. ErasePlayList(
  167. int cdrom
  168. )
  169. {
  170. PTRACK_PLAY temp, temp1;
  171. //
  172. // Free memory for each track in play list
  173. //
  174. temp = PLAYLIST( cdrom );
  175. while (temp!=NULL) {
  176. temp1 = temp->nextplay;
  177. LocalFree( (HLOCAL)temp );
  178. temp = temp1;
  179. }
  180. //
  181. // Reset pointers
  182. //
  183. PLAYLIST( cdrom ) = NULL;
  184. CURRTRACK( cdrom ) = NULL;
  185. }
  186. /******************************Public*Routine******************************\
  187. * EraseSaveList
  188. *
  189. * Erases the current save list. This includes freeing the memory
  190. * for the nodes in the save list.
  191. *
  192. *
  193. * History:
  194. * 18-11-93 - ricktu - Created
  195. *
  196. \**************************************************************************/
  197. VOID
  198. EraseSaveList(
  199. int cdrom
  200. )
  201. {
  202. PTRACK_PLAY temp, temp1;
  203. //
  204. // Free memory for each track in play list
  205. //
  206. temp = SAVELIST( cdrom );
  207. while ( temp != NULL ) {
  208. temp1 = temp->nextplay;
  209. LocalFree( (HLOCAL)temp );
  210. temp = temp1;
  211. }
  212. //
  213. // Reset pointers
  214. //
  215. SAVELIST( cdrom ) = NULL;
  216. }
  217. /*****************************Private*Routine******************************\
  218. * EraseTrackList
  219. *
  220. * Erases the current track list. This includes freeing the memory
  221. * for the nodes in the track list, and resetting the track list
  222. * pointer to NULL.
  223. *
  224. *
  225. * History:
  226. * 18-11-93 - ricktu - Created
  227. *
  228. \**************************************************************************/
  229. VOID
  230. EraseTrackList(
  231. int cdrom
  232. )
  233. {
  234. PTRACK_INF temp, temp1;
  235. //
  236. // Free memory for each track in track list
  237. //
  238. temp = ALLTRACKS( cdrom );
  239. while ( temp != NULL ) {
  240. temp1 = temp->next;
  241. LocalFree( (HLOCAL)temp );
  242. temp = temp1;
  243. }
  244. //
  245. // Reset pointers
  246. //
  247. ALLTRACKS( cdrom ) = NULL;
  248. }
  249. /******************************Public*Routine******************************\
  250. * CopyPlayList
  251. *
  252. * Returns a copy of the playlist pointed to by p.
  253. *
  254. *
  255. * History:
  256. * 18-11-93 - ricktu - Created
  257. *
  258. \**************************************************************************/
  259. PTRACK_PLAY
  260. CopyPlayList(
  261. PTRACK_PLAY p
  262. )
  263. {
  264. PTRACK_PLAY t,t1,tend,tret;
  265. tret = tend = NULL;
  266. //
  267. // Duplicate list pointed to by p.
  268. //
  269. t = p;
  270. while( t!=NULL ) {
  271. t1 = (PTRACK_PLAY)AllocMemory( sizeof(TRACK_PLAY) );
  272. t1->TocIndex = t->TocIndex;
  273. t1->min = t->min;
  274. t1->sec = t->sec;
  275. t1->nextplay = NULL;
  276. t1->prevplay = tend;
  277. if (tret==NULL) {
  278. tret = tend = t1;
  279. }
  280. else {
  281. tend->nextplay = t1;
  282. tend = t1;
  283. }
  284. t = t->nextplay;
  285. }
  286. return(tret);
  287. }
  288. /*****************************Private*Routine******************************\
  289. * ResetPlayList
  290. *
  291. * Resets play order for the disc. Used to initialize/reset
  292. * the play list. This is done by reseting the doubly-linked list
  293. * of tracks in the g_Devices[...]->CdInfo.PlayList.[prevplay,nextplay]
  294. * pointers. All the tracks on the CD are stored in a singly linked list
  295. * pointed to by g_Devices[...]->CdInfo.AllTracks pointer.
  296. *
  297. *
  298. * History:
  299. * 18-11-93 - ricktu - Created
  300. *
  301. \**************************************************************************/
  302. VOID
  303. ResetPlayList(
  304. int cdrom
  305. )
  306. {
  307. PTRACK_INF t;
  308. PTRACK_PLAY temp, prev;
  309. //
  310. // Kill old play list
  311. //
  312. ErasePlayList( cdrom );
  313. EraseSaveList( cdrom );
  314. //
  315. // Duplicate each node in AllTracks and insert in-order
  316. // in SaveList list. The SaveList is the master which is
  317. // used for the playlist.
  318. //
  319. t = ALLTRACKS( cdrom );
  320. prev = NULL;
  321. while (t!=NULL) {
  322. temp = (PTRACK_PLAY)AllocMemory( sizeof(TRACK_PLAY) );
  323. temp->TocIndex = t->TocIndex;
  324. temp->min = 0;
  325. temp->sec = 0;
  326. temp->prevplay = prev;
  327. temp->nextplay = NULL;
  328. if (prev!=NULL) {
  329. prev->nextplay = temp;
  330. }
  331. else {
  332. SAVELIST( cdrom ) = temp;
  333. }
  334. prev = temp;
  335. t=t->next;
  336. }
  337. PLAYLIST( cdrom ) = CopyPlayList( SAVELIST( cdrom) );
  338. }
  339. /*****************************Private*Routine******************************\
  340. * DeleteEntry
  341. *
  342. * The ID format has changed to make the id's for the different CD's
  343. * more unique. This routine will completely delete the old key value
  344. * from the ini file. We remove it by writing a NULL entry.
  345. *
  346. *
  347. * History:
  348. * 18-11-93 - ricktu - Created
  349. *
  350. \**************************************************************************/
  351. BOOL
  352. DeleteEntry(
  353. DWORD Id
  354. )
  355. {
  356. TCHAR Section[80];
  357. wsprintf( Section, g_szSectionF, Id );
  358. return WritePrivateProfileSection( Section, g_szEmpty, g_IniFileName );
  359. }
  360. /*****************************Private*Routine******************************\
  361. * WriteEntry
  362. *
  363. * Write current disc information into database ini file.
  364. * The section for the current disc (section name is a hex
  365. * value of the disc id) is completely rewritten.
  366. *
  367. * This function uses 64K of stack !!
  368. *
  369. * History:
  370. * 18-11-93 - ricktu - Created
  371. *
  372. \**************************************************************************/
  373. BOOL
  374. WriteEntry(
  375. int cdrom
  376. )
  377. {
  378. TCHAR *Buffer;
  379. LPTSTR s;
  380. int i;
  381. TCHAR Section[ 10 ];
  382. PTRACK_INF temp;
  383. PTRACK_PLAY temp1;
  384. BOOL fRc;
  385. //
  386. // Construct ini file buffer, form of:
  387. //
  388. // artist = artist name
  389. // title = Title of disc
  390. // numtracks = n
  391. // 0 = Title of track 1
  392. // 1 = Title of track 2
  393. // n-1 = Title of track n
  394. // order = 0 4 3 2 6 7 8 ... (n-1)
  395. // numplay = # of entries in order list
  396. //
  397. //
  398. // Is it legal to save this information?
  399. //
  400. if (!g_Devices[ cdrom ]->CdInfo.save)
  401. return( TRUE );
  402. Buffer = AllocMemory( 64000 * sizeof(TCHAR) );
  403. // note: if the memory allocation fails, AllocMemory will terminate
  404. // the application
  405. g_Devices[ cdrom ]->CdInfo.IsVirginCd = FALSE;
  406. s = Buffer;
  407. s += 1 + wsprintf( s, g_szEntryTypeF, 1 );
  408. s += 1 + wsprintf( s, g_szArtistF, g_Devices[ cdrom ]->CdInfo.Artist );
  409. s += 1 + wsprintf( s, g_szTitleF, g_Devices[ cdrom ]->CdInfo.Title );
  410. s += 1 + wsprintf( s, g_szNumTracksF, g_Devices[ cdrom ]->CdInfo.NumTracks );
  411. for ( temp = g_Devices[ cdrom ]->CdInfo.AllTracks;
  412. temp!=NULL; temp = temp->next ) {
  413. s += 1 + wsprintf( s, TEXT("%d=%s"), temp->TocIndex, temp->name );
  414. }
  415. s += wsprintf( s, g_szOrderF );
  416. i = 0;
  417. for ( temp1 = g_Devices[ cdrom ]->CdInfo.SaveList;
  418. temp1!=NULL; temp1 = temp1->nextplay ) {
  419. s += wsprintf( s, TEXT("%d "), temp1->TocIndex );
  420. i++;
  421. }
  422. s += 1;
  423. s += 1 + wsprintf( s, g_szNumPlayF, i );
  424. //
  425. // Just make sure there are NULLs at end of buffer
  426. //
  427. wsprintf( s, g_szThreeNulls );
  428. wsprintf( Section, g_szSectionF, g_Devices[ cdrom ]->CdInfo.Id );
  429. //
  430. // Try writing buffer into ini file
  431. //
  432. fRc = WritePrivateProfileSection( Section, Buffer, g_IniFileName );
  433. LocalFree( (HLOCAL)Buffer );
  434. return fRc;
  435. }
  436. /******************************Public*Routine******************************\
  437. * ReadMusicBoxEntry
  438. *
  439. * Try to parse the music box database ini file looking for the given disk
  440. * id.
  441. *
  442. * History:
  443. * dd-mm-94 - StephenE - Created
  444. *
  445. \**************************************************************************/
  446. BOOL
  447. ReadMusicBoxEntry(
  448. int cdrom,
  449. DWORD dwId
  450. )
  451. {
  452. TCHAR Section[32];
  453. TCHAR s[TITLE_LENGTH];
  454. int i;
  455. PTRACK_INF temp, curr;
  456. g_Devices[ cdrom ]->CdInfo.iFrameOffset = NEW_FRAMEOFFSET;
  457. //
  458. // Try to read in section from ini file. Note that music box stores
  459. // the key in decimal NOT hex.
  460. //
  461. wsprintf( Section, TEXT("%ld"), dwId );
  462. GetPrivateProfileString( Section, g_szDiscTitle, g_szNothingThere,
  463. g_Devices[ cdrom ]->CdInfo.Title,
  464. TITLE_LENGTH, g_szMusicBoxIni );
  465. //
  466. // Was the section found?
  467. //
  468. if ( _tcscmp(g_Devices[ cdrom ]->CdInfo.Title, g_szNothingThere) == 0 ) {
  469. //
  470. // Nope, notify caller
  471. //
  472. return FALSE;
  473. }
  474. /*
  475. ** Now read the track information. Also the artists name is unknown.
  476. */
  477. _tcscpy( ARTIST(cdrom), IdStr(STR_UNKNOWN) );
  478. NUMTRACKS(cdrom) = LASTTRACK(cdrom) - FIRSTTRACK(cdrom) + 1;
  479. // Make sure there is at least one track!!!
  480. if (0 == NUMTRACKS(cdrom)) {
  481. return FALSE;
  482. }
  483. for ( i = 0, curr = NULL; i < NUMTRACKS(cdrom); i++ ) {
  484. wsprintf( s, g_szMusicBoxFormat, i + 1 );
  485. temp = (PTRACK_INF)AllocMemory( sizeof(TRACK_INF) );
  486. GetPrivateProfileString( Section, s, s, temp->name,
  487. TRACK_TITLE_LENGTH, g_szMusicBoxIni );
  488. temp->TocIndex = i;
  489. temp->next = NULL;
  490. if ( curr == NULL ) {
  491. ALLTRACKS( cdrom ) = curr = temp;
  492. }
  493. else {
  494. curr->next = temp;
  495. curr = temp;
  496. }
  497. }
  498. // Make sure there is at least one track in Default playlist!!!
  499. if (NULL == ALLTRACKS(cdrom)) {
  500. return FALSE;
  501. }
  502. _tcscpy( ARTIST(cdrom), IdStr(STR_UNKNOWN) );
  503. /*
  504. ** Process the play list
  505. */
  506. GetPrivateProfileString( Section, g_szPlayList, g_szNothingThere,
  507. s, TITLE_LENGTH, g_szMusicBoxIni );
  508. /*
  509. ** Was the section found?
  510. */
  511. if ( _tcscmp(g_Devices[ cdrom ]->CdInfo.Title, g_szNothingThere) == 0 ) {
  512. /*
  513. ** Nope, just use the default playlist.
  514. */
  515. ResetPlayList( cdrom );
  516. }
  517. else {
  518. LPTSTR lpPlayList, porder;
  519. PTRACK_PLAY temp1, prev;
  520. int i;
  521. const PLAYLEN = 8192;
  522. lpPlayList = AllocMemory( sizeof(TCHAR) * PLAYLEN );
  523. GetPrivateProfileString( Section, g_szPlayList, g_szNothingThere,
  524. lpPlayList, PLAYLEN, g_szMusicBoxIni );
  525. _tcscat( lpPlayList, g_szBlank );
  526. porder = lpPlayList;
  527. prev = NULL;
  528. while ( *porder && (_stscanf( porder, TEXT("%d"), &i ) == 1) ) {
  529. i--;
  530. /*
  531. ** Assert that i is a valid index.
  532. ** ie 0 <= i <= (NUMTRACKS(cdrom) - 1)
  533. */
  534. i = min( (NUMTRACKS(cdrom) - 1), max( 0, i ) );
  535. temp1 = (PTRACK_PLAY)AllocMemory( sizeof(TRACK_PLAY) );
  536. temp1->TocIndex = i;
  537. temp1->min = 0;
  538. temp1->sec = 0;
  539. temp1->prevplay = prev;
  540. temp1->nextplay = NULL;
  541. if (prev == NULL) {
  542. SAVELIST( cdrom ) = temp1;
  543. }
  544. else {
  545. prev->nextplay = temp1;
  546. }
  547. prev = temp1;
  548. porder = _tcschr( porder, TEXT(' ') ) + 1;
  549. }
  550. // Make sure there is at least one track in SAVED playlist!!!
  551. if (NULL == SAVELIST(cdrom)) {
  552. // Nope, just use the default playlist instead!!!
  553. ResetPlayList( cdrom );
  554. }
  555. PLAYLIST( cdrom ) = CopyPlayList( SAVELIST( cdrom ) );
  556. LocalFree( (HLOCAL)lpPlayList );
  557. }
  558. return TRUE;
  559. }
  560. /*****************************Private*Routine******************************\
  561. * ReadEntry
  562. *
  563. * Try to read entry for new disc from database ini file.
  564. * The section name we are trying to read is a hex
  565. * value of the disc id. If the sections is found,
  566. * fill in the data for the disc in the cdrom drive.
  567. *
  568. * This function uses over 16K of stack space !!
  569. *
  570. * History:
  571. * 18-11-93 - ricktu - Created
  572. *
  573. \**************************************************************************/
  574. BOOL
  575. ReadEntry(
  576. int cdrom,
  577. DWORD dwId
  578. )
  579. {
  580. DWORD rc;
  581. TCHAR Section[10];
  582. TCHAR s[100],s1[100];
  583. TCHAR order[ 8192 ];
  584. TCHAR torder[ 8192 ];
  585. int i;
  586. LPTSTR porder;
  587. int numtracks, numplay;
  588. PTRACK_INF temp, curr;
  589. PTRACK_PLAY temp1, prev;
  590. BOOL OldEntry;
  591. BOOL fRewriteEntry = FALSE;
  592. g_Devices[ cdrom ]->CdInfo.iFrameOffset = NEW_FRAMEOFFSET;
  593. //
  594. // Try to read in section from ini file
  595. //
  596. wsprintf( Section, g_szSectionF, dwId );
  597. rc = GetPrivateProfileString( Section, g_szTitle, g_szNothingThere,
  598. g_Devices[ cdrom ]->CdInfo.Title,
  599. TITLE_LENGTH, g_IniFileName );
  600. //
  601. // Was the section found?
  602. //
  603. if ( _tcscmp(g_Devices[ cdrom ]->CdInfo.Title, g_szNothingThere) == 0 ) {
  604. //
  605. // Nope, notify caller
  606. //
  607. return( FALSE );
  608. }
  609. //
  610. // We found an entry for this disc, so copy all the information
  611. // from the ini file entry
  612. //
  613. // Is this an old entry?
  614. //
  615. i = GetPrivateProfileInt( Section, g_szEntryType, 0, g_IniFileName );
  616. OldEntry = (i==0);
  617. numtracks = GetPrivateProfileInt( Section, g_szNumTracks,
  618. 0, g_IniFileName );
  619. // Make sure there is at least one track!!!
  620. if (0 == numtracks) {
  621. fRewriteEntry = TRUE;
  622. }
  623. g_Devices[ cdrom ]->CdInfo.NumTracks = numtracks;
  624. rc = GetPrivateProfileString( Section, g_szArtist, g_szUnknownTxt,
  625. (LPTSTR)ARTIST(cdrom), ARTIST_LENGTH,
  626. g_IniFileName );
  627. //
  628. // Validate the stored track numbers
  629. //
  630. if (g_Devices[cdrom]->fIsTocValid) {
  631. int maxTracks; // validate the high point in ini file
  632. maxTracks = g_Devices[cdrom]->toc.LastTrack;
  633. if (numtracks > maxTracks) {
  634. // Current ini file contains invalid data
  635. // this can result in the CD not playing at all as the end
  636. // point is likely to be invalid
  637. g_Devices[ cdrom ]->CdInfo.NumTracks
  638. = numtracks
  639. = maxTracks;
  640. fRewriteEntry = TRUE;
  641. }
  642. }
  643. //
  644. // Read the track list information
  645. //
  646. for (i=0, curr = NULL; i < numtracks; i++) {
  647. temp = (PTRACK_INF)AllocMemory( sizeof(TRACK_INF) );
  648. temp->TocIndex = i;
  649. temp->next = NULL;
  650. wsprintf( s1, IdStr(STR_INIT_TRACK), i + 1 );
  651. wsprintf( s, TEXT("%d"), i );
  652. rc = GetPrivateProfileString( Section, s, s1, (LPTSTR)temp->name,
  653. TRACK_TITLE_LENGTH, g_IniFileName );
  654. if (curr==NULL) {
  655. ALLTRACKS( cdrom ) = curr = temp;
  656. } else {
  657. curr->next = temp;
  658. curr = temp;
  659. }
  660. }
  661. // Make sure there is at least one entry in TRACK list
  662. if (ALLTRACKS(cdrom) == NULL)
  663. {
  664. fRewriteEntry = TRUE;
  665. }
  666. //
  667. // if we detected a problem in the ini file, or the entry is an
  668. // old format, rewrite the section.
  669. //
  670. if (OldEntry || fRewriteEntry) {
  671. //
  672. // Generate generic play list (all tracks in order)
  673. //
  674. ResetPlayList( cdrom );
  675. //
  676. // Need to rewrite this entry in new format
  677. //
  678. WriteEntry( cdrom );
  679. }
  680. else {
  681. //
  682. // Read play list (order) information and construct play list doubly
  683. // linked list
  684. //
  685. numplay = GetPrivateProfileInt( Section, g_szNumPlay,
  686. 0, g_IniFileName );
  687. porder = torder;
  688. ZeroMemory( porder, sizeof(torder) );
  689. //
  690. // construct a default play order list
  691. //
  692. for ( i = 0; i < numtracks; i++ ) {
  693. wsprintf( porder, TEXT("%d "), i );
  694. /* porder += (_tcslen( porder ) * sizeof( TCHAR )); */
  695. porder += _tcslen( porder );
  696. }
  697. rc = GetPrivateProfileString( Section, g_szOrder,
  698. torder, (LPTSTR)order, 8192,
  699. g_IniFileName );
  700. //
  701. // Ensure a trailing space
  702. //
  703. _tcscat( order, g_szBlank );
  704. porder = order;
  705. prev = NULL;
  706. while ( *porder && (_stscanf( porder, TEXT("%d"), &i ) == 1) ) {
  707. /*
  708. ** Assert that i is a valid index.
  709. ** ie 0 <= i <= (numtracks - 1)
  710. */
  711. i = min( (numtracks - 1), max( 0, i ) );
  712. temp1 = (PTRACK_PLAY)AllocMemory( sizeof(TRACK_PLAY) );
  713. temp1->TocIndex = i;
  714. temp1->min = 0;
  715. temp1->sec = 0;
  716. temp1->prevplay = prev;
  717. temp1->nextplay = NULL;
  718. if (prev==NULL) {
  719. SAVELIST( cdrom ) = temp1;
  720. } else {
  721. prev->nextplay = temp1;
  722. }
  723. prev = temp1;
  724. porder = _tcschr( porder, g_chBlank ) + 1;
  725. }
  726. // Make sure there is at least one entry in SAVED list
  727. if (SAVELIST(cdrom) == NULL)
  728. {
  729. // Nope, use default list instead
  730. ResetPlayList( cdrom );
  731. WriteEntry( cdrom );
  732. }
  733. PLAYLIST( cdrom ) = CopyPlayList( SAVELIST( cdrom ) );
  734. }
  735. return TRUE;
  736. }
  737. /******************************Public*Routine******************************\
  738. * WriteSettings
  739. *
  740. *
  741. *
  742. * History:
  743. * 18-11-93 - ricktu - Created
  744. *
  745. \**************************************************************************/
  746. BOOL
  747. WriteSettings(
  748. VOID
  749. )
  750. {
  751. WINDOWPLACEMENT wndpl;
  752. HKEY hKey;
  753. LONG lRet;
  754. DWORD dwTmp;
  755. extern BOOL g_fTitlebarShowing; //cdplayer.c
  756. extern int cyMenuCaption; //cdplayer.c
  757. lRet = RegCreateKey( HKEY_CURRENT_USER, g_szRegistryKey, &hKey );
  758. if ( lRet != ERROR_SUCCESS) {
  759. return FALSE;
  760. }
  761. // Save settings on exit
  762. dwTmp = (DWORD)g_fSaveOnExit;
  763. RegSetValueEx( hKey, g_szSaveSettingsOnExit, 0L, REG_DWORD,
  764. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  765. if ( !g_fSaveOnExit ) {
  766. RegCloseKey( hKey );
  767. return TRUE;
  768. }
  769. // Small LED font
  770. dwTmp = (DWORD)g_fSmallLedFont;
  771. RegSetValueEx( hKey, g_szSmallFont, 0L, REG_DWORD,
  772. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  773. // Enable Tooltips
  774. dwTmp = (DWORD)g_fToolTips;
  775. RegSetValueEx( hKey, g_szToolTips, 0L, REG_DWORD,
  776. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  777. // Stop CD playing on exit
  778. dwTmp = (DWORD)g_fStopCDOnExit;
  779. RegSetValueEx( hKey, g_szStopCDPlayingOnExit, 0L, REG_DWORD,
  780. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  781. // Currect track time
  782. dwTmp = (DWORD)g_fDisplayT;
  783. RegSetValueEx( hKey, g_szDisplayT, 0L, REG_DWORD,
  784. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  785. // Time remaining for this track
  786. dwTmp = (DWORD)g_fDisplayTr;
  787. RegSetValueEx( hKey, g_szDisplayTr, 0L, REG_DWORD,
  788. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  789. // Time remaining for this play list
  790. dwTmp = (DWORD)g_fDisplayDr;
  791. RegSetValueEx( hKey, g_szDisplayDr, 0L, REG_DWORD,
  792. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  793. // Play in selected order
  794. dwTmp = (DWORD)g_fSelectedOrder;
  795. RegSetValueEx( hKey, g_szInOrderPlay, 0L, REG_DWORD,
  796. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  797. // Use single disk
  798. dwTmp = (DWORD)!g_fSingleDisk;
  799. RegSetValueEx( hKey, g_szMultiDiscPlay, 0L, REG_DWORD,
  800. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  801. // Intro play ( Default 10Secs)
  802. dwTmp = (DWORD)g_fIntroPlay;
  803. RegSetValueEx( hKey, g_szIntroPlay, 0L, REG_DWORD,
  804. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  805. dwTmp = (DWORD)g_IntroPlayLength;
  806. RegSetValueEx( hKey, g_szIntroPlayLen, 0L, REG_DWORD,
  807. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  808. // Continuous play (loop at end)
  809. dwTmp = (DWORD)g_fContinuous;
  810. RegSetValueEx( hKey, g_szContinuousPlay, 0L, REG_DWORD,
  811. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  812. // Show toolbar
  813. dwTmp = (DWORD)g_fToolbarVisible;
  814. RegSetValueEx( hKey, g_szToolbar, 0L, REG_DWORD,
  815. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  816. // Show track information
  817. dwTmp = (DWORD)g_fTrackInfoVisible;
  818. RegSetValueEx( hKey, g_szDiscAndTrackDisplay, 0L, REG_DWORD,
  819. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  820. // Show track status bar
  821. dwTmp = (DWORD)g_fStatusbarVisible;
  822. RegSetValueEx( hKey, g_szStatusBar, 0L, REG_DWORD,
  823. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  824. // Save window position.
  825. wndpl.length = sizeof(WINDOWPLACEMENT);
  826. GetWindowPlacement(g_hwndApp,&wndpl);
  827. if (!g_fTitlebarShowing) {
  828. wndpl.rcNormalPosition.top -= cyMenuCaption;
  829. }
  830. // X pos
  831. dwTmp = (DWORD)wndpl.rcNormalPosition.left;
  832. RegSetValueEx( hKey, g_szWindowOriginX, 0L, REG_DWORD,
  833. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  834. // Y pos
  835. dwTmp = (DWORD)wndpl.rcNormalPosition.top;
  836. RegSetValueEx( hKey, g_szWindowOriginY, 0L, REG_DWORD,
  837. (LPBYTE)&dwTmp, sizeof(dwTmp) );
  838. RegCloseKey( hKey );
  839. return TRUE;
  840. }
  841. /******************************Public*Routine******************************\
  842. * AddFindEntry
  843. *
  844. * Search the database file for the current disc, if found, read the
  845. * information, otherwise, generate some default artist and track names etc.
  846. * but don't store this in the database. A new entry is only added to the
  847. * database after the user has used the "Edit Track Titles" dialog box.
  848. *
  849. * The design of this function is complicated by the fact that we have to
  850. * support two previous attempts at generating CDplayer keys. Also, we try
  851. * to support the MusicBox key format now that it is compatible with the
  852. * new CDplayer format.
  853. *
  854. *
  855. * History:
  856. * 18-11-93 - ricktu - Created
  857. *
  858. \**************************************************************************/
  859. VOID
  860. AddFindEntry(
  861. int cdrom,
  862. DWORD key,
  863. PCDROM_TOC lpTOC
  864. )
  865. {
  866. int i, num;
  867. PTRACK_INF temp, temp1;
  868. /*
  869. ** Kill off old PlayList, Save lists if they exists.
  870. */
  871. ErasePlayList( cdrom );
  872. EraseSaveList( cdrom );
  873. EraseTrackList( cdrom );
  874. /*
  875. ** Check ini file for an existing entry
  876. **
  877. ** First Look in cdplayer.ini using the new key, return if found
  878. */
  879. // We initialize this field early, otherwise ReadEntry will not be
  880. // able to save any new information (or lose invalid).
  881. g_Devices[ cdrom ]->CdInfo.save = TRUE;
  882. if ( ReadEntry(cdrom, key) ) {
  883. return;
  884. }
  885. /*
  886. ** Initialize these fields
  887. */
  888. g_Devices[ cdrom ]->CdInfo.IsVirginCd = FALSE;
  889. g_Devices[ cdrom ]->CdInfo.Id = key;
  890. /*
  891. ** Look again in cdplayer.ini. This time use the original cdplayer key.
  892. ** If we found the original key in cdplayer.ini write the new key into
  893. ** cdplayer.ini and then return
  894. */
  895. if ( ReadEntry(cdrom, ComputeOrgDiscId(cdrom)) ) {
  896. /*
  897. ** If the disc was under an Original id, we need to delete the
  898. ** old one, convert it to the new format, and save it under
  899. ** its new key.
  900. */
  901. DeleteEntry( ComputeOrgDiscId(cdrom) );
  902. WriteEntry( cdrom );
  903. }
  904. /*
  905. ** Final look in cdplayer.ini. This time use the OLD cdplayer key.
  906. ** If we found the OLD key in cdplayer.ini write the new key into
  907. ** cdplayer.ini and then return
  908. */
  909. else if ( ReadEntry(cdrom, ComputeOldDiscId(cdrom)) ) {
  910. /*
  911. ** If the disc was under an OLD id, we need to delete the
  912. ** old one, convert it to the new format, and save it under
  913. ** its new key.
  914. */
  915. DeleteEntry( ComputeOldDiscId(cdrom) );
  916. WriteEntry( cdrom );
  917. }
  918. /*
  919. ** Couldn't find it in cdplayer.ini, now look for the key in musicbox.ini
  920. ** If we found the key in musicbox.ini write it into cdplayer.ini and
  921. ** then return
  922. */
  923. else if ( ReadMusicBoxEntry(cdrom, key) ) {
  924. WriteEntry( cdrom );
  925. }
  926. /*
  927. ** This is a new entry, fill it in but don't store it in the database.
  928. */
  929. else {
  930. g_Devices[ cdrom ]->CdInfo.IsVirginCd = TRUE;
  931. wsprintf( (LPTSTR)ARTIST( cdrom ), IdStr( STR_NEW_ARTIST ) );
  932. wsprintf( (LPTSTR)TITLE( cdrom ), IdStr( STR_NEW_TITLE ) );
  933. NUMTRACKS( cdrom ) = num = lpTOC->LastTrack - lpTOC->FirstTrack + 1;
  934. /*
  935. ** Create generic playlist, which is all audio tracks
  936. ** played in the order they are on the CD. First, create
  937. ** a singly linked list that contains all the tracks.
  938. ** Then, create a double linked list, using the nodes of
  939. ** from the single linked list for the play list.
  940. */
  941. for( i = 0; i < num; i++ ) {
  942. /*
  943. ** Create storage for track
  944. */
  945. temp = (PTRACK_INF)AllocMemory( sizeof(TRACK_INF) );
  946. /*
  947. ** Initialize information (storage already ZERO initialized)
  948. */
  949. wsprintf( (LPTSTR)temp->name, IdStr( STR_INIT_TRACK ), i+1 );
  950. temp->TocIndex = i;
  951. temp->next = NULL;
  952. /*
  953. ** Add node to singly linked list of all tracks
  954. */
  955. if (i == 0) {
  956. temp1 = ALLTRACKS( cdrom ) = temp;
  957. }
  958. else {
  959. temp1->next = temp;
  960. temp1 = temp;
  961. }
  962. }
  963. /*
  964. ** Generate generic play list (all tracks in order)
  965. */
  966. ResetPlayList( cdrom );
  967. }
  968. }