thg_sdi.c
上传用户:super_houu
上传日期:2008-09-21
资源大小:4099k
文件大小:36k
源码类别:

DVD

开发平台:

Others

  1. /*******************************************************************************
  2. * Copyright(c) Philips Consumer Electronics B.V. 2001
  3. * The attached material and the information contained therein is proprietary
  4. * to Philips and is issued only under strict confidentiality arrangements.
  5. * It shall not be used, reproduced, copied in whole or in part, adapted,
  6. * modified, or disseminated without a written license of Philips.           
  7. * It must be returned to Philips upon its first request.
  8. *
  9. *  Project:        SA-MP ( Super Audio Media Player )
  10. *  File %name:     thg_sdi.c %
  11. *  %version:       33 %
  12. *  %date_modified: Thu Nov 28 10:59:56 2002 %
  13. *  %derived_by:    potm %
  14. *  Creation date:  Thu Jun 14 16:22:32 2001
  15. *  First author:   klerxm
  16. *
  17. *  Advanced Systems and Applications Lab - Eindhoven
  18. *
  19. *  Continuus %full_filespec: thg_sdi.c~33:csrc:1 %
  20. *
  21. *  Description:    Test harness of SACD Disc Information
  22. *
  23. * Change history:
  24. *
  25. * Rev  Date       Who      Comments
  26. * ---- ---------- -------- -----------------------------------------------------
  27. *   1  2001-06-06 klerxm   Dummy version
  28. *   2  2001-06-14 klerxm   Template update
  29. *   3  2001-08-24 potm     First real version
  30. *   4  2001-09-04 klerxm   Changes required for new global header files
  31. *   5  2001-09-13 klerxm
  32. *   6  2001-10-12 coenen
  33. *   7  2001-10-18 potm     - Added parameter for language to text functions
  34. *                          - Area info now returned by SDI EventActivated
  35. *   8  2001-10-30 potm     - Removed (Un)RegisterClient
  36. *                          - Fixed wrong types in TH_GetParam
  37. *                          - Added SetAvailableCharSets
  38. *   9  2001-11-07 potm     Replaced SDI_AreaInfoDef with SAMP_AreaInfoDef
  39. *  10  2001-11-13 potm     Increased size of UInt8Array
  40. *  11  2001-11-20 potm     - Added pHybrid parameter to SDI_Activate
  41. *                          - Extended DumpToc test harness function to
  42. *                            print the address and the length of the TOC
  43. *                            simplifying dumping the TOC to a file from
  44. *                            the debugger
  45. *  12  2001-11-22 kasterej Add subscribe/unsubscribe functions
  46. *                          (subscription removed in Init function)
  47. *  13  2001-11-29 potm     Extended DumpToc to be able to retrieve the master
  48. *                          TOC (0=master, 1=stereo, 2=multichannel)
  49. *  14  2001-12-20 klerxm   Include all local stuff only if THGSDI defined
  50. *  15  2002-01-04 kokh     Fixed bug in SetAvailableCharSets and
  51. *                          SetLanguagePreference
  52. *  16  2002-01-10 sribnyid GetAudioMode added
  53. *  17  2002-01-16 potm     - Added comments
  54. *                          - Fixed bug in GetSubRangeStart
  55. *  18  2002-01-22 potm     Added SDI_RecogniseDisc (CR218)
  56. *  19  2002-01-30 potm     Adapted to new prototype of SDI_Activate (CR284)
  57. *  20  2002-02-18 potm     Adapted to new prototype of
  58. *                          SDI_SetLanguagePreference (CR340)
  59. *  21  2002-02-22 potm     Replaced SDI_InputChannels with 
  60. *                          SACD_ChannelsConfigDef (CR260)
  61. *  22  2002-02-27 kokh     TH_Send -> SAMP(TH_Send)
  62. *  23  2002-03-04 potm     Fixed several bugs in PrepareTextItem
  63. *  24  2002-04-19 klerxm   Fixed compiler warning if THGSDI not defined
  64. *  25  2002-05-13 potm     Added proper string termination for SDI_GetAlbumText
  65. *  26  2002-06-07 klerxm   Moved tocBuffer and textBuffer outside groupswitch to
  66. *                          prevent stack overflow
  67. *  27  2002-09-23 klerxm   Use only UInt32 type parameters with TH_GetParam
  68. *  28  2002-10-14 potm     Fixed some warnings
  69. *  29  2002-10-16 potm     Added functions testAreaInfoTrackStart and
  70. *                          testAreaInfoTrackLength to be able to test area info
  71. *                          returned after activation (PR417)
  72. *  30  2002-11-08 potm     Added parameter to EVENT_NOT_ACTIVATED (PR423)
  73. *  31  2002-11-13 klerxm   Increased size of textBuffer (PR448)
  74. *  32  2002-11-28 potm     Added asynchronous version of RecogniseDisc function
  75. *                          (test harness only) to be able to test SDI more
  76. *                          thoroughly (PR440)
  77. *  33  2003-02-14 potm     Added SDI_GetSpecVersion and SDI_GetDTCP_Info (CR405)
  78. *
  79. *******************************************************************************/
  80. #define COMP_PREFIX "SDI"
  81. /*******************************************************************************
  82. *                                Include Files
  83. *******************************************************************************/
  84. #include "config.h"
  85. #ifdef TEST_HARNASS
  86. #include <samp_gen.h>
  87. #include <samp_sdi.h>
  88. #include <samp_sdi_exp.h>
  89. #include <glue_osa.h>
  90. #if 0 
  91. #include <sbm.h>
  92. #include <sdi.h>
  93. #include <sdm.h>
  94. #endif
  95. #include "samp_osa_exp.h"
  96. #include <stdio.h>
  97. #include <testharn.h>
  98. #include <fatal.h>
  99. #include <glue_test.h>
  100. #ifdef THGSDI
  101. /*******************************************************************************
  102. *                               Macro Definitions
  103. *******************************************************************************/
  104. /*
  105.  * The following lines are copied from sdi_tocoffsets.h
  106.  */
  107. #define SDI_MASTER_TOC_0                0
  108.   #define SDI_DISC_INFO                   (SDI_MASTER_TOC_0 + 64)
  109.     #define SDI_2CH_TOC_LENGTH              (SDI_DISC_INFO + 20)
  110.     #define SDI_MC_TOC_LENGTH               (SDI_DISC_INFO + 22)
  111. /*******************************************************************************
  112. *                               Data Definitions
  113. *******************************************************************************/
  114. static SAMP(Bool)             sacd;
  115. static SAMP(SAMP_AreaInfoDef) stAreaInfo;
  116. static SAMP(SAMP_AreaInfoDef) mcAreaInfo;
  117. static SAMP(Bool)             hybrid;
  118. static SAMP(Byte)             textBuffer[400];
  119. #ifdef DUMPTOC
  120. static SAMP(Byte)             tocBuffer[79*2048];
  121. /*******************************************************************************
  122. *                              External functions
  123. *******************************************************************************/
  124. extern SAMP(SBM_ID) SAMP(sdiAreaToBufferId)(SAMP(SACD_Area) area);
  125. #endif
  126. extern SAMP(UInt32)    SAMP(sdiMasterTocId);
  127. /*******************************************************************************
  128. *                                Local functions
  129. *******************************************************************************/
  130. static void SdiCallback(SAMP(BitSet32) Event, void * EventData)
  131. {
  132.   switch( Event )
  133.   {
  134. #if 0
  135.   case SDI_EVENT_ACTIVATED:
  136.     SAMP(TH_Send)( "SDI" , "EventActivated", "%d%d%u%u%u%d%d%u%u%u%s",
  137.                                                        stAreaInfo.NumberOfTracks,
  138.                                                        stAreaInfo.TrackOffset,
  139.                                                        stAreaInfo.TotalAreaTime.min,
  140.                                                        stAreaInfo.TotalAreaTime.sec,
  141.                                                        stAreaInfo.TotalAreaTime.fr,
  142.                                                        mcAreaInfo.NumberOfTracks,
  143.                                                        mcAreaInfo.TrackOffset,
  144.                                                        mcAreaInfo.TotalAreaTime.min,
  145.                                                        mcAreaInfo.TotalAreaTime.sec,
  146.                                                        mcAreaInfo.TotalAreaTime.fr,
  147.                                                        hybrid ? "TRUE" : "FALSE");
  148.   break;
  149.   case SDI_EVENT_NOT_ACTIVATED:
  150.     SAMP(TH_Send)( "SDI" , "EventNotActivated", "%u", (SAMP(UInt32))EventData );
  151.   break;
  152. #endif
  153.   
  154.   default:
  155.     SAMP(TH_Send)( "TESTH" , "***ERROR***", "Unknown event received" );
  156.   break;
  157.   }
  158. }
  159. static void PrepareTextItem(SAMP(Byte) *str, int maxLength, int bytesPerChar)
  160. {
  161.   int i = 0, j, len = 0;
  162.   SAMP(Byte) *ptr;
  163.   SAMP(Bool) truncated = FALSE;
  164.   
  165.   if(bytesPerChar == 1)
  166.   {
  167.     len = strlen((char *)str);
  168.   }
  169.   else
  170.   {
  171.     ptr = str;
  172.     while(ptr[0] && ptr[1])
  173.     {
  174.       len += 2;
  175.       ptr += 2;
  176.     }
  177.   }
  178.   if(len + 1 > maxLength)
  179.   {
  180.     truncated = TRUE;
  181.   }
  182.   while (i < len)
  183.   {
  184.     if ( (str[i] < 32) || 
  185.          (str[i] >= 127) ||
  186.          (str[i] == ',') ||
  187.          (str[i] == '[') ||
  188.          (str[i] == ']') ||
  189.          (str[i] == 'n') ||
  190.          (str[i] == 'r') )
  191.     {
  192.       j = len;
  193.       if(j + 4 > maxLength)
  194.       {
  195.         truncated = TRUE;
  196.         j = maxLength - 4;
  197.       }
  198.       else
  199.       {
  200.         len += 3;
  201.       }
  202.       while(j >= i)
  203.       {
  204.         str[j + 3] = str[j];
  205.         j--;
  206.       }
  207.       if((i + 4) < maxLength)
  208.       {
  209.         str[i+1] = 'x';
  210.         str[i+2] = (str[i] >> 4) + '0';
  211.         if(str[i+2] > '9') str[i+2] = str[i+2] - '9' - 1 + 'A';
  212.         str[i+3] = (str[i] & 0x0F) + '0';
  213.         if(str[i+3] > '9') str[i+3] = str[i+3] - '9' - 1 + 'A';
  214.         str[i] = '\';
  215.       }
  216.       i += 3;
  217.     }
  218.     i++;
  219.   }
  220.   if(truncated)
  221.   {
  222.     if(maxLength > 0)
  223.     {
  224.       str[maxLength - 1] = '';
  225.       if( (bytesPerChar == 2) &&
  226.           (maxLength & 1) &&
  227.           (maxLength > 1) )
  228.       {
  229.         str[maxLength - 2] = '';
  230.       }
  231.     }
  232.   }
  233. }
  234. static void PrepareBinaryData(SAMP(Byte) *pData, int inputLength, int maxOutputLength)
  235. {
  236.   int i = 0, j;
  237.   SAMP(Bool) truncated = FALSE;
  238.   
  239.   if(inputLength + 1 > maxOutputLength)
  240.   {
  241.     truncated = TRUE;
  242.   }
  243.   while (i < inputLength)
  244.   {
  245.     if ( (pData[i] < 32) || 
  246.          (pData[i] >= 127) ||
  247.          (pData[i] == ',') ||
  248.          (pData[i] == '[') ||
  249.          (pData[i] == ']') ||
  250.          (pData[i] == 'n') ||
  251.          (pData[i] == 'r') )
  252.     {
  253.       j = inputLength;
  254.       if(j + 4 > maxOutputLength)
  255.       {
  256.         truncated = TRUE;
  257.         j = maxOutputLength - 4;
  258.       }
  259.       else
  260.       {
  261.         inputLength += 3;
  262.       }
  263.       while(j >= i)
  264.       {
  265.         pData[j + 3] = pData[j];
  266.         j--;
  267.       }
  268.       if((i + 4) < maxOutputLength)
  269.       {
  270.         pData[i+1] = 'x';
  271.         pData[i+2] = (pData[i] >> 4) + '0';
  272.         if(pData[i+2] > '9') pData[i+2] = pData[i+2] - '9' - 1 + 'A';
  273.         pData[i+3] = (pData[i] & 0x0F) + '0';
  274.         if(pData[i+3] > '9') pData[i+3] = pData[i+3] - '9' - 1 + 'A';
  275.         pData[i] = '\';
  276.       }
  277.       i += 3;
  278.     }
  279.     i++;
  280.   }
  281.   if(truncated)
  282.   {
  283.     if(maxOutputLength > 0)
  284.     {
  285.       pData[maxOutputLength - 1] = '';
  286.     }
  287.   }
  288. }
  289. #if 0
  290. void callRecogniseDisc(void)
  291. {
  292.   SAMP(UInt32) semId;
  293.   SAMP(ErrCode) lErr;
  294.   if(SAMP(OS_SemCreate)(0, &semId) == SAMP(ERR_OK))
  295.   {
  296.     if(SAMP(OS_SemP)(semId, 10) == SAMP(ERR_FAILED))
  297.     {
  298.       if(SAMP(OS_SemDelete)(semId) == SAMP(ERR_OK))
  299.       {
  300.         lErr = SAMP(SDI_RecogniseDisc)(&sacd, &hybrid);
  301.         SAMP(TH_Send)("SDI", "RecogniseDiscAsync", "%u%s%s", lErr, sacd ? "TRUE" : "FALSE", hybrid ? "TRUE" : "FALSE");
  302.       }
  303.     }
  304.     else
  305.     {
  306.       SAMP(Fatal)();
  307.     }
  308.   }
  309.   else
  310.   {
  311.     SAMP(Fatal)();
  312.   }
  313. }
  314. #endif
  315. #endif
  316. DECLARE_GROUPFUNC(THG_SDI)
  317. /*******************************************************************************
  318. *                          Global test-harness function
  319. *******************************************************************************/
  320. DEFINE_GROUPFUNC(THG_SDI)
  321. #ifdef THGSDI
  322.   SAMP(ErrCode) lErr = SAMP(ERR_OK);
  323.   SAMP(UInt32) index;
  324.   SAMP(UInt8) UInt8Array[10];
  325.   SAMP(UInt16) UInt16Array[12];
  326.   SAMP(UInt32) UInt32Array[12];
  327.   SAMP(SACD_TimeCode) timeCodeArray[3];
  328.   SAMP(SACD_ChannelsConfigDef) inputChannels;
  329.   SAMP(SDI_Album_Info) albumInfo;
  330.   SAMP(SDI_Disc_Info) discInfo;
  331.   SAMP(SDI_Track_Info) trackInfo;
  332.   SAMP(Byte) language[3];
  333. #if 0
  334.   SAMP(SDI_FrameFormat) frameFormat;
  335. #endif
  336. #endif
  337.   GROUP_SWITCH
  338. #ifdef THGSDI
  339.   /*********************************************
  340.    *
  341.    * Functions exported from SAMP (See [API])
  342.    *
  343.    *********************************************/
  344.   /*
  345.    * Parameters:
  346.    *   number of character sets
  347.    *   1st character set
  348.    *   2nd character set
  349.    *     ...
  350.    *   10th character set
  351.    */
  352.   CASE_CMD( "SetAvailableCharSets" )
  353.     TH_GetParam (OPTIONS, "%u%u%u%u%u%u%u%u%u%u%u", &UInt32Array[0],
  354.                                                     &UInt32Array[1], &UInt32Array[2],
  355.                                                     &UInt32Array[3], &UInt32Array[4],
  356.                                                     &UInt32Array[5], &UInt32Array[6],
  357.                                                     &UInt32Array[7], &UInt32Array[8],
  358.                                                     &UInt32Array[9], &UInt32Array[10]);
  359.     if(UInt32Array[0] > 10)
  360.     {
  361.       SAMP(TH_Trace)("Too many parameters provided. Change test harness if necessary.");
  362.       lErr = SAMP(ERR_INVALID_PARAM);
  363.     }
  364.     else
  365.     {
  366.       for(index = 0; index < 10; index++)
  367.       {
  368.         UInt8Array[index] = (SAMP(UInt8))UInt32Array[1+index];
  369.       }
  370.       lErr = SAMP_EXP(SDI_SetAvailableCharSets)((SAMP(UInt8))UInt32Array[0], UInt8Array);
  371.     }
  372.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u", lErr);
  373.   END_CASE
  374.   /*
  375.    * Parameters:
  376.    *   number of languages
  377.    *   1st language
  378.    *   2nd language
  379.    *     ...
  380.    *   10th language
  381.    */
  382.   CASE_CMD( "SetLanguagePreference" )
  383.     SAMP(SDI_LanguageCodeDef) languages[10];
  384.     char languageStrings[10][100];
  385.     TH_GetParam (OPTIONS, "%u%s%s%s%s%s%s%s%s%s%s", &UInt32Array[0],
  386.                                                     languageStrings[0], languageStrings[1],
  387.                                                     languageStrings[2], languageStrings[3],
  388.                                                     languageStrings[4], languageStrings[5],
  389.                                                     languageStrings[6], languageStrings[7],
  390.                                                     languageStrings[8], languageStrings[9]);
  391.     if(UInt32Array[0] > 10)
  392.     {
  393.       SAMP(TH_Trace)("Too many parameters provided. Change test harness if necessary.");
  394.       lErr = SAMP(ERR_INVALID_PARAM);
  395.     }
  396.     else
  397.     {
  398.       for(index = 0; index < 10; index++)
  399.       {
  400.         languages[index][0] = languageStrings[index][0];
  401.         languages[index][1] = languageStrings[index][1];
  402.       }
  403.       lErr = SAMP_EXP(SDI_SetLanguagePreference)((SAMP(UInt8))UInt32Array[0], languages);
  404.     }
  405.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u", lErr);
  406.   END_CASE
  407. #ifdef DUMPTOC
  408.   /*
  409.    * Parameters:
  410.    *   TOC (0 = master, 1 = stereo, 2 = multichannel)
  411.    */
  412.   CASE_CMD( "DumpToc" )
  413.     TH_GetParam (OPTIONS, "%u", &UInt32Array[0]);
  414.     if(UInt32Array[0] < 3)
  415.     {
  416.       if(UInt32Array[0] == 0)
  417.       {
  418.         /* Master TOC */
  419.         UInt32Array[1] = 10 * 2048;
  420.         lErr = SAMP(SBM_Read)(SAMP(sdiMasterTocId), 0, UInt32Array[1], tocBuffer);
  421.         if(lErr == SAMP(ERR_OK))
  422.         {
  423.           sprintf((char *)textBuffer, "%s TOC @ 0x%08X (size = %lu)", "MASTER",
  424.                                                                       (int) tocBuffer,
  425.                                                                       UInt32Array[1]);
  426.           SAMP(TH_Send)(COMP_PREFIX, (char *)textBuffer, "%u", SAMP(ERR_OK));
  427.         }
  428.       }
  429.       else
  430.       {
  431.         /* Convert input to something that can be used as an SACD_Area */
  432.         UInt32Array[0]--;
  433.         /* Read area TOC size from master TOC */
  434.         if(SAMP(SBM_Read)(SAMP(sdiMasterTocId), (UInt32Array[0] == SAMP(SACD_AREA_STEREO)) ? SDI_2CH_TOC_LENGTH : SDI_MC_TOC_LENGTH,
  435.                                                 sizeof(SAMP(UInt16)),
  436.                                                 &UInt16Array[0]) == SAMP(ERR_OK))
  437.         {
  438.           UInt16Array[0] = (UInt16Array[0] >> 8) | (UInt16Array[0] << 8);
  439.           UInt32Array[1] = (SAMP(UInt32))UInt16Array[0] * 2048;
  440.         }
  441.         else
  442.         {
  443.           UInt32Array[1] = 79 * 2048;
  444.         }
  445.         /* Read area TOC */
  446.         lErr = SAMP(SBM_Read)(SAMP(sdiAreaToBufferId)(UInt32Array[0]), 0, UInt32Array[1], tocBuffer);
  447.         if(lErr == SAMP(ERR_OK))
  448.         {
  449.           sprintf((char *)textBuffer, "%s TOC @ 0x%08X (size = %lu)",
  450.                                                        (UInt32Array[0] == 0) ? "STEREO" : "MULTICHANNEL",
  451.                                                        (int) tocBuffer,
  452.                                                        UInt32Array[1]);
  453.           SAMP(TH_Send)(COMP_PREFIX, (char *)textBuffer, "%u", SAMP(ERR_OK));
  454.         }
  455.       }
  456.     }
  457.     else
  458.     {
  459.       lErr = SAMP(ERR_INVALID_PARAM);
  460.     }
  461.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u", lErr);
  462.   END_CASE
  463.   /*
  464.    * Parameters:
  465.    *   none
  466.    */
  467. #endif
  468.   CASE_CMD( "GetAlbumInfo" )
  469.     lErr = SAMP_EXP(SDI_GetAlbumInfo)(&albumInfo);
  470.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u%u%s%u%u%u%u%u%u%u%u", lErr, albumInfo.Album_Set_Size,
  471.                                                           albumInfo.Album_Sequence_Number,
  472.                                                           albumInfo.Album_Catalog_Number,
  473.                                                           albumInfo.Album_Genre[0].Genre_Table,
  474.                                                           albumInfo.Album_Genre[0].Genre_Index,
  475.                                                           albumInfo.Album_Genre[1].Genre_Table,
  476.                                                           albumInfo.Album_Genre[1].Genre_Index,
  477.                                                           albumInfo.Album_Genre[2].Genre_Table,
  478.                                                           albumInfo.Album_Genre[2].Genre_Index,
  479.                                                           albumInfo.Album_Genre[3].Genre_Table,
  480.                                                           albumInfo.Album_Genre[3].Genre_Index);
  481.   END_CASE
  482.   /*
  483.    * Parameters:
  484.    *   album text field
  485.    *   album text type (0 = normal, 1 = phonetic)
  486.    *   text buffer size
  487.    */
  488.   CASE_CMD( "GetAlbumText" )
  489.     TH_GetParam (OPTIONS, "%u%u%u", &UInt32Array[0], &UInt32Array[1], &UInt32Array[2]);
  490.     textBuffer[0] = '';
  491.     if(UInt32Array[2] >= sizeof(textBuffer))
  492.     {
  493.       SAMP(TH_Trace)("The specified buffer size is too large. Change test harness if necessary.");
  494.       lErr = SAMP(ERR_INVALID_PARAM);
  495.     }
  496.     else
  497.     {
  498.       lErr = SAMP_EXP(SDI_GetAlbumText)(UInt32Array[0], UInt32Array[1], UInt32Array[2], &textBuffer, &UInt8Array[0], (SAMP(SDI_LanguageCodeDef) *)&language);
  499.     }
  500.     textBuffer[UInt32Array[2]] = 0;
  501.     PrepareTextItem(textBuffer, sizeof(textBuffer), ((UInt8Array[0] >= 3) && (UInt8Array[0] <= 6)) ? 2 : 1 );
  502.     language[2] = '';
  503.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%s%u%s", lErr, textBuffer, UInt8Array[0], &language[0]);
  504.   END_CASE
  505.   /*
  506.    * Parameters:
  507.    *   none
  508.    */
  509.   CASE_CMD( "GetDiscInfo" )
  510.     lErr = SAMP_EXP(SDI_GetDiscInfo)(&discInfo);
  511.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%s%u%u%u%u%u%u%u%u%u%u%u", lErr, discInfo.Disc_Catalog_Number,
  512.                                                                   discInfo.Disc_Genre[0].Genre_Table,
  513.                                                                   discInfo.Disc_Genre[0].Genre_Index,
  514.                                                                   discInfo.Disc_Genre[1].Genre_Table,
  515.                                                                   discInfo.Disc_Genre[1].Genre_Index,
  516.                                                                   discInfo.Disc_Genre[2].Genre_Table,
  517.                                                                   discInfo.Disc_Genre[2].Genre_Index,
  518.                                                                   discInfo.Disc_Genre[3].Genre_Table,
  519.                                                                   discInfo.Disc_Genre[3].Genre_Index,
  520.                                                                   discInfo.Disc_Date.Year,
  521.                                                                   discInfo.Disc_Date.Month,
  522.                                                                   discInfo.Disc_Date.Day);
  523.   END_CASE
  524.   /*
  525.    * Parameters:
  526.    *   disc text field
  527.    *   disc text type (0 = normal, 1 = phonetic)
  528.    *   text buffer size
  529.    */
  530.   CASE_CMD( "GetDiscText" )
  531.     TH_GetParam (OPTIONS, "%u%u%u", &UInt32Array[0], &UInt32Array[1], &UInt32Array[2]);
  532.     textBuffer[0] = '';
  533.     if(UInt32Array[2] >= sizeof(textBuffer))
  534.     {
  535.       SAMP(TH_Trace)("The specified buffer size is too large. Change test harness if necessary.");
  536.       lErr = SAMP(ERR_INVALID_PARAM);
  537.     }
  538.     else
  539.     {
  540.       lErr = SAMP_EXP(SDI_GetDiscText)(UInt32Array[0], UInt32Array[1], UInt32Array[2], &textBuffer, &UInt8Array[0], (SAMP(SDI_LanguageCodeDef) *)&language);
  541.     }
  542.     textBuffer[UInt32Array[2]] = 0;
  543.     language[2] = '';
  544.     PrepareTextItem(textBuffer, sizeof(textBuffer), ((UInt8Array[0] >= 3) && (UInt8Array[0] <= 6)) ? 2 : 1 );
  545.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%s%u%s", lErr, textBuffer, UInt8Array[0], &language[0]);
  546.   END_CASE
  547.   /*
  548.    * Parameters:
  549.    *   area
  550.    *   area text field
  551.    *   area text type (0 = normal, 1 = phonetic)
  552.    *   text buffer size
  553.    */
  554.   CASE_CMD( "GetAreaText" )
  555.     textBuffer[0] = '';
  556.     TH_GetParam (OPTIONS, "%u%u%u%u", &UInt32Array[0], &UInt32Array[1], &UInt32Array[2], &UInt32Array[3]);
  557.     if(UInt32Array[3] >= sizeof(textBuffer))
  558.     {
  559.       SAMP(TH_Trace)("The specified buffer size is too large. Change test harness if necessary.");
  560.       lErr = SAMP(ERR_INVALID_PARAM);
  561.     }
  562.     else
  563.     {
  564.       lErr = SAMP_EXP(SDI_GetAreaText)(UInt32Array[0], UInt32Array[1], UInt32Array[2], UInt32Array[3], &textBuffer, &UInt8Array[0], (SAMP(SDI_LanguageCodeDef) *)&language);
  565.     }
  566.     textBuffer[UInt32Array[3]] = 0;
  567.     PrepareTextItem(textBuffer, sizeof(textBuffer), ((UInt8Array[0] >= 3) && (UInt8Array[0] <= 6)) ? 2 : 1 );
  568.     language[2] = '';
  569.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%s%u%s", lErr, textBuffer, UInt8Array[0], &language[0]);
  570.   END_CASE
  571.   /*
  572.    * Parameters:
  573.    *   area
  574.    *   track
  575.    */
  576.   CASE_CMD( "GetTrackInfo" )
  577.     TH_GetParam (OPTIONS, "%u%u", &UInt32Array[0], &UInt32Array[1]);
  578.     lErr = SAMP_EXP(SDI_GetTrackInfo)(UInt32Array[0], (SAMP(UInt8))UInt32Array[1], &trackInfo);
  579.     memcpy(&textBuffer[0], trackInfo.ISRC.Country_Code, 2);
  580.     textBuffer[2] = 0;
  581.     memcpy(&textBuffer[3], trackInfo.ISRC.Owner_Code, 3);
  582.     textBuffer[6] = 0;
  583.     memcpy(&textBuffer[7], trackInfo.ISRC.Recording_Year, 2);
  584.     textBuffer[9] = 0;
  585.     memcpy(&textBuffer[10], trackInfo.ISRC.Designation_Code, 5);
  586.     textBuffer[15] = 0;
  587.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u%u%s%s%s%s", lErr, trackInfo.Genre.Genre_Table,
  588.                                                       trackInfo.Genre.Genre_Index,
  589.                                                       &textBuffer[0],
  590.                                                       &textBuffer[3],
  591.                                                       &textBuffer[7],
  592.                                                       &textBuffer[10]);
  593.   END_CASE
  594.   /*
  595.    * Parameters:
  596.    *   area
  597.    *   track
  598.    *   track text field
  599.    *   track text type (0 = normal, 1 = phonetic)
  600.    *   text buffer size
  601.    */
  602.   CASE_CMD( "GetTrackText" )
  603.     TH_GetParam (OPTIONS, "%u%u%u%u%u", &UInt32Array[0], &UInt32Array[1], &UInt32Array[2], &UInt32Array[3], &UInt32Array[4]);
  604.     textBuffer[0] = '';
  605.     if(UInt32Array[4] >= sizeof(textBuffer))
  606.     {
  607.       SAMP(TH_Trace)("The specified buffer size is too large. Change test harness if necessary.");
  608.       lErr = SAMP(ERR_INVALID_PARAM);
  609.     }
  610.     else
  611.     {
  612.       lErr = SAMP_EXP(SDI_GetTrackText)(UInt32Array[0], (SAMP(UInt8))UInt32Array[1], UInt32Array[2], UInt32Array[3], UInt32Array[4], &textBuffer, &UInt8Array[0], (SAMP(SDI_LanguageCodeDef) *)&language);
  613.     }
  614.     textBuffer[UInt32Array[4]] = 0;
  615.     language[2] = '';
  616.     PrepareTextItem(textBuffer, sizeof(textBuffer), ((UInt8Array[0] >= 3) && (UInt8Array[0] <= 6)) ? 2 : 1 );
  617.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%s%u%s", lErr, textBuffer, UInt8Array[0], &language[0]);
  618.   END_CASE
  619.   /*
  620.    * Parameters:
  621.    *   offset
  622.    *   size
  623.    */
  624.   CASE_CMD( "GetDTCP_Info" )
  625.     TH_GetParam (OPTIONS, "%u%u", &UInt32Array[0], &UInt32Array[1]);
  626.     textBuffer[0] = '';
  627.     if(UInt32Array[1] >= sizeof(textBuffer))
  628.     {
  629.       SAMP(TH_Trace)("The specified buffer size is too large. Change test harness if necessary.");
  630.       lErr = SAMP(ERR_INVALID_PARAM);
  631.     }
  632.     else
  633.     {
  634.       lErr = SAMP_EXP(SDI_GetDTCP_Info)(UInt32Array[0], UInt32Array[1], &textBuffer);
  635.     }
  636.     textBuffer[UInt32Array[1]] = 0;
  637.     PrepareBinaryData(textBuffer, (int)UInt32Array[1], sizeof(textBuffer));
  638.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%s", lErr, textBuffer);
  639.   END_CASE
  640.   /*
  641.    * Parameters:
  642.    *   none
  643.    */
  644.   CASE_CMD( "GetSpecVersion" )
  645.     SAMP(SDI_Spec_Version) specVersion;
  646.     lErr = SAMP_EXP(SDI_GetSpecVersion)(&specVersion);
  647.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u%u", lErr, specVersion.Major_Version, specVersion.Minor_Version);
  648.   END_CASE
  649. #if 0
  650.   CASE_CMD( "Subscribe" )
  651.     lErr = SAMP_EXP(SDI_Subscribe)( SdiCallback,
  652.                                 ( SDI_EVENT_ACTIVATED
  653.                                 | SDI_EVENT_NOT_ACTIVATED ) );
  654.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u", lErr);
  655.   END_CASE
  656. #endif
  657.   CASE_CMD( "Unsubscribe" )
  658.     lErr = SAMP_EXP(SDI_Subscribe)( SdiCallback, 0 );
  659.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u", lErr);
  660.   END_CASE
  661.   /*********************************************
  662.    *
  663.    * Functions local to SAMP (See [SCS_SDI])
  664.    *
  665.    *********************************************/
  666.   CASE_CMD( "Init" )
  667.     lErr = SAMP(SDI_Init)();
  668.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u", lErr);
  669.   END_CASE
  670.   CASE_CMD( "Term" )
  671.     lErr = SAMP(SDI_Term)();
  672.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u", lErr);
  673.   END_CASE
  674. /* TODO: Check how to report events
  675. SAMP(ErrCode) SAMP(SDI_Subscribe)( SAMP(SDI_CallbackDef) Callback, SAMP(BitSet32) Events );*/
  676.   CASE_CMD( "RecogniseDisc" )
  677.     lErr = SAMP_EXP(SDI_RecogniseDisc)(&sacd, &hybrid);
  678.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%s%s", lErr, sacd ? "TRUE" : "FALSE", hybrid ? "TRUE" : "FALSE");
  679.   END_CASE
  680. #if 0
  681.   /* This function is only present in the test harness and can be used to test
  682.      SDI_RecogniseDisc more thoroughly. */
  683.   CASE_CMD( "RecogniseDiscAsync" )
  684.     SAMP(UInt32) taskId;
  685.     SAMP_EXP(OS_TaskCreate)(SDM_PRIORITY_NAV, SDM_STACKSIZE_NAV, callRecogniseDisc, &taskId);
  686.   END_CASE
  687. #endif
  688.   /*
  689.    * Parameters:
  690.    *   disc recognised (0 = read master TOC, 1 = master TOC already read)
  691.    */
  692.   CASE_CMD( "Activate" )
  693.     TH_GetParam (OPTIONS, "%u", &UInt32Array[0]);
  694.     lErr = SAMP_EXP(SDI_Activate)((SAMP(Bool))((UInt32Array[0] == 0) ? FALSE : TRUE), &stAreaInfo, &mcAreaInfo, &hybrid);
  695.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u", lErr);
  696.   END_CASE
  697.   CASE_CMD( "testAreaInfoTrackStart" )
  698.     TH_GetParam (OPTIONS, "%u%u", &UInt32Array[0], &UInt32Array[1]);
  699.     if(UInt32Array[1] >= 1 && UInt32Array[0] <= SACD_MAX_TRACK_NUMBER)
  700.     {
  701.       timeCodeArray[0] = (UInt32Array[0] == SAMP(SACD_AREA_STEREO)) ?
  702.                             stAreaInfo.TrackStart[UInt32Array[1] - 1] :
  703.                             mcAreaInfo.TrackStart[UInt32Array[1] - 1];
  704.     }
  705.     else
  706.     {
  707.       lErr = SAMP(ERR_INVALID_PARAM);
  708.     }
  709.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u%u%u", lErr, timeCodeArray[0].min,
  710.                                                       timeCodeArray[0].sec,
  711.                                                       timeCodeArray[0].fr);
  712.   END_CASE
  713.   CASE_CMD( "testAreaInfoTrackLength" )
  714.     TH_GetParam (OPTIONS, "%u%u", &UInt32Array[0], &UInt32Array[1]);
  715.     if(UInt32Array[1] >= 1 && UInt32Array[0] <= SACD_MAX_TRACK_NUMBER)
  716.     {
  717.       timeCodeArray[0] = (UInt32Array[0] == SAMP(SACD_AREA_STEREO)) ?
  718.                             stAreaInfo.TrackLength[UInt32Array[1] - 1] :
  719.                             mcAreaInfo.TrackLength[UInt32Array[1] - 1];
  720.     }
  721.     else
  722.     {
  723.       lErr = SAMP(ERR_INVALID_PARAM);
  724.     }
  725.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u%u%u", lErr, timeCodeArray[0].min,
  726.                                                       timeCodeArray[0].sec,
  727.                                                       timeCodeArray[0].fr);
  728.   END_CASE
  729.   CASE_CMD( "Deactivate" )
  730.     lErr = SAMP_EXP(SDI_Deactivate)();
  731.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u", lErr);
  732.   END_CASE
  733.   CASE_CMD( "Reactivate" )
  734.     lErr = SAMP_EXP(SDI_Reactivate)();
  735.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u", lErr);
  736.   END_CASE
  737. #if 0
  738.   CASE_CMD( "GetState" )
  739.     lErr = SAMP(SDI_GetState)((SAMP(SDI_StateDef) *)&UInt16Array[0]);
  740.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u", lErr, UInt16Array[0]);
  741.   END_CASE
  742. #endif
  743.   /*
  744.    * Parameters:
  745.    *   area
  746.    *   track
  747.    */
  748.   CASE_CMD( "GetTrackStartTimeCode" )
  749.     TH_GetParam (OPTIONS, "%u%u", &UInt32Array[0], &UInt32Array[1]);
  750.     lErr = SAMP_EXP(SDI_GetTrackStartTimeCode)(UInt32Array[0], (SAMP(UInt8))UInt32Array[1], &timeCodeArray[0]);
  751.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u%u%u", lErr, timeCodeArray[0].min, timeCodeArray[0].sec, timeCodeArray[0].fr);
  752.   END_CASE
  753.   /*
  754.    * Parameters:
  755.    *   area
  756.    *   track
  757.    */
  758.   CASE_CMD( "GetTrackEndTimeCode" )
  759.     TH_GetParam (OPTIONS, "%u%u", &UInt32Array[0], &UInt32Array[1]);
  760.     lErr = SAMP_EXP(SDI_GetTrackEndTimeCode)(UInt32Array[0], (SAMP(UInt8))UInt32Array[1], &timeCodeArray[0]);
  761.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u%u%u", lErr, timeCodeArray[0].min, timeCodeArray[0].sec, timeCodeArray[0].fr);
  762.   END_CASE
  763.   /*
  764.    * Parameters:
  765.    *   area
  766.    *   minutes
  767.    *   seconds
  768.    *   frames
  769.    */
  770.   CASE_CMD( "AreaTimeToTrack" )
  771.     TH_GetParam (OPTIONS, "%u%u%u%u", &UInt32Array[0], &UInt32Array[1], &UInt32Array[2], &UInt32Array[3]);
  772.     timeCodeArray[0].min = (SAMP(UInt8))UInt32Array[1];
  773.     timeCodeArray[0].sec = (SAMP(UInt8))UInt32Array[2];
  774.     timeCodeArray[0].fr  = (SAMP(UInt8))UInt32Array[3];
  775.     lErr = SAMP_EXP(SDI_AreaTimeToTrack)(UInt32Array[0], timeCodeArray[0], &UInt8Array[0], &timeCodeArray[0], &UInt8Array[1], &UInt8Array[2]);
  776.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u%u%u%u%u%u", lErr, UInt8Array[0],
  777.                                                       timeCodeArray[0].min,
  778.                                                       timeCodeArray[0].sec,
  779.                                                       timeCodeArray[0].fr,
  780.                                                       UInt8Array[1],
  781.                                                       UInt8Array[2]);
  782.   END_CASE
  783.   /*
  784.    * Parameters:
  785.    *   area
  786.    *   minutes
  787.    *   seconds
  788.    *   frames
  789.    */
  790.   CASE_CMD( "AreaTimeToTrack2" )
  791.     TH_GetParam (OPTIONS, "%u%u%u%u", &UInt32Array[0], &UInt32Array[1], &UInt32Array[2], &UInt32Array[3]);
  792.     timeCodeArray[0].min = (SAMP(UInt8))UInt32Array[1];
  793.     timeCodeArray[0].sec = (SAMP(UInt8))UInt32Array[2];
  794.     timeCodeArray[0].fr  = (SAMP(UInt8))UInt32Array[3];
  795.     lErr = SAMP_EXP(SDI_AreaTimeToTrack)(UInt32Array[0], timeCodeArray[0], &UInt8Array[0], &timeCodeArray[0], &UInt8Array[1], NULL);
  796.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u%u%u%u%u%u", lErr, UInt8Array[0],
  797.                                                       timeCodeArray[0].min,
  798.                                                       timeCodeArray[0].sec,
  799.                                                       timeCodeArray[0].fr,
  800.                                                       UInt8Array[1],
  801.                                                       0);
  802.   END_CASE
  803.   /*
  804.    * Parameters:
  805.    *   area
  806.    *   minutes
  807.    *   seconds
  808.    *   frames
  809.    */
  810.   CASE_CMD( "AreaTimeToLogSector" )
  811.     TH_GetParam (OPTIONS, "%u%u%u%u", &UInt32Array[0], &UInt32Array[1], &UInt32Array[2], &UInt32Array[3]);
  812.     timeCodeArray[0].min = (SAMP(UInt8))UInt32Array[1];
  813.     timeCodeArray[0].sec = (SAMP(UInt8))UInt32Array[2];
  814.     timeCodeArray[0].fr  = (SAMP(UInt8))UInt32Array[3];
  815.     lErr = SAMP_EXP(SDI_AreaTimeToLogSector)(UInt32Array[0], timeCodeArray[0], &UInt32Array[0], &UInt32Array[1]);
  816.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u%u", lErr, UInt32Array[0], UInt32Array[1]);
  817.   END_CASE
  818.   /*
  819.    * Parameters:
  820.    *   area
  821.    *   track
  822.    */
  823.   CASE_CMD( "GetNumberOfIndices" )
  824.     TH_GetParam (OPTIONS, "%u%u", &UInt32Array[0], &UInt32Array[1]);
  825.     lErr = SAMP_EXP(SDI_GetNumberOfIndices)(UInt32Array[0], (SAMP(UInt8))UInt32Array[1], &UInt8Array[0]);
  826.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u", lErr, UInt8Array[0]);
  827.   END_CASE
  828.   /*
  829.    * Parameters:
  830.    *   area
  831.    */
  832.   CASE_CMD( "GetNumberOfTracks" )
  833.     TH_GetParam (OPTIONS, "%u", &UInt32Array[0]);
  834.     lErr = SAMP_EXP(SDI_GetNumberOfTracks)((SAMP(UInt16))UInt32Array[0], &UInt8Array[0]);
  835.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u", lErr, UInt8Array[0]);
  836.   END_CASE
  837.   /*
  838.    * Parameters:
  839.    *   area
  840.    *   track
  841.    *   index
  842.    */
  843.   CASE_CMD( "GetIndexStartTimeCode" )
  844.     TH_GetParam (OPTIONS, "%u%u%u", &UInt32Array[0], &UInt32Array[1], &UInt32Array[2]);
  845.     lErr = SAMP_EXP(SDI_GetIndexStartTimeCode)(UInt32Array[0], (SAMP(UInt8))UInt32Array[1], (SAMP(UInt8))UInt32Array[2], &timeCodeArray[0]);
  846.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u%u%u", lErr, timeCodeArray[0].min, timeCodeArray[0].sec, timeCodeArray[0].fr);
  847.   END_CASE
  848.   /*
  849.    * Parameters:
  850.    *   area
  851.    *   begin.min
  852.    *   begin.sec
  853.    *   begin.fr
  854.    *   end.min
  855.    *   end.sec
  856.    *   end.fr
  857.    *   current.min
  858.    *   current.sec
  859.    *   current.fr
  860.    */
  861.   CASE_CMD( "GetSubRangeEnd" )
  862.     TH_GetParam (OPTIONS, "%u%u%u%u%u%u%u%u%u%u", &UInt32Array[0],
  863.                                                   &UInt32Array[1], &UInt32Array[2], &UInt32Array[3],
  864.                                                   &UInt32Array[4], &UInt32Array[5], &UInt32Array[6],
  865.                                                   &UInt32Array[7], &UInt32Array[8], &UInt32Array[9]);
  866.     timeCodeArray[0].min = (SAMP(UInt8))UInt32Array[1];
  867.     timeCodeArray[0].sec = (SAMP(UInt8))UInt32Array[2];
  868.     timeCodeArray[0].fr  = (SAMP(UInt8))UInt32Array[3];
  869.     timeCodeArray[1].min = (SAMP(UInt8))UInt32Array[4];
  870.     timeCodeArray[1].sec = (SAMP(UInt8))UInt32Array[5];
  871.     timeCodeArray[1].fr  = (SAMP(UInt8))UInt32Array[6];
  872.     timeCodeArray[2].min = (SAMP(UInt8))UInt32Array[7];
  873.     timeCodeArray[2].sec = (SAMP(UInt8))UInt32Array[8];
  874.     timeCodeArray[2].fr  = (SAMP(UInt8))UInt32Array[9];
  875.     lErr = SAMP_EXP(SDI_GetSubRangeEnd)(UInt32Array[0], timeCodeArray[0], timeCodeArray[1], timeCodeArray[2], &timeCodeArray[0], &inputChannels);
  876.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u%u%u%u", lErr, timeCodeArray[0].min, timeCodeArray[0].sec, timeCodeArray[0].fr, inputChannels);
  877.   END_CASE
  878.   /*
  879.    * Parameters:
  880.    *   area
  881.    *   begin.min
  882.    *   begin.sec
  883.    *   begin.fr
  884.    *   end.min
  885.    *   end.sec
  886.    *   end.fr
  887.    *   current.min
  888.    *   current.sec
  889.    *   current.fr
  890.    */
  891.   CASE_CMD( "GetSubRangeStart" )
  892.     TH_GetParam (OPTIONS, "%u%u%u%u%u%u%u%u%u%u", &UInt32Array[0],
  893.                                                   &UInt32Array[1], &UInt32Array[2], &UInt32Array[3],
  894.                                                   &UInt32Array[4], &UInt32Array[5], &UInt32Array[6],
  895.                                                   &UInt32Array[7], &UInt32Array[8], &UInt32Array[9]);
  896.     timeCodeArray[0].min = (SAMP(UInt8))UInt32Array[1];
  897.     timeCodeArray[0].sec = (SAMP(UInt8))UInt32Array[2];
  898.     timeCodeArray[0].fr  = (SAMP(UInt8))UInt32Array[3];
  899.     timeCodeArray[1].min = (SAMP(UInt8))UInt32Array[4];
  900.     timeCodeArray[1].sec = (SAMP(UInt8))UInt32Array[5];
  901.     timeCodeArray[1].fr  = (SAMP(UInt8))UInt32Array[6];
  902.     timeCodeArray[2].min = (SAMP(UInt8))UInt32Array[7];
  903.     timeCodeArray[2].sec = (SAMP(UInt8))UInt32Array[8];
  904.     timeCodeArray[2].fr  = (SAMP(UInt8))UInt32Array[9];
  905.     lErr = SAMP_EXP(SDI_GetSubRangeStart)(UInt32Array[0], timeCodeArray[0], timeCodeArray[1], timeCodeArray[2], &timeCodeArray[0], &inputChannels);
  906.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u%u%u%u", lErr, timeCodeArray[0].min, timeCodeArray[0].sec, timeCodeArray[0].fr, inputChannels);
  907.   END_CASE
  908. #if 0
  909.   CASE_CMD( "GetAudioMode" )
  910.     TH_GetParam (OPTIONS, "%u", &UInt32Array[0]);
  911.     lErr = SAMP(SDI_GetAudioMode)(UInt32Array[0], &frameFormat, &UInt8Array[0]);
  912.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%u%u%u", lErr, frameFormat, UInt8Array[0]);
  913.   END_CASE
  914. #endif
  915. #endif
  916.   DEFAULT
  917.     SAMP(TH_Send)(COMP_PREFIX, cmd, "%s", "Unknown command");
  918.   END_CASE
  919. END_GROUPFUNC
  920. /*******************************************************************************
  921. *                                 End of File
  922. *******************************************************************************/
  923. #endif