view dmengine.c @ 360:d5a90ba09dc4

Fix to match with resource management changes.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 16 Oct 2012 21:28:56 +0300
parents 59045853853d
children 38e10b5f4e09
line wrap: on
line source

#include "dmengine.h"
#include "dmimage.h"


#ifdef DM_USE_TREMOR
#include <tremor/ivorbiscodec.h>
#include <tremor/ivorbisfile.h>
#endif


DMEngineData engine;
DMFrameData frame;


static int engineResImageLoad(DMResource *res)
{
    SDL_Surface *img = dmLoadImage(res);
    if (res != NULL)
    {
        res->rdata = img;
        return DMERR_OK;
    }
    else
        return dmferror(res);
}


static void engineResImageFree(DMResource *res)
{
    SDL_FreeSurface((SDL_Surface *)res->rdata);
}

static BOOL engineResImageProbe(DMResource *res, const char *fext)
{
    (void) res;
    return fext != NULL && (strcasecmp(fext, ".jpg") == 0 || strcasecmp(fext, ".png") == 0);
}


#ifdef JSS_SUP_XM
static int engineResModuleLoad(DMResource *res)
{
    return jssLoadXM(res, (JSSModule **) &(res->rdata));
}

static void engineResModuleFree(DMResource *res)
{
    jssFreeModule((JSSModule *) res->rdata);
}

static BOOL engineResModuleProbe(DMResource *res, const char *fext)
{
    (void) res;
    return fext != NULL && (strcasecmp(fext, ".xm") == 0 || strcasecmp(fext, ".jmod") == 0);
}
#endif


#ifdef DM_USE_TREMOR
static size_t vorbisFileRead(void *ptr, size_t size, size_t nmemb, void *datasource)
{
    return dmfread(ptr, size, nmemb, (DMResource *) datasource);
}

static int vorbisFileSeek(void *datasource, ogg_int64_t offset, int whence)
{
    return dmfseek((DMResource *) datasource, offset, whence);
}

static int vorbisFileClose(void *datasource)
{
    (void) datasource;
    return 0;
}

static long vorbisFileTell(void *datasource)
{
    return dmftell((DMResource *) datasource);
}
      

static ov_callbacks vorbisFileCBS =
{
    vorbisFileRead,
    vorbisFileSeek,
    vorbisFileClose,
    vorbisFileTell
};

static int engineResVorbisLoad(DMResource *res)
{
    OggVorbis_File vf;

    dmMsg(1, "vorbisfile '%s', %d bytes resource loading\n",
        res->filename, res->dataSize);

    if (ov_open_callbacks(res, &vf, NULL, 0, vorbisFileCBS) < 0)
        return DMERR_FOPEN;

    res->rdataSize = ov_pcm_total(&vf, -1) * 2 * 2;
    if ((res->rdata = dmMalloc(res->rdataSize + 16)) == NULL)
    {
        ov_clear(&vf);
        return DMERR_MALLOC;
    }

    dmMsg(1, "rdataSize=%d bytes?\n", res->rdataSize);

    BOOL eof = FALSE;
    int left = res->rdataSize;
    char *ptr = res->rdata;
    int current_section;
    while (!eof && left > 0)
    {
        int ret = ov_read(&vf, ptr, left > 4096 ? 4096 : left, &current_section);
        if (ret == 0)
            eof = TRUE;
        else
        if (ret < 0)
        {
            ov_clear(&vf);
            return DMERR_INVALID_DATA;
        }
        else
        {
            left -= ret;
            ptr += ret;
        }
    }

    ov_clear(&vf);
    return DMERR_OK;
}

static void engineResVorbisFree(DMResource *res)
{
    dmFree(res->rdata);
}

static BOOL engineResVorbisProbe(DMResource *res, const char *fext)
{
    (void) res;
    return fext != NULL && (strcasecmp(fext, ".ogg") == 0);
}
#endif


static DMResourceDataOps engineResOps[] =
{
    {
        engineResImageProbe,
        engineResImageLoad,
        engineResImageFree
    },

#ifdef JSS_SUP_XM
    {
        engineResModuleProbe,
        engineResModuleLoad,
        engineResModuleFree
    },
#endif

#ifdef DM_USE_TREMOR
    {
        engineResVorbisProbe,
        engineResVorbisLoad,
        engineResVorbisFree
    },
#endif
};

static const int nengineResOps = sizeof(engineResOps) / sizeof(engineResOps[0]);


int engineClassifier(DMResource *res)
{
    int i;
    char *fext;

    if (res == NULL)
        return DMERR_NULLPTR;
    
    fext = strrchr(res->filename, '.');
    for (i = 0; i < nengineResOps; i++)
    {
        DMResourceDataOps *rops = &engineResOps[i];
        if (rops->probe != NULL && rops->probe(res, fext))
        {
            res->rops = rops;
            return DMERR_OK;
        }
    }
    
    return DMERR_OK;
}


void *engineGetResource(const char *name)
{
    DMResource *res = dmres_find(engine.resources, name);
    if (res != NULL && res->rdata != NULL)
        return res->rdata;
    else
    {
        dmError("Could not find resource '%s'.\n", name);
        return NULL;
    }
}


#ifdef DM_USE_JSS
void engineGetJSSInfo(BOOL *playing, int *order, JSSPattern **pat, int *npattern, int *row)
{
    JSS_LOCK(engine.plr);

    *playing = engine.plr->isPlaying;
    *row = engine.plr->row;
    *pat = engine.plr->pattern;
    *npattern = engine.plr->npattern;
    *order = engine.plr->order;

    JSS_UNLOCK(engine.plr);
}

void engineGetJSSChannelInfo(const int channel, int *ninst, int *nextInst, int *freq, int *note)
{
    JSS_LOCK(engine.plr);
    JSSPlayerChannel *chn = &(engine.plr->channels[channel]);
    *ninst = chn->ninstrument;
    *nextInst = chn->nextInstrument;
    *freq = chn->freq;
    *note = chn->note;
    JSS_UNLOCK(engine.plr);
}
#endif