
/*
**
**  $VER: classbase.c 1.1 (9.11.97)
**  mpegaudio.datatype 1.1
**
**  Library routines for a DataTypes class
**
**  Written 1996/97 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/68881 (required by the included "maplay" decoder).
*          This datatype checks the CPU installed and rejects any attempt to
*          open it if the CPU/FPU is not available.
*
*        - ixemul.library V46.1 or higer (required by the included "maplay"
*          decoder)
*
*        - "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.
*        Currently, a own version of "maplay" is used here (which is
*        __very__ slow).
*        Usage of Stephane Tavendard's "mpega" would be possible, but
*        due a bug in mpega (<=2.4) the output seems to be unuseable
*        (for the main purpose "mpegaudio.datatype" was written for).
*        The bug causes that if the sample is played back in sync with
*        a video, the sample got from "mpega" runs a few secs behind
*        the video, which looks/sounds very ugly. Using the included
*        "maplay", this won't occur.
*
*    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 December 1997 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 "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
*
*       - Wating for a bugfixed version of "mpega", and then enable "mpega"
*         support again.
*
*       - Support for SDTM_LOADFRAME / SDTM_UNLOADFRAME (implies also support
*         for 16-bit audio á la RTA /  AHI).
*
*   HISTORY
*       V1.1
*         First public release.
*
*   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_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) );

      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) );
      }
      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 );
}




