view dmtimelinew.c @ 510:43ea59887c69

Start work on making C64 formats encoding possible by changing DMDecodeOps to DMEncDecOps and adding fields and op enums for custom encode functions, renaming, etc. Split generic op sanity checking into a separate function in preparation for its use in generic encoding function.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 19 Nov 2012 15:06:01 +0200
parents 0f290af63fc1
children d4b84101e480
line wrap: on
line source

#include "dmengine.h"
#include "dmresw.h"


static BOOL dmSaveFloatValue(DMResource *res, DMFloat val)
{
    char tmp[DT_FLOAT_STORE_SIZE];
    snprintf(tmp, DT_FLOAT_STORE_SIZE, "%f", val);
    return !dmf_write_str(res, (Uint8 *) tmp, DT_FLOAT_STORE_SIZE);
}


static int dmSaveTimelinePoints(DMResource *res, DMTimelinePoints *points, int type)
{
    int point;
    Uint32 npoints;

    // Save number of points
    npoints = points->npoints;
    if (!dmf_write_le32(res, npoints))
        return DMERR_FWRITE;
    
    // Save points
    for (point = 0; point < points->npoints; point++)
    {
        DMTimelinePoint *pt = &(points->points[point]);
        Uint32 ptype, ptime;
        ptype = pt->type;
        ptime = pt->time;
        if (!dmf_write_le32(res, ptype) ||
            !dmf_write_le32(res, ptime))
            return DMERR_FWRITE;

        switch (type)
        {
            case EFPT_INT:
                if (!dmf_write_le32(res, pt->vint))
                    return DMERR_FWRITE;
                break;

            case EFPT_FLOAT:
                if (!dmSaveFloatValue(res, pt->vfloat))
                    return DMERR_FWRITE;
                break;
            
            case EFPT_VECTOR:
                if (!dmSaveFloatValue(res, pt->vector.x) ||
                    !dmSaveFloatValue(res, pt->vector.y) ||
                    !dmSaveFloatValue(res, pt->vector.z) ||
                    !dmSaveFloatValue(res, pt->vector.W))
                    return DMERR_FWRITE;
                break;

            case EFPT_MATRIX:
                {
                    int x, y;
                    for (y = 0; y < DM_MATRIX_SIZE; y++)
                    for (x = 0; x < DM_MATRIX_SIZE; x++)
                    {
                        if (!dmSaveFloatValue(res, pt->matrix.m[y][x]))
                            return DMERR_FWRITE;
                    }
                }
                break;
        }
    }
    return DMERR_OK;
}


static int dmSaveTimelineCurve(DMResource *res, DMTimelineCurve *curve)
{
    int err;

    dmfputc(curve->enabled, res);
    if ((err = dmSaveTimelinePoints(res, &(curve->points), EFPT_FLOAT)) != DMERR_OK)
        return err;
    
    return DMERR_OK;
}


static int dmSaveTimelineEventParam(DMResource *res, DMTimelineEventParam *param)
{
    int err;
    DMFTimelineEventParam hdr;
    Uint16 len;

    strncpy(hdr.name, param->name, sizeof(hdr.name));
    hdr.type = param->type;

    if (!dmf_write_str(res, (Uint8 *) hdr.name, sizeof(hdr.name)) ||
        !dmf_write_le32(res, hdr.type))
        return DMERR_FWRITE;

    switch (param->type)
    {
        case EFPT_INT:
        case EFPT_FLOAT:
        case EFPT_VECTOR:
        case EFPT_MATRIX:
            if ((err = dmSaveTimelinePoints(res, &param->pts, param->type)) != DMERR_OK)
                return err;
            break;

        case EFPT_STRING:
            len = strlen(param->vstr);
            if (!dmf_write_le16(res, len))
                return DMERR_FWRITE;

            if (!dmf_write_str(res, (Uint8 *) param->vstr, len))
                return DMERR_FWRITE;
            break;
    }

    return DMERR_OK;
}


static int dmSaveTimelineEvent(DMResource *res, DMTimelineEvent *event)
{
    int param, err;
    DMFTimelineEvent hdr;

    strncpy(hdr.effectName, event->effect->name, sizeof(hdr.effectName));
    hdr.start    = event->start;
    hdr.duration = event->duration;
    hdr.nparams  = event->nparams;

    if (!dmf_write_le32(res, hdr.start) ||
        !dmf_write_le32(res, hdr.duration) ||
        !dmf_write_str(res, (Uint8 *) hdr.effectName, sizeof(hdr.effectName)) ||
        !dmf_write_le32(res, hdr.nparams))
        return DMERR_FWRITE;

    for (param = 0; param < event->nparams; param++)
    {
        if ((err = dmSaveTimelineEventParam(res, &(event->params[param]))) != DMERR_OK)
            return err;
    }

    return DMERR_OK;
}


static int dmSaveTimelineTrack(DMResource *res, DMTimelineTrack *track)
{
    int event, err;
    DMFTimelineTrack hdr;
    
    strncpy(hdr.name, track->name, sizeof(hdr.name));
    hdr.enabled = track->enabled;
    hdr.nevents = track->nevents;

    if (!dmf_write_str(res, (Uint8 *) &hdr.name, sizeof(hdr.name)))
        return DMERR_FWRITE;

    dmfputc(hdr.enabled, res);
    if (!dmf_write_le32(res, hdr.nevents))
        return DMERR_FWRITE;

    for (event = 0; event < track->nevents; event++)
    {
        if ((err = dmSaveTimelineEvent(res, track->events[event])) != DMERR_OK)
            return err;
    }

    if ((err = dmSaveTimelineCurve(res, &(track->composite))) != DMERR_OK)
        return err;

    return DMERR_OK;
}


int dmSaveTimeline(DMResource *res, DMTimeline *tl)
{
    int track, err;
    DMFTimeline hdr;

    memcpy(&hdr.magic, DT_MAGIC_ID, sizeof(hdr.magic));
    strncpy(hdr.name, tl->name, sizeof(hdr.name));
    hdr.ntracks = tl->ntracks;
    hdr.duration = tl->duration;
    
    if (!dmf_write_str(res, (Uint8 *) hdr.magic, sizeof(hdr.magic)) ||
        !dmf_write_str(res, (Uint8 *) hdr.name, sizeof(hdr.name)) ||
        !dmf_write_le32(res, hdr.ntracks) ||
        !dmf_write_le32(res, hdr.duration))
        return DMERR_FWRITE;

    for (track = 0; track < tl->ntracks; track++)
    {
        if ((err = dmSaveTimelineTrack(res, tl->tracks[track])) != DMERR_OK)
            return err;
    }

    return DMERR_OK;
}


int dmTimelineNew(DMTimeline **ptl, const char *name)
{
    DMTimeline *tl;
    if ((*ptl = tl = dmMalloc0(sizeof(DMTimeline))) == NULL)
        return DMERR_MALLOC;

    tl->name = dm_strdup(name);
    
    return DMERR_OK;
}


int dmTimelineAddTrack(DMTimeline *tl, DMTimelineTrack **ptrack, const char *name)
{
    DMTimelineTrack *track;
    
    if ((*ptrack = track = dmMalloc0(sizeof(DMTimelineTrack))) == NULL)
        return DMERR_MALLOC;
    
    track->name = dm_strdup(name);
    track->enabled = TRUE;

    if (tl->ntracks + 1 >= tl->nallocated)
    {
        tl->nallocated += 16;
        tl->tracks = dmRealloc(tl->tracks, sizeof(DMTimelineTrack *) * tl->nallocated);
        if (tl->tracks == NULL)
            return DMERR_MALLOC;
    }
    
    tl->tracks[tl->ntracks] = track;
    tl->ntracks++;
    
    return DMERR_OK;
}


int dmTimelineTrackAddEvent(DMTimelineTrack *track, int start, int duration, DMTimelineEvent **pev)
{
    DMTimelineEvent *ev;
    
    if ((*pev = ev = dmMalloc0(sizeof(DMTimelineEvent))) == NULL)
        return DMERR_MALLOC;
    
    ev->start    = start;
    ev->duration = duration;
    
    if (track->nevents + 1 >= track->nallocated)
    {
        track->nallocated += 16;
        track->events = dmRealloc(track->events, sizeof(DMTimelineEvent *) * track->nallocated);
        if (track->events == NULL)
            return DMERR_MALLOC;
    }
    
    track->events[track->nevents] = ev;
    track->nevents++;
    
    return DMERR_OK;
}


int dmTimelineEventSetEffect(DMTimelineEvent *event, DMEffect *ef)
{
    int param;
    if (ef == NULL)
        return DMERR_INVALID_DATA;

    event->effect = ef;
    event->nparams = ef->nparams;
    event->params = dmCalloc(ef->nparams, sizeof(DMTimelineEventParam));
    if (event->params == NULL)
        return DMERR_MALLOC;
    
    for (param = 0; param < ef->nparams; param++)
    {
        DMTimelineEventParam *psrc = &ef->params[param],
                             *pdst = &event->params[param];

        pdst->name   = dm_strdup(psrc->name);
        pdst->type   = psrc->type;
        pdst->vstr   = dm_strdup(psrc->vstr);

        if (psrc->pts.points != NULL && psrc->pts.npoints > 0)
        {
            pdst->pts.npoints    = psrc->pts.npoints;
            pdst->pts.nallocated = psrc->pts.nallocated;
            pdst->pts.points     = dmMalloc(psrc->pts.nallocated * sizeof(DMTimelinePoint));
            if (pdst->pts.points == NULL)
                return DMERR_MALLOC;

            memcpy(pdst->pts.points, psrc->pts.points, pdst->pts.npoints * sizeof(DMTimelinePoint));
        }
    }
    
    return DMERR_OK;
}


int dmTimelineEventSetEffectByIndex(DMTimelineEvent *event, const int index)
{
    if (index < 0 || index >= nengineEffects)
        return DMERR_INVALID_DATA;

    return dmTimelineEventSetEffect(event, &engineEffects[index]);
}


int dmTimelineEventSetEffectByName(DMTimelineEvent *event, const char *name)
{
    return dmTimelineEventSetEffect(event, engineFindEffectByName(name));
}


DMTimelineEvent *dmTimelineGetEventAt(DMTimelineTrack *track, const int time)
{
    int event;
    for (event = 0; event < track->nevents; event++)
    {
        DMTimelineEvent *ev = track->events[event];
        if (time >= ev->start && time <= ev->start + ev->duration)
            return ev;
    }
    return NULL;
}


int dmCopyTimelinePoints(const DMTimelinePoints *src, DMTimelinePoints *dst)
{
    if (src->points == NULL || src->npoints <= 0 || src->nallocated <= 0)
        return DMERR_OK;

    dst->npoints    = src->npoints;
    dst->nallocated = src->nallocated;
    dst->points     = dmCalloc(src->nallocated, sizeof(DMTimelinePoint));
    if (dst->points == NULL)
        return DMERR_MALLOC;

    memcpy(dst->points, src->points, sizeof(DMTimelinePoint) * src->npoints);
    
    return DMERR_OK;
}


int dmCopyTimelineEventParam(const DMTimelineEventParam *src, DMTimelineEventParam *dst)
{
    dst->name = dm_strdup(src->name);
    dst->type = src->type;
    dst->vstr = dm_strdup(src->vstr);

    return dmCopyTimelinePoints(&src->pts, &dst->pts);
}


int dmCopyTimelineEvent(const DMTimelineEvent *src, DMTimelineEvent **pdst)
{
    int param;
    DMTimelineEvent *dst;
    if ((*pdst = dst = dmMalloc0(sizeof(DMTimelineEvent))) == NULL)
        return DMERR_MALLOC;
    
    dst->start     = src->start;
    dst->duration  = src->duration;
    dst->nparams   = src->nparams;
    dst->effect    = src->effect;
    dst->params    = dmCalloc(src->nparams, sizeof(DMTimelineEventParam));
    if (dst->params == NULL)
        return DMERR_MALLOC;

    for (param = 0; param < src->nparams; param++)
    {
        int err;
        if ((err = dmCopyTimelineEventParam(&(src->params[param]), &(dst->params[param]))) != DMERR_OK)
            return err;
    }

    return DMERR_OK;
}


int dmCopyTimelineCurve(const DMTimelineCurve *src, DMTimelineCurve *dst)
{
    dst->enabled = src->enabled;
    return dmCopyTimelinePoints(&(src->points), &(dst->points));
}


int dmCopyTimelineTrack(const DMTimelineTrack *src, DMTimelineTrack **pdst)
{
    int event, err;
    DMTimelineTrack *dst;
    if ((*pdst = dst = dmMalloc0(sizeof(DMTimelineTrack))) == NULL)
        return DMERR_MALLOC;

    if ((dst->events = dmCalloc(src->nevents, sizeof(DMTimelineEvent *))) == NULL)
        return DMERR_MALLOC;
    
    dst->name    = dm_strdup(src->name);
    dst->enabled = src->enabled;
    dst->nevents = src->nevents;

    for (event = 0; event < src->nevents; event++)
    {
        if ((err = dmCopyTimelineEvent(src->events[event], &(dst->events[event]))) != DMERR_OK)
            return err;
    }

    if ((err = dmCopyTimelineCurve(&(src->composite), &(dst->composite))) != DMERR_OK)
        return err;

    return DMERR_OK;
}


int dmCopyTimeline(const DMTimeline *src, DMTimeline **pdst)
{
    int track, err;
    DMTimeline *dst;
    if ((*pdst = dst = dmMalloc0(sizeof(DMTimeline))) == NULL)
        return DMERR_MALLOC;
    
    dst->tracks = (DMTimelineTrack **) dmCalloc(src->ntracks, sizeof(DMTimelineTrack *));
    if (dst->tracks == NULL)
        return DMERR_MALLOC;

    dst->name     = dm_strdup(src->name);
    dst->duration = src->duration;
    dst->ntracks  = src->ntracks;

    for (track = 0; track < src->ntracks; track++)
    {
        if ((err = dmCopyTimelineTrack(src->tracks[track], &(dst->tracks[track]))) != DMERR_OK)
            return err;
    }
    
    return DMERR_OK;
}