
/*
**
**  $VER: classbase.c 2.1 (14.2.98)
**  mpegaudio.datatype 2.1
**
**  Library routines for a DataTypes class
**
**  Written 1996-1998 by Roland 'Gizzy' Mainz
**  Original example source from David N. Junod
**
*/


/* main includes */
#include "classbase.h"


/****** mpegaudio.datatype/MAIN **********************************************
*
*    INTRODUCTION
*        Datatypes class for MPEG audio streams.
*
*    REQUIREMENTS
*        - You need at least Kick/WB 3.0.
*
*        - mc68020 (required by the "mpega" decoder).
*          This datatype checks the CPU installed and rejects any attempt to
*          open it if the CPU is not available.
*
*        - "datatypes/sound.datatype", >= V39.
*
*    USAGE
*        If the datatypes descriptor file was activated, any attempt to load
*        a MPEG audio stream using GMultiView, MultiView, AmigaGuide or
*        SwitchWindow will load and play the sample.
*
*        If you want to save the current sample in mpegaudio.datatype's local
*        format, use MultiView's "Project/Save As..." menu (or GMultiView's
*        "Project/Save As Raw...").
*        (NOT IMPLEMENTED YET)
*
*    INSTALLATION
*        After unpacking this archive:
*        Because this version does not include an Installer script, you have
*        to do the installation manually through the shell:
*
*          - Unpack this archive and copy the "mpegaudio.datatype" to
*            SYS:Classes/DataTypes:
*
*     Copy CLONE FROM "mpegaudio.datatype" TO
*       "SYS:Classes/DataTypes/mpegaudio.datatype"
*
*          - Then copy the datatypes descriptor into the DEVS:DataTypes
*            directory.
*            If the descriptor already exists, you should not replace it,
*            otherwise you may loose "toolnodes" and other settings stored in
*            the existing descriptor.
*
*     Copy CLONE FROM "MPEG Audio(%|.info)" TO DEVS:Datatypes/
*
*    NOTE
*        The datatype "hooks" on an external mpeg audio decoder like "mpega".
*
*    SOURCE
*        Source is fully included here.
*
*    AUTHOR
*        If you want to blame me, report any bugs, or wants a new version
*        send your letter to:
*                        Roland Mainz
*                        Hohenstaufenstraße 8
*                        52388 Nörvenich
*                        GERMANY
*
*        Phone: (+49)(0)2426/901568
*        Fax:   (+49)(0)2426/901569
*
*        EMAIL is also available (if you want to send me attachments
*        larger than 1MB (up to 5MB, more with my permission):
*
*        GISBURN@w-specht.rhein-ruhr.de
*
*        Up to April 1998 I'm reachable using this email address, too:
*        Reinhold.A.Mainz@KBV.DE
*
*        | Please put your name and address in your mails !
*        | German mailers should add their phone numbers.
*        | See BUGS section above when submitting bug reports.
*
*        Sorry, but I can only look once a week for mails.
*        If you don't hear something from me within three weeks, please
*        send your mail again (but watch about new releases) (problems with
*        this email port are caused by reconfigurations, hackers, network
*        problems etc.).
*
*        The  entire  "mpegaudio.datatype"  package  may  be  noncommercially
*        redistributed, provided  that  the package  is always  distributed
*        in it's complete  form (including it's documentation). A small
*        copy fee  for media costs is okay but any kind of commercial
*        distribution is strictly forbidden without my permission !
*        Comments and suggestions how to improve this program are
*        generally appreciated!
*
*        Thanks to David Junod, who wrote the datatypes environment and lots
*        of the datatypes example code, Matt Dillon for his DICE, Olaf 
*        'Olsen' Barthel for his help, ideas and some text clips from his 
*        documentations.
*
******************************************************************************
*
*/


/****** mpegaudio.datatype/--datasheed-- *************************************
*
*   NAME
*       mpegaudio.datatype -- data type for MPEG audio streams
*
*   SUPERCLASS
*       sound.datatype
*
*   DESCRIPTION
*       The mpegaudio.datatype, a sub-class of the sound.datatype, is
*       used to load and save MPEG audio streams using "maplay" / "mpega"
*       and the 8SVX/AIFF datatype.
*
*   METHODS
*       OM_NEW -- Create a new sound object from a description file. The
*           source may only be a file. An empty object (DTST_RAM) can
*           also be created (unless the project was compiled with
*           the NO_ENCODER flag).
*
*       OM_UPDATE -- Perform an ICM_CHECKLOOP check, and if succesfull, the
*           method will be executed like OM_SET downstairs.
*
*       OM_SET -- Pass msg to superclass and call GM_RENDER if retval from
*           superclass was != 0UL.
*
*       DTM_WRITE -- Save data in local (MPEG audio) or superclass (IFF 8SVX)
*           format.
*
*       All other methods are passed unchanged to superclass.
*
*   ATTRIBUTES
*       Following attributes are set by the object and are READ-ONLY for
*       applications (if the datatype is used for saving (e.g. the
*       application creates an empty mpegaudio.datatype object and fills
*       in some required atrributes as shown in the "DTConvert" example),
*       these attributes are used by the encoder to create a MPEG audio
*       sound file):
*
*       DTA_ObjName         -- Set by DTA_Name's value.
*       SDTA_VoiceHeader    -- Copy from the embedded 8svx/aiff.datatype 
*                              object
*       SDTA_Sample         -- 8 bit sample data
*       SDTA_SampleLength   -- length of 8 bit sample data
*       SDTA_Volume         -- volume (got from the voiceheader)
*       SDTA_Period         -- created from (VoiceHeader -> vh_SamplesPerSec)
*                              and system's clock
*
*   BUGS
*       The project has been not very well tested yet. Therefore...
*       ... no known bugs.
*
*   TODO
*       - Fixing the bugs above
*
*       - Support for SDTM_LOADFRAME / SDTM_UNLOADFRAME (implies also support
*         for 16-bit audio á la RTA /  AHI).
*
*       - Encoder support (e.g. DTM_WRITE).
*
*   HISTORY
*       V1.1
*         First public release.
*
*       V1.2
*         - Swichted to Stephane Tavenard's "mpega".
*           (Have gave me the tip how to get in sync with the video (using
*           the options -b 1 -t 0).
*           Thank you very much Stephane !
*
*         - Small code cleanup (the class dispatcher is now a static
*           function etc.)
*
*       V1.2
*         - Swichted to Stephane Tavenard's "mpega.library".
*           Thank you very much Stephane !
*
*
*   SEE ALSO
*       sound.datatype
*
*******************************************************************************
*
*/


/****** mpegaudio.datatype/--input_format-- **********************************
*
*    NAME
*        MPEG audio --
*
*    DESCRIPTION
*        <not written yet>
*
*    SEE ALSO
*
*******************************************************************************
*
*/



/*****************************************************************************/

DISPATCHERFLAGS
struct IClass *ObtainMPEGAudioEngine( REGA6 struct ClassBase *cb )
{
    return( (cb -> cb_Lib . cl_Class) );
}

/*****************************************************************************/

DISPATCHERFLAGS
struct Library *LibInit( REGD0 struct ClassBase *cb, REGA0 BPTR seglist, REGA6 struct ExecBase *sysbase )
{
    cb -> cb_SegList = seglist;
    cb -> cb_SysBase = sysbase;

    InitSemaphore( (&(cb -> cb_Lock)) );

#ifdef REQUIREDAFF
    /* Check if the requested cpu/fpu is available */
    if( ((sysbase -> AttnFlags) | REQUIREDAFF) != (sysbase -> AttnFlags) )
    {
      return( NULL );
    }
#endif /* REQUIREDAFF */

    if( (cb -> cb_SysBase -> LibNode . lib_Version) >= 39UL )
    {
      /* Obtain ROM libs */
      if( cb -> cb_UtilityBase = OpenLibrary( "utility.library", 39UL ) )
      {
        if( cb -> cb_DOSBase = OpenLibrary( "dos.library", 39UL ) )
        {
          if( cb -> cb_IntuitionBase = OpenLibrary( "intuition.library", 39UL ) )
          {
            return( (&(cb -> cb_Lib . cl_Lib)) );

#ifdef COMMENTED_OUT
              CloseLibrary( (cb -> cb_IntuitionBase) );
#endif /* COMMENTED_OUT */
          }

          CloseLibrary( (cb -> cb_DOSBase) );
        }

        CloseLibrary( (cb -> cb_UtilityBase) );
      }
    }

    return( NULL );
}

/*****************************************************************************/

DISPATCHERFLAGS
LONG LibOpen( REGA6 struct ClassBase *cb )
{
    LONG retval = (LONG)cb;
    BOOL success = TRUE;

    ObtainSemaphore( (&(cb -> cb_Lock)) );

    /* Use an internal use counter */
    cb -> cb_Lib . cl_Lib . lib_OpenCnt++;
    cb -> cb_Lib . cl_Lib . lib_Flags &= ~LIBF_DELEXP;

    if( (cb -> cb_Lib . cl_Lib . lib_OpenCnt) == 1U )
    {
      if( (cb -> cb_Lib . cl_Class) == NULL )
      {
        success = FALSE;

        if( cb -> cb_MPEGABase = OpenLibrary( "mpega.library", 0UL ) )
        {
          if( cb -> cb_DataTypesBase = OpenLibrary( "datatypes.library", 39UL ) )
          {
            if( cb -> cb_SuperClassBase = OpenLibrary( "datatypes/sound.datatype", 39UL ) )
            {
              if( cb -> cb_Lib . cl_Class = initClass( cb ) )
              {
                success = TRUE;
              }
            }
          }
        }
      }
    }

    if( !success )
    {
      CloseLibrary( (cb -> cb_SuperClassBase) );
      CloseLibrary( (cb -> cb_DataTypesBase) );
      CloseLibrary( (cb -> cb_MPEGABase) );

      cb -> cb_DataTypesBase = cb -> cb_SuperClassBase = NULL;

      (cb -> cb_Lib . cl_Lib . lib_OpenCnt)--;

      retval = 0L;
    }

    ReleaseSemaphore( (&(cb -> cb_Lock)) );

    return( retval );
}

/*****************************************************************************/

DISPATCHERFLAGS
LONG LibClose( REGA6 struct ClassBase *cb )
{
    LONG retval = 0L;

    ObtainSemaphore( (&(cb -> cb_Lock)) );

    if( cb -> cb_Lib . cl_Lib . lib_OpenCnt )
    {
      (cb -> cb_Lib . cl_Lib . lib_OpenCnt)--;
    }

    if( ((cb -> cb_Lib . cl_Lib . lib_OpenCnt) == 0U) && (cb -> cb_Lib . cl_Class) )
    {
      if( FreeClass( (cb -> cb_Lib . cl_Class) ) )
      {
        cb -> cb_Lib . cl_Class = NULL;

        CloseLibrary( (cb -> cb_SuperClassBase) );
        CloseLibrary( (cb -> cb_DataTypesBase) );
        CloseLibrary( (cb -> cb_MPEGABase) );
      }
      else
      {
        cb -> cb_Lib . cl_Lib . lib_Flags |= LIBF_DELEXP;
      }
    }

    ReleaseSemaphore( (&(cb -> cb_Lock)) );

    if( cb -> cb_Lib . cl_Lib . lib_Flags & LIBF_DELEXP )
    {
      retval = LibExpunge( cb );
    }

    return( retval );
}

/*****************************************************************************/

DISPATCHERFLAGS
LONG LibExpunge( REGA6 struct ClassBase *cb )
{
    BPTR seg;

    if( cb -> cb_Lib . cl_Lib . lib_OpenCnt )
    {
      cb -> cb_Lib . cl_Lib . lib_Flags |= LIBF_DELEXP;

      seg = NULL;
    }
    else
    {
      Remove( (&(cb -> cb_Lib . cl_Lib . lib_Node)) );

      seg = cb -> cb_SegList;

      CloseLibrary( (cb -> cb_IntuitionBase) );
      CloseLibrary( (cb -> cb_DOSBase) );
      CloseLibrary( (cb -> cb_UtilityBase) );

      FreeMem( (APTR)((ULONG)(cb) - (ULONG)(cb -> cb_Lib . cl_Lib . lib_NegSize)), (ULONG)((cb -> cb_Lib . cl_Lib . lib_NegSize) + (cb -> cb_Lib . cl_Lib . lib_PosSize)) );
    }

    return( (LONG)seg );
}




