home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format 106 / af106sub.adf / datatypes.LZX / 16sv_datatype / dispatch.c < prev    next >
C/C++ Source or Header  |  1982-01-30  |  30KB  |  904 lines

  1.  
  2. /*
  3. **
  4. **  $VER: dispatch.c 1.2 (9.11.97)
  5. **  16sv.datatype 1.2
  6. **
  7. **  Dispatch routine for a DataTypes class
  8. **
  9. **  Written 1996/97 by Roland 'Gizzy' Mainz
  10. **  Original example source from David N. Junod
  11. **
  12. */
  13.  
  14. /* main includes */
  15. #include "classbase.h"
  16. #include "classdata.h"
  17.  
  18. /*****************************************************************************/
  19.  
  20. /* local prototypes */
  21. static                 LONG              Load16SV( struct ClassBase *, Object * );
  22. static                 LONG              Load16SVBody( SAMPLE8 *, UBYTE *, ULONG );
  23.  
  24. #ifndef NO_ENCODER
  25. static                 ULONG             SaveIFF16SV( struct ClassBase *, Object *, struct dtWrite * );
  26.  
  27. static                 struct IFFHandle *CreateDOSIFFHandle( struct ClassBase *, BPTR );
  28.  
  29. static                 LONG              PutIFFObjectInfo( struct ClassBase *, struct IFFHandle *, STRPTR, STRPTR, STRPTR, STRPTR, STRPTR );
  30. static                 LONG              PutIFFString( struct ClassBase *, struct IFFHandle *, ULONG, STRPTR );
  31.  
  32. static                 LONG              Put16SVBODY( struct ClassBase *, struct IFFHandle *, SAMPLE8 *, ULONG );
  33. #endif /* NO_ENCODER */
  34.  
  35.  
  36.  
  37. /*****************************************************************************/
  38.  
  39. /* Create "16sv.datatype" BOOPSI class */
  40. struct IClass *initClass( struct ClassBase *cb )
  41. {
  42.     struct IClass *cl;
  43.  
  44.     /* Create our class... */
  45.     if( cl = MakeClass( IFF16SVDTCLASS, SOUNDDTCLASS, NULL, 0UL, 0UL ) )
  46.     {
  47. #define DTSTACKSIZE (16384UL)
  48.       cl -> cl_Dispatcher . h_Entry    = (HOOKFUNC)StackSwapDispatch; /* see stackswap.c */
  49.       cl -> cl_Dispatcher . h_SubEntry = (HOOKFUNC)Dispatch;          /* see stackswap.c */
  50.       cl -> cl_Dispatcher . h_Data     = (APTR)DTSTACKSIZE;           /* see stackswap.c */
  51.       cl -> cl_UserData                = (ULONG)cb;                   /* class library base as expected by datatypes.library */
  52.  
  53.       AddClass( cl );
  54.     }
  55.  
  56.     return( cl );
  57. }
  58.  
  59. /*****************************************************************************/
  60.  
  61. /* IFF errors to DOS errors */
  62. static
  63. const
  64. LONG ifferr2doserr[] =
  65. {
  66.     0L,                         /* End of file (not an error).                   */
  67.     0L,                         /* End of context (not an error).                */
  68.     DTERROR_INVALID_DATA,       /* No lexical scope.                             */
  69.     ERROR_NO_FREE_STORE,        /* Insufficient memory.                          */
  70.     ERROR_SEEK_ERROR,           /* Stream read error.                            */
  71.     ERROR_SEEK_ERROR,           /* Stream write error.                           */
  72.     ERROR_SEEK_ERROR,           /* Stream seek error.                            */
  73.     DTERROR_INVALID_DATA,       /* File is corrupt.                              */
  74.     DTERROR_INVALID_DATA,       /* IFF syntax error.                             */
  75.     ERROR_OBJECT_WRONG_TYPE,    /* Not an IFF file.                              */
  76.     ERROR_REQUIRED_ARG_MISSING, /* Required call-back hook missing.              */
  77.     0xDEADDEAD                  /* Return to client. You should never see this ! */
  78. };
  79.  
  80. /*****************************************************************************/
  81.  
  82.  
  83. /* class dispatcher */
  84. DISPATCHERFLAGS
  85. ULONG Dispatch( REGA0 struct IClass *cl, REGA2 Object *o, REGA1 Msg msg )
  86. {
  87.     struct ClassBase *cb = (struct ClassBase *)(cl -> cl_UserData);
  88.     ULONG             retval = 0UL;
  89.  
  90.     switch( msg -> MethodID )
  91.     {
  92. /****** 16sv.datatype/OM_NEW *************************************************
  93. *
  94. *    NAME
  95. *        OM_NEW -- Create a 16sv.datatype object.
  96. *
  97. *    FUNCTION
  98. *        The OM_NEW method is used to create an instance of the 16sv.datatype
  99. *        class. This method is passed to the superclass first. After this,
  100. *        16sv.datatype parses the file and loads the sample.
  101. *
  102. *    ATTRIBUTES
  103. *        The following attributes can be specified at creation time.
  104. *
  105. *        DTA_SourceType (ULONG) -- Determinates the type of DTA_Handle
  106. *            attribute. DTST_FILE, DTST_CLIPBOARD and DTST_RAM are supported.
  107. *            If any other type was set in a given DTA_SourceType,
  108. *            OM_NEW will be rejected.
  109. *            Defaults to DTST_FILE.
  110. *
  111. *        DTA_Handle -- For both supported DTST_FILE and DTST_CLIPBOARD, a
  112. *            (struct IFFHandle *) is expected.
  113. *            (DTST_FILE expects a IFF Stream handle because this is a IFF
  114. *            type DataType (DTF_IFF)).
  115. *            A DTST_RAM (create empty object) source type requires a NULL
  116. *            handle.
  117. *
  118. *    NOTE
  119. *        If the datatype was compiled with the NO_ENCODER flag set,
  120. *        DTA_SourceType == DTST_RAM causes OM_NEW to reject the method.
  121. *
  122. *    RESULT
  123. *        If the object was created a pointer to the object is returned,
  124. *        otherwise NULL is returned.
  125. *
  126. ******************************************************************************
  127. *
  128. */
  129.       case OM_NEW:
  130.       {
  131.           struct TagItem *ti;
  132.  
  133.           /* We only support DTST_FILE, DTST_CLIPBOARD or DTST_RAM as source type */
  134.           if( ti = FindTagItem( DTA_SourceType, (((struct opSet *)msg) -> ops_AttrList) ) )
  135.           {
  136.             if( ((ti -> ti_Data) != DTST_FILE)      &&
  137.                 ((ti -> ti_Data) != DTST_CLIPBOARD)
  138. #ifndef NO_ENCODER
  139. && ((ti -> ti_Data) != DTST_RAM)
  140. #endif /* !NO_ENCODER */
  141.  
  142. )
  143.             {
  144.               SetIoErr( ERROR_OBJECT_WRONG_TYPE );
  145.  
  146.               break;
  147.             }
  148.           }
  149.  
  150.           /* This must not be a subclass of 16sv.datatype
  151.            * (not implemented yet)
  152.            */
  153.           if( o == (Object *)cl )
  154.           {
  155.             if( retval = DoSuperMethodA( cl, o, msg ) )
  156.             {
  157.               LONG error;
  158.  
  159.               /* Load sample... */
  160.               if( error = Load16SV( cb, (Object *)retval ) )
  161.               {
  162.                 /* Something went fatally wrong, dispose object */
  163.                 CoerceMethod( cl, (Object *)retval, OM_DISPOSE );
  164.                 retval = 0UL;
  165.               }
  166.  
  167.               SetIoErr( error );
  168.             }
  169.           }
  170.           else
  171.           {
  172.             /* Subclasses of 16sv.datatype are not implemented */
  173.             SetIoErr( ERROR_NOT_IMPLEMENTED );
  174.           }
  175.       }
  176.           break;
  177.  
  178.       case OM_UPDATE:
  179.       {
  180.           if( DoMethod( o, ICM_CHECKLOOP ) )
  181.           {
  182.             break;
  183.           }
  184.       }
  185.       case OM_SET:
  186.       {
  187.           /* Pass the attributes to the sound class and force a refresh if we need it */
  188.           if( retval = DoSuperMethodA( cl, o, msg ) )
  189.           {
  190. /* The following check statement isn't needed because OM_NEW does not allow subclasses of 16sv.datatype,
  191.  * therefore, we're always the top instance...
  192.  */
  193. #ifdef COMMENTED_OUT
  194.             /* Top instance ? */
  195.             if( OCLASS( o ) == cl )
  196. #endif /* COMMENTED_OUT */
  197.             {
  198.               struct RastPort *rp;
  199.  
  200.               /* Get a pointer to the rastport */
  201.               if( rp = ObtainGIRPort( (((struct opSet *)msg) -> ops_GInfo) ) )
  202.               {
  203.                 struct gpRender gpr;
  204.  
  205.                 /* Force a redraw */
  206.                 gpr . MethodID   = GM_RENDER;
  207.                 gpr . gpr_GInfo  = ((struct opSet *)msg) -> ops_GInfo;
  208.                 gpr . gpr_RPort  = rp;
  209.                 gpr . gpr_Redraw = GREDRAW_UPDATE;
  210.  
  211.                 DoMethodA( o, (Msg)(&gpr) );
  212.  
  213.                 /* Release the temporary rastport */
  214.                 ReleaseGIRPort( rp );
  215.  
  216.                 retval = 0UL;
  217.               }
  218.             }
  219.           }
  220.       }
  221.           break;
  222.  
  223. /****** 16sv.datatype/DTM_WRITE **********************************************
  224. *
  225. *    NAME
  226. *        DTM_WRITE -- Save data
  227. *
  228. *    FUNCTION
  229. *        This method saves the object's contents to disk.
  230. *
  231. *        If dtw_Mode is DTWM_IFF, the method is passed unchanged to the
  232. *        superclass, sound.datatype, which writes an IFF 8SVX sample.
  233. *
  234. *        If dtw_mode is DTWM_RAW, the object writes an IFF 16SV sample to
  235. *        the filehandle given.
  236. *        (If the class library was compiled with the NO_ENCODER switch
  237. *        (not the default), result == 0 and resul2 == ERROR_NOT_IMPLEMENTED
  238. *        are returned).
  239. *
  240. *    BUGS
  241. *        - The encoder does not support compression. A request to save
  242. *          compressed data returns DTERROR_UNKNOWN_COMPRESSION.
  243. *
  244. *    TAGS
  245. *        None defined.
  246. *
  247. *    RESULT
  248. *        Returns 0 for failure (IoErr() returns result2), non-zero
  249. *        for success.
  250. *
  251. ******************************************************************************
  252. *
  253. */
  254.       case DTM_WRITE:
  255.       {
  256.           struct dtWrite *dtw;
  257.  
  258.           dtw = (struct dtWrite *)msg;
  259.  
  260.           /* Local data format requested ? */
  261.           if( (dtw -> dtw_Mode) == DTWM_RAW )
  262.           {
  263. /* Enable the followng code if you don't have an encoder implemented... */
  264. #ifdef NO_ENCODER
  265.             SetIoErr( ERROR_NOT_IMPLEMENTED );
  266.             retval = 0UL;
  267. #else
  268.             retval = SaveIFF16SV( cb, o, dtw );
  269. #endif /* NO_ENCODER */
  270.           }
  271.           else
  272.           {
  273.             /* Pass msg to superclass (which writes an IFF 8SVX sample)... */
  274.             retval = DoSuperMethodA( cl, o, msg );
  275.           }
  276.       }
  277.           break;
  278.  
  279.       /* Let the superclass handle everything else */
  280.       default:
  281.       {
  282.           retval = DoSuperMethodA( cl, o, msg );
  283.       }
  284.           break;
  285.     }
  286.  
  287.     return( retval );
  288. }
  289.  
  290.  
  291. static
  292. LONG Load16SV( struct ClassBase *cb, Object *o )
  293. {
  294.     LONG                 error = 0L;
  295.     APTR                 fh;               /* IFF stream handle               */
  296.     ULONG                sourcetype;       /* type of stream (either DTST_FILE, DTST_CLIPBOARD or DTST_RAM */
  297.     struct VoiceHeader  *vh;               /* obj's voice header              */
  298.  
  299.     /* Get file handle, handle type and VoiceHeader */
  300.     if( GetDTAttrs( o, DTA_SourceType,    (&sourcetype),
  301.                        DTA_Handle,        (&fh),
  302.                        SDTA_VoiceHeader,  (&vh),
  303.                        TAG_DONE ) == 3UL )
  304.     {
  305.       struct IFFHandle *iff = NULL;
  306.  
  307.       switch( sourcetype )
  308.       {
  309.         case DTST_CLIPBOARD:
  310.         case DTST_FILE:
  311.         {
  312.             /* This is an IFF DataType, datatypesclass provides an IFFHandle for us.
  313.              * (See datatypesclass autdocs for details !)
  314.              */
  315.             iff = (struct IFFHandle *)fh;
  316.         }
  317.             break;
  318.  
  319. #ifndef NO_ENCODER
  320.         case DTST_RAM:
  321.         {
  322.             /* Do nothing... */
  323.         }
  324.             break;
  325. #endif /* !NO_ENCODER */
  326.  
  327.         default:
  328.         {
  329.             /* unsupported source type */
  330.             error = ERROR_NOT_IMPLEMENTED;
  331.         }
  332.             break;
  333.       }
  334.  
  335.       /* Any error ? */
  336.       if( error == 0L )
  337.       {
  338.         /* Any handle to proccess ? */
  339.         if( iff )
  340.         {
  341.           SAMPLE8               *sample       = NULL; /* resulting sample (e.g. SDTA_Sample) */
  342.           ULONG                  samplelength = 0UL;  /* resulting sample length (e.g. SDTA_SampleLength) */
  343.  
  344.           struct StoredProperty *vhdrprop       = NULL, /* 16SV VHDR (struct VoiceHeader)         */
  345.                                 *bodyprop       = NULL, /* 16SV BODY                              */
  346.                                 *annoprop       = NULL, /* Generic IFF ANNO (annotation) chunk    */
  347.                                 *authprop       = NULL, /* Generic IFF AUTH (author) chunk        */
  348.                                 *copyrightprop  = NULL, /* Generic IFF (C)  (copyright) chunk     */
  349.                                 *fverprop       = NULL, /* Generic IFF FVER (version) chunk       */
  350.                                 *nameprop       = NULL; /* Generic IFF NAME (name) chunk          */
  351.  
  352. #define NUM_PROPCHUNKS (7L)
  353.           const
  354.           LONG propchunks[ (NUM_PROPCHUNKS * 2) ] =
  355.           {
  356.             ID_16SV, ID_VHDR,
  357.             ID_16SV, ID_BODY,
  358.             ID_16SV, ID_ANNO,
  359.             ID_16SV, ID_AUTH,
  360.             ID_16SV, ID_Copyright,
  361.             ID_16SV, ID_FVER,
  362.             ID_16SV, ID_NAME
  363.           };
  364.  
  365.           if( !(error = PropChunks( iff, (LONG *)propchunks, NUM_PROPCHUNKS )) )
  366.           {
  367.             /* Scan IFF stream until an error or an EOF occurs */
  368.             for( ;; )
  369.             {
  370.               if( error = ParseIFF( iff, IFFPARSE_STEP ) )
  371.               {
  372.                 /* EOF (End Of File) is no error here... */
  373.                 if( error == IFFERR_EOF )
  374.                 {
  375.                   error = 0L;
  376.                   break;
  377.                 }
  378.  
  379.                 /* vhdr header loaded ? */
  380.                 if( vhdrprop == NULL )
  381.                 {
  382.                   if( vhdrprop = FindProp( iff, ID_16SV, ID_VHDR ) )
  383.                   {
  384.                     *vh = *((struct VoiceHeader *)(vhdrprop -> sp_Data));
  385.  
  386.                     /* BODY data compression is currently not implemented yet... */
  387.                     if( (vh -> vh_Compression) != CMP_NONE )
  388.                     {
  389.                       error = DTERROR_UNKNOWN_COMPRESSION;
  390.                     }
  391.                   }
  392.                 }
  393.  
  394.                 /* annotation loaded ? */
  395.                 if( annoprop == NULL )
  396.                 {
  397.                   /* IFF ANNO found ? */
  398.                   if( annoprop = FindProp( iff, ID_16SV, ID_ANNO ) )
  399.                   {
  400.                     STRPTR buff;
  401.  
  402.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  403.                     if( buff = (STRPTR)AllocVec( ((annoprop -> sp_Size) + 2UL), MEMF_ANY ) )
  404.                     {
  405.                       stccpy( buff, (annoprop -> sp_Data), (int)(annoprop -> sp_Size) );
  406.  
  407.                       SetDTAttrs( o, NULL, NULL, DTA_ObjAnnotation, buff, TAG_DONE );
  408.  
  409.                       FreeVec( buff );
  410.                     }
  411.                     else
  412.                     {
  413.                       /* no temp. buffer */
  414.                       error = ERROR_NO_FREE_STORE;
  415.                     }
  416.                   }
  417.                 }
  418.  
  419.                 /* autor loaded ? */
  420.                 if( authprop == NULL )
  421.                 {
  422.                   /* IFF AUTH found ? */
  423.                   if( authprop = FindProp( iff, ID_16SV, ID_AUTH ) )
  424.                   {
  425.                     STRPTR buff;
  426.  
  427.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  428.                     if( buff = (STRPTR)AllocVec( ((authprop -> sp_Size) + 2UL), MEMF_ANY ) )
  429.                     {
  430.                       stccpy( buff, (authprop -> sp_Data), (int)(authprop -> sp_Size) );
  431.  
  432.                       SetDTAttrs( o, NULL, NULL, DTA_ObjAuthor, buff, TAG_DONE );
  433.  
  434.                       FreeVec( buff );
  435.                     }
  436.                     else
  437.                     {
  438.                       /* no temp. buffer */
  439.                       error = ERROR_NO_FREE_STORE;
  440.                     }
  441.                   }
  442.                 }
  443.  
  444.                 /* copyright loaded ? */
  445.                 if( copyrightprop == NULL )
  446.                 {
  447.                   /* IFF (C) found ? */
  448.                   if( copyrightprop = FindProp( iff, ID_16SV, ID_Copyright ) )
  449.                   {
  450.                     STRPTR buff;
  451.  
  452.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  453.                     if( buff = (STRPTR)AllocVec( ((copyrightprop -> sp_Size) + 2UL), MEMF_ANY ) )
  454.                     {
  455.                       stccpy( buff, (copyrightprop -> sp_Data), (int)(copyrightprop -> sp_Size) );
  456.  
  457.                       SetDTAttrs( o, NULL, NULL, DTA_ObjCopyright, buff, TAG_DONE );
  458.  
  459.                       FreeVec( buff );
  460.                     }
  461.                     else
  462.                     {
  463.                       /* no temp. buffer */
  464.                       error = ERROR_NO_FREE_STORE;
  465.                     }
  466.                   }
  467.                 }
  468.  
  469.                 /* file version loaded ? */
  470.                 if( fverprop == NULL )
  471.                 {
  472.                   /* IFF FVER found ? */
  473.                   if( fverprop = FindProp( iff, ID_16SV, ID_FVER ) )
  474.                   {
  475.                     STRPTR buff;
  476.  
  477.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  478.                     if( buff = (STRPTR)AllocVec( ((fverprop -> sp_Size) + 2UL), MEMF_ANY ) )
  479.                     {
  480.                       stccpy( buff, (fverprop -> sp_Data), (int)(fverprop -> sp_Size) );
  481.  
  482.                       SetDTAttrs( o, NULL, NULL, DTA_ObjVersion, buff, TAG_DONE );
  483.  
  484.                       FreeVec( buff );
  485.                     }
  486.                     else
  487.                     {
  488.                       /* no temp. buffer */
  489.                       error = ERROR_NO_FREE_STORE;
  490.                     }
  491.                   }
  492.                 }
  493.  
  494.                 /* name loaded ? */
  495.                 if( nameprop == NULL )
  496.                 {
  497.                   /* IFF NAME found ? */
  498.                   if( nameprop = FindProp( iff, ID_16SV, ID_NAME ) )
  499.                   {
  500.                     STRPTR buff;
  501.  
  502.                     /* Allocate a temp buffer so that stccpy can add a '\0'-terminator */
  503.                     if( buff = (STRPTR)AllocVec( ((nameprop -> sp_Size) + 2UL), MEMF_ANY ) )
  504.                     {
  505.                       stccpy( buff, (nameprop -> sp_Data), (int)(nameprop -> sp_Size) );
  506.  
  507.                       SetDTAttrs( o, NULL, NULL, DTA_ObjName, buff, TAG_DONE );
  508.  
  509.                       FreeVec( buff );
  510.                     }
  511.                     else
  512.                     {
  513.                       /* no temp. buffer */
  514.                       error = ERROR_NO_FREE_STORE;
  515.                     }
  516.                   }
  517.                 }
  518.  
  519.                 /* body loaded  ? */
  520.                 if( bodyprop == NULL )
  521.                 {
  522.                   if( bodyprop = FindProp( iff, ID_16SV, ID_BODY ) )
  523.                   {
  524.                     if( vhdrprop )
  525.                     {
  526.                       /* 8 bit sample data needs half of the size of 16 bit samples */
  527.                       samplelength = ((bodyprop -> sp_Size) / (sizeof( SAMPLE16 ) / sizeof( SAMPLE8 )));
  528.  
  529.                       if( sample = (SAMPLE8 *)AllocVec( (samplelength + 16UL), (MEMF_PUBLIC | MEMF_CLEAR) ) )
  530.                       {
  531.                         error = Load16SVBody( sample, (bodyprop -> sp_Data), (bodyprop -> sp_Size) );
  532.                       }
  533.                       else
  534.                       {
  535.                         /* No sample */
  536.                         error = ERROR_NO_FREE_STORE;
  537.                       }
  538.                     }
  539.                     else
  540.                     {
  541.                       /* No VHDR chunk before BODY chunk */
  542.                       error = DTERROR_INVALID_DATA;
  543.                     }
  544.                   }
  545.                 }
  546.  
  547.                 /* on error: leave for-loop */
  548.                 if( error )
  549.                 {
  550.                   if( error != IFFERR_EOC )
  551.                   {
  552.                     break;
  553.                   }
  554.                 }
  555.               }
  556.             }
  557.           }
  558.  
  559.           /*  voiceheader, body and all other required information available ? */
  560.           if( ((vhdrprop == NULL) || (bodyprop == NULL) || (sample == NULL)) && (samplelength == 0UL) && (error == 0L) )
  561.           {
  562.             error = DTERROR_INVALID_DATA;
  563.           }
  564.  
  565.           /* Any error ? */
  566.           if( error == 0L )
  567.           {
  568.             if( vh -> vh_SamplesPerSec )
  569.             {
  570.               ULONG clock = ((SysBase -> ex_EClockFrequency) * 5UL),
  571.                     period;
  572.               ULONG volume;
  573.  
  574.               /* Calc sample period */
  575.               period = clock / (vh -> vh_SamplesPerSec);
  576.  
  577.               /* scale IFF 8SVX volume resolution (0 - VOLUME_UNITY) to sound.datatype resolution (0 - 63) */
  578.               volume = ((vh -> vh_Volume) * 63UL) / VOLUME_UNITY;
  579.  
  580.               /* No name chunk ? */
  581.               if( nameprop == NULL )
  582.               {
  583.                 STRPTR name;
  584.  
  585.                 GetDTAttrs( o, DTA_Name, (&name), TAG_DONE );
  586.                 SetDTAttrs( o, NULL, NULL, DTA_ObjName, name, TAG_DONE );
  587.               }
  588.  
  589.               /* Set misc attributes
  590.                * In fact, SDTA_Period and SDTA_Volume are calculated from SDTA_VoiceHeader info,
  591.                * but we set it here EXPLICITLY that noone can say we didn't pass this to sound.datatype...
  592.                */
  593.               SetDTAttrs( o, NULL, NULL, SDTA_Sample,         sample,
  594.                                          SDTA_SampleLength,   samplelength,
  595.                                          SDTA_Period,         period,
  596.                                          SDTA_Volume,         volume,
  597.                                          TAG_DONE );
  598.  
  599.               /* sound.datatype now owns the sample data and will FreeVec then at OM_DISPOSE time... */
  600.               sample = NULL;
  601.             }
  602.             else
  603.             {
  604.               /* we need a valid sps value here */
  605.               error = DTERROR_INVALID_DATA;
  606.             }
  607.           }
  608.  
  609.           /* If the sample data were not used by sound.datatype (e.g. eaten up), free them here */
  610.           if( sample )
  611.           {
  612.             FreeVec( sample );
  613.           }
  614.         }
  615.         else
  616.         {
  617.           /* No iff handle ? - Be sure we got a DTST_RAM sourcetype */
  618.           if( sourcetype != DTST_RAM )
  619.           {
  620.             /* No handle ! */
  621.             error = ERROR_REQUIRED_ARG_MISSING;
  622.           }
  623.         }
  624.       }
  625.     }
  626.     else
  627.     {
  628.       /* can't get required attributes from superclass */
  629.       error = ERROR_OBJECT_WRONG_TYPE;
  630.     }
  631.  
  632.     /* Error codes below 0 are related to the IFFParse.library functions */
  633.     if( error < 0L )
  634.     {
  635.       /* convert IFFParse error to DOS error */
  636.       error = ifferr2doserr[ (-error - 1) ];
  637.     }
  638.  
  639.     return( error );
  640. }
  641.  
  642.  
  643. /* The IFF 16SV BODY loader */
  644. static
  645. LONG Load16SVBody( SAMPLE8 *sample8, UBYTE *buffer, ULONG buffersize )
  646. {
  647.     LONG      error = 0L;
  648.     ULONG     i;
  649.     SAMPLE16 *sample16 = (SAMPLE16 *)buffer;
  650.  
  651.     buffersize /= (sizeof( SAMPLE16 ) / sizeof( SAMPLE8 ));
  652.  
  653.     for( i = 0UL ; i < buffersize ; i++ )
  654.     {
  655.       /* scale sample from 16 down to 8 bit resolution... */
  656.       *sample8++ = ((ULONG)sample16[ i ] * SAMPLE8_MAX) / SAMPLE16_MAX;
  657.     }
  658.  
  659.     return( error );
  660. }
  661.  
  662.  
  663. #ifndef NO_ENCODER
  664. /* The IFF 16SV encoder */
  665. static
  666. ULONG SaveIFF16SV( struct ClassBase *cb, Object *o, struct dtWrite *dtw )
  667. {
  668.     ULONG retval = 0UL;
  669.     LONG  error  = 0L;
  670.  
  671.     /* A NULL file handle is a nop (GMultiView uses this to test if a datatype supports RAW writing) */
  672.     if( dtw -> dtw_FileHandle )
  673.     {
  674.       struct DTSpecialInfo *si = (struct DTSpecialInfo *)(G( o ) -> SpecialInfo);
  675.       STRPTR                objname,
  676.                             objauthor,
  677.                             objannotation,
  678.                             objcopyright,
  679.                             objversion;
  680.       struct VoiceHeader   *vh;
  681.       SAMPLE8              *sample;
  682.       ULONG                 samplelength;
  683.       ULONG                 volume;
  684.       ULONG                 period;
  685.  
  686.       /* Lock data that noone could change it...
  687.        * We use here a shared lock because we don't chaange any object data below
  688.        * Theoretically, this allows that multiple savers acts on the same object :-)
  689.        */
  690.       ObtainSemaphoreShared( (&(si -> si_Lock)) );
  691.  
  692.       if( GetDTAttrs( o, DTA_ObjName,       (&objname),
  693.                          DTA_ObjAuthor,     (&objauthor),
  694.                          DTA_ObjAnnotation, (&objannotation),
  695.                          DTA_ObjCopyright,  (&objcopyright),
  696.                          DTA_ObjVersion,    (&objversion),
  697.                          SDTA_VoiceHeader,  (&vh),
  698.                          SDTA_Sample,       (&sample),
  699.                          SDTA_SampleLength, (&samplelength),
  700.                          SDTA_Volume,       (&volume),
  701.                          SDTA_Period,       (&period),
  702.                          TAG_DONE ) == 10UL )
  703.       {
  704.         if( sample && samplelength && period )
  705.         {
  706.           /* BODY data compression for IFF 16SV is currently not implemented */
  707.           if( (vh -> vh_Compression) == CMP_NONE )
  708.           {
  709.             struct IFFHandle  *iff;
  710.             struct VoiceHeader vhdr;
  711.  
  712.             /* Fill voiceheader... */
  713.             vhdr . vh_OneShotHiSamples     = samplelength;
  714.             vhdr . vh_RepeatHiSamples      = 0UL;
  715.             vhdr . vh_SamplesPerHiCycle    = 0UL;
  716.             vhdr . vh_SamplesPerSec        = ((SysBase -> ex_EClockFrequency) * 5UL) / period;
  717.             vhdr . vh_Octaves              = 1UL;
  718.             vhdr . vh_Compression          = CMP_NONE;
  719.             vhdr . vh_Volume               = MAX( (((vh -> vh_Volume) * VOLUME_UNITY) / 64UL), VOLUME_UNITY );
  720.  
  721.             /* Create IFF handle based in the given file handle */
  722.             if( iff = CreateDOSIFFHandle( cb, (dtw -> dtw_FileHandle) ) )
  723.             {
  724.               if( !(error = OpenIFF( iff, IFFF_WRITE )) )
  725.               {
  726.                 for( ;; ) /* not a loop, used as a jump table */
  727.                 {
  728.                   if( error = PushChunk( iff, ID_16SV, ID_FORM, IFFSIZE_UNKNOWN ) )
  729.                     break;
  730.  
  731.                   /* write VHDR (VoiceHeader) */
  732.                   {
  733.                     if( error = PushChunk( iff, 0UL, ID_VHDR, sizeof( struct VoiceHeader ) ) )
  734.                       break;
  735.  
  736.                     if( (error = WriteChunkBytes( iff, (APTR)(&vhdr), sizeof( struct VoiceHeader ) )) != sizeof( struct VoiceHeader ) )
  737.                     {
  738.                       break;
  739.                     }
  740.  
  741.                     if( error = PopChunk( iff ) )
  742.                       break;
  743.                   }
  744.  
  745.                   /* write misc info (name, author, annotation etc.) */
  746.                   if( error = PutIFFObjectInfo( cb, iff, objname, objauthor, objannotation, objcopyright, objversion ) )
  747.                     break;
  748.  
  749.                   /* Write 16SV BODY */
  750.                   if( error = Put16SVBODY( cb, iff, sample, samplelength ) )
  751.                     break;
  752.  
  753.                   if( error = PopChunk( iff ) )
  754.                     break;
  755.  
  756.                   break; /* end of jump table */
  757.                 }
  758.  
  759.                 CloseIFF( iff );
  760.               }
  761.  
  762.               /* No error == success */
  763.               if( error == 0L )
  764.               {
  765.                 retval = 1UL; /* success ! */
  766.               }
  767.  
  768.               FreeIFF( iff );
  769.             }
  770.             else
  771.             {
  772.               /* Can't alloc iff handle */
  773.               error = ERROR_NO_FREE_STORE;
  774.             }
  775.           }
  776.           else
  777.           {
  778.             /* IFF 16SV does currectly not implement compresion */
  779.             error = DTERROR_UNKNOWN_COMPRESSION;
  780.           }
  781.         }
  782.         else
  783.         {
  784.           /* Some things are missing (e.g. no sample etc.)... */
  785.           error = DTERROR_NOT_ENOUGH_DATA;
  786.         }
  787.       }
  788.       else
  789.       {
  790.         /* Object does not support the attributes we need... */
  791.         error = ERROR_OBJECT_WRONG_TYPE;
  792.       }
  793.  
  794.       /* Release data */
  795.       ReleaseSemaphore( (&(si -> si_Lock)) );
  796.     }
  797.  
  798.     /* Error codes below 0 are related to the IFFParse.library functions */
  799.     if( error < 0L )
  800.     {
  801.       /* convert IFFParse error to DOS error */
  802.       error = ifferr2doserr[ (-error - 1) ];
  803.     }
  804.  
  805.     /* Store Result2 */
  806.     SetIoErr( error );
  807.  
  808.     return( retval );
  809. }
  810.  
  811.  
  812. /* Create IFF handle based on given file handle */
  813. static
  814. struct IFFHandle *CreateDOSIFFHandle( struct ClassBase *cb, BPTR fh )
  815. {
  816.     struct IFFHandle *iff;
  817.  
  818.     if( iff = AllocIFF() )
  819.     {
  820.       iff -> iff_Stream = (ULONG)fh;
  821.  
  822.       InitIFFasDOS( iff );
  823.     }
  824.  
  825.     return( iff );
  826. }
  827.  
  828.  
  829. /* Put IFF generic info chunks (NAME, AUTH, ANNO, (C), FVER etc. */
  830. static
  831. LONG PutIFFObjectInfo( struct ClassBase *cb, struct IFFHandle *iff, STRPTR objname, STRPTR objauthor, STRPTR objannotation, STRPTR objcopyright, STRPTR objversion )
  832. {
  833.     LONG error;
  834.  
  835.     if( error = PutIFFString( cb, iff, ID_NAME,      objname       ) ) return( error );
  836.     if( error = PutIFFString( cb, iff, ID_AUTH,      objauthor     ) ) return( error );
  837.     if( error = PutIFFString( cb, iff, ID_ANNO,      objannotation ) ) return( error );
  838.     if( error = PutIFFString( cb, iff, ID_Copyright, objcopyright  ) ) return( error );
  839.     if( error = PutIFFString( cb, iff, ID_FVER,      objversion    ) ) return( error );
  840.  
  841.     return( 0L );
  842. }
  843.  
  844.  
  845. /* write an string into a chunk (like generic AUTH, ANNO etc. chunks)  */
  846. static
  847. LONG PutIFFString( struct ClassBase *cb, struct IFFHandle *iff, ULONG id, STRPTR string )
  848. {
  849.     LONG error = 0L;
  850.  
  851.     if( string )
  852.     {
  853.       ULONG len = (ULONG)(strlen( string ) + 1UL);
  854.  
  855.       if( error = PushChunk( iff, 0UL, id, len ) )
  856.         return( error );
  857.  
  858.       if( (error = WriteChunkBytes( iff, (APTR)string, len )) != len )
  859.       {
  860.         return( error );
  861.       }
  862.  
  863.       error = PopChunk( iff );
  864.     }
  865.  
  866.     return( error );
  867. }
  868.  
  869.  
  870. /*****************************************************************************/
  871.  
  872. /* Write 16SV BODY data */
  873. static
  874. LONG Put16SVBODY( struct ClassBase *cb, struct IFFHandle *iff, SAMPLE8 *sample, ULONG samplelength )
  875. {
  876.     LONG  error;
  877.     ULONG i;
  878.  
  879.     /* Write out a BODY chunk header */
  880.     if( error = PushChunk( iff, 0L, ID_BODY, (samplelength * 2L) ) )
  881.       return( error );
  882.  
  883.       /* Write out the BODY contents */
  884.       for( i = 0UL ; i < samplelength ; i++ )
  885.       {
  886.         SAMPLE16 sample16 = (LONG)sample[ i ] * 256L;
  887.  
  888.         if( (error = WriteChunkBytes( iff, (APTR)(&sample16), sizeof( SAMPLE16 ) )) != sizeof( SAMPLE16 ) )
  889.           return( error );
  890.       }
  891.  
  892.     /* Finish the chunk */
  893.     error = PopChunk( iff );
  894.  
  895.     return( error );
  896. }
  897.  
  898. #endif /* NO_ENCODER */
  899.  
  900.  
  901.  
  902.  
  903.  
  904.