Source Code for MIDI Player (In-Process)


The following source files, led by gray banners, contain all the class functions needed for the in-process simulator in MIDI Player for SansGUI.  The sections highlighted by a yellow background Color are manually entered.  Code sections with white background color are generated by the SansGUI Source Code Framework.  The source files are compiled into a dynamic linked library to be invoked by SansGUI during simulation runs.

Classes S-1 through S-4 are subclasses of class Base.Channel.  They contain only Evaluation routines, which call the same function in class Base.Channel for the common behavior.  We list the source code of class Base.Channel.S-1 to show how to call the parent function.  Other channels, S-2 through S-4, contain similar code and are omitted from the listings.  For more details about the complete package, please read the MIDI Player for SansGUI Manual on-line.

Implementation in C/C++ (MSVC)

Functions in Class Collection.MIDI

/* Collection_MIDI.c
 * - DLL routines for class <Reference>Collection.MIDI
 * DATE: Sunday, April 21, 2002 TIME: 04:53:34 PM
 * The skeleton of this file is generated by SansGUI(tm)
 */

#include <windows.h> /* for shared memory functions */

#include <stdio.h>

#include <string.h>

#include "SGdll.h"

#ifdef __cplusplus
extern "C"
{
#endif

SG_EXPORT SG_SIM_FUNC SG_xInit_Collection_MIDI;
SG_EXPORT SG_SIM_FUNC SG_xPreEval_Collection_MIDI;
SG_EXPORT SG_SIM_FUNC SG_xPostEval_Collection_MIDI;
SG_EXPORT SG_SIM_FUNC SG_xEndRun_Collection_MIDI;

#ifdef __cplusplus
}
#endif

 

/* Macros for attribute indices in class version [1.0.0.0] */
#define SG_NDX_CFILENAME 0 /* cFileName - MIDI File Name */
#define SG_NDX_CSHARENAME 1 /* cShareName - Unique Name for Shared Memory */
#define SG_NDX_FINTERVAL 2 /* fInterval - Sampling Interval */
#define SG_NDX_FTIME 3 /* fTime - Current Sampling Time */
#define SG_NDX_IHANDLE 4 /* iHandle - Shared Memory Handle */
#define SG_NDX_IMEMORY 5 /* iMemory - Shared Memory Pointer */
#define SG_NDX_ICHANNEL 6 /* iChannel - Current MIDI Channel */
#define SG_NDX_IDATA 7 /* iData - Current MIDI Data */

 

/* ============================================================
 * SG_xInit - Initialization
 * ------------------------------------------------------------
 */
SG_RET_CODE SG_xInit_Collection_MIDI(SG_OBJ *const self,
          SG_OBJ *const simCtrl, SG_OBJ *const chgChild,
          SG_OBJ *const refObjs[], const INT *const piRefObjs,
          SG_OBJ *const adjObjs[], const INT *const piAdjObjs,
          SG_OBJ *const lnkObjs[], const INT *const piLnkObjs,
          TCHAR *const cMessage, const INT iMsgLen,
          TCHAR *const cCommand, const INT iCmdLen,
          SG_FILE *const pOutFile )
{
    /* TODO: declare your local variables here */

    HANDLE hMappedFile;
    LPVOID pSharedMem;

    if (!SG_IsSchemaOK(self->nSGobjSchema))
        return SG_R_SCHM;

    /* TODO: put your simulator code here */

    /* find the shared memory created by the external process simulator */
    hMappedFile = OpenFileMapping(PAGE_READONLY, FALSE,
                  &self->zValues[SG_NDX_CSHARENAME].cData[0] );
    if (hMappedFile == (HANDLE*)0)
    {
        strcpy(cMessage,
            "Invoke external process simulator and check shared memory name.");
        return SG_R_STOP;
    }
    pSharedMem = MapViewOfFile(hMappedFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
    if (pSharedMem == (LPVOID*)NULL)
    {
        strcpy(cMessage, "Cannot map shared memory.");
        return SG_R_STOP;
    }

    /* successful, register the handle and the shared memory pointer */
    self->zValues[SG_NDX_IHANDLE].iData[0] = (INT)hMappedFile;
    self->zValues[SG_NDX_IMEMORY].iData[0] = (INT)pSharedMem;

 

    /* reset current sampling time */
    self->zValues[SG_NDX_FTIME].fData[0] = 0.0f;

    return SG_R_OK;
}

/* ============================================================
 * SG_xPreEval - Pre-Evaluation
 * ------------------------------------------------------------
 */
SG_RET_CODE SG_xPreEval_Collection_MIDI(SG_OBJ *const self,
          SG_OBJ *const simCtrl, SG_OBJ *const chgChild,
          SG_OBJ *const refObjs[], const INT *const piRefObjs,
          SG_OBJ *const adjObjs[], const INT *const piAdjObjs,
          SG_OBJ *const lnkObjs[], const INT *const piLnkObjs,
          TCHAR *const cMessage, const INT iMsgLen,
          TCHAR *const cCommand, const INT iCmdLen,
          SG_FILE *const pOutFile )
{
    /* TODO: declare your local variables here */

    HANDLE hMappedFile = (HANDLE)self->zValues[SG_NDX_IHANDLE].iData[0];
    LPVOID pSharedMem = (LPVOID)self->zValues[SG_NDX_IMEMORY].iData[0];
    INT* pChannel = pSharedMem;
    INT* pData = pChannel + 1; /* warning: pointer arithmetic */

    if (!SG_IsSchemaOK(self->nSGobjSchema))
        return SG_R_SCHM;

    /* TODO: put your simulator code here */

    /* when the channel number is negative, the MIDI player has ended */
    if (*pChannel < 0)
    {
        strcpy(cMessage, "External Process Simulator has been terminated.");
        if (pSharedMem != (LPVOID)NULL)
            UnmapViewOfFile(pSharedMem);
        if (hMappedFile != (HANDLE)0)
            CloseHandle(hMappedFile);
        return SG_R_STOP;
    }
    /* still playing, copy the channel number and the data field from
     * the shared memory
     */
    self->zValues[SG_NDX_ICHANNEL].iData[0] = *pChannel;
    self->zValues[SG_NDX_IDATA].iData[0] = *pData;

    return SG_R_OK;
}

/* ============================================================
 * SG_xPostEval - Post-Evaluation
 * ------------------------------------------------------------
 */
SG_RET_CODE SG_xPostEval_Collection_MIDI(SG_OBJ *const self,
          SG_OBJ *const simCtrl, SG_OBJ *const chgChild,
          SG_OBJ *const refObjs[], const INT *const piRefObjs,
          SG_OBJ *const adjObjs[], const INT *const piAdjObjs,
          SG_OBJ *const lnkObjs[], const INT *const piLnkObjs,
          TCHAR *const cMessage, const INT iMsgLen,
          TCHAR *const cCommand, const INT iCmdLen,
          SG_FILE *const pOutFile )
{
    /* TODO: declare your local variables here */

    const INT ciInterval = (INT)self->zValues[SG_NDX_FINTERVAL].fData[0];

    if (!SG_IsSchemaOK(self->nSGobjSchema))
        return SG_R_SCHM;

    /* TODO: put your simulator code here */

    if (ciInterval > 0)
    {   /* if interval is specified, sleep until the next time */
        Sleep(ciInterval);
        /* advance current time register */
        self->zValues[SG_NDX_FTIME].fData[0] += (FLOAT)ciInterval;
    }
    else
    {   /* we just do as quick as we can and indicate 1 millisecond per cycle */
        self->zValues[SG_NDX_FTIME].fData[0] += 1.0f;
    }

    return SG_R_OK;
}

/* ============================================================
 * SG_xEndRun - End Run
 * ------------------------------------------------------------
 */
SG_RET_CODE SG_xEndRun_Collection_MIDI(SG_OBJ *const self,
          SG_OBJ *const simCtrl, SG_OBJ *const chgChild,
          SG_OBJ *const refObjs[], const INT *const piRefObjs,
          SG_OBJ *const adjObjs[], const INT *const piAdjObjs,
          SG_OBJ *const lnkObjs[], const INT *const piLnkObjs,
          TCHAR *const cMessage, const INT iMsgLen,
          TCHAR *const cCommand, const INT iCmdLen,
          SG_FILE *const pOutFile )
{
    /* TODO: declare your local variables here */

    HANDLE hMappedFile = (HANDLE)self->zValues[SG_NDX_IHANDLE].iData[0];
    LPVOID pSharedMem = (LPVOID)self->zValues[SG_NDX_IMEMORY].iData[0];

    if (!SG_IsSchemaOK(self->nSGobjSchema))
        return SG_R_SCHM;

    /* TODO: put your simulator code here */

    /* do clean up here */
    if (pSharedMem != (LPVOID)NULL)
        UnmapViewOfFile(pSharedMem);
    if (hMappedFile != (HANDLE)0)
        CloseHandle(hMappedFile);

    /* if the user terminated the MIDIplayer prematurely, StopReq status
     * bit is set by SansGUI to inform the simulator.
     */
    if (SG_IsStopReq(simCtrl->iStatus))
    {
        strcpy(cMessage,
        "User STOP request detected - simulation resources released." );
        return SG_R_LMSG;
    }

    return SG_R_OK;
}

INT get_MIDI_Channel_Data(SG_OBJ* self, INT* piData)
{
    /* fetch MIDI channel number and data from this object */
    /* This is a service routine to be called by objects of other classes */
    *piData = self->zValues[SG_NDX_IDATA].iData[0]; /* data field */
    return self->zValues[SG_NDX_ICHANNEL].iData[0]; /* channel number */
}
Functions in Class Base.Channel

/* Base_Channel.c
* - DLL routines for class <Component>Base.Channel
* DATE: Sunday, April 21, 2002 TIME: 04:53:35 PM
* The skeleton of this file is generated by SansGUI(tm)
*/

#include <stdio.h>

#include <string.h>

#include "SGdll.h"

#ifdef __cplusplus
extern "C"
{
#endif

SG_EXPORT SG_SIM_FUNC SG_xEval_Base_Channel;

#ifdef __cplusplus
}
#endif

 

/* Macros for attribute indices in class version [1.0.0.0] */
#define SG_NDX_INUMBER 0 /* iNumber - Channel Number */
#define SG_NDX_RREF 1 /* rRef - MIDI Message Object */

/* Manually added index to fetch the iData attribute in the derived classes */
/* It's safe because we know all derived classes will have this attribute defined */
#define SG_NDX_IDATA 2 /* iData - MIDI Data */

/* ============================================================
* SG_xEval - Evaluation
* ------------------------------------------------------------
*/
SG_RET_CODE SG_xEval_Base_Channel(SG_OBJ *const self,
          SG_OBJ *const simCtrl, SG_OBJ *const chgChild,
          SG_OBJ *const refObjs[], const INT *const piRefObjs,
          SG_OBJ *const adjObjs[], const INT *const piAdjObjs,
          SG_OBJ *const lnkObjs[], const INT *const piLnkObjs,
          TCHAR *const cMessage, const INT iMsgLen,
          TCHAR *const cCommand, const INT iCmdLen,
          SG_FILE *const pOutFile )
{
    /* TODO: declare your local variables here */

    /* defined in Collection_MIDI.c */
    extern INT get_MIDI_Channel_Data(SG_OBJ*, INT*);

    INT iChannel;
    INT iData;

    if (!SG_IsSchemaOK(self->nSGobjSchema))
        return SG_R_SCHM;

    /* TODO: put your simulator code here */

    /* a MIDI reference object is required */
    if (*piRefObjs < 1)
    {
        strcpy(cMessage, "Reference to a common MIDI object is required.");
        return SG_R_STOP;
    }
    /* Although this class does not contain the data field with index

     * SG_NDX_IDATA, this function uses it as a common properties in the

     * subclasses.  The subclass functions call this base class function

     * for the default behavior.
     * To prevent users from creating any instance of this class and; hence,
     * corrupting the memory, we simply define this class as an abstract

     * class in the Schema Definition.
     */
    if (self->iNumVars > SG_NDX_IDATA)
    {
        iChannel = get_MIDI_Channel_Data(refObjs[0], &iData);
        /* copy the data field from the MIDI object if the channel number

         * matches

         */
        if (self->zValues[SG_NDX_INUMBER].iData[0] == iChannel)
            self->zValues[SG_NDX_IDATA].iData[0] = iData;
    }

    return SG_R_OK;
}

Functions in Class Base.Channel.S-1

/* Base_Channel_S_1.c
* - DLL routines for class <Component>Base.Channel.S-1
* DATE: Sunday, April 21, 2002 TIME: 04:53:34 PM
* The skeleton of this file is generated by SansGUI(tm)
*/

#include <stdio.h>
#include "SGdll.h"

#ifdef __cplusplus
extern "C"
{
#endif

SG_EXPORT SG_SIM_FUNC SG_xEval_Base_Channel_S_1;

#ifdef __cplusplus
}
#endif

 

/* Macros for attribute indices in class version [1.0.0.0] */
#define SG_NDX_INUMBER 0 /* iNumber - Channel Number */
#define SG_NDX_RREF 1 /* rRef - MIDI Message Object */
#define SG_NDX_IDATA 2 /* iData - MIDI Data */

 

/* ============================================================
* SG_xEval - Evaluation
* ------------------------------------------------------------
*/
SG_RET_CODE SG_xEval_Base_Channel_S_1(SG_OBJ *const self,
          SG_OBJ *const simCtrl, SG_OBJ *const chgChild,
          SG_OBJ *const refObjs[], const INT *const piRefObjs,
          SG_OBJ *const adjObjs[], const INT *const piAdjObjs,
          SG_OBJ *const lnkObjs[], const INT *const piLnkObjs,
          TCHAR *const cMessage, const INT iMsgLen,
          TCHAR *const cCommand, const INT iCmdLen,
          SG_FILE *const pOutFile )
{
    /* TODO: declare your local variables here */

    extern SG_SIM_FUNC SG_xEval_Base_Channel;

    if (!SG_IsSchemaOK(self->nSGobjSchema))
        return SG_R_SCHM;

    /* TODO: put your simulator code here */

    /* call parent class function for common behavior */
    return SG_xEval_Base_Channel(self, simCtrl, chgChild,
                                 refObjs, piRefObjs,
                                 adjObjs, piAdjObjs,
                                 lnkObjs, piLnkObjs,
                                 cMessage, iMsgLen, cCommand, iCmdLen,
                                 pOutFile );

}

 


MIDI Player for SansGUI version 1.0

Copyright 2002 ProtoDesign, Inc. All rights reserved.

http://protodesign-inc.com