summaryrefslogtreecommitdiff
path: root/cgme.c
blob: c6706fb436f406dfada04d301df1cf09a08bef43 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gme/gme.h"
#include "codec.h"
#include "cgme.h"
#include "playlist.h"

static Music_Emu *emu;
static int reallength;
static int nzerosamples;

int
cgme_init (const char *fname, int track, float start, float end) {
    gme_open_file (fname, &emu, 44100);
    gme_start_track (emu, track);
    track_info_t inf;
    gme_track_info (emu, &inf, track);
    cgme.info.bitsPerSample = 16;
    cgme.info.channels = 2;
    cgme.info.samplesPerSecond = 44100;
    reallength = inf.length; 
    nzerosamples = 0;
    if (inf.length == -1) {
        cgme.info.duration = 120;
    }
    else {
        cgme.info.duration = (float)inf.length/1000.f;
    }
    cgme.info.position = 0;
    return 0;
}

void
cgme_free (void) {
    if (emu) {
        gme_delete (emu);
        emu = NULL;
    }
}

int
cgme_read (char *bytes, int size) {
    if (gme_play (emu, size/2, (short*)bytes)) {
        return 1;
    }
    cgme.info.position += (size/4) / 44100.f;
    if (reallength == -1) {
        // check if whole buffer is zeroes
        int i;
        for (i = 0; i < size; i++) {
            if (bytes[i]) {
                break;
            }
        }
        if (i == size) {
            nzerosamples += size / 4;
            if (nzerosamples > 44100 * 4) {
                return -1;
            }
        }
        else {
            nzerosamples = 0;
        }
    }
    if (reallength == -1 && cgme.info.position >= cgme.info.duration) {
        return -1;
    }
    return 0;
}

int
cgme_seek (float time) {
    if (gme_seek (emu, (long)(time * 1000))) {
        return -1;
    }
    cgme.info.position = time;
    return 0;
}

int
cgme_add (const char *fname) {
//    printf ("adding %s chiptune\n", fname);
    Music_Emu *emu;
    if (!gme_open_file (fname, &emu, 44100)) {
        int cnt = gme_track_count (emu);
        for (int i = 0; i < cnt; i++) {
            track_info_t inf;
            const char *ret = gme_track_info (emu, &inf, i);
            if (!ret) {
                playItem_t *it = malloc (sizeof (playItem_t));
                memset (it, 0, sizeof (playItem_t));
                it->codec = &cgme;
                it->fname = strdup (fname);
                char str[1024];
                if (inf.song[0]) {
                    snprintf (str, 1024, "%d %s - %s", i, inf.game, inf.song);
                }
                else {
                    snprintf (str, 1024, "%d %s - ?", i, inf.game);
                }
                it->tracknum = i;
                it->displayname = strdup (str);
                ps_append_item (it);
//                printf ("added %s subtune\n", str);
            }
            else {
                printf ("gme error: %s\n", ret);
            }
        }
        if (emu) {
            gme_delete (emu);
        }
    }
    else {
        printf ("error adding %s\n", fname);
    }
    return 0;
}

codec_t cgme = {
    .init = cgme_init,
    .free = cgme_free,
    .read = cgme_read,
    .seek = cgme_seek,
    .add = cgme_add
};