/*
* upkg: tool for manipulating Unreal Tournament packages.
* Copyright © 2009-2011 Nick Bowler
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include "modplug-types.h"
#include "music-module.h"
#include "upkg.h"
struct music_mod {
ModPlugFile *f;
size_t len, alloc;
unsigned char buf[];
};
#define BUF_INIT_SIZE 65536
int music_mod_init(void)
{
ModPlug_Settings settings = {
.mFlags = MODPLUG_ENABLE_OVERSAMPLING,
.mChannels = 2,
.mFrequency = 44100,
.mResamplingMode = MODPLUG_RESAMPLE_SPLINE,
.mLoopCount = -1,
};
ModPlug_SetSettings(&settings);
return 0;
}
void music_mod_exit(void)
{
}
static struct music_mod *readfile(struct upkg_file *f)
{
struct music_mod *m = malloc(sizeof *m + BUF_INIT_SIZE);
if (!m) return NULL;
*m = (struct music_mod) {
.alloc = BUF_INIT_SIZE
};
while (1) {
struct music_mod *tmp;
size_t sz = m->alloc - m->len;
m->len += upkg_export_read(f, m->buf + m->len, sz);
if (m->alloc != m->len) {
if (f->eof) {
tmp = realloc(m, sizeof *m + m->len);
return tmp ? tmp : m;
}
break;
}
tmp = realloc(m, sizeof *m + 2*m->alloc);
if (!tmp)
break;
m = tmp;
m->alloc *= 2;
}
free(m);
return NULL;
}
struct music_mod *music_mod_open(struct upkg_file *f)
{
struct music_mod *m = readfile(f);
if (!m) return NULL;
m->f = ModPlug_Load(m->buf, m->len);
if (!m->f) {
free(m);
return NULL;
}
return m;
}
int music_mod_dump(struct music_mod *m, FILE *of)
{
if (fwrite(m->buf, m->len, 1, of) != 1)
return -1;
return 0;
}
void music_mod_close(struct music_mod *m)
{
ModPlug_Unload(m->f);
free(m);
}
const char *music_mod_type(struct music_mod *m)
{
int type = ModPlug_GetModuleType(m->f);
if (type & MOD_TYPE_MOD)
return "mod";
if (type & MOD_TYPE_S3M)
return "s3m";
if (type & MOD_TYPE_XM)
return "xm";
if (type & MOD_TYPE_IT)
return "it";
return "unknown";
}