home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / warptlk3.zip / TOOLKIT / SAMPLES / MM / CDMCIDRV / IBMCDROM.C < prev    next >
C/C++ Source or Header  |  1995-08-24  |  45KB  |  919 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /* SOURCE FILE NAME:  IBMCDROM.C                                            */
  4. /*                                                                          */
  5. /* DESCRIPTIVE NAME:  IBM CD-ROMs                                           */
  6. /*                                                                          */
  7. /* COPYRIGHT:  (c) IBM Corp. 1990 - 1993                                    */
  8. /*                                                                          */
  9. /* FUNCTION:  This file contains the device dependent code for the CD Audio */
  10. /*            Vendor Specific Driver (VSD).  This file is called by the     */
  11. /*            general CD Audio MCI Driver, CDAUDIO.DLL or CDAUDIOT.DLL      */
  12. /*                                                                          */
  13. /* NOTES:  The hardware independent code is found in file CDAUDIO.C.  As    */
  14. /*         more and more CD ROM drives are supported, hardware dependent    */
  15. /*         files can be made into DLLs and register be registered in the    */
  16. /*         MMPM2.INI file upon installation to be recognized.               */
  17. /*                                                                          */
  18. /* ENTRY POINTS:                                                            */
  19. /*       vsdDriverEntry     - entry point to the VSD                        */
  20. /*                                                                          */
  21. /*                                                                          */
  22. /* OTHER FUNCTIONS:                                                         */
  23. /*       process_msg        - Process the requested command message.        */
  24. /*       CDAudErrRecov      - Error recovery routine.                       */
  25. /*       CDAudClose         - Close an instance.                            */
  26. /*       CDAudInfo          - Returns information about the component.      */
  27. /*       CDAudOpen          - Open an instance.                             */
  28. /*       CDAudRegDisc       - Register a disc for the multimedia component. */
  29. /*       CDAudRegDrive      - Register a drive for the multimedia component.*/
  30. /*       CDAudSet           - Set various attributes of the device.         */
  31. /*       CDAudSetVerify     - Tests flags for the set command.              */
  32. /*       CDAudStatus        - Returns the requested attribute.              */
  33. /*       CDAudStatCVol      - Returns mapped volume levels for volume given.*/
  34. /*                                                                          */
  35. /*                                                                          */
  36. /****************************************************************************/
  37.  
  38. #define INCL_DOSERRORS
  39. #define INCL_DOSDEVICES
  40. #define INCL_DOSPROCESS
  41. #define INCL_DOSFILEMGR
  42. #define INCL_DOSSEMAPHORES
  43. #include <os2.h>
  44. #include <string.h>
  45. #include <stdlib.h>
  46. #define INCL_MCIOS2
  47. #include <os2me.h>
  48. #include <cdaudos2.h>
  49. #include "ibmcdrom.h"
  50. #include "hhpheap.h"
  51.  
  52. extern PVOID          CDMC_hHeap;
  53.  
  54. /****************************************************************************/
  55. /*                                                                          */
  56. /* SUBROUTINE NAME:  vsdDriverEntry                                         */
  57. /*                                                                          */
  58. /* DESCRIPTIVE NAME:  Hardware specific code entry point.                   */
  59. /*                                                                          */
  60. /* FUNCTION:  Receive command message from the general MCI Driver for CD    */
  61. /*            Audio (CDAUDIOT.DLL).                                         */
  62. /*                                                                          */
  63. /* PARAMETERS:                                                              */
  64. /*      PVOID  lpInstance -- Pointer to device handle.                      */
  65. /*      USHORT usMessage  -- Command message.                               */
  66. /*      ULONG  *pulParam1 -- Pointer to flag for this message.              */
  67. /*      PVOID  pParam2    -- Pointer to data record structure.              */
  68. /*      USHORT usUserParm -- User Parameter.                                */
  69. /*                                                                          */
  70. /* EXIT CODES:                                                              */
  71. /*      MCIERR_SUCCESS    -- action completed without error.                */
  72. /*      MCIERR_INI_FILE   -- corrupted INI file, drive is not CD-ROM drive. */
  73. /*      MCIERR_DEVICE_NOT_READY      -- device was closed from an error.    */
  74. /*      MCIERR_MEDIA_CHANGED         -- device was reopened, waiting for    */
  75. /*                                      MCIDRV_REGISTER message.            */
  76. /*      MCIERR_FLAGS_NOT_COMPATIBLE  -- missing or multiple flags.          */
  77. /*      MCIERR_UNRECOGNIZED_COMMAND  -- unknown command.                    */
  78. /*      MCIERR_UNSUPPORTED_FUNCTION  -- unsupported command.                */
  79. /*      MCIERR_UNSUPPORTED_FLAG      -- unsupported flag.                   */
  80. /*      MCIERR_INVALID_FLAG          -- flag not supported by this VSD.     */
  81. /*      MCIERR_OUT_OF_MEMORY         -- couldn't allocate instance.         */
  82. /*      MCIERR_INVALID_ITEM_FLAG     -- Unknown item specified.             */
  83. /*      MCIERR_OUTOFRANGE            -- Invalid value.                      */
  84. /*      MCIERR_INVALID_MEDIA_TYPE    -- No audio tracks were found.         */
  85. /*      MCIERR_CUEPOINT_LIMIT_REACHED -- no more room to add events.        */
  86. /*      MCIERR_INVALID_CUEPOINT       -- unable to locate event.            */
  87. /*      MCIERR_DEVICE_LOCKED -- CD-ROM drive, previously opened exclusively.*/
  88. /*                                                                          */
  89. /* NOTES:                                                                   */
  90. /*                                                                          */
  91. /****************************************************************************/
  92. ULONG APIENTRY vsdDriverEntry(PVOID lpInstance, USHORT usMessage,
  93.                               ULONG *pulParam1, PVOID pParam2,
  94.                               USHORT usUserParm)
  95. {
  96.    ULONG  rc, ulP1Temp = MCI_WAIT;
  97.    USHORT try = 1;
  98.  
  99.    if (pulParam1 == 0L)
  100.       pulParam1 = &ulP1Temp;
  101.  
  102.    /* check to see if the drive is open, unless it is an Open message */
  103.    if (usMessage == MCI_OPEN)
  104.       rc = CDAudOpen(*pulParam1, (MMDRV_OPEN_PARMS *)pParam2);
  105.    else
  106.    {
  107.       /* if the device is closed try reopening it unless you are closing */
  108.       if (((PINST) lpInstance)->hDrive == 0 && usMessage != MCI_CLOSE)
  109.       {
  110.          rc = CD01_Open((PINST) lpInstance);
  111.          /* Clear commands not needing an open hardware device */
  112.          if (rc == MCIERR_DEVICE_NOT_READY)
  113.             if ((usMessage == MCI_DEVICESETTINGS) ||
  114.                 (usMessage == MCI_GETDEVCAPS) ||
  115.                 (usMessage == MCI_INFO) ||
  116.                 (usMessage == MCIDRV_REGISTER_DRIVE) ||
  117.                 (usMessage == MCI_SET_CUEPOINT) ||
  118.                 (usMessage == MCI_SET_POSITION_ADVISE) ||
  119.                 (usMessage == MCIDRV_CD_STATUS_CVOL) ||
  120.                 (usMessage == MCIDRV_SYNC &&
  121.                    !(*pulParam1 & MCIDRV_SYNC_REC_PULSE)))
  122.                rc = MCIERR_SUCCESS;
  123.  
  124.       }  /* of if drive needs to be open */
  125.       else      /* drive was opened */
  126.          rc = MCIERR_SUCCESS;
  127.  
  128.       if (!rc)
  129.          do
  130.          {
  131.             /* process message */
  132.             rc = process_msg((PINST) lpInstance, usMessage,
  133.                              pulParam1, pParam2, usUserParm);
  134.  
  135.             if (rc == MCIERR_DEVICE_NOT_READY ||       /* ERROR RECOVERY */
  136.                 rc == MCIERR_MEDIA_CHANGED)
  137.             {
  138.                if (((PINST)lpInstance)->Drive == '0')     /* drive is closed */
  139.                {                                   /* don't reissue commands */
  140.                   rc = MCIERR_SUCCESS;
  141.                   break;
  142.                }
  143.                else
  144.                   if (try == 2)
  145.                      break;                         /* quit after 2 tries. */
  146.                   else
  147.                   {
  148.                      rc = CDAudErrRecov((PINST) lpInstance);
  149.                      if (rc)                   /* error is still there, exit */
  150.                         break;
  151.                      else
  152.                         try++;
  153.                   }  /* of else only tried the command once (try == 1) */
  154.  
  155.             }  /* of if the drive was not ready */
  156.             else
  157.                break;                          /* clear flag to exit */
  158.  
  159.          } while (try);  /* end of do loop and if no open error */
  160.  
  161.    } /* of else command was not MCI_OPEN */
  162.  
  163.    return(rc);
  164.  
  165. }  /* of vsdDriverEntry() */
  166.  
  167.  
  168.  
  169. /****************************************************************************/
  170. /*                                                                          */
  171. /* SUBROUTINE NAME:  process_msg                                            */
  172. /*                                                                          */
  173. /* DESCRIPTIVE NAME:  Process message command.                              */
  174. /*                                                                          */
  175. /* FUNCTION:  Process the command message received by vsdDriverEntry().     */
  176. /*                                                                          */
  177. /* PARAMETERS:                                                              */
  178. /*      PINST  pInst      -- Pointer to instance structure.                 */
  179. /*      USHORT usMessage  -- Command message.                               */
  180. /*      ULONG  *pulParam1 -- Pointer to flag for this message.              */
  181. /*      PVOID  pParam2    -- Pointer to data record structure.              */
  182. /*      USHORT usUserParm -- User Parameter.                                */
  183. /*                                                                          */
  184. /* EXIT CODES:                                                              */
  185. /*      MCIERR_SUCCESS    -- action completed without error.                */
  186. /*      MCIERR_DEVICE_NOT_READY      -- device was not ready, no disc.      */
  187. /*      MCIERR_MEDIA_CHANGED         -- device was reopened, waiting for    */
  188. /*                                      MCIDRV_REGISTER message.            */
  189. /*      MCIERR_FLAGS_NOT_COMPATIBLE  -- missing or multiple flags.          */
  190. /*      MCIERR_UNRECOGNIZED_COMMAND  -- unknown command.                    */
  191. /*      MCIERR_UNSUPPORTED_FUNCTION  -- unsupported command.                */
  192. /*      MCIERR_UNSUPPORTED_FLAG      -- unsupported flag.                   */
  193. /*      MCIERR_INVALID_BUFFER        -- Buffer size was too small.          */
  194. /*      MCIERR_INVALID_FLAG          -- Unknown flag.                       */
  195. /*      MCIERR_INVALID_MEDIA_TYPE    -- No audio tracks were found.         */
  196. /*      ERROR_TOO_MANY_EVENTS --  no more room to add events.               */
  197. /*      ERROR_INVALID_EVENT   --  unable to locate event.                   */
  198. /*      ERROR_INVALID_MMTIME  --  duplicate cuepoint.                       */
  199. /*                                                                          */
  200. /* NOTES:                                                                   */
  201. /*                                                                          */
  202. /****************************************************************************/
  203. static ULONG process_msg(PINST pInst, USHORT usMessage,
  204.                          ULONG *pulParam1, PVOID pParam2, USHORT usUserParm)
  205. {
  206.    ULONG rc;
  207.  
  208.    DosRequestMutexSem(pInst->hInstSem, WAIT_FOREVER);
  209.    if (usMessage != MCI_PLAY)
  210.       DosReleaseMutexSem(pInst->hInstSem);       // No protection needed
  211.  
  212.    /* process message */
  213.    switch(usMessage)
  214.    {
  215.       case MCI_CLOSE :
  216.          rc = CDAudClose(pInst, *pulParam1);
  217.          break;
  218.       case MCI_CUE :                           /* Pre-roll */
  219.          rc = CD01_Cue(pInst);
  220.          break;
  221.       case MCI_GETDEVCAPS :                    /* Get Device Capabilities */
  222.          rc = CD01_GetCaps(*pulParam1, (MCI_GETDEVCAPS_PARMS *)pParam2);
  223.          break;
  224.       case MCI_GETTOC :                        /* Get Table of Contents */
  225.          if (*pulParam1 & WAIT_NOTIFY_MASK)
  226.             rc = MCIERR_INVALID_FLAG;
  227.          else
  228.             rc = CD01_GetTOC(pInst, (MCI_TOC_PARMS *)pParam2);
  229.          break;
  230.       case MCI_INFO :
  231.          rc = CDAudInfo(pInst, *pulParam1, (MCI_INFO_PARMS *)pParam2);
  232.          break;
  233.       /* case MCI_OPEN :          open was already done in vsdDriverEntry() */
  234.  
  235.       case MCI_PAUSE :
  236.          rc = CD01_Stop(pInst, TIMER_PLAY_SUSPEND);
  237.          break;
  238.       case MCI_PLAY :
  239.          rc = CD01_Play(pInst, pulParam1,
  240.                         ((MCI_PLAY_PARMS *)pParam2)->ulFrom,
  241.                         ((MCI_PLAY_PARMS *)pParam2)->ulTo, usUserParm,
  242.                         ((MCI_PLAY_PARMS *)pParam2)->hwndCallback);
  243.          break;
  244.       case MCIDRV_CD_READ_LONG :                   /* Read Long */
  245.          rc = MCIERR_UNSUPPORTED_FUNCTION;
  246.          break;
  247.       case MCIDRV_REGISTER_DISC :                  /* Register Disc */
  248.          rc = CDAudRegDisc(pInst, REG_BOTH, (MCI_CD_REGDISC_PARMS *)pParam2);
  249.          break;
  250.       case MCIDRV_REGISTER_DRIVE :                 /* Register Drive */
  251.          rc = CDAudRegDrive(pInst, (MCI_CD_REGDRIVE_PARMS *)pParam2);
  252.          break;
  253.       case MCIDRV_REGISTER_TRACKS :                /* Register Tracks */
  254.          rc = CD01_RegTracks(pInst, (MCI_CD_REGTRACKS_PARMS *)pParam2);
  255.          break;
  256.       case MCIDRV_RESTORE :
  257.          rc = CD01_Restore(pInst, (MCIDRV_CD_SAVE_PARMS *)pParam2);
  258.          break;
  259.       case MCI_RESUME :                            /* Unpause */
  260.          rc = CD01_Resume(pInst);
  261.          break;
  262.       case MCIDRV_SAVE :
  263.          rc = CD01_Save(pInst, (MCIDRV_CD_SAVE_PARMS *)pParam2);
  264.          break;
  265.       case MCI_SEEK :
  266.          rc = CD01_Seek(pInst, ((MCI_SEEK_PARMS *)pParam2)->ulTo);
  267.          break;
  268.       case MCI_SET :
  269.          rc = CDAudSet(pInst, pulParam1, (MCI_SET_PARMS *)pParam2);
  270.          break;
  271.       case MCI_SET_CUEPOINT :
  272.          rc = CD01_CuePoint(pInst, *pulParam1, (MCI_CUEPOINT_PARMS *)pParam2);
  273.          break;
  274.       case MCI_SET_POSITION_ADVISE :
  275.          rc = CD01_PosAdvise(pInst, *pulParam1, (MCI_POSITION_PARMS *)pParam2);
  276.          break;
  277.       case MCIDRV_CD_SET_VERIFY :
  278.          rc = CDAudSetVerify(*pulParam1);
  279.          break;
  280.       case MCI_STATUS :
  281.          rc = CDAudStatus(pInst, *pulParam1, (MCI_STATUS_PARMS *)pParam2);
  282.          break;
  283.       case MCIDRV_CD_STATUS_CVOL :
  284.          rc = CDAudStatCVol(&((MCI_STATUS_PARMS *)pParam2)->ulReturn);
  285.          break;
  286.       case MCI_STOP :
  287.          rc = CD01_Stop(pInst, TIMER_EXIT_ABORTED);
  288.          break;
  289.       case MCIDRV_SYNC :
  290.          rc = CD01_Sync(pInst, *pulParam1, (MCIDRV_SYNC_PARMS *)pParam2);
  291.          break;
  292.       default :
  293.          if (usMessage <= MCI_MAX_COMMAND)
  294.             rc = MCIERR_UNSUPPORTED_FUNCTION;
  295.          else
  296.             rc = MCIERR_UNRECOGNIZED_COMMAND;
  297.  
  298.    }  /* of switch */
  299.  
  300.    return(rc);
  301.  
  302. }  /* of process_msg() */
  303.  
  304.  
  305.  
  306. /****************************************************************************/
  307. /*                                                                          */
  308. /* SUBROUTINE NAME:  CDAudErrRecov                                          */
  309. /*                                                                          */
  310. /* DESCRIPTIVE NAME:  CD Audio Information.                                 */
  311. /*                                                                          */
  312. /* FUNCTION:  Returns string information from a device driver.              */
  313. /*                                                                          */
  314. /* PARAMETERS:                                                              */
  315. /*      PINST pInst      -- Instance structure.                             */
  316. /*                                                                          */
  317. /* EXIT CODES:                                                              */
  318. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  319. /*      MCIERR_INI_FILE  -- corrupted INI file, drive is not CD-ROM drive.  */
  320. /*      MCIERR_DEVICE_NOT_READY      -- device was not ready, no disc.      */
  321. /*      MCIERR_MEDIA_CHANGED         -- device was reopened.                */
  322. /*                                                                          */
  323. /* NOTES:                                                                   */
  324. /*                                                                          */
  325. /****************************************************************************/
  326. static ULONG CDAudErrRecov(PINST pInst)
  327. {
  328.    ULONG rc;
  329.  
  330.    /* Close the device */
  331.    DosClose(pInst->hDrive);
  332.    pInst->hDrive = 0;                    /* mark the instance structure */
  333.  
  334.    /* Try to reopen the device */
  335.    rc = CD01_Open(pInst);
  336.  
  337.    return(rc);
  338.  
  339. }  /* of CDAudErrRecov() */
  340.  
  341.  
  342.  
  343. /****************************************************************************/
  344. /*                                                                          */
  345. /* SUBROUTINE NAME:  CDAudClose                                             */
  346. /*                                                                          */
  347. /* DESCRIPTIVE NAME:  CD Audio Close                                        */
  348. /*                                                                          */
  349. /* FUNCTION:  Close a device dependent instance.                            */
  350. /*                                                                          */
  351. /* PARAMETERS:                                                              */
  352. /*      PINST pInst      -- Instance structure.                             */
  353. /*      ULONG ulParam1   -- Flag for this message.                          */
  354. /*                                                                          */
  355. /* EXIT CODES:                                                              */
  356. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  357. /*      MCIERR_INVALID_FLAG -- flag not supported by this VSD.              */
  358. /*                                                                          */
  359. /* NOTES:                                                                   */
  360. /*                                                                          */
  361. /****************************************************************************/
  362. static ULONG CDAudClose(PINST pInst, ULONG ulParam1)
  363. {
  364.    ULONG rc;
  365.  
  366.    if (ulParam1 & WAIT_NOTIFY_MASK)
  367.       rc = MCIERR_INVALID_FLAG;
  368.    else
  369.    {
  370.       pInst->Drive = '0';              /* destroy drive to prevent reopening */
  371.  
  372.       /* stop play & timer if one is going */
  373.       switch(pInst->usPlayFlag)
  374.       {
  375.          case TIMER_PLAY_SUSPEND :                 //suspended, stop only timer
  376.          case TIMER_PLAY_SUSP_2  :
  377.             if (DosWaitThread(&pInst->ulPlayTID, 1L) ==
  378.                                          ERROR_THREAD_NOT_TERMINATED)
  379.             {
  380.                pInst->usPlayFlag = TIMER_EXIT_ABORTED;
  381.                DosPostEventSem(pInst->hTimeLoopSem);  //continue timer loop
  382.             }
  383.             else
  384.                pInst->usPlayFlag = TIMER_AVAIL;
  385.             break;
  386.          case TIMER_PLAYING :                      //playing, stop device
  387.             CD01_Stop(pInst, TIMER_EXIT_ABORTED);
  388.             break;
  389.       }  /* of switch() */
  390.  
  391.       /* wait for commands to terminate */
  392.       while (pInst->usPlayFlag != TIMER_AVAIL)
  393.          DosSleep(HALF_TIME_MIN);
  394.  
  395.       DosClose(pInst->hDrive);
  396.       DosCloseMutexSem(pInst->hIOSem);
  397.       DosCloseMutexSem(pInst->hInstSem);
  398.       DosCloseEventSem(pInst->hTimeLoopSem);
  399.       DosCloseEventSem(pInst->hReturnSem);
  400.       HhpFreeMem(CDMC_hHeap, pInst);
  401.       rc = MCIERR_SUCCESS;                  /* assume all will work right */
  402.    }  /* of else flags were okay */
  403.  
  404.    return(rc);
  405.  
  406. }  /* of CDAudClose() */
  407.  
  408.  
  409.  
  410. /****************************************************************************/
  411. /*                                                                          */
  412. /* SUBROUTINE NAME:  CDAudInfo                                              */
  413. /*                                                                          */
  414. /* DESCRIPTIVE NAME:  CD Audio Information.                                 */
  415. /*                                                                          */
  416. /* FUNCTION:  Returns string information from a device driver.              */
  417. /*                                                                          */
  418. /* PARAMETERS:                                                              */
  419. /*      PINST pInst      -- Instance structure.                             */
  420. /*      ULONG ulParam1   -- Flag for this message.                          */
  421. /*      MCI_INFO_PARMS *pParam2 -- Pointer to data record structure.        */
  422. /*                                                                          */
  423. /* EXIT CODES:                                                              */
  424. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  425. /*      MCIERR_FLAGS_NOT_COMPATIBLE  -- Mis-match in flags.                 */
  426. /*      MCIERR_INVALID_BUFFER        -- Buffer too small.                   */
  427. /*      MCIERR_INVALID_FLAG          -- Unknown flag.                       */
  428. /*                                                                          */
  429. /* NOTES:                                                                   */
  430. /*      The CD ID and UPC is processed by the MCD.                          */
  431. /*                                                                          */
  432. /****************************************************************************/
  433. static ULONG CDAudInfo(PINST pInst, ULONG ulParam1, MCI_INFO_PARMS *pParam2)
  434. {
  435.    ULONG rc, ulLen;
  436.    USHORT i;
  437.  
  438.    ulParam1 &= WAIT_NOTIFY_MASK;
  439.  
  440.    if (ulParam1 == MCI_INFO_PRODUCT)
  441.    {
  442.       if (pParam2->ulRetSize >= INFO_SIZE)
  443.       {
  444.          ulLen = INFO_SIZE;
  445.          if (pParam2->ulRetSize > INFO_SIZE)   // if buffer is big enough
  446.             ulLen++;                           // capture the NULL
  447.          rc = MCIERR_SUCCESS;
  448.       }
  449.       else
  450.       {
  451.          ulLen = pParam2->ulRetSize;
  452.          rc = MCIERR_INVALID_BUFFER;
  453.       }
  454.  
  455.       /* fill in product information */
  456.       if (ulLen)   //if 0, it may be an invalid address
  457.          memcpy(pParam2->pszReturn, "IBMCD010", ulLen);
  458.       pParam2->ulRetSize = INFO_SIZE;
  459.  
  460.    }
  461.    else
  462.       rc = MCIERR_INVALID_FLAG;
  463.  
  464.    if (rc && rc != MCIERR_INVALID_BUFFER)
  465.       pParam2->ulRetSize = 0L;
  466.  
  467.    return(rc);
  468.  
  469. }  /* of CDAudInfo() */
  470.  
  471.  
  472.  
  473. /****************************************************************************/
  474. /*                                                                          */
  475. /* SUBROUTINE NAME:  CDAudOpen                                              */
  476. /*                                                                          */
  477. /* DESCRIPTIVE NAME:  CD Audio Open.                                        */
  478. /*                                                                          */
  479. /* FUNCTION:  Open a device dependent instance.                             */
  480. /*                                                                          */
  481. /* PARAMETERS:                                                              */
  482. /*      ULONG ulParam1   -- Flag for this message.                          */
  483. /*      MMDRV_OPEN_PARMS *pParam2 -- Pointer to data record structure.      */
  484. /*                                                                          */
  485. /* EXIT CODES:                                                              */
  486. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  487. /*      MCIERR_INI_FILE  -- corrupted INI file, drive is not CD-ROM drive.  */
  488. /*      MCIERR_OUT_OF_MEMORY       -- couldn't allocate memory for instance.*/
  489. /*      MCIERR_INVALID_FLAG -- flag not supported by this VSD.              */
  490. /*      MCIERR_DEVICE_LOCKED -- CD-ROM drive, previously opened exclusively.*/
  491. /*                                                                          */
  492. /* NOTES:                                                                   */
  493. /*                                                                          */
  494. /****************************************************************************/
  495. static ULONG CDAudOpen(ULONG ulParam1, MMDRV_OPEN_PARMS *pParam2)
  496. {
  497.    ULONG rc;
  498.    PINST pInst;
  499.    BYTE i;
  500.    ULONG ulDevParmLen;
  501.    PVOID pVSDParm;
  502.    CHAR *pDrive, *pModel;
  503.  
  504.    /* validate flags */
  505.    /* this VSD will only support standard flags */
  506.    ulParam1 &= WAIT_NOTIFY_MASK;
  507.    if (ulParam1)
  508.       rc = MCIERR_INVALID_FLAG;
  509.    else
  510.    {
  511.       /* get memory */
  512.       pInst = HhpAllocMem(CDMC_hHeap, sizeof(struct instance_state));
  513.       if (pInst == NULL)
  514.          rc = MCIERR_OUT_OF_MEMORY;
  515.       else
  516.       {
  517.          /* create semaphore so only one IOCLT call will be made at a time */
  518.          rc = DosCreateMutexSem((PSZ) NULL, &pInst->hIOSem, 0L, FALSE);
  519.          if (!rc)
  520.             rc = DosCreateEventSem((PSZ) NULL, &pInst->hTimeLoopSem, 0L, FALSE);
  521.          if (!rc)
  522.             rc = DosCreateMutexSem((PSZ) NULL, &pInst->hInstSem, 0L, FALSE);
  523.          if (!rc)
  524.             rc = DosCreateEventSem((PSZ) NULL, &pInst->hReturnSem, 0L, FALSE);
  525.          if (rc)
  526.          {
  527.             DosCloseMutexSem(pInst->hIOSem);
  528.             DosCloseMutexSem(pInst->hInstSem);
  529.             DosCloseEventSem(pInst->hTimeLoopSem);
  530.             DosCloseEventSem(pInst->hReturnSem);
  531.             rc = MCIERR_OUT_OF_MEMORY;
  532.  
  533.          }  /* of if error creating semaphores */
  534.       }  /* else no error creating instance structure's memory */
  535.  
  536.       /* init instance */
  537.       if (!rc)
  538.       {  /* instance entry created */
  539.          /* init instance */
  540.          pInst->hDrive = 0;                     // drive handle
  541.          pInst->ulCurPos = 0L;                  // set current position;
  542.          pInst->usDeviceID = pParam2->usDeviceID;
  543.  
  544.          /* validate and get drive & hardware type */
  545.          /* copy string so that it doesn't get disturb */
  546.          ulDevParmLen = strlen(pParam2->pDevParm) + 1;
  547.          pVSDParm = HhpAllocMem(CDMC_hHeap, ulDevParmLen);
  548.          strcpy(pVSDParm, pParam2->pDevParm);
  549.          parse_DevParm((CHAR *)pVSDParm, &pDrive, &pModel);
  550.          pInst->Drive = *pDrive;
  551.          strncpy(pInst->szModel, pModel, MODEL_SIZE);
  552.          pInst->szModel[MODEL_SIZE - 1] = '\0';     //make sure NULL terminated
  553.  
  554.          HhpFreeMem(CDMC_hHeap, pVSDParm);
  555.          QueryTable(pInst);                   // id drive and get capabilities
  556.  
  557.          pInst->qptPosAdvise.ulEvent = 0L;
  558.          for (i=0; i < CDMCD_CUEPOINT_MAX; i++)          // init arrays
  559.             pInst->arrCuePoint[i].ulEvent = (ULONG) -1L;
  560.  
  561.          pInst->usPlayFlag = TIMER_AVAIL;
  562.          pInst->ulPlayTID  = 0L;
  563.          pInst->DiscID.ulLeadOut = 0L;         // used as a first time flag
  564.          pInst->StreamMaster = FALSE;
  565.  
  566.          /* Try opening the device.  Ignore things like disc not present, */
  567.          /* but report errors involving the INI file or that the drive    */
  568.          /* was previously opened in an exclusive mode.                   */
  569.          rc = CD01_Open(pInst);
  570.          if (rc != MCIERR_INI_FILE && rc != MCIERR_DEVICE_LOCKED)
  571.             rc = MCIERR_SUCCESS;        /* pretend that all went well */
  572.  
  573.       }  /* of if no errors getting memory */
  574.  
  575.       if (rc)                                  /* if error, free memory */
  576.          HhpFreeMem(CDMC_hHeap, pInst);
  577.       else
  578.          pParam2->pInstance = pInst;           /* pass pointer back */
  579.  
  580.    }  /* of else no invalid flags */
  581.  
  582.    return(rc);
  583.  
  584. }  /* of CDAudOpen() */
  585.  
  586.  
  587.  
  588. /****************************************************************************/
  589. /*                                                                          */
  590. /* SUBROUTINE NAME:  CDAudRegDisc                                           */
  591. /*                                                                          */
  592. /* DESCRIPTIVE NAME:  CD Audio Register Compact Disc.                       */
  593. /*                                                                          */
  594. /* FUNCTION:  Register a CD media so that the disc may be recognized by     */
  595. /*            the calling MCD.                                              */
  596. /*                                                                          */
  597. /* PARAMETERS:                                                              */
  598. /*      PINST  pInst     -- Instance structure.                             */
  599. /*      USHORT usFlag    -- Action Flag to copy into pParam2.               */
  600. /*      MCI_CD_REGDISC_PARMS *pParam2 -- Pointer to data record.            */
  601. /*                                                                          */
  602. /* EXIT CODES:                                                              */
  603. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  604. /*      MCIERR_DEVICE_NOT_READY      -- device was not ready, no disc.      */
  605. /*                                                                          */
  606. /* NOTES:                                                                   */
  607. /*                                                                          */
  608. /****************************************************************************/
  609. ULONG CDAudRegDisc(PINST pInst, USHORT usFlag, MCI_CD_REGDISC_PARMS *pParam2)
  610. {
  611.    ULONG rc;
  612.    USHORT i;
  613.    BYTE lowest, highest;
  614.    ULONG ulDataLen = STANDRD_DMAX, ulParamLen = STANDRD_PMAX;
  615.    MCI_CD_ID DiscID;
  616.  
  617.    memcpy(&DiscID, &pInst->DiscID, sizeof(MCI_CD_ID));  //save original
  618.  
  619.    if (usFlag == REG_BOTH || usFlag == REG_INST)
  620.    {   /* register with the internal instance */
  621.       rc = CD01_GetID(pInst, &pInst->DiscID, &lowest, &highest);
  622.       if (!rc && usFlag == REG_BOTH)
  623.          /* copy information to external source */
  624.          memcpy(&pParam2->DiscID, &pInst->DiscID, sizeof(MCI_CD_ID));
  625.    }   /* of if update instance structure */
  626.    else      /* the flag is REG_PARAM2 */
  627.       rc = CD01_GetID(pInst, &pParam2->DiscID, &lowest, &highest);
  628.  
  629.    /* complete registration for param2 */
  630.    if (!rc && (usFlag == REG_BOTH || usFlag == REG_PARAM2))
  631.    {
  632.       /* get low and high track numbers */
  633.       pParam2->LowestTrackNum  = lowest;
  634.       pParam2->HighestTrackNum = highest;
  635.  
  636.       /* get upc code -- device cannot do this so set this to zero */
  637.       for (i=0; i < UPC_SIZE; i++)
  638.          pParam2->UPC[i] = 0;
  639.  
  640.    }  /* of if need to complete Param2 */
  641.  
  642.    return(rc);
  643.  
  644. }  /* of CDAudRegDisc() */
  645.  
  646.  
  647.  
  648. /****************************************************************************/
  649. /*                                                                          */
  650. /* SUBROUTINE NAME:  CDAudRegDrive                                          */
  651. /*                                                                          */
  652. /* DESCRIPTIVE NAME:  CD Audio Register CD-ROM Drive and its capabilities.  */
  653. /*                                                                          */
  654. /* FUNCTION:  Register a CD drive so that the disc may be recognized by     */
  655. /*            the calling MCD.                                              */
  656. /*                                                                          */
  657. /* PARAMETERS:                                                              */
  658. /*      PINST pInst      -- Instance structure.                             */
  659. /*      MCI_CD_REGDRIVE_PARMS *pParam2 -- Pointer to data record.           */
  660. /*                                                                          */
  661. /* EXIT CODES:                                                              */
  662. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  663. /*                                                                          */
  664. /* NOTES:                                                                   */
  665. /*                                                                          */
  666. /****************************************************************************/
  667. static ULONG CDAudRegDrive(PINST pInst, MCI_CD_REGDRIVE_PARMS *pParam2)
  668. {
  669.    /* get the CD MCD return function information */
  670.    pInst->ulCDMCDID    = pParam2->ulCDMCDID;
  671.    pInst->pCDMCDReturn = pParam2->pCDMCDReturn;
  672.  
  673.    /* fill in capabilities */
  674.    pParam2->usCaps = CD01_CAPS;       //This example supports the IBM 3510-001
  675.  
  676.    /* fill in preroll information */
  677.    pParam2->ulPrerollType  = MCI_PREROLL_NONE;
  678.    pParam2->ulPrerollTime  = 0L;
  679.    pParam2->ulMinStartTime = SPEC_START;
  680.  
  681.    return(MCIERR_SUCCESS);
  682.  
  683. }  /* of CDAudRegDrive() */
  684.  
  685.  
  686.  
  687. /****************************************************************************/
  688. /*                                                                          */
  689. /* SUBROUTINE NAME:  CDAudSet                                               */
  690. /*                                                                          */
  691. /* DESCRIPTIVE NAME:  CD Audio Set.                                         */
  692. /*                                                                          */
  693. /* FUNCTION:  Set features and attributes of the CD-ROM drive.              */
  694. /*                                                                          */
  695. /* PARAMETERS:                                                              */
  696. /*      PINST  pInst      -- Instance structure.                            */
  697. /*      ULONG  *pulParam1 -- Flag for this message.                         */
  698. /*      MCI_SET_PARMS *pParam2   -- Pointer to data record structure.       */
  699. /*                                                                          */
  700. /* EXIT CODES:                                                              */
  701. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  702. /*      MCIERR_UNSUPPORTED_FLAG      -- unsupported flag.                   */
  703. /*      MCIERR_INVALID_FLAG          -- Unknown flag.                       */
  704. /*      MCIERR_DEVICE_NOT_READY      -- device was not ready, no disc.      */
  705. /*                                                                          */
  706. /* NOTES:  Mutual Exclusive flags (LOCK/UNLOCK & OPEN/CLOSE DOOR) are       */
  707. /*         tested in the MCD.                                               */
  708. /*                                                                          */
  709. /****************************************************************************/
  710. static ULONG CDAudSet(PINST pInst, ULONG *pulParam1, MCI_SET_PARMS *pParam2)
  711. {
  712.    ULONG rc;
  713.    ULONG ulDataLen = STANDRD_DMAX, ulParamLen = STANDRD_PMAX;
  714.    ULONG ulType;
  715.  
  716.    /* validate flags */
  717.    rc = CDAudSetVerify(*pulParam1);
  718.  
  719.    if (!rc)
  720.    {
  721.       ulType = *pulParam1 & WAIT_NOTIFY_MASK;
  722.  
  723.       if (ulType & MCI_SET_DOOR_OPEN)
  724.       {
  725.          /* hardware does not support eject if playing, so stop it. */
  726.          if (pInst->usPlayFlag == TIMER_PLAYING)
  727.             rc = CD01_Stop(pInst, TIMER_EXIT_ABORTED);
  728.  
  729.          if (!rc)             // no error, proceed, else disc is already out
  730.          {
  731.             /* make sure that door is unlocked so eject can be successful */
  732.             CD01_LockDoor(pInst, MCI_FALSE);
  733.             CallIOCtl(pInst, CDDRIVE_CAT, EJECT__DISK,
  734.                       "CD01", ulParamLen, &ulParamLen,
  735.                        NULL,  ulDataLen,  &ulDataLen);
  736.          }
  737.          rc = MCIERR_SUCCESS;
  738.  
  739.       }  /* of if EJECTing disc */
  740.  
  741.       if (ulType & MCI_SET_DOOR_LOCK)
  742.          rc = CD01_LockDoor(pInst, MCI_TRUE);
  743.       else if (ulType & MCI_SET_DOOR_UNLOCK)
  744.          rc = CD01_LockDoor(pInst, MCI_FALSE);
  745.  
  746.       if (ulType & MCI_SET_VOLUME)
  747.          /* Hardware for example cannot support vectored volume */
  748.          rc = CD01_SetVolume(pInst, pParam2->ulLevel);
  749.  
  750.    }  /* of if no error */
  751.  
  752.    return(rc);
  753.  
  754. }  /* of CDAudSet() */
  755.  
  756.  
  757.  
  758. /****************************************************************************/
  759. /*                                                                          */
  760. /* SUBROUTINE NAME:  CDAudSetVerify                                         */
  761. /*                                                                          */
  762. /* DESCRIPTIVE NAME:  CD Audio Set Verify                                   */
  763. /*                                                                          */
  764. /* FUNCTION:  Verify flags for SET command.  This function is called by     */
  765. /*            the MCD to validate flags prior to calling other components,  */
  766. /*            like the Amp/Mixer or SSM, to process their flags.            */
  767. /*                                                                          */
  768. /* PARAMETERS:                                                              */
  769. /*      ULONG ulParam1   -- Flag for this message.                          */
  770. /*                                                                          */
  771. /* EXIT CODES:                                                              */
  772. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  773. /*      MCIERR_UNSUPPORTED_FLAG      -- unsupported flag.                   */
  774. /*      MCIERR_INVALID_FLAG          -- Unknown flag.                       */
  775. /*                                                                          */
  776. /* NOTES:  Mutual Exclusive flags (LOCK/UNLOCK & OPEN/CLOSE DOOR) are       */
  777. /*         tested in the MCD.                                               */
  778. /*                                                                          */
  779. /****************************************************************************/
  780. static ULONG CDAudSetVerify(ULONG ulParam1)
  781. {
  782.    ULONG rc = MCIERR_SUCCESS;
  783.  
  784.    /* check unsupported flags */
  785.    if (ulParam1 & MCI_SET_DOOR_CLOSED)
  786.       rc = MCIERR_UNSUPPORTED_FLAG;
  787.    else
  788.       /* check unknown flags */
  789.       if (ulParam1 & ~(MCI_SET_DOOR_OPEN   | MCI_SET_DOOR_LOCK |
  790.                        MCI_SET_DOOR_UNLOCK | MCI_SET_VOLUME | MCI_OVER |
  791.                        MCI_NOTIFY | MCI_WAIT))
  792.          rc = MCIERR_INVALID_FLAG;
  793.  
  794.    return(rc);
  795.  
  796. }  /* of CDAudSetVerify() */
  797.  
  798.  
  799.  
  800. /****************************************************************************/
  801. /*                                                                          */
  802. /* SUBROUTINE NAME:  CDAudStatus                                            */
  803. /*                                                                          */
  804. /* DESCRIPTIVE NAME:  CD Audio Status.                                      */
  805. /*                                                                          */
  806. /* FUNCTION:  Query and return the status of the features and attributes    */
  807. /*            of the CD-ROM drive.                                          */
  808. /*                                                                          */
  809. /* PARAMETERS:                                                              */
  810. /*      PINST pInst      -- Instance structure.                             */
  811. /*      ULONG ulParam1   -- Flag for this message.                          */
  812. /*      MCI_STATUS_PARMS *pParam2   -- Pointer to data record structure.    */
  813. /*                                                                          */
  814. /* EXIT CODES:                                                              */
  815. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  816. /*      MCIERR_DEVICE_NOT_READY      -- device was not ready, no disc.      */
  817. /*      MCIERR_FLAGS_NOT_COMPATIBLE  -- Mis-match in flags.                 */
  818. /*      MCIERR_UNSUPPORTED_FUNCTION  -- Flags not supported.                */
  819. /*      MCIERR_INVALID_FLAG          -- Unknown flag.                       */
  820. /*      MCIERR_INVALID_ITEM_FLAG     -- Unknown item specified.             */
  821. /*                                                                          */
  822. /* NOTES:                                                                   */
  823. /*                                                                          */
  824. /****************************************************************************/
  825. static ULONG CDAudStatus(PINST pInst,
  826.                          ULONG ulParam1, MCI_STATUS_PARMS *pParam2)
  827. {
  828.    ULONG rc;
  829.  
  830.    ulParam1 &= WAIT_NOTIFY_MASK;
  831.  
  832.    /* verify flags */
  833.    if (ulParam1 & MCI_STATUS_ITEM)
  834.       if (ulParam1 != MCI_STATUS_ITEM)
  835.          if (ulParam1 & MCI_STATUS_START && ulParam1 & MCI_TRACK)
  836.             rc = MCIERR_FLAGS_NOT_COMPATIBLE;
  837.          else
  838.             rc = MCIERR_INVALID_FLAG;
  839.       else
  840.          rc = MCIERR_SUCCESS;
  841.    else                                      // no ITEM flag
  842.       if (ulParam1 & MCI_TRACK)
  843.          rc = MCIERR_MISSING_FLAG;
  844.       else if (ulParam1 & MCI_STATUS_START)
  845.          rc = MCIERR_MISSING_FLAG;
  846.       else
  847.          rc = MCIERR_INVALID_FLAG;
  848.  
  849.    if (!rc)                         // ulParam1 == MCI_STATUS_ITEM only
  850.    {
  851.       switch(pParam2->ulItem)
  852.       {
  853.          case MCI_STATUS_POSITION :
  854.             rc = CD01_GetPosition(pInst, &pParam2->ulReturn);
  855.             break;
  856.          case MCI_STATUS_VOLUME :
  857.             rc = CD01_GetVolume(pInst, &pParam2->ulReturn);
  858.             break;
  859.          case MCI_STATUS_MEDIA_PRESENT :
  860.          case MCI_STATUS_MODE :
  861.          case MCI_STATUS_READY :
  862.             rc = CD01_GetDiscInfo(pInst, pParam2->ulItem, pParam2);
  863.             break;
  864.          default :
  865.             rc = MCIERR_INVALID_ITEM_FLAG;
  866.  
  867.       }  /* of item switch */
  868.    }  /* of if valid flag */
  869.  
  870.    return(rc);
  871.  
  872. }  /* of CDAudStatus() */
  873.  
  874.  
  875.  
  876. /****************************************************************************/
  877. /*                                                                          */
  878. /* SUBROUTINE NAME:  CDAudStatCVol                                          */
  879. /*                                                                          */
  880. /* DESCRIPTIVE NAME:  CD Audio Status Component Volume.                     */
  881. /*                                                                          */
  882. /* FUNCTION:  Remaps the component volume to what it would be from the      */
  883. /*            hardware if master audio was at 100%.                         */
  884. /*                                                                          */
  885. /* PARAMETERS:                                                              */
  886. /*      ULONG *pulLevel  -- Pointer to volume level.                        */
  887. /*                                                                          */
  888. /* EXIT CODES:                                                              */
  889. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  890. /*                                                                          */
  891. /* NOTES:                                                                   */
  892. /*                                                                          */
  893. /****************************************************************************/
  894. ULONG CDAudStatCVol(ULONG *pulLevel)
  895. {
  896.    USHORT usLeft, usRight;
  897.  
  898.    usLeft = LOUSHORT(*pulLevel);
  899.    usRight = HIUSHORT(*pulLevel);
  900.  
  901.    if (usLeft) usLeft = 100; else usLeft = 0;
  902.    if (usRight) usRight = 100; else usRight = 0;
  903.  
  904.    /* Adjust for hardware limitations, VOL = MAX(Left, Right) */
  905.    if (usLeft && usRight)
  906.       if (usLeft > usRight)
  907.          usRight = usLeft;
  908.       else
  909.          usLeft = usRight;
  910.  
  911.    *pulLevel = MAKEULONG(usLeft, usRight);
  912.  
  913.    return(MCIERR_SUCCESS);
  914.  
  915. }  /* of CDAudStatCVol() */
  916.  
  917.  
  918.  
  919.