home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / cset21v6.zip / MMPM2TK / TK / CDMCT / IBMCDROM.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  44KB  |  916 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_REGISTER_DISC :                  /* Register Disc */
  245.          rc = CDAudRegDisc(pInst, REG_BOTH, (MCI_CD_REGDISC_PARMS *)pParam2);
  246.          break;
  247.       case MCIDRV_REGISTER_DRIVE :                 /* Register Drive */
  248.          rc = CDAudRegDrive(pInst, (MCI_CD_REGDRIVE_PARMS *)pParam2);
  249.          break;
  250.       case MCIDRV_REGISTER_TRACKS :                /* Register Tracks */
  251.          rc = CD01_RegTracks(pInst, (MCI_CD_REGTRACKS_PARMS *)pParam2);
  252.          break;
  253.       case MCIDRV_RESTORE :
  254.          rc = CD01_Restore(pInst, (MCIDRV_CD_SAVE_PARMS *)pParam2);
  255.          break;
  256.       case MCI_RESUME :                            /* Unpause */
  257.          rc = CD01_Resume(pInst);
  258.          break;
  259.       case MCIDRV_SAVE :
  260.          rc = CD01_Save(pInst, (MCIDRV_CD_SAVE_PARMS *)pParam2);
  261.          break;
  262.       case MCI_SEEK :
  263.          rc = CD01_Seek(pInst, ((MCI_SEEK_PARMS *)pParam2)->ulTo);
  264.          break;
  265.       case MCI_SET :
  266.          rc = CDAudSet(pInst, pulParam1, (MCI_SET_PARMS *)pParam2);
  267.          break;
  268.       case MCI_SET_CUEPOINT :
  269.          rc = CD01_CuePoint(pInst, *pulParam1, (MCI_CUEPOINT_PARMS *)pParam2);
  270.          break;
  271.       case MCI_SET_POSITION_ADVISE :
  272.          rc = CD01_PosAdvise(pInst, *pulParam1, (MCI_POSITION_PARMS *)pParam2);
  273.          break;
  274.       case MCIDRV_CD_SET_VERIFY :
  275.          rc = CDAudSetVerify(*pulParam1);
  276.          break;
  277.       case MCI_STATUS :
  278.          rc = CDAudStatus(pInst, *pulParam1, (MCI_STATUS_PARMS *)pParam2);
  279.          break;
  280.       case MCIDRV_CD_STATUS_CVOL :
  281.          rc = CDAudStatCVol(&((MCI_STATUS_PARMS *)pParam2)->ulReturn);
  282.          break;
  283.       case MCI_STOP :
  284.          rc = CD01_Stop(pInst, TIMER_EXIT_ABORTED);
  285.          break;
  286.       case MCIDRV_SYNC :
  287.          rc = CD01_Sync(pInst, *pulParam1, (MCIDRV_SYNC_PARMS *)pParam2);
  288.          break;
  289.       default :
  290.          if (usMessage <= MCI_MAX_COMMAND)
  291.             rc = MCIERR_UNSUPPORTED_FUNCTION;
  292.          else
  293.             rc = MCIERR_UNRECOGNIZED_COMMAND;
  294.  
  295.    }  /* of switch */
  296.  
  297.    return(rc);
  298.  
  299. }  /* of process_msg() */
  300.  
  301.  
  302.  
  303. /****************************************************************************/
  304. /*                                                                          */
  305. /* SUBROUTINE NAME:  CDAudErrRecov                                          */
  306. /*                                                                          */
  307. /* DESCRIPTIVE NAME:  CD Audio Information.                                 */
  308. /*                                                                          */
  309. /* FUNCTION:  Returns string information from a device driver.              */
  310. /*                                                                          */
  311. /* PARAMETERS:                                                              */
  312. /*      PINST pInst      -- Instance structure.                             */
  313. /*                                                                          */
  314. /* EXIT CODES:                                                              */
  315. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  316. /*      MCIERR_INI_FILE  -- corrupted INI file, drive is not CD-ROM drive.  */
  317. /*      MCIERR_DEVICE_NOT_READY      -- device was not ready, no disc.      */
  318. /*      MCIERR_MEDIA_CHANGED         -- device was reopened.                */
  319. /*                                                                          */
  320. /* NOTES:                                                                   */
  321. /*                                                                          */
  322. /****************************************************************************/
  323. static ULONG CDAudErrRecov(PINST pInst)
  324. {
  325.    ULONG rc;
  326.  
  327.    /* Close the device */
  328.    DosClose(pInst->hDrive);
  329.    pInst->hDrive = 0;                    /* mark the instance structure */
  330.  
  331.    /* Try to reopen the device */
  332.    rc = CD01_Open(pInst);
  333.  
  334.    return(rc);
  335.  
  336. }  /* of CDAudErrRecov() */
  337.  
  338.  
  339.  
  340. /****************************************************************************/
  341. /*                                                                          */
  342. /* SUBROUTINE NAME:  CDAudClose                                             */
  343. /*                                                                          */
  344. /* DESCRIPTIVE NAME:  CD Audio Close                                        */
  345. /*                                                                          */
  346. /* FUNCTION:  Close a device dependent instance.                            */
  347. /*                                                                          */
  348. /* PARAMETERS:                                                              */
  349. /*      PINST pInst      -- Instance structure.                             */
  350. /*      ULONG ulParam1   -- Flag for this message.                          */
  351. /*                                                                          */
  352. /* EXIT CODES:                                                              */
  353. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  354. /*      MCIERR_INVALID_FLAG -- flag not supported by this VSD.              */
  355. /*                                                                          */
  356. /* NOTES:                                                                   */
  357. /*                                                                          */
  358. /****************************************************************************/
  359. static ULONG CDAudClose(PINST pInst, ULONG ulParam1)
  360. {
  361.    ULONG rc;
  362.  
  363.    if (ulParam1 & WAIT_NOTIFY_MASK)
  364.       rc = MCIERR_INVALID_FLAG;
  365.    else
  366.    {
  367.       pInst->Drive = '0';              /* destroy drive to prevent reopening */
  368.  
  369.       /* stop play & timer if one is going */
  370.       switch(pInst->usPlayFlag)
  371.       {
  372.          case TIMER_PLAY_SUSPEND :                 //suspended, stop only timer
  373.          case TIMER_PLAY_SUSP_2  :
  374.             if (DosWaitThread(&pInst->ulPlayTID, 1L) ==
  375.                                          ERROR_THREAD_NOT_TERMINATED)
  376.             {
  377.                pInst->usPlayFlag = TIMER_EXIT_ABORTED;
  378.                DosPostEventSem(pInst->hTimeLoopSem);  //continue timer loop
  379.             }
  380.             else
  381.                pInst->usPlayFlag = TIMER_AVAIL;
  382.             break;
  383.          case TIMER_PLAYING :                      //playing, stop device
  384.             CD01_Stop(pInst, TIMER_EXIT_ABORTED);
  385.             break;
  386.       }  /* of switch() */
  387.  
  388.       /* wait for commands to terminate */
  389.       while (pInst->usPlayFlag != TIMER_AVAIL)
  390.          DosSleep(HALF_TIME_MIN);
  391.  
  392.       DosClose(pInst->hDrive);
  393.       DosCloseMutexSem(pInst->hIOSem);
  394.       DosCloseMutexSem(pInst->hInstSem);
  395.       DosCloseEventSem(pInst->hTimeLoopSem);
  396.       DosCloseEventSem(pInst->hReturnSem);
  397.       HhpFreeMem(CDMC_hHeap, pInst);
  398.       rc = MCIERR_SUCCESS;                  /* assume all will work right */
  399.    }  /* of else flags were okay */
  400.  
  401.    return(rc);
  402.  
  403. }  /* of CDAudClose() */
  404.  
  405.  
  406.  
  407. /****************************************************************************/
  408. /*                                                                          */
  409. /* SUBROUTINE NAME:  CDAudInfo                                              */
  410. /*                                                                          */
  411. /* DESCRIPTIVE NAME:  CD Audio Information.                                 */
  412. /*                                                                          */
  413. /* FUNCTION:  Returns string information from a device driver.              */
  414. /*                                                                          */
  415. /* PARAMETERS:                                                              */
  416. /*      PINST pInst      -- Instance structure.                             */
  417. /*      ULONG ulParam1   -- Flag for this message.                          */
  418. /*      MCI_INFO_PARMS *pParam2 -- Pointer to data record structure.        */
  419. /*                                                                          */
  420. /* EXIT CODES:                                                              */
  421. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  422. /*      MCIERR_FLAGS_NOT_COMPATIBLE  -- Mis-match in flags.                 */
  423. /*      MCIERR_INVALID_BUFFER        -- Buffer too small.                   */
  424. /*      MCIERR_INVALID_FLAG          -- Unknown flag.                       */
  425. /*                                                                          */
  426. /* NOTES:                                                                   */
  427. /*      The CD ID and UPC is processed by the MCD.                          */
  428. /*                                                                          */
  429. /****************************************************************************/
  430. static ULONG CDAudInfo(PINST pInst, ULONG ulParam1, MCI_INFO_PARMS *pParam2)
  431. {
  432.    ULONG rc, ulLen;
  433.    USHORT i;
  434.  
  435.    ulParam1 &= WAIT_NOTIFY_MASK;
  436.  
  437.    if (ulParam1 == MCI_INFO_PRODUCT)
  438.    {
  439.       if (pParam2->ulRetSize >= INFO_SIZE)
  440.       {
  441.          ulLen = INFO_SIZE;
  442.          if (pParam2->ulRetSize > INFO_SIZE)   // if buffer is big enough
  443.             ulLen++;                           // capture the NULL
  444.          rc = MCIERR_SUCCESS;
  445.       }
  446.       else
  447.       {
  448.          ulLen = pParam2->ulRetSize;
  449.          rc = MCIERR_INVALID_BUFFER;
  450.       }
  451.  
  452.       /* fill in product information */
  453.       if (ulLen)   //if 0, it may be an invalid address
  454.          memcpy(pParam2->pszReturn, "IBMCD010", ulLen);
  455.       pParam2->ulRetSize = INFO_SIZE;
  456.  
  457.    }
  458.    else
  459.       rc = MCIERR_INVALID_FLAG;
  460.  
  461.    if (rc && rc != MCIERR_INVALID_BUFFER)
  462.       pParam2->ulRetSize = 0L;
  463.  
  464.    return(rc);
  465.  
  466. }  /* of CDAudInfo() */
  467.  
  468.  
  469.  
  470. /****************************************************************************/
  471. /*                                                                          */
  472. /* SUBROUTINE NAME:  CDAudOpen                                              */
  473. /*                                                                          */
  474. /* DESCRIPTIVE NAME:  CD Audio Open.                                        */
  475. /*                                                                          */
  476. /* FUNCTION:  Open a device dependent instance.                             */
  477. /*                                                                          */
  478. /* PARAMETERS:                                                              */
  479. /*      ULONG ulParam1   -- Flag for this message.                          */
  480. /*      MMDRV_OPEN_PARMS *pParam2 -- Pointer to data record structure.      */
  481. /*                                                                          */
  482. /* EXIT CODES:                                                              */
  483. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  484. /*      MCIERR_INI_FILE  -- corrupted INI file, drive is not CD-ROM drive.  */
  485. /*      MCIERR_OUT_OF_MEMORY       -- couldn't allocate memory for instance.*/
  486. /*      MCIERR_INVALID_FLAG -- flag not supported by this VSD.              */
  487. /*      MCIERR_DEVICE_LOCKED -- CD-ROM drive, previously opened exclusively.*/
  488. /*                                                                          */
  489. /* NOTES:                                                                   */
  490. /*                                                                          */
  491. /****************************************************************************/
  492. static ULONG CDAudOpen(ULONG ulParam1, MMDRV_OPEN_PARMS *pParam2)
  493. {
  494.    ULONG rc;
  495.    PINST pInst;
  496.    BYTE i;
  497.    ULONG ulDevParmLen;
  498.    PVOID pVSDParm;
  499.    CHAR *pDrive, *pModel;
  500.  
  501.    /* validate flags */
  502.    /* this VSD will only support standard flags */
  503.    ulParam1 &= WAIT_NOTIFY_MASK;
  504.    if (ulParam1)
  505.       rc = MCIERR_INVALID_FLAG;
  506.    else
  507.    {
  508.       /* get memory */
  509.       pInst = HhpAllocMem(CDMC_hHeap, sizeof(struct instance_state));
  510.       if (pInst == NULL)
  511.          rc = MCIERR_OUT_OF_MEMORY;
  512.       else
  513.       {
  514.          /* create semaphore so only one IOCLT call will be made at a time */
  515.          rc = DosCreateMutexSem((PSZ) NULL, &pInst->hIOSem, 0L, FALSE);
  516.          if (!rc)
  517.             rc = DosCreateEventSem((PSZ) NULL, &pInst->hTimeLoopSem, 0L, FALSE);
  518.          if (!rc)
  519.             rc = DosCreateMutexSem((PSZ) NULL, &pInst->hInstSem, 0L, FALSE);
  520.          if (!rc)
  521.             rc = DosCreateEventSem((PSZ) NULL, &pInst->hReturnSem, 0L, FALSE);
  522.          if (rc)
  523.          {
  524.             DosCloseMutexSem(pInst->hIOSem);
  525.             DosCloseMutexSem(pInst->hInstSem);
  526.             DosCloseEventSem(pInst->hTimeLoopSem);
  527.             DosCloseEventSem(pInst->hReturnSem);
  528.             rc = MCIERR_OUT_OF_MEMORY;
  529.  
  530.          }  /* of if error creating semaphores */
  531.       }  /* else no error creating instance structure's memory */
  532.  
  533.       /* init instance */
  534.       if (!rc)
  535.       {  /* instance entry created */
  536.          /* init instance */
  537.          pInst->hDrive = 0;                     // drive handle
  538.          pInst->ulCurPos = 0L;                  // set current position;
  539.          pInst->usDeviceID = pParam2->usDeviceID;
  540.  
  541.          /* validate and get drive & hardware type */
  542.          /* copy string so that it doesn't get disturb */
  543.          ulDevParmLen = strlen(pParam2->pDevParm) + 1;
  544.          pVSDParm = HhpAllocMem(CDMC_hHeap, ulDevParmLen);
  545.          strcpy(pVSDParm, pParam2->pDevParm);
  546.          parse_DevParm((CHAR *)pVSDParm, &pDrive, &pModel);
  547.          pInst->Drive = *pDrive;
  548.          strncpy(pInst->szModel, pModel, MODEL_SIZE);
  549.          pInst->szModel[MODEL_SIZE - 1] = '\0';     //make sure NULL terminated
  550.  
  551.          HhpFreeMem(CDMC_hHeap, pVSDParm);
  552.          QueryTable(pInst);                   // id drive and get capabilities
  553.  
  554.          pInst->qptPosAdvise.ulEvent = 0L;
  555.          for (i=0; i < CDMCD_CUEPOINT_MAX; i++)          // init arrays
  556.             pInst->arrCuePoint[i].ulEvent = (ULONG) -1L;
  557.  
  558.          pInst->usPlayFlag = TIMER_AVAIL;
  559.          pInst->ulPlayTID  = 0L;
  560.          pInst->DiscID.ulLeadOut = 0L;         // used as a first time flag
  561.          pInst->StreamMaster = FALSE;
  562.  
  563.          /* Try opening the device.  Ignore things like disc not present, */
  564.          /* but report errors involving the INI file or that the drive    */
  565.          /* was previously opened in an exclusive mode.                   */
  566.          rc = CD01_Open(pInst);
  567.          if (rc != MCIERR_INI_FILE && rc != MCIERR_DEVICE_LOCKED)
  568.             rc = MCIERR_SUCCESS;        /* pretend that all went well */
  569.  
  570.       }  /* of if no errors getting memory */
  571.  
  572.       if (rc)                                  /* if error, free memory */
  573.          HhpFreeMem(CDMC_hHeap, pInst);
  574.       else
  575.          pParam2->pInstance = pInst;           /* pass pointer back */
  576.  
  577.    }  /* of else no invalid flags */
  578.  
  579.    return(rc);
  580.  
  581. }  /* of CDAudOpen() */
  582.  
  583.  
  584.  
  585. /****************************************************************************/
  586. /*                                                                          */
  587. /* SUBROUTINE NAME:  CDAudRegDisc                                           */
  588. /*                                                                          */
  589. /* DESCRIPTIVE NAME:  CD Audio Register Compact Disc.                       */
  590. /*                                                                          */
  591. /* FUNCTION:  Register a CD media so that the disc may be recognized by     */
  592. /*            the calling MCD.                                              */
  593. /*                                                                          */
  594. /* PARAMETERS:                                                              */
  595. /*      PINST  pInst     -- Instance structure.                             */
  596. /*      USHORT usFlag    -- Action Flag to copy into pParam2.               */
  597. /*      MCI_CD_REGDISC_PARMS *pParam2 -- Pointer to data record.            */
  598. /*                                                                          */
  599. /* EXIT CODES:                                                              */
  600. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  601. /*      MCIERR_DEVICE_NOT_READY      -- device was not ready, no disc.      */
  602. /*                                                                          */
  603. /* NOTES:                                                                   */
  604. /*                                                                          */
  605. /****************************************************************************/
  606. ULONG CDAudRegDisc(PINST pInst, USHORT usFlag, MCI_CD_REGDISC_PARMS *pParam2)
  607. {
  608.    ULONG rc;
  609.    USHORT i;
  610.    BYTE lowest, highest;
  611.    ULONG ulDataLen = STANDRD_DMAX, ulParamLen = STANDRD_PMAX;
  612.    MCI_CD_ID DiscID;
  613.  
  614.    memcpy(&DiscID, &pInst->DiscID, sizeof(MCI_CD_ID));  //save original
  615.  
  616.    if (usFlag == REG_BOTH || usFlag == REG_INST)
  617.    {   /* register with the internal instance */
  618.       rc = CD01_GetID(pInst, &pInst->DiscID, &lowest, &highest);
  619.       if (!rc && usFlag == REG_BOTH)
  620.          /* copy information to external source */
  621.          memcpy(&pParam2->DiscID, &pInst->DiscID, sizeof(MCI_CD_ID));
  622.    }   /* of if update instance structure */
  623.    else      /* the flag is REG_PARAM2 */
  624.       rc = CD01_GetID(pInst, &pParam2->DiscID, &lowest, &highest);
  625.  
  626.    /* complete registration for param2 */
  627.    if (!rc && (usFlag == REG_BOTH || usFlag == REG_PARAM2))
  628.    {
  629.       /* get low and high track numbers */
  630.       pParam2->LowestTrackNum  = lowest;
  631.       pParam2->HighestTrackNum = highest;
  632.  
  633.       /* get upc code -- device cannot do this so set this to zero */
  634.       for (i=0; i < UPC_SIZE; i++)
  635.          pParam2->UPC[i] = 0;
  636.  
  637.    }  /* of if need to complete Param2 */
  638.  
  639.    return(rc);
  640.  
  641. }  /* of CDAudRegDisc() */
  642.  
  643.  
  644.  
  645. /****************************************************************************/
  646. /*                                                                          */
  647. /* SUBROUTINE NAME:  CDAudRegDrive                                          */
  648. /*                                                                          */
  649. /* DESCRIPTIVE NAME:  CD Audio Register CD-ROM Drive and its capabilities.  */
  650. /*                                                                          */
  651. /* FUNCTION:  Register a CD drive so that the disc may be recognized by     */
  652. /*            the calling MCD.                                              */
  653. /*                                                                          */
  654. /* PARAMETERS:                                                              */
  655. /*      PINST pInst      -- Instance structure.                             */
  656. /*      MCI_CD_REGDRIVE_PARMS *pParam2 -- Pointer to data record.           */
  657. /*                                                                          */
  658. /* EXIT CODES:                                                              */
  659. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  660. /*                                                                          */
  661. /* NOTES:                                                                   */
  662. /*                                                                          */
  663. /****************************************************************************/
  664. static ULONG CDAudRegDrive(PINST pInst, MCI_CD_REGDRIVE_PARMS *pParam2)
  665. {
  666.    /* get the CD MCD return function information */
  667.    pInst->ulCDMCDID    = pParam2->ulCDMCDID;
  668.    pInst->pCDMCDReturn = pParam2->pCDMCDReturn;
  669.  
  670.    /* fill in capabilities */
  671.    pParam2->usCaps = CD01_CAPS;       //This example supports the IBM 3510-001
  672.  
  673.    /* fill in preroll information */
  674.    pParam2->ulPrerollType  = MCI_PREROLL_NONE;
  675.    pParam2->ulPrerollTime  = 0L;
  676.    pParam2->ulMinStartTime = SPEC_START;
  677.  
  678.    return(MCIERR_SUCCESS);
  679.  
  680. }  /* of CDAudRegDrive() */
  681.  
  682.  
  683.  
  684. /****************************************************************************/
  685. /*                                                                          */
  686. /* SUBROUTINE NAME:  CDAudSet                                               */
  687. /*                                                                          */
  688. /* DESCRIPTIVE NAME:  CD Audio Set.                                         */
  689. /*                                                                          */
  690. /* FUNCTION:  Set features and attributes of the CD-ROM drive.              */
  691. /*                                                                          */
  692. /* PARAMETERS:                                                              */
  693. /*      PINST  pInst      -- Instance structure.                            */
  694. /*      ULONG  *pulParam1 -- Flag for this message.                         */
  695. /*      MCI_SET_PARMS *pParam2   -- Pointer to data record structure.       */
  696. /*                                                                          */
  697. /* EXIT CODES:                                                              */
  698. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  699. /*      MCIERR_UNSUPPORTED_FLAG      -- unsupported flag.                   */
  700. /*      MCIERR_INVALID_FLAG          -- Unknown flag.                       */
  701. /*      MCIERR_DEVICE_NOT_READY      -- device was not ready, no disc.      */
  702. /*                                                                          */
  703. /* NOTES:  Mutual Exclusive flags (LOCK/UNLOCK & OPEN/CLOSE DOOR) are       */
  704. /*         tested in the MCD.                                               */
  705. /*                                                                          */
  706. /****************************************************************************/
  707. static ULONG CDAudSet(PINST pInst, ULONG *pulParam1, MCI_SET_PARMS *pParam2)
  708. {
  709.    ULONG rc;
  710.    ULONG ulDataLen = STANDRD_DMAX, ulParamLen = STANDRD_PMAX;
  711.    ULONG ulType;
  712.  
  713.    /* validate flags */
  714.    rc = CDAudSetVerify(*pulParam1);
  715.  
  716.    if (!rc)
  717.    {
  718.       ulType = *pulParam1 & WAIT_NOTIFY_MASK;
  719.  
  720.       if (ulType & MCI_SET_DOOR_OPEN)
  721.       {
  722.          /* hardware does not support eject if playing, so stop it. */
  723.          if (pInst->usPlayFlag == TIMER_PLAYING)
  724.             rc = CD01_Stop(pInst, TIMER_EXIT_ABORTED);
  725.  
  726.          if (!rc)             // no error, proceed, else disc is already out
  727.          {
  728.             /* make sure that door is unlocked so eject can be successful */
  729.             CD01_LockDoor(pInst, MCI_FALSE);
  730.             CallIOCtl(pInst, CDDRIVE_CAT, EJECT__DISK,
  731.                       "CD01", ulParamLen, &ulParamLen,
  732.                        NULL,  ulDataLen,  &ulDataLen);
  733.          }
  734.          rc = MCIERR_SUCCESS;
  735.  
  736.       }  /* of if EJECTing disc */
  737.  
  738.       if (ulType & MCI_SET_DOOR_LOCK)
  739.          rc = CD01_LockDoor(pInst, MCI_TRUE);
  740.       else if (ulType & MCI_SET_DOOR_UNLOCK)
  741.          rc = CD01_LockDoor(pInst, MCI_FALSE);
  742.  
  743.       if (ulType & MCI_SET_VOLUME)
  744.          /* Hardware for example cannot support vectored volume */
  745.          rc = CD01_SetVolume(pInst, pParam2->ulLevel);
  746.  
  747.    }  /* of if no error */
  748.  
  749.    return(rc);
  750.  
  751. }  /* of CDAudSet() */
  752.  
  753.  
  754.  
  755. /****************************************************************************/
  756. /*                                                                          */
  757. /* SUBROUTINE NAME:  CDAudSetVerify                                         */
  758. /*                                                                          */
  759. /* DESCRIPTIVE NAME:  CD Audio Set Verify                                   */
  760. /*                                                                          */
  761. /* FUNCTION:  Verify flags for SET command.  This function is called by     */
  762. /*            the MCD to validate flags prior to calling other components,  */
  763. /*            like the Amp/Mixer or SSM, to process their flags.            */
  764. /*                                                                          */
  765. /* PARAMETERS:                                                              */
  766. /*      ULONG ulParam1   -- Flag for this message.                          */
  767. /*                                                                          */
  768. /* EXIT CODES:                                                              */
  769. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  770. /*      MCIERR_UNSUPPORTED_FLAG      -- unsupported flag.                   */
  771. /*      MCIERR_INVALID_FLAG          -- Unknown flag.                       */
  772. /*                                                                          */
  773. /* NOTES:  Mutual Exclusive flags (LOCK/UNLOCK & OPEN/CLOSE DOOR) are       */
  774. /*         tested in the MCD.                                               */
  775. /*                                                                          */
  776. /****************************************************************************/
  777. static ULONG CDAudSetVerify(ULONG ulParam1)
  778. {
  779.    ULONG rc = MCIERR_SUCCESS;
  780.  
  781.    /* check unsupported flags */
  782.    if (ulParam1 & MCI_SET_DOOR_CLOSED)
  783.       rc = MCIERR_UNSUPPORTED_FLAG;
  784.    else
  785.       /* check unknown flags */
  786.       if (ulParam1 & ~(MCI_SET_DOOR_OPEN   | MCI_SET_DOOR_LOCK |
  787.                        MCI_SET_DOOR_UNLOCK | MCI_SET_VOLUME | MCI_OVER |
  788.                        MCI_NOTIFY | MCI_WAIT))
  789.          rc = MCIERR_INVALID_FLAG;
  790.  
  791.    return(rc);
  792.  
  793. }  /* of CDAudSetVerify() */
  794.  
  795.  
  796.  
  797. /****************************************************************************/
  798. /*                                                                          */
  799. /* SUBROUTINE NAME:  CDAudStatus                                            */
  800. /*                                                                          */
  801. /* DESCRIPTIVE NAME:  CD Audio Status.                                      */
  802. /*                                                                          */
  803. /* FUNCTION:  Query and return the status of the features and attributes    */
  804. /*            of the CD-ROM drive.                                          */
  805. /*                                                                          */
  806. /* PARAMETERS:                                                              */
  807. /*      PINST pInst      -- Instance structure.                             */
  808. /*      ULONG ulParam1   -- Flag for this message.                          */
  809. /*      MCI_STATUS_PARMS *pParam2   -- Pointer to data record structure.    */
  810. /*                                                                          */
  811. /* EXIT CODES:                                                              */
  812. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  813. /*      MCIERR_DEVICE_NOT_READY      -- device was not ready, no disc.      */
  814. /*      MCIERR_FLAGS_NOT_COMPATIBLE  -- Mis-match in flags.                 */
  815. /*      MCIERR_UNSUPPORTED_FUNCTION  -- Flags not supported.                */
  816. /*      MCIERR_INVALID_FLAG          -- Unknown flag.                       */
  817. /*      MCIERR_INVALID_ITEM_FLAG     -- Unknown item specified.             */
  818. /*                                                                          */
  819. /* NOTES:                                                                   */
  820. /*                                                                          */
  821. /****************************************************************************/
  822. static ULONG CDAudStatus(PINST pInst,
  823.                          ULONG ulParam1, MCI_STATUS_PARMS *pParam2)
  824. {
  825.    ULONG rc;
  826.  
  827.    ulParam1 &= WAIT_NOTIFY_MASK;
  828.  
  829.    /* verify flags */
  830.    if (ulParam1 & MCI_STATUS_ITEM)
  831.       if (ulParam1 != MCI_STATUS_ITEM)
  832.          if (ulParam1 & MCI_STATUS_START && ulParam1 & MCI_TRACK)
  833.             rc = MCIERR_FLAGS_NOT_COMPATIBLE;
  834.          else
  835.             rc = MCIERR_INVALID_FLAG;
  836.       else
  837.          rc = MCIERR_SUCCESS;
  838.    else                                      // no ITEM flag
  839.       if (ulParam1 & MCI_TRACK)
  840.          rc = MCIERR_MISSING_FLAG;
  841.       else if (ulParam1 & MCI_STATUS_START)
  842.          rc = MCIERR_MISSING_FLAG;
  843.       else
  844.          rc = MCIERR_INVALID_FLAG;
  845.  
  846.    if (!rc)                         // ulParam1 == MCI_STATUS_ITEM only
  847.    {
  848.       switch(pParam2->ulItem)
  849.       {
  850.          case MCI_STATUS_POSITION :
  851.             rc = CD01_GetPosition(pInst, &pParam2->ulReturn);
  852.             break;
  853.          case MCI_STATUS_VOLUME :
  854.             rc = CD01_GetVolume(pInst, &pParam2->ulReturn);
  855.             break;
  856.          case MCI_STATUS_MEDIA_PRESENT :
  857.          case MCI_STATUS_MODE :
  858.          case MCI_STATUS_READY :
  859.             rc = CD01_GetDiscInfo(pInst, pParam2->ulItem, pParam2);
  860.             break;
  861.          default :
  862.             rc = MCIERR_INVALID_ITEM_FLAG;
  863.  
  864.       }  /* of item switch */
  865.    }  /* of if valid flag */
  866.  
  867.    return(rc);
  868.  
  869. }  /* of CDAudStatus() */
  870.  
  871.  
  872.  
  873. /****************************************************************************/
  874. /*                                                                          */
  875. /* SUBROUTINE NAME:  CDAudStatCVol                                          */
  876. /*                                                                          */
  877. /* DESCRIPTIVE NAME:  CD Audio Status Component Volume.                     */
  878. /*                                                                          */
  879. /* FUNCTION:  Remaps the component volume to what it would be from the      */
  880. /*            hardware if master audio was at 100%.                         */
  881. /*                                                                          */
  882. /* PARAMETERS:                                                              */
  883. /*      ULONG *pulLevel  -- Pointer to volume level.                        */
  884. /*                                                                          */
  885. /* EXIT CODES:                                                              */
  886. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  887. /*                                                                          */
  888. /* NOTES:                                                                   */
  889. /*                                                                          */
  890. /****************************************************************************/
  891. ULONG CDAudStatCVol(ULONG *pulLevel)
  892. {
  893.    USHORT usLeft, usRight;
  894.  
  895.    usLeft = LOUSHORT(*pulLevel);
  896.    usRight = HIUSHORT(*pulLevel);
  897.  
  898.    if (usLeft) usLeft = 100; else usLeft = 0;
  899.    if (usRight) usRight = 100; else usRight = 0;
  900.  
  901.    /* Adjust for hardware limitations, VOL = MAX(Left, Right) */
  902.    if (usLeft && usRight)
  903.       if (usLeft > usRight)
  904.          usRight = usLeft;
  905.       else
  906.          usLeft = usRight;
  907.  
  908.    *pulLevel = MAKEULONG(usLeft, usRight);
  909.  
  910.    return(MCIERR_SUCCESS);
  911.  
  912. }  /* of CDAudStatCVol() */
  913.  
  914.  
  915.  
  916.