Reboot (int19) under DOS now does ExitProcess.
[wine] / dlls / msacm / winemp3 / interface.c
1 /*
2  * Copyright (c) Michael Hipp and other authors of the mpglib project.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include <stdlib.h>
20 #include <stdio.h>
21
22 #include "mpg123.h"
23 #include "mpglib.h"
24
25 /* Global mp .. it's a hack */
26 struct mpstr *gmp;
27
28
29 BOOL InitMP3(struct mpstr *mp)
30 {
31         static int init = 0;
32
33         memset(mp,0,sizeof(struct mpstr));
34
35         mp->framesize = 0;
36         mp->fsizeold = -1;
37         mp->bsize = 0;
38         mp->head = mp->tail = NULL;
39         mp->fr.single = -1;
40         mp->bsnum = 0;
41         mp->synth_bo = 1;
42
43         if(!init) {
44                 init = 1;
45                 make_decode_tables(32767);
46                 init_layer2();
47                 init_layer3(SBLIMIT);
48         }
49
50         return !0;
51 }
52
53 void ExitMP3(struct mpstr *mp)
54 {
55         struct buf *b,*bn;
56
57         b = mp->tail;
58         while(b) {
59                 free(b->pnt);
60                 bn = b->next;
61                 free(b);
62                 b = bn;
63         }
64 }
65
66 static struct buf *addbuf(struct mpstr *mp,char *buf,int size)
67 {
68         struct buf *nbuf;
69
70         nbuf = malloc( sizeof(struct buf) );
71         if(!nbuf) {
72                 fprintf(stderr,"Out of memory!\n");
73                 return NULL;
74         }
75         nbuf->pnt = malloc(size);
76         if(!nbuf->pnt) {
77                 free(nbuf);
78                 return NULL;
79         }
80         nbuf->size = size;
81         memcpy(nbuf->pnt,buf,size);
82         nbuf->next = NULL;
83         nbuf->prev = mp->head;
84         nbuf->pos = 0;
85
86         if(!mp->tail) {
87                 mp->tail = nbuf;
88         }
89         else {
90           mp->head->next = nbuf;
91         }
92
93         mp->head = nbuf;
94         mp->bsize += size;
95
96         return nbuf;
97 }
98
99 static void remove_buf(struct mpstr *mp)
100 {
101   struct buf *buf = mp->tail;
102
103   mp->tail = buf->next;
104   if(mp->tail)
105     mp->tail->prev = NULL;
106   else {
107     mp->tail = mp->head = NULL;
108   }
109
110   free(buf->pnt);
111   free(buf);
112
113 }
114
115 static int read_buf_byte(struct mpstr *mp)
116 {
117         unsigned int b;
118
119         int pos;
120
121         pos = mp->tail->pos;
122         while(pos >= mp->tail->size) {
123                 remove_buf(mp);
124                 pos = mp->tail->pos;
125                 if(!mp->tail) {
126                         fprintf(stderr,"Fatal error!\n");
127                         exit(1);
128                 }
129         }
130
131         b = mp->tail->pnt[pos];
132         mp->bsize--;
133         mp->tail->pos++;
134
135
136         return b;
137 }
138
139 static void read_head(struct mpstr *mp)
140 {
141         unsigned long head;
142
143         head = read_buf_byte(mp);
144         head <<= 8;
145         head |= read_buf_byte(mp);
146         head <<= 8;
147         head |= read_buf_byte(mp);
148         head <<= 8;
149         head |= read_buf_byte(mp);
150
151         mp->header = head;
152 }
153
154 int decodeMP3(struct mpstr *mp,char *in,int isize,char *out,
155                 int osize,int *done)
156 {
157         int len;
158
159         gmp = mp;
160
161         if(osize < 4608) {
162                 fprintf(stderr,"To less out space\n");
163                 return MP3_ERR;
164         }
165
166         if(in) {
167                 if(addbuf(mp,in,isize) == NULL) {
168                         return MP3_ERR;
169                 }
170         }
171
172         /* First decode header */
173         if(mp->framesize == 0) {
174                 if(mp->bsize < 4) {
175                         return MP3_NEED_MORE;
176                 }
177                 read_head(mp);
178                 decode_header(&mp->fr,mp->header);
179                 mp->framesize = mp->fr.framesize;
180         }
181
182         if(mp->fr.framesize > mp->bsize)
183                 return MP3_NEED_MORE;
184
185         wordpointer = mp->bsspace[mp->bsnum] + 512;
186         mp->bsnum = (mp->bsnum + 1) & 0x1;
187         bitindex = 0;
188
189         len = 0;
190         while(len < mp->framesize) {
191                 int nlen;
192                 int blen = mp->tail->size - mp->tail->pos;
193                 if( (mp->framesize - len) <= blen) {
194                   nlen = mp->framesize-len;
195                 }
196                 else {
197                   nlen = blen;
198                 }
199                 memcpy(wordpointer+len,mp->tail->pnt+mp->tail->pos,nlen);
200                 len += nlen;
201                 mp->tail->pos += nlen;
202                 mp->bsize -= nlen;
203                 if(mp->tail->pos == mp->tail->size) {
204                    remove_buf(mp);
205                 }
206         }
207
208         *done = 0;
209         if(mp->fr.error_protection)
210            getbits(16);
211         switch(mp->fr.lay) {
212           case 1:
213             do_layer1(&mp->fr,(unsigned char *) out,done);
214             break;
215           case 2:
216             do_layer2(&mp->fr,(unsigned char *) out,done);
217             break;
218           case 3:
219             do_layer3(&mp->fr,(unsigned char *) out,done);
220             break;
221         }
222
223         mp->fsizeold = mp->framesize;
224         mp->framesize = 0;
225
226         return MP3_OK;
227 }
228
229 int set_pointer(long backstep)
230 {
231   unsigned char *bsbufold;
232   if(gmp->fsizeold < 0 && backstep > 0) {
233     fprintf(stderr,"Can't step back %ld!\n",backstep);
234     return MP3_ERR;
235   }
236   bsbufold = gmp->bsspace[gmp->bsnum] + 512;
237   wordpointer -= backstep;
238   if (backstep)
239     memcpy(wordpointer,bsbufold+gmp->fsizeold-backstep,backstep);
240   bitindex = 0;
241   return MP3_OK;
242 }