home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / viscobv6.zip / vac22os2 / ibmcobol / samples / toolkit / mm / cdmcidrv / ibmcdmsc.c < prev    next >
C/C++ Source or Header  |  1996-11-19  |  35KB  |  756 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /* SOURCE FILE NAME:  IBMCDMSC.C                                            */
  4. /*                                                                          */
  5. /* DESCRIPTIVE NAME:  IBM CD-ROMs Miscellaneous                             */
  6. /*                                                                          */
  7. /* COPYRIGHT:  (c) IBM Corp. 1990 - 1993                                    */
  8. /*                                                                          */
  9. /* FUNCTION:  This file contains miscellaneous functions such as the timer  */
  10. /*            routine for the MCI_PLAY command, querying the CD table, and  */
  11. /*            packaging the IOCTL calls.                                    */
  12. /*                                                                          */
  13. /*                                                                          */
  14. /* FUNCTIONS:                                                               */
  15. /*       CD01_StartPlay     - Start the play operation.                     */
  16. /*       CD01_Sync          - Sync to MDM request.                          */
  17. /*       CD01_Timer         - Timer routine for play operation.             */
  18. /*       CD01_TimerNotify   - Timer routine to setup and notify events.     */
  19. /*       GetTableName       - Get the full path name of the CD table.       */
  20. /*       OpenFirstTime      - First time device open tests.                 */
  21. /*       QueryTable         - Query CD look-up table.                       */
  22. /*       CallIOCtl          - Call the hardware via IOCTLs.                 */
  23. /*                                                                          */
  24. /*       NOTE:  CD01_... refers to commands that are compatible with the    */
  25. /*              IBM 3510 CD-ROM drive.  CD02_... may refer to commands      */
  26. /*              that are compatible with the CD02 drives, which are         */
  27. /*              not compatible with the CD01_... commands.  This way        */
  28. /*              different hardware can share the same VSD.                  */
  29. /*                                                                          */
  30. /*                                                                          */
  31. /****************************************************************************/
  32.  
  33. #define INCL_DOS
  34. #define INCL_DOSERRORS
  35. #define INCL_DOSDEVICES
  36. #define INCL_DOSPROCESS
  37. #define INCL_DOSFILEMGR
  38. #define INCL_DOSSEMAPHORES
  39. #define INCL_WINSHELLDATA
  40. #include <os2.h>
  41. #include <string.h>
  42. #include <stdlib.h>
  43. #define INCL_MCIOS2
  44. #include <os2me.h>
  45. #include <cdaudos2.h>
  46. #include "ibmcdrom.h"
  47.  
  48.  
  49. /****************************************************************************/
  50. /*                                                                          */
  51. /* SUBROUTINE NAME:  CD01_StartPlay                                         */
  52. /*                                                                          */
  53. /* DESCRIPTIVE NAME:  CD Start Play.                                        */
  54. /*                                                                          */
  55. /* FUNCTION:  Start playing audio data to internal DAC(s).                  */
  56. /*                                                                          */
  57. /* PARAMETERS:                                                              */
  58. /*      PINST pInst       -- Instance pointer.                              */
  59. /*                                                                          */
  60. /* EXIT CODES:                                                              */
  61. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  62. /*      MCIERR_DEVICE_NOT_READY  -- device was not ready, no disc.          */
  63. /*      MCIERR_MEDIA_CHANGED     -- Disc changed.                           */
  64. /*                                                                          */
  65. /* NOTES:                                                                   */
  66. /*                                                                          */
  67. /****************************************************************************/
  68. ULONG CD01_StartPlay(PINST pInst)
  69. {
  70.    ULONG rc;
  71.    BYTE param[PLAYAUD_PMAX] = {'C', 'D', '0', '1', RBMODE};
  72.    ULONG ulDataLen = STANDRD_DMAX, ulParamLen = PLAYAUD_PMAX;
  73.    ULONG cnt;
  74.    PTIB ptib;
  75.    PPIB ppib;
  76.  
  77.    /* convert MM Time into Redbook 2 format */
  78.    * (ULONG *)¶m[STARTFFFLD] = REDBOOK2FROMMM(pInst->ulCurPos);
  79.    * (ULONG *)¶m[END_FF_FLD] = REDBOOK2FROMMM(pInst->ulEndPos);
  80.  
  81.    /* play drive */
  82.    rc = CallIOCtl(pInst, CDAUDIO_CAT, PLAY__AUDIO,
  83.                   param, ulParamLen, &ulParamLen,
  84.                   NULL,  ulDataLen,  &ulDataLen);
  85.  
  86.    if (!rc)
  87.    {
  88.       /* set timer play flag */
  89.       pInst->usPlayFlag = TIMER_PLAYING;
  90.       DosGetInfoBlocks(&ptib, &ppib);
  91.       pInst->ulPlayTID = ptib->tib_ptib2->tib2_ultid;
  92.       DosResetEventSem(pInst->hTimeLoopSem, &cnt);  // force a wait in timer
  93.  
  94.    }  /* if no error */
  95.  
  96.    /* original thread owns Mutex sem,               */
  97.    /* if not WAIT tell original thead to release it */
  98.    if (pInst->usPlayNotify == MCI_WAIT)
  99.       DosReleaseMutexSem(pInst->hInstSem);
  100.    else
  101.       DosPostEventSem(pInst->hReturnSem);
  102.  
  103.    return(rc);
  104.  
  105. }  /* of CD01_StartPlay() */
  106.  
  107.  
  108.  
  109. /****************************************************************************/
  110. /*                                                                          */
  111. /* SUBROUTINE NAME:  CD01_Sync                                              */
  112. /*                                                                          */
  113. /* DESCRIPTIVE NAME:  CD Synchronization.                                   */
  114. /*                                                                          */
  115. /* FUNCTION:  Process SYNC messages from MCIDRV_SYNC message.               */
  116. /*                                                                          */
  117. /* PARAMETERS:                                                              */
  118. /*      PINST pInst      -- Instance pointer.                               */
  119. /*      ULONG ulParam1   -- Flag for this message.                          */
  120. /*      MCIDRV_SYNC_PARMS *pParam2 -- pointer to record structure.          */
  121. /*                                                                          */
  122. /* EXIT CODES:                                                              */
  123. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  124. /*      MCIERR_DEVICE_NOT_READY      -- device was not ready, no disc.      */
  125. /*      MCIERR_INVALID_FLAG          -- Unknown flag.                       */
  126. /*                                                                          */
  127. /* NOTES:                                                                   */
  128. /*                                                                          */
  129. /****************************************************************************/
  130. ULONG CD01_Sync(PINST pInst, ULONG ulParam1, MCIDRV_SYNC_PARMS *pParam2)
  131. {
  132.    ULONG  rc = MCIERR_SUCCESS;
  133.    ULONG  ulPosition;
  134.    MMTIME mmTime;
  135.    LONG   lDelta;
  136.    CHAR   szBuf[SSM_LOAD_SIZE];
  137.    HMODULE hMod;                         // handle to SSM module
  138.  
  139.    ulParam1 &= WAIT_NOTIFY_MASK;
  140.  
  141.    switch (ulParam1)
  142.    {
  143.       case MCIDRV_SYNC_ENABLE :
  144.          pParam2->pevcbSyncPulse  = &pInst->evcbSync;
  145.          pParam2->NonStreamMaster = TRUE;
  146.          break;
  147.       case MCIDRV_SYNC_DISABLE :
  148.          pInst->StreamMaster = FALSE;
  149.          break;
  150.       case MCIDRV_SYNC_MASTER :
  151.          pInst->StreamMaster = TRUE;                  // set master stream flag
  152.          pInst->RptEvent.hid = pParam2->hidMaster;    // store id for SSM calls
  153.          pInst->RptEvent.pevcbEvent = (PEVCB) &pInst->evcbSync;
  154.          pInst->evcbSync.mmtimeMaster = (MMTIME) pInst->ulCurPos;   // set time
  155.  
  156.          /* get SSM loaded, if not yet loaded */
  157.          if (pInst->pSyncNotify == NULL)
  158.          {
  159.             rc = DosLoadModule(szBuf, SSM_LOAD_SIZE, "SSM", &hMod);
  160.             if (!rc)
  161.                rc = DosQueryProcAddr(hMod, 0L, "SMHEntryPoint",
  162.                                &pInst->pSyncNotify);
  163.             if (rc)
  164.             {
  165.                pInst->pSyncNotify = NULL;
  166.                rc = MCIERR_CANNOT_LOAD_DRIVER;
  167.             }  /* of if error */
  168.          }  /* of if need to get sync entry point */
  169.          break;
  170.       case MCIDRV_SYNC_REC_PULSE :
  171.          /* get current position */
  172.          CD01_GetPosition(pInst, &ulPosition);
  173.  
  174.          mmTime = pInst->evcbSync.mmtimeMaster;
  175.          lDelta = ulPosition - mmTime - SYNC_LATENCY;
  176.          if (lDelta < -SYNC_TOLERANCE || lDelta > SYNC_TOLERANCE)
  177.             rc = CD01_PlayCont(pInst, (ULONG) mmTime, pInst->ulEndPos);
  178.          pInst->evcbSync.mmtimeSlave = mmTime;         // reset current time
  179.          /* Clear Sync Flags */
  180.          pInst->evcbSync.ulSyncFlags &= ~(SYNCOVERRUN | SYNCPOLLING);
  181.          break;
  182.       default :
  183.          rc = MCIERR_INVALID_FLAG;
  184.    }  /* of switch */
  185.  
  186.    return(rc);
  187.  
  188. }  /* of CD01_Sync() */
  189.  
  190.  
  191.  
  192. /****************************************************************************/
  193. /*                                                                          */
  194. /* SUBROUTINE NAME:  CD01_Timer                                             */
  195. /*                                                                          */
  196. /* DESCRIPTIVE NAME:  CD Timer                                              */
  197. /*                                                                          */
  198. /* FUNCTION:  Queries the device once a second to determine is a play       */
  199. /*            command is still going on.                                    */
  200. /*                                                                          */
  201. /* PARAMETERS:                                                              */
  202. /*      PINST pInst      -- Instance pointer.                               */
  203. /*                                                                          */
  204. /* EXIT CODES:                                                              */
  205. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  206. /*      MCIERR_DEVICE_NOT_READY  -- device was not ready, no disc.          */
  207. /*      MCIERR_MEDIA_CHANGED     -- Disc changed on restore as reported by  */
  208. /*                                  MCD.  Return error on play thread.      */
  209. /*                                                                          */
  210. /* NOTES:                                                                   */
  211. /*                                                                          */
  212. /****************************************************************************/
  213. ULONG CD01_Timer(PINST pInst)
  214. {
  215.    ULONG rc;
  216.    ULONG ulDelay, ulPrevLimit;
  217.    ULONG ulPosAdvise = 0L, ulSyncPos = 0L, ulOldPosAdvise = 0L;
  218.    BYTE dataAud[AUDSTAT_DMAX];    //values for the audio status command
  219.    BYTE dataPos[LOCATON_DMAX],
  220.           param[LOCATON_PMAX] = {'C', 'D', '0', '1', RBMODE};
  221.    ULONG ulDataLen, ulParamLen;
  222.    ULONG cnt, DoLoop = TRUE;
  223.    USHORT usNotifyType = MCI_NOTIFY_SUCCESSFUL;
  224.  
  225.    /* start playing */
  226.    rc = CD01_StartPlay(pInst);
  227.    ulPrevLimit = pInst->ulCurPos;
  228.  
  229.    if (!rc)
  230.    do
  231.    {
  232.       /* check position advise before calling notification routine. */
  233.       /* event must be multiple address relative to address 0.      */
  234.       if (pInst->qptPosAdvise.ulEvent != ulOldPosAdvise)
  235.       {
  236.          ulOldPosAdvise = pInst->qptPosAdvise.ulEvent;
  237.          if (ulOldPosAdvise)
  238.             if (pInst->ulCurPos % ulOldPosAdvise)    //if past, get next one
  239.                ulPosAdvise = (pInst->ulCurPos / ulOldPosAdvise + 1)
  240.                               * ulOldPosAdvise;
  241.             else
  242.                ulPosAdvise = pInst->ulCurPos;
  243.          else
  244.             ulPosAdvise = 0L;
  245.       }  /* of if position advise changed */
  246.  
  247.       ulDelay = CD01_TimerNotify(pInst, &ulPosAdvise, &ulSyncPos, &ulPrevLimit);
  248.  
  249.       /********************************************************************
  250.        * wait on the semaphore.  If the instance is PAUSED or being SAVED *
  251.        * (no longer active) then wait until RESUME or RESTORE clears the  *
  252.        * semaphore.  If a destructive STOP is received, the wait will     *
  253.        * terminate immediately.  Otherwise, wait as long as ulDelay.      *
  254.        ********************************************************************/
  255.  
  256.       if (!DosWaitEventSem(pInst->hTimeLoopSem, ulDelay))
  257.          /* semaphore is cleared.  Reset it incase we don't exit loop */
  258.          DosResetEventSem(pInst->hTimeLoopSem, &cnt);
  259.  
  260.       /* get new position */
  261.       ulDataLen  = LOCATON_DMAX;
  262.       ulParamLen = LOCATON_PMAX;
  263.       rc = CallIOCtl(pInst, CDDRIVE_CAT, Q__LOCATION,
  264.                      param,   ulParamLen, &ulParamLen,
  265.                      dataPos, ulDataLen,  &ulDataLen);
  266.  
  267.       /* The only way to receive a media change rc is when closing   *
  268.        * an inactive instance after a disc change, process the abort */
  269.       if (rc)
  270.          if (rc == MCIERR_MEDIA_CHANGED)
  271.             rc = MCIERR_SUCCESS;
  272.          else   // an error occurred, break out of the loop
  273.             break;
  274.  
  275.       switch (pInst->usPlayFlag)
  276.       {
  277.          case TIMER_EXIT_SUPER :
  278.             usNotifyType = MCI_NOTIFY_SUPERSEDED;
  279.             DoLoop = FALSE;
  280.             break;
  281.          case TIMER_EXIT_ABORTED :
  282.             usNotifyType = MCI_NOTIFY_ABORTED;
  283.             DoLoop = FALSE;
  284.             break;
  285.          case TIMER_EXIT_CHANGED :
  286.             rc = MCIERR_MEDIA_CHANGED;
  287.             DoLoop = FALSE;
  288.             break;
  289.          case TIMER_AVAIL :
  290.             rc = MCIERR_DRIVER_INTERNAL;       // abondon ship
  291.             DoLoop = FALSE;
  292.             break;
  293.          case TIMER_PLAY_SUSPEND :             // do nothing
  294.          case TIMER_PLAY_SUSP_2  :
  295.             break;
  296.          case TIMER_PLAYING :
  297.             /* update current location */
  298.             pInst->ulCurPos = REDBOOK2TOMM(*(ULONG *)dataPos);
  299.  
  300.             DosRequestMutexSem(pInst->hIOSem, (ULONG)-1L);
  301.  
  302.             /* check if drive is still playing */
  303.             ulDataLen  = AUDSTAT_DMAX;
  304.             ulParamLen = STANDRD_PMAX;
  305.             if (DosDevIOCtl(pInst->hDrive, CDDRIVE_CAT, DEV__STATUS,
  306.                             "CD01",  ulParamLen, &ulParamLen,
  307.                             dataAud, ulDataLen,  &ulDataLen))
  308.             {                         // Error
  309.                rc = MCIERR_DEVICE_NOT_READY;
  310.                DoLoop = FALSE;
  311.             }  /* of if error calling device */
  312.             else
  313.             {
  314.                if (!(dataAud[STATAUDFLD] & IS_PLAYING))      // if NOT Playing
  315.                {
  316.                   /* check to see if PLAY terminated or was STOPPED/PAUSED */
  317.                   ulDataLen  = AUDSTAT_DMAX;
  318.                   ulParamLen = STANDRD_PMAX;
  319.                   if (DosDevIOCtl(pInst->hDrive, CDAUDIO_CAT, AUD__STATUS,
  320.                                   "CD01",  ulParamLen, &ulParamLen,
  321.                                   dataAud, ulDataLen,  &ulDataLen))
  322.                   {
  323.                      rc = MCIERR_DEVICE_NOT_READY;
  324.                      DoLoop = FALSE;
  325.                   }  /* of if error calling device */
  326.                   else
  327.                      if (!(dataAud[AUDSTATFLD] & WAS_STOPPED))
  328.                      {     /* PLAY command finished */
  329.                         rc = MCIERR_SUCCESS;
  330.                         DoLoop = FALSE;
  331.                         pInst->ulCurPos = pInst->ulEndPos;
  332.                      }  /* of else PLAY command terminated itself (finished) */
  333.                      /* else it is paused, continue the clock */
  334.  
  335.                }  /* of if NOT Playing */
  336.             }  /* of else no error querying status */
  337.  
  338.             DosReleaseMutexSem(pInst->hIOSem);
  339.             break;
  340.          default :
  341.             rc = MCIERR_DRIVER_INTERNAL;       // unknown play flag
  342.             DoLoop = FALSE;
  343.             break;
  344.  
  345.       }   /* of switch on play flag */
  346.    } while(DoLoop);  /* of do loop */
  347.  
  348.    if (!rc)         // if no error, report any events
  349.       CD01_TimerNotify(pInst, &ulPosAdvise, &ulSyncPos, &ulPrevLimit);
  350.  
  351.    pInst->ulPlayTID  = 0L;                     // clear before exit or return
  352.  
  353.    if (pInst->usPlayNotify != MCI_WAIT)
  354.    {
  355.       if (rc)
  356.          usNotifyType = (USHORT) rc;
  357.  
  358.       /* inform MDM that play has terminated */
  359.       if (pInst->usPlayNotify == MCI_NOTIFY)
  360.          mdmDriverNotify(pInst->usDeviceID, pInst->hwndPlayCallback,
  361.                          MM_MCINOTIFY, pInst->usPlayUserParm,
  362.                          MAKEULONG(MCI_PLAY, usNotifyType));
  363.  
  364.       /* inform MCD that play has terminated */
  365.       pInst->pCDMCDReturn(pInst->ulCDMCDID, MAKEULONG(MCI_PLAY, usNotifyType),
  366.                           0L);               //MCD ignores 3rd field for PLAY
  367.  
  368.       pInst->usPlayFlag = TIMER_AVAIL;
  369.       DosExit(0L, 0L);
  370.    }  /* of if notify was used */
  371.  
  372.    if (!rc && usNotifyType == MCI_NOTIFY_SUCCESSFUL)
  373.       pInst->ulCurPos = pInst->ulEndPos;
  374.  
  375.    pInst->usPlayFlag = TIMER_AVAIL;
  376.  
  377.    return(rc);
  378.  
  379. }  /* of CD01_Timer() */
  380.  
  381.  
  382.  
  383. /****************************************************************************/
  384. /*                                                                          */
  385. /* SUBROUTINE NAME:  CD01_TimerNotify                                       */
  386. /*                                                                          */
  387. /* DESCRIPTIVE NAME:  CD Timer Notify                                       */
  388. /*                                                                          */
  389. /* FUNCTION:  Sets up the wait value to suspend the timer thread based on   */
  390. /*            upcoming events.  It also sends notification of past or soon  */
  391. /*            to pass events.                                               */
  392. /*                                                                          */
  393. /* PARAMETERS:                                                              */
  394. /*      PINST pInst         -- Instance pointer.                            */
  395. /*      ULONG *pulPosAdvise -- Position for next Position Advise Event.     */
  396. /*      ULONG *pSyncPos     -- Position for next Sync Pulse if master.      */
  397. /*      ULONG *pulPrevLimit -- Last range checked.                          */
  398. /*                                                                          */
  399. /* EXIT CODES:                                                              */
  400. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  401. /*      MCIERR_DEVICE_NOT_READY      -- device was not ready, no disc.      */
  402. /*                                                                          */
  403. /* NOTES:  It is important to note that events are in MM Time and delay     */
  404. /*         factors are in milliseconds.                                     */
  405. /*                                                                          */
  406. /****************************************************************************/
  407. ULONG CD01_TimerNotify(PINST pInst, ULONG *pulPosAdvise,
  408.                        ULONG *pSyncPos, ULONG *pulPrevLimit)
  409. {
  410.    ULONG ulDelay, ulUpperLimit, ulEvent;
  411.    LONG lTemp;
  412.    int i;
  413.  
  414.    /* find wait value by finding time to next event */
  415.    ulDelay = WAIT_TIME_MAX;
  416.    ulUpperLimit = pInst->ulCurPos + HALF_TIME_MIN * 3; // *3 is ms to mmtime
  417.  
  418.    /* process cuepoints */
  419.    for (i=0; i < CDMCD_CUEPOINT_MAX; i++)
  420.    {
  421.       ulEvent = pInst->arrCuePoint[i].ulEvent;
  422.  
  423.       /* skip if no event */
  424.       if (ulEvent == (ULONG) -1L)
  425.          continue;
  426.  
  427.       /* check to see if event is in window */
  428.       if (ulEvent >= *pulPrevLimit && ulEvent < ulUpperLimit)
  429.       {
  430.          mdmDriverNotify(pInst->usDeviceID,
  431.                          pInst->arrCuePoint[i].hwndCallback,
  432.                          MM_MCICUEPOINT, pInst->arrCuePoint[i].usUserParm,
  433.                          ulEvent);
  434.          continue;
  435.       }
  436.                                           // there is an implied ELSE here
  437.       lTemp = (LONG)(ulEvent - pInst->ulCurPos) / 3;
  438.       if (lTemp > 0 && (ULONG)lTemp < ulDelay)
  439.          ulDelay = (ULONG)lTemp;
  440.  
  441.    }  /* of cuepoint for loop */
  442.  
  443.    /* process position advise */
  444.    if (*pulPosAdvise)
  445.    {
  446.       /* loop for small advise frequencies */
  447.       do
  448.       {
  449.          lTemp = (LONG)(*pulPosAdvise - pInst->ulCurPos) / 3;
  450.          if (lTemp < HALF_TIME_MIN)
  451.          {
  452.             mdmDriverNotify(pInst->usDeviceID,
  453.                             pInst->qptPosAdvise.hwndCallback,
  454.                             MM_MCIPOSITIONCHANGE,
  455.                             pInst->qptPosAdvise.usUserParm,
  456.                             (ULONG) *pulPosAdvise);
  457.             *pulPosAdvise += pInst->qptPosAdvise.ulEvent;
  458.          }
  459.       }  while (lTemp < HALF_TIME_MIN);
  460.  
  461.       if ((ULONG)lTemp < ulDelay)
  462.          ulDelay = (ULONG)lTemp;
  463.    }  /* of if process advise event pending */
  464.  
  465.    /* process sync pulse if VSD is the master */
  466.    if (pInst->StreamMaster)
  467.    {
  468.       if (*pSyncPos)
  469.       {
  470.          lTemp = (LONG)(*pSyncPos - pInst->ulCurPos) / 3;
  471.          if (lTemp < HALF_TIME_MIN)
  472.          {
  473.             /* set current position/time */
  474.             pInst->evcbSync.mmtimeMaster = (MMTIME) pInst->ulCurPos;
  475.             pInst->RptEvent.ulFunction   = SMH_REPORTEVENT;
  476.             pInst->RptEvent.hevent       = 0;
  477.             pInst->pSyncNotify(&pInst->RptEvent);
  478.             *pSyncPos = pInst->ulCurPos + SYNC_TOLERANCE * 2 * 3;
  479.          }
  480.       }
  481.       else      // new event just started
  482.          *pSyncPos = pInst->ulCurPos + SYNC_TOLERANCE * 2 * 3;
  483.    }  /* of if position advise is set */
  484.    else
  485.       *pSyncPos = 0L;
  486.  
  487.    *pulPrevLimit = ulUpperLimit;
  488.  
  489.    /* if suspeneded, set delay flag to forever */
  490.    if (pInst->usPlayFlag == TIMER_PLAY_SUSPEND ||
  491.        pInst->usPlayFlag == TIMER_PLAY_SUSP_2)
  492.       ulDelay = (ULONG) WAIT_FOREVER;
  493.  
  494.    return(ulDelay);
  495.  
  496. }  /* of CD01_TimerNotify() */
  497.  
  498.  
  499.  
  500. /****************************************************************************/
  501. /*                                                                          */
  502. /* SUBROUTINE NAME:  GetTableName              DEVELOPER:  Garry Lewis      */
  503. /*                                                                          */
  504. /* DESCRIPTIVE NAME:  Get CD Table full path name.                          */
  505. /*                                                                          */
  506. /* FUNCTION:  Get the full path name of the CD look-up table, MMPMCD.INI.   */
  507. /*                                                                          */
  508. /* PARAMETERS:                                                              */
  509. /*      CHAR *pName      -- Instance structure.                             */
  510. /*                                                                          */
  511. /* EXIT CODES:  None                                                        */
  512. /*                                                                          */
  513. /* NOTES:                                                                   */
  514. /*                                                                          */
  515. /****************************************************************************/
  516. VOID GetTableName(CHAR *pName)
  517. {
  518.    CHAR *ptr;
  519.  
  520.    /* find path */
  521.    if (DosScanEnv("MMBASE", &ptr))
  522.       strcpy(pName, "\\MMOS2\\MMPMCD.INI");
  523.    else
  524.    {
  525.       strcpy(pName, ptr);
  526.       ptr = strstr(pName, ";");
  527.       if (ptr)
  528.          *ptr = '\0';
  529.       ptr = pName + strlen(pName);
  530.       strcpy(ptr, "\\MMPMCD.INI");
  531.  
  532.    } /* of else environmental variable was found */
  533.  
  534. }  /* of GetTableName() */
  535.  
  536.  
  537.  
  538. /****************************************************************************/
  539. /*                                                                          */
  540. /* SUBROUTINE NAME:  OpenFirstTime             DEVELOPER:  Garry Lewis      */
  541. /*                                                                          */
  542. /* DESCRIPTIVE NAME:  Open drive for the First Time.                        */
  543. /*                                                                          */
  544. /* FUNCTION:  Run tests on the drive after the first successful hardware    */
  545. /*            open.                                                         */
  546. /*                                                                          */
  547. /* PARAMETERS:                                                              */
  548. /*      PINST pInst      -- Instance structure.                             */
  549. /*                                                                          */
  550. /* EXIT CODES:  None                                                        */
  551. /*                                                                          */
  552. /* NOTES:                                                                   */
  553. /*                                                                          */
  554. /****************************************************************************/
  555. ULONG OpenFirstTime(PINST pInst)
  556. {
  557.    ULONG rc;
  558.    BYTE data[LOCATON_DMAX], param[LOCATON_PMAX] = {'C', 'D', '0', '1', RBMODE};
  559.    ULONG ulDataLen, ulParamLen, ulStatus;
  560.  
  561.    /* test to see if drive is really a CD-ROM Drive */
  562.    ulDataLen  = IDCDROM_DMAX;
  563.    ulParamLen = STANDRD_PMAX;
  564.    if (CallIOCtl(pInst, CDDRIVE_CAT, ID___CD_ROM,
  565.                  param, ulParamLen, &ulParamLen,
  566.                  data,  ulDataLen,  &ulDataLen))
  567.       rc = MCIERR_INI_FILE;
  568.    else
  569.       if (memcmp(data, "CD01", IDCDROM_DMAX))
  570.          rc = MCIERR_INI_FILE;
  571.       else
  572.          rc = MCIERR_SUCCESS;
  573.  
  574.    if (!rc)
  575.    {  /** Get current position and let the registration *
  576.         * insert information to the instance structure. **/
  577.       ulDataLen  = LOCATON_DMAX;
  578.       ulParamLen = LOCATON_PMAX;
  579.       rc = CallIOCtl(pInst, CDDRIVE_CAT, Q__LOCATION,
  580.                      param, ulParamLen, &ulParamLen,
  581.                      data,  ulDataLen,  &ulDataLen);
  582.       pInst->ulCurPos = REDBOOK2TOMM(*(ULONG *)data);
  583.  
  584.       rc = CDAudRegDisc(pInst, REG_INST, NULL);
  585.  
  586.    }   /* of if no error identifying drive */
  587.  
  588.    return(rc);
  589.  
  590. }  /* of OpenFirstTime() */
  591.  
  592.  
  593.  
  594. /****************************************************************************/
  595. /*                                                                          */
  596. /* SUBROUTINE NAME:  QueryTable                DEVELOPER:  Garry Lewis      */
  597. /*                                                                          */
  598. /* DESCRIPTIVE NAME:  Query Table from CD INI file.                         */
  599. /*                                                                          */
  600. /* FUNCTION:  Query the CD look-up table, MMPMCD.INI, and extract           */
  601. /*            information or set default information if error.              */
  602. /*                                                                          */
  603. /* PARAMETERS:                                                              */
  604. /*      PINST pInst      -- Instance structure.                             */
  605. /*      VVOL_SET_REC *pVVolRec -- pointer to Vector Volume record.          */
  606. /*                                                                          */
  607. /* EXIT CODES:  None                                                        */
  608. /*                                                                          */
  609. /* NOTES:                                                                   */
  610. /*      This is an example of how to query the CD look-up table, file       */
  611. /*      MMPMCD.INI, to get the capabilities and features of a CD-ROM drive. */
  612. /*      A VSD designed to control a specific hardware device, such as this  */
  613. /*      VSD, would not need to call the INI file because the capabilities   */
  614. /*      should already be known.                                            */
  615. /*                                                                          */
  616. /*                                                                          */
  617. /****************************************************************************/
  618. VOID QueryTable(PINST pInst)
  619. {
  620.    ULONG rc;
  621.    HAB habTemp;
  622.    HINI hiniFile;
  623.    ULONG ulSize;
  624.    CHAR szIniFile[CCHMAXPATH];
  625.    CHAR szAppName[CDINI_APPSIZE+1], szKeyName[CDINI_KEYSIZE+1];
  626.    MMPMCD_REC recCDEntry;
  627.    BYTE i;
  628.    int len;
  629.    ULONG ulCaps1, ulCaps2, ulMinStart;
  630.    BYTE VolCnt, VolValues[VOLUME_CONTROL];
  631.  
  632.    /* open INI file and get info */
  633.    habTemp = WinInitialize(0);
  634.    if (habTemp)                 // if sucessful, open INI file
  635.    {
  636.       /* get complete path name for INI file */
  637.       GetTableName(szIniFile);
  638.  
  639.       hiniFile = PrfOpenProfile(habTemp, szIniFile);
  640.       if (hiniFile)
  641.       {
  642.          memcpy(szAppName, pInst->szModel, CDINI_APPSIZE);
  643.          szAppName[CDINI_APPSIZE] = '\0';
  644.          memcpy(szKeyName, pInst->szModel + CDINI_APPSIZE, CDINI_KEYSIZE);
  645.          szKeyName[CDINI_KEYSIZE] = '\0';
  646.  
  647.          /* check to see Key name needs padding, */
  648.          /* trailing spaces are lost in MMPM2.INI */
  649.          for (len = strlen(szKeyName); len < CDINI_KEYSIZE; len++)
  650.             szKeyName[len] = ' ';
  651.          ulSize = sizeof(MMPMCD_REC);
  652.  
  653.          /* make query */
  654.          if (PrfQueryProfileData(hiniFile, szAppName, szKeyName, &recCDEntry,
  655.                                  &ulSize ))
  656.          {    /* if query is okay, extract data */
  657.             ulCaps1    = recCDEntry.ulCaps1;
  658.             ulCaps2    = recCDEntry.ulCaps2;
  659.             ulMinStart = REDBOOK2TOMM(recCDEntry.ulMinStart);
  660.             VolCnt     = (BYTE)recCDEntry.usVolCnt;
  661.             for (i=0; i < VolCnt; i++)
  662.                VolValues[i] = (BYTE)recCDEntry.ausVolValues[i];
  663.  
  664.             /******************************************************************
  665.              *  In this sample VSD, the IBM 3510-001 CD-ROM Drive is assumed  *
  666.              *  to be the associated CD-ROM drive.  Thus the capabilities of  *
  667.              *  the drive are already known and the table information is      *
  668.              *  ignored.                                                      *
  669.              ******************************************************************/
  670.  
  671.          } /* of if successful query */
  672.  
  673.          PrfCloseProfile(hiniFile);
  674.  
  675.       } /* of if successful */
  676.  
  677.       WinTerminate(habTemp);
  678.  
  679.    } /* of if successful WinInit */
  680.  
  681. }  /* of QueryTable() */
  682.  
  683.  
  684.  
  685. /****************************************************************************/
  686. /*                                                                          */
  687. /* SUBROUTINE NAME:  CallIOCtl                                              */
  688. /*                                                                          */
  689. /* DESCRIPTIVE NAME:  Call DosDevIOCTL()                                    */
  690. /*                                                                          */
  691. /* FUNCTION:  Call the DosDevIOCTLM Time to Redbook address.                */
  692. /*                                                                          */
  693. /* PARAMETERS:                                                              */
  694. /*      PINST pInst      -- Instance pointer.                               */
  695. /*      ULONG ulCat      -- Category.                                       */
  696. /*      ULONG ulFunction -- Function number.                                */
  697. /*      PVOID pParam     -- pointer to Parameter array.                     */
  698. /*      ULONG ulPLen     -- Parameter array length.                         */
  699. /*      ULONG *pulPLen   -- pointer to Parameter array length.              */
  700. /*      PVOID pData      -- pointer to Data array.                          */
  701. /*      ULONG ulDLen     -- Data array length.                              */
  702. /*      ULONG *pulDLen   -- pointer to Data array length.                   */
  703. /*                                                                          */
  704. /* EXIT CODES:                                                              */
  705. /*      MCIERR_SUCCESS   -- action completed without error.                 */
  706. /*      MCIERR_DEVICE_NOT_READY      -- device was not ready, no disc.      */
  707. /*      MCIERR_MEDIA_CHANGED         -- a disc was inserted.                */
  708. /*      MCIERR_HARDWARE              -- unknown error occurred.             */
  709. /*      MCIERR_OUTOFRANGE            -- Invalid value.                      */
  710. /*      MCIERR_UNSUPPORTED_FUNCTION  -- unsupported command.                */
  711. /*                                                                          */
  712. /* NOTES:  DosDevIOCTL sometimes fail when called by a second thread.  To   */
  713. /*      avoid this, a generated thread should have at least a 16K stack     */
  714. /*      size.                                                               */
  715. /*                                                                          */
  716. /****************************************************************************/
  717. ULONG CallIOCtl(PINST pInst,  ULONG ulCat,  ULONG ulFunction,
  718.                 PVOID pParam, ULONG ulPLen, ULONG *pulPLen,
  719.                 PVOID pData,  ULONG ulDLen, ULONG *pulDLen)
  720. {
  721.    ULONG rc;
  722.  
  723.    DosRequestMutexSem(pInst->hIOSem, (ULONG)-1L);
  724.    rc = DosDevIOCtl(pInst->hDrive, ulCat, ulFunction,
  725.                     pParam, ulPLen, pulPLen,
  726.                     pData,  ulDLen, pulDLen);
  727.    DosReleaseMutexSem(pInst->hIOSem);
  728.  
  729.    switch(rc)
  730.    {
  731.       case 0L :
  732.          rc = MCIERR_SUCCESS;
  733.          break;
  734.       case 0xFF03 :
  735.          rc = MCIERR_UNSUPPORTED_FUNCTION;
  736.          break;
  737.       case 0xFF06 :
  738.       case 0xFF08 :
  739.          rc = MCIERR_OUTOFRANGE;
  740.          break;
  741.       case 0xFF04 :
  742.       case 0xFF0C :
  743.          rc = MCIERR_HARDWARE;
  744.          break;
  745.       case 0xFF10 :
  746.          rc = MCIERR_MEDIA_CHANGED;
  747.          break;
  748.       default :
  749.          rc = MCIERR_DEVICE_NOT_READY;
  750.    }
  751.  
  752.    return(rc);
  753.  
  754. }  /* of CallIOCtl() */
  755.  
  756.