wined3d: Move setting the draw buffer to a separate function.
[wine] / dlls / winemp3.acm / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #include "config.h"
20 #include <stdlib.h>
21 #include <stdio.h>
22
23 #include "wine/debug.h"
24 #include "mpg123.h"
25 #include "mpglib.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(mpeg3);
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         mp->fr.mp = mp;
43
44         if(!init) {
45                 init = 1;
46                 make_decode_tables(32767);
47                 init_layer2();
48                 init_layer3(SBLIMIT);
49         }
50
51         return !0;
52 }
53
54 void ClearMP3Buffer(struct mpstr *mp)
55 {
56         struct buf *b,*bn;
57
58         b = mp->tail;
59         while(b) {
60                 free(b->pnt);
61                 bn = b->next;
62                 free(b);
63                 b = bn;
64         }
65         mp->tail = NULL;
66         mp->head = NULL;
67         mp->bsize = 0;
68 }
69
70 static struct buf *addbuf(struct mpstr *mp,const unsigned char *buf,int size)
71 {
72         struct buf *nbuf;
73
74         nbuf = malloc( sizeof(struct buf) );
75         if(!nbuf) {
76                 WARN("Out of memory!\n");
77                 return NULL;
78         }
79         nbuf->pnt = malloc(size);
80         if(!nbuf->pnt) {
81                 free(nbuf);
82                 WARN("Out of memory!\n");
83                 return NULL;
84         }
85         nbuf->size = size;
86         memcpy(nbuf->pnt,buf,size);
87         nbuf->next = NULL;
88         nbuf->prev = mp->head;
89         nbuf->pos = 0;
90
91         if(!mp->tail) {
92                 mp->tail = nbuf;
93         }
94         else {
95           mp->head->next = nbuf;
96         }
97
98         mp->head = nbuf;
99         mp->bsize += size;
100
101         return nbuf;
102 }
103
104 static void remove_buf(struct mpstr *mp)
105 {
106   struct buf *buf = mp->tail;
107
108   mp->tail = buf->next;
109   if(mp->tail)
110     mp->tail->prev = NULL;
111   else {
112     mp->tail = mp->head = NULL;
113   }
114
115   free(buf->pnt);
116   free(buf);
117
118 }
119
120 static int read_buf_byte(struct mpstr *mp)
121 {
122         unsigned int b;
123
124         int pos;
125
126         pos = mp->tail->pos;
127         while(pos >= mp->tail->size) {
128                 remove_buf(mp);
129                 pos = mp->tail->pos;
130         }
131
132         b = mp->tail->pnt[pos];
133         mp->bsize--;
134         mp->tail->pos++;
135
136
137         return b;
138 }
139
140 static void read_head(struct mpstr *mp)
141 {
142         unsigned long head;
143
144         head = read_buf_byte(mp);
145         head <<= 8;
146         head |= read_buf_byte(mp);
147         head <<= 8;
148         head |= read_buf_byte(mp);
149         head <<= 8;
150         head |= read_buf_byte(mp);
151
152         mp->header = head;
153 }
154
155 int decodeMP3(struct mpstr *mp,const unsigned char *in,int isize,unsigned char *out,
156                 int osize,int *done)
157 {
158         int len;
159
160         if(osize < 4608) {
161                 ERR("Output buffer too small\n");
162                 return MP3_ERR;
163         }
164
165         if(in) {
166                 if(addbuf(mp,in,isize) == NULL) {
167                         return MP3_ERR;
168                 }
169         }
170
171         /* First decode header */
172         if(mp->framesize == 0) {
173                 int ret;
174                 if(mp->bsize < 4) {
175                         return MP3_NEED_MORE;
176                 }
177                 read_head(mp);
178                 while (!(ret = decode_header(&mp->fr,mp->header)) && mp->bsize)
179                 {
180                         mp->header = mp->header << 8;
181                         mp->header |= read_buf_byte(mp);
182                 }
183
184                 if (!ret) {
185                         return MP3_NEED_MORE;
186                 }
187                 mp->framesize = mp->fr.framesize;
188         }
189
190         if(mp->fr.framesize > mp->bsize)
191                 return MP3_NEED_MORE;
192
193         wordpointer = mp->bsspace[mp->bsnum] + 512;
194         mp->bsnum = (mp->bsnum + 1) & 0x1;
195         bitindex = 0;
196
197         len = 0;
198         while(len < mp->framesize) {
199                 int nlen;
200                 int blen = mp->tail->size - mp->tail->pos;
201                 if( (mp->framesize - len) <= blen) {
202                   nlen = mp->framesize-len;
203                 }
204                 else {
205                   nlen = blen;
206                 }
207                 memcpy(wordpointer+len,mp->tail->pnt+mp->tail->pos,nlen);
208                 len += nlen;
209                 mp->tail->pos += nlen;
210                 mp->bsize -= nlen;
211                 if(mp->tail->pos == mp->tail->size) {
212                    remove_buf(mp);
213                 }
214         }
215
216         *done = 0;
217         if(mp->fr.error_protection)
218            getbits(16);
219         switch(mp->fr.lay) {
220           case 1:
221             do_layer1(&mp->fr,out,done);
222             break;
223           case 2:
224             do_layer2(&mp->fr,out,done);
225             break;
226           case 3:
227             do_layer3(&mp->fr,out,done);
228             break;
229         }
230
231         mp->fsizeold = mp->framesize;
232         mp->framesize = 0;
233
234         return MP3_OK;
235 }
236
237 int set_pointer(struct mpstr *mp, long backstep)
238 {
239   unsigned char *bsbufold;
240   if(mp->fsizeold < 0 && backstep > 0) {
241     /* This is not a bug if we just did seeking, the first frame is dropped then */
242     WARN("Can't step back %ld!\n",backstep);
243     return MP3_ERR;
244   }
245   bsbufold = mp->bsspace[mp->bsnum] + 512;
246   wordpointer -= backstep;
247   if (backstep)
248     memcpy(wordpointer,bsbufold+mp->fsizeold-backstep,backstep);
249   bitindex = 0;
250   return MP3_OK;
251 }