summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/libmad/libmadplugin.cpp52
1 files changed, 43 insertions, 9 deletions
diff --git a/core/multimedia/opieplayer/libmad/libmadplugin.cpp b/core/multimedia/opieplayer/libmad/libmadplugin.cpp
index 9a1ab2a..9d1ff8c 100644
--- a/core/multimedia/opieplayer/libmad/libmadplugin.cpp
+++ b/core/multimedia/opieplayer/libmad/libmadplugin.cpp
@@ -1,826 +1,860 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2001 Trolltech AS. All rights reserved. 2** Copyright (C) 2001 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of Qtopia Environment. 4** This file is part of Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20// largly modified by Maximilian Reiss <max.reiss@gmx.de> 20// largly modified by Maximilian Reiss <max.reiss@gmx.de>
21 21
22#include <stdio.h> 22#include <stdio.h>
23#include <stdarg.h> 23#include <stdarg.h>
24#include <stdlib.h> 24#include <stdlib.h>
25#include <sys/types.h> 25#include <sys/types.h>
26#include <sys/stat.h> 26#include <sys/stat.h>
27#include <fcntl.h> 27#include <fcntl.h>
28#include <unistd.h> 28#include <unistd.h>
29#include <string.h> 29#include <string.h>
30#include <ctype.h> 30#include <ctype.h>
31#include <errno.h> 31#include <errno.h>
32#include <time.h> 32#include <time.h>
33#include <locale.h> 33#include <locale.h>
34#include <math.h> 34#include <math.h>
35#include <assert.h> 35#include <assert.h>
36 36
37#include <qapplication.h> 37#include <qapplication.h>
38#include <qmessagebox.h> 38#include <qmessagebox.h>
39#include <qregexp.h> 39#include <qregexp.h>
40 40
41#include <qpe/config.h> 41#include <qpe/config.h>
42 42
43// for network handling 43// for network handling
44#include <netinet/in.h> 44#include <netinet/in.h>
45#include <netdb.h> 45#include <netdb.h>
46#include <linux/limits.h> 46#include <linux/limits.h>
47#include <sys/socket.h> 47#include <sys/socket.h>
48#include <arpa/inet.h> 48#include <arpa/inet.h>
49#include <unistd.h> 49#include <unistd.h>
50 50
51 51
52//#define HAVE_MMAP 52//#define HAVE_MMAP
53 53
54#if defined(HAVE_MMAP) 54#if defined(HAVE_MMAP)
55# include <sys/mman.h> 55# include <sys/mman.h>
56#endif 56#endif
57#include "libmadplugin.h" 57#include "libmadplugin.h"
58 58
59 59
60extern "C" { 60extern "C" {
61#include "mad.h" 61#include "mad.h"
62} 62}
63 63
64 64
65#define MPEG_BUFFER_SIZE 65536 65#define MPEG_BUFFER_SIZE 65536
66//#define MPEG_BUFFER_SIZE 32768 //16384 // 8192 66//#define MPEG_BUFFER_SIZE 32768 //16384 // 8192
67//#define debugMsg(a) qDebug(a) 67//#define debugMsg(a) qDebug(a)
68#define debugMsg(a) 68#define debugMsg(a)
69 69
70 70
71class Input { 71class Input {
72public: 72public:
73 char const *path; 73 char const *path;
74 int fd; 74 int fd;
75#if defined(HAVE_MMAP) 75#if defined(HAVE_MMAP)
76 void *fdm; 76 void *fdm;
77#endif 77#endif
78 unsigned char *data; 78 unsigned long fileLength;
79 unsigned char *data;
79 unsigned long length; 80 unsigned long length;
80 int eof; 81 int eof;
81}; 82};
82 83
83 84
84class Output { 85class Output {
85public: 86public:
86 mad_fixed_t attenuate; 87 mad_fixed_t attenuate;
87 struct filter *filters; 88 struct filter *filters;
88 unsigned int channels_in; 89 unsigned int channels_in;
89 unsigned int channels_out; 90 unsigned int channels_out;
90 unsigned int speed_in; 91 unsigned int speed_in;
91 unsigned int speed_out; 92 unsigned int speed_out;
92 const char *path; 93 const char *path;
93}; 94};
94 95
95 96
96# if defined(HAVE_MMAP) 97# if defined(HAVE_MMAP)
97static void *map_file(int fd, unsigned long *length) 98static void *map_file(int fd, unsigned long *length)
98{ 99{
99 void *fdm; 100 void *fdm;
100 101
101 *length += MAD_BUFFER_GUARD; 102 *length += MAD_BUFFER_GUARD;
102 103
103 fdm = mmap(0, *length, PROT_READ, MAP_SHARED, fd, 0); 104 fdm = mmap(0, *length, PROT_READ, MAP_SHARED, fd, 0);
104 if (fdm == MAP_FAILED) 105 if (fdm == MAP_FAILED)
105 return 0; 106 return 0;
106 107
107# if defined(HAVE_MADVISE) 108# if defined(HAVE_MADVISE)
108 madvise(fdm, *length, MADV_SEQUENTIAL); 109 madvise(fdm, *length, MADV_SEQUENTIAL);
109# endif 110# endif
110 111
111 return fdm; 112 return fdm;
112} 113}
113 114
114 115
115static int unmap_file(void *fdm, unsigned long length) 116static int unmap_file(void *fdm, unsigned long length)
116{ 117{
117 if (munmap(fdm, length) == -1) 118 if (munmap(fdm, length) == -1)
118 return -1; 119 return -1;
119 120
120 return 0; 121 return 0;
121} 122}
122# endif 123# endif
123 124
124 125
125static inline QString tr( const char *str ) { 126static inline QString tr( const char *str ) {
126 // Apparently this is okay from a plugin as it runs in the process space of the owner of the plugin 127 // Apparently this is okay from a plugin as it runs in the process space of the owner of the plugin
127 return qApp->translate( "OpiePlayer", str, "libmad strings for mp3 file info" ); 128 return qApp->translate( "OpiePlayer", str, "libmad strings for mp3 file info" );
128} 129}
129 130
130 131
131class LibMadPluginData { 132class LibMadPluginData {
132public: 133public:
133 Input input; 134 Input input;
134 Output output; 135 Output output;
135 int bad_last_frame; 136 int bad_last_frame;
136 struct mad_stream stream; 137 struct mad_stream stream;
137 struct mad_frame frame; 138 struct mad_frame frame;
138 struct mad_synth synth; 139 struct mad_synth synth;
139 bool flush; 140 bool flush;
140}; 141};
141 142
142 143
143LibMadPlugin::LibMadPlugin() { 144LibMadPlugin::LibMadPlugin() {
144 d = new LibMadPluginData; 145 d = new LibMadPluginData;
145 d->input.fd = 0; 146 d->input.fd = 0;
146#if defined(HAVE_MMAP) 147#if defined(HAVE_MMAP)
147 d->input.fdm = 0; 148 d->input.fdm = 0;
148#endif 149#endif
149 d->input.data = 0; 150 d->input.data = 0;
150 d->flush = TRUE; 151 d->flush = TRUE;
151 info = tr( "No Song Open" ); 152 info = tr( "No Song Open" );
152} 153}
153 154
154 155
155LibMadPlugin::~LibMadPlugin() { 156LibMadPlugin::~LibMadPlugin() {
156 close(); 157 close();
157 delete d; 158 delete d;
158} 159}
159 160
160 161
161bool LibMadPlugin::isFileSupported( const QString& path ) { 162bool LibMadPlugin::isFileSupported( const QString& path ) {
162 debugMsg( "LibMadPlugin::isFileSupported" ); 163 debugMsg( "LibMadPlugin::isFileSupported" );
163 164
164 // Mpeg file extensions 165 // Mpeg file extensions
165 // "mp2","mp3","m1v","m2v","m2s","mpg","vob","mpeg","ac3" 166 // "mp2","mp3","m1v","m2v","m2s","mpg","vob","mpeg","ac3"
166 // Other media extensions 167 // Other media extensions
167 // "wav","mid","mod","s3m","ogg","avi","mov","sid" 168 // "wav","mid","mod","s3m","ogg","avi","mov","sid"
168 169
169 char *ext = strrchr( path.latin1(), '.' ); 170 char *ext = strrchr( path.latin1(), '.' );
170 171
171 // Test file extension 172 // Test file extension
172 if ( ext ) { 173 if ( ext ) {
173 if ( strncasecmp(ext, ".mp2", 4) == 0 ) 174 if ( strncasecmp(ext, ".mp2", 4) == 0 )
174 return TRUE; 175 return TRUE;
175 if ( strncasecmp(ext, ".mp3", 4) == 0 ) 176 if ( strncasecmp(ext, ".mp3", 4) == 0 )
176 return TRUE; 177 return TRUE;
177 } 178 }
178 179
179 // UGLY - just for fast testing 180 // UGLY - just for fast testing
180 if ( path.left(4) == "http") { 181 if ( path.left(4) == "http") {
181 return TRUE; 182 return TRUE;
182 } 183 }
183 184
184 return FALSE; 185 return FALSE;
185} 186}
186 187
187 188
188 189
189int LibMadPlugin::is_address_multicast(unsigned long address) { 190int LibMadPlugin::is_address_multicast(unsigned long address) {
190 if ((address & 255) >= 224 && (address & 255) <= 239) 191 if ((address & 255) >= 224 && (address & 255) <= 239)
191 return (1); 192 return (1);
192 return (0); 193 return (0);
193} 194}
194 195
195 196
196int LibMadPlugin::udp_open(char *address, int port) { 197int LibMadPlugin::udp_open(char *address, int port) {
197 198
198 int enable = 1L; 199 int enable = 1L;
199 struct sockaddr_in stAddr; 200 struct sockaddr_in stAddr;
200 struct sockaddr_in stLclAddr; 201 struct sockaddr_in stLclAddr;
201 struct ip_mreq stMreq; 202 struct ip_mreq stMreq;
202 struct hostent *host; 203 struct hostent *host;
203 int sock; 204 int sock;
204 205
205 stAddr.sin_family = AF_INET; 206 stAddr.sin_family = AF_INET;
206 stAddr.sin_port = htons(port); 207 stAddr.sin_port = htons(port);
207 208
208 if ((host = gethostbyname(address)) == NULL) { 209 if ((host = gethostbyname(address)) == NULL) {
209 return (0); 210 return (0);
210 } 211 }
211 212
212 stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]); 213 stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]);
213 214
214 /* Create a UDP socket */ 215 /* Create a UDP socket */
215 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 216 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
216 return (0); 217 return (0);
217 } 218 }
218 219
219 /* Allow multiple instance of the client to share the same address and port */ 220 /* Allow multiple instance of the client to share the same address and port */
220 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&enable, sizeof(unsigned long int)) < 0) { 221 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&enable, sizeof(unsigned long int)) < 0) {
221 return (0); 222 return (0);
222 } 223 }
223 224
224 /* If the address is multicast, register to the multicast group */ 225 /* If the address is multicast, register to the multicast group */
225 if (is_address_multicast(stAddr.sin_addr.s_addr)) { 226 if (is_address_multicast(stAddr.sin_addr.s_addr)) {
226 /* Bind the socket to port */ 227 /* Bind the socket to port */
227 stLclAddr.sin_family = AF_INET; 228 stLclAddr.sin_family = AF_INET;
228 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY); 229 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
229 stLclAddr.sin_port = stAddr.sin_port; 230 stLclAddr.sin_port = stAddr.sin_port;
230 if (bind(sock, (struct sockaddr *)&stLclAddr, sizeof(stLclAddr)) < 0) { 231 if (bind(sock, (struct sockaddr *)&stLclAddr, sizeof(stLclAddr)) < 0) {
231 return (0); 232 return (0);
232 } 233 }
233 234
234 /* Register to a multicast address */ 235 /* Register to a multicast address */
235 stMreq.imr_multiaddr.s_addr = stAddr.sin_addr.s_addr; 236 stMreq.imr_multiaddr.s_addr = stAddr.sin_addr.s_addr;
236 stMreq.imr_interface.s_addr = INADDR_ANY; 237 stMreq.imr_interface.s_addr = INADDR_ANY;
237 if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq)) < 0) { 238 if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&stMreq, sizeof(stMreq)) < 0) {
238 return (0); 239 return (0);
239 } 240 }
240 } else { 241 } else {
241 /* Bind the socket to port */ 242 /* Bind the socket to port */
242 stLclAddr.sin_family = AF_INET; 243 stLclAddr.sin_family = AF_INET;
243 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY); 244 stLclAddr.sin_addr.s_addr = htonl(INADDR_ANY);
244 stLclAddr.sin_port = htons(0); 245 stLclAddr.sin_port = htons(0);
245 if (bind(sock, (struct sockaddr *)&stLclAddr, sizeof(stLclAddr)) < 0) { 246 if (bind(sock, (struct sockaddr *)&stLclAddr, sizeof(stLclAddr)) < 0) {
246 return (0); 247 return (0);
247 } 248 }
248 } 249 }
249 return (sock); 250 return (sock);
250} 251}
251 252
252int LibMadPlugin::tcp_open(char *address, int port) { 253int LibMadPlugin::tcp_open(char *address, int port) {
253 struct sockaddr_in stAddr; 254 struct sockaddr_in stAddr;
254 struct hostent *host; 255 struct hostent *host;
255 int sock; 256 int sock;
256 struct linger l; 257 struct linger l;
257 258
258 memset(&stAddr, 0, sizeof(stAddr)); 259 memset(&stAddr, 0, sizeof(stAddr));
259 stAddr.sin_family = AF_INET; 260 stAddr.sin_family = AF_INET;
260 stAddr.sin_port = htons(port); 261 stAddr.sin_port = htons(port);
261 262
262 if ((host = gethostbyname(address)) == NULL) { 263 if ((host = gethostbyname(address)) == NULL) {
263 return (0); 264 return (0);
264 } 265 }
265 266
266 stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]); 267 stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]);
267 268
268 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { 269 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
269 return (0); 270 return (0);
270 } 271 }
271 272
272 l.l_onoff = 1; 273 l.l_onoff = 1;
273 l.l_linger = 5; 274 l.l_linger = 5;
274 if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l)) < 0) { 275 if (setsockopt(sock, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l)) < 0) {
275 return (0); 276 return (0);
276 } 277 }
277 278
278 if (connect(sock, (struct sockaddr *)&stAddr, sizeof(stAddr)) < 0) { 279 if (connect(sock, (struct sockaddr *)&stAddr, sizeof(stAddr)) < 0) {
279 return (0); 280 return (0);
280 } 281 }
281 282
282 return (sock); 283 return (sock);
283} 284}
284 285
285 286
286/** 287/**
287 * Read a http line header. 288 * Read a http line header.
288 * This function read character by character. 289 * This function read character by character.
289 * @param tcp_sock the socket use to read the stream 290 * @param tcp_sock the socket use to read the stream
290 * @param buf a buffer to receive the data 291 * @param buf a buffer to receive the data
291 * @param size size of the buffer 292 * @param size size of the buffer
292 * @return the size of the stream read or -1 if an error occured 293 * @return the size of the stream read or -1 if an error occured
293 */ 294 */
294int LibMadPlugin::http_read_line(int tcp_sock, char *buf, int size) { 295int LibMadPlugin::http_read_line(int tcp_sock, char *buf, int size) {
295 int offset = 0; 296 int offset = 0;
296 297
297 do { 298 do {
298 if (::read(tcp_sock, buf + offset, 1) < 0) 299 if (::read(tcp_sock, buf + offset, 1) < 0)
299 return -1; 300 return -1;
300 if (buf[offset] != '\r') /* Strip \r from answer */ 301 if (buf[offset] != '\r') /* Strip \r from answer */
301 offset++; 302 offset++;
302 } while (offset < size - 1 && buf[offset - 1] != '\n'); 303 } while (offset < size - 1 && buf[offset - 1] != '\n');
303 304
304 buf[offset] = 0; 305 buf[offset] = 0;
305 return offset; 306 return offset;
306} 307}
307 308
308int LibMadPlugin::http_open(const QString& path ) { 309int LibMadPlugin::http_open(const QString& path ) {
309 char *host; 310 char *host;
310 int port; 311 int port;
311 char *request; 312 char *request;
312 int tcp_sock; 313 int tcp_sock;
313 char http_request[PATH_MAX]; 314 char http_request[PATH_MAX];
314 char filename[PATH_MAX]; 315 char filename[PATH_MAX];
315 //char c; 316 //char c;
316 char *arg =strdup(path.latin1()); 317 char *arg =strdup(path.latin1());
317 318
318 /* Check for URL syntax */ 319 /* Check for URL syntax */
319 if (strncmp(arg, "http://", strlen("http://"))) { 320 if (strncmp(arg, "http://", strlen("http://"))) {
320 return (0); 321 return (0);
321 } 322 }
322 323
323 /* Parse URL */ 324 /* Parse URL */
324 port = 80; 325 port = 80;
325 host = arg + strlen("http://"); 326 host = arg + strlen("http://");
326 if ((request = strchr(host, '/')) == NULL) { 327 if ((request = strchr(host, '/')) == NULL) {
327 return (0); 328 return (0);
328 } 329 }
329 330
330 *request++ = 0; 331 *request++ = 0;
331 332
332 if (strchr(host, ':') != NULL) { /* port is specified */ 333 if (strchr(host, ':') != NULL) { /* port is specified */
333 port = atoi(strchr(host, ':') + 1); 334 port = atoi(strchr(host, ':') + 1);
334 *strchr(host, ':') = 0; 335 *strchr(host, ':') = 0;
335 } 336 }
336 337
337 /* Open a TCP socket */ 338 /* Open a TCP socket */
338 if (!(tcp_sock = tcp_open(host, port))) { 339 if (!(tcp_sock = tcp_open(host, port))) {
339 perror("http_open"); 340 perror("http_open");
340 return (0); 341 return (0);
341 } 342 }
342 343
343 snprintf(filename, sizeof(filename) - strlen(host) - 75, "%s", request); 344 snprintf(filename, sizeof(filename) - strlen(host) - 75, "%s", request);
344 345
345 /* Send HTTP GET request */ 346 /* Send HTTP GET request */
346 /* Please don't use a Agent know by shoutcast (Lynx, Mozilla) seems to be reconized and print 347 /* Please don't use a Agent know by shoutcast (Lynx, Mozilla) seems to be reconized and print
347 * a html page and not the stream */ 348 * a html page and not the stream */
348 snprintf(http_request, sizeof(http_request), "GET /%s HTTP/1.0\r\n" 349 snprintf(http_request, sizeof(http_request), "GET /%s HTTP/1.0\r\n"
349 /* "User-Agent: Mozilla/2.0 (Win95; I)\r\n" */ 350 /* "User-Agent: Mozilla/2.0 (Win95; I)\r\n" */
350 "Pragma: no-cache\r\n" "Host: %s\r\n" "Accept: */*\r\n" "\r\n", filename, host); 351 "Pragma: no-cache\r\n" "Host: %s\r\n" "Accept: */*\r\n" "\r\n", filename, host);
351 352
352 send(tcp_sock, http_request, strlen(http_request), 0); 353 send(tcp_sock, http_request, strlen(http_request), 0);
353 354
354 /* Parse server reply */ 355 /* Parse server reply */
355#if 0 356#if 0
356 do 357 do
357 read(tcp_sock, &c, sizeof(char)); 358 read(tcp_sock, &c, sizeof(char));
358 while (c != ' '); 359 while (c != ' ');
359 read(tcp_sock, http_request, 4 * sizeof(char)); 360 read(tcp_sock, http_request, 4 * sizeof(char));
360 http_request[4] = 0; 361 http_request[4] = 0;
361 if (strcmp(http_request, "200 ")) { 362 if (strcmp(http_request, "200 ")) {
362 fprintf(stderr, "http_open: "); 363 fprintf(stderr, "http_open: ");
363 do { 364 do {
364 read(tcp_sock, &c, sizeof(char)); 365 read(tcp_sock, &c, sizeof(char));
365 fprintf(stderr, "%c", c); 366 fprintf(stderr, "%c", c);
366 } while (c != '\r'); 367 } while (c != '\r');
367 fprintf(stderr, "\n"); 368 fprintf(stderr, "\n");
368 return (0); 369 return (0);
369 } 370 }
370#endif 371#endif
371 372
372 QString name; 373 QString name;
373 QString genre; 374 QString genre;
374 QString bitrate; 375 QString bitrate;
375 QString url; 376 QString url;
376 QString message = tr("Info: "); 377 QString message = tr("Info: ");
377 do { 378 do {
378 379
379 int len; 380 int len;
380 381
381 len = http_read_line(tcp_sock, http_request, sizeof(http_request)); 382 len = http_read_line(tcp_sock, http_request, sizeof(http_request));
382 383
383 if (len == -1) { 384 if (len == -1) {
384 qDebug( "http_open: "+ QString(strerror(errno)) +"\n"); 385 qDebug( "http_open: "+ QString(strerror(errno)) +"\n");
385 return 0; 386 return 0;
386 } 387 }
387 388
388 if (QString(http_request).left(9) == "Location:") { 389 if (QString(http_request).left(9) == "Location:") {
389 /* redirect */ 390 /* redirect */
390 ::close(tcp_sock); 391 ::close(tcp_sock);
391 http_request[strlen(http_request) - 1] = '\0'; 392 http_request[strlen(http_request) - 1] = '\0';
392 return http_open(&http_request[10]); 393 return http_open(&http_request[10]);
393 } 394 }
394 395
395 if (QString(http_request).left(4) == "ICY ") { 396 if (QString(http_request).left(4) == "ICY ") {
396 /* This is shoutcast/icecast streaming */ 397 /* This is shoutcast/icecast streaming */
397 if (strncmp(http_request + 4, "200 ", 4)) { 398 if (strncmp(http_request + 4, "200 ", 4)) {
398 qDebug("http_open: " + QString(http_request) + "\n"); 399 qDebug("http_open: " + QString(http_request) + "\n");
399 return 0; 400 return 0;
400 } 401 }
401 } else if (QString(http_request).left(4) == "icy-") { 402 } else if (QString(http_request).left(4) == "icy-") {
402 /* we can have: icy-noticeX, icy-name, icy-genre, icy-url, icy-pub, icy-metaint, icy-br */ 403 /* we can have: icy-noticeX, icy-name, icy-genre, icy-url, icy-pub, icy-metaint, icy-br */
403 if ( QString( http_request ).left( 8 ) == "icy-name" ) { 404 if ( QString( http_request ).left( 8 ) == "icy-name" ) {
404 name = tr("Name: ") + QString(http_request).mid(9, (QString(http_request).length())- 9 ); 405 name = tr("Name: ") + QString(http_request).mid(9, (QString(http_request).length())- 9 );
405 } else if ( QString( http_request ).left( 9 ) == "icy-genre" ) { 406 } else if ( QString( http_request ).left( 9 ) == "icy-genre" ) {
406 genre = tr("Genre: ") + QString(http_request).mid(10, (QString(http_request).length())-10 ); 407 genre = tr("Genre: ") + QString(http_request).mid(10, (QString(http_request).length())-10 );
407 } else if ( QString( http_request ).left( 6 ) == "icy-br" ) { 408 } else if ( QString( http_request ).left( 6 ) == "icy-br" ) {
408 bitrate = tr("Bitrate: ") + QString(http_request).mid(7, (QString(http_request).length())- 7 ); 409 bitrate = tr("Bitrate: ") + QString(http_request).mid(7, (QString(http_request).length())- 7 );
409 } else if ( QString( http_request ).left( 7 ) == "icy-url" ) { 410 } else if ( QString( http_request ).left( 7 ) == "icy-url" ) {
410 url = tr("URL: ") + QString(http_request).mid(8, (QString(http_request).length())- 8 ); 411 url = tr("URL: ") + QString(http_request).mid(8, (QString(http_request).length())- 8 );
411 } else if ( QString( http_request ).left( 10 ) == "icy-notice" ) { 412 } else if ( QString( http_request ).left( 10 ) == "icy-notice" ) {
412 message += QString(http_request).mid(11, QString(http_request).length()-11 ) ; 413 message += QString(http_request).mid(11, QString(http_request).length()-11 ) ;
413 } 414 }
414 } 415 }
415 } while (strcmp(http_request, "\n") != 0); 416 } while (strcmp(http_request, "\n") != 0);
416 417
417 info = QString(name + genre + url + bitrate + message).replace( QRegExp("\n"), " : " ); 418 info = QString(name + genre + url + bitrate + message).replace( QRegExp("\n"), " : " );
418 419
419 qDebug("Stream info: " + info); 420 qDebug("Stream info: " + info);
420 421
421 return (tcp_sock); 422 return (tcp_sock);
422} 423}
423 424
424 425
425 426
426bool LibMadPlugin::open( const QString& path ) { 427bool LibMadPlugin::open( const QString& path ) {
427 debugMsg( "LibMadPlugin::open" ); 428 debugMsg( "LibMadPlugin::open" );
428 Config cfg("OpiePlayer"); 429 Config cfg("OpiePlayer");
429 cfg.setGroup("Options"); 430 cfg.setGroup("Options");
430 bufferSize = cfg.readNumEntry("MPeg_BufferSize",MPEG_BUFFER_SIZE); 431 bufferSize = cfg.readNumEntry("MPeg_BufferSize",MPEG_BUFFER_SIZE);
431 qDebug("buffer size is %d", bufferSize); 432 qDebug("buffer size is %d", bufferSize);
432 d->bad_last_frame = 0; 433 d->bad_last_frame = 0;
433 d->flush = TRUE; 434 d->flush = TRUE;
434 info = QString( "" ); 435 info = QString( "" );
435 436
436 //qDebug( "Opening %s", path.latin1() ); 437 //qDebug( "Opening %s", path.latin1() );
437 438
438 if (path.left( 4 ) == "http" ) { 439 if (path.left( 4 ) == "http" ) {
439 // in case of any error we get 0 here 440 // in case of any error we get 0 here
440 if ( !(http_open(path) == 0) ) { 441 if ( !(http_open(path) == 0) ) {
441 d->input.fd = http_open(path); 442 d->input.fd = http_open(path);
442 } else { 443 } else {
443 return FALSE; 444 return FALSE;
444 } 445 }
445 } else { 446 } else {
446 d->input.path = path.latin1(); 447 d->input.path = path.latin1();
447 d->input.fd = ::open( d->input.path, O_RDONLY ); 448 d->input.fd = ::open( d->input.path, O_RDONLY );
448 // thats a better place, since it should only seek for ID3 tags on mp3 files, not streams 449 // thats a better place, since it should only seek for ID3 tags on mp3 files, not streams
449 printID3Tags(); 450 printID3Tags();
450 } 451 }
451 if (d->input.fd == -1) { 452 if (d->input.fd == -1) {
452 qDebug("error opening %s", d->input.path ); 453 qDebug("error opening %s", d->input.path );
453 return FALSE; 454 return FALSE;
454 } 455 }
455 456
456#if defined(HAVE_MMAP)
457 struct stat stat; 457 struct stat stat;
458 if (fstat(d->input.fd, &stat) == -1) { 458 if (fstat(d->input.fd, &stat) == -1) {
459 //qDebug("error calling fstat"); return FALSE; 459 qDebug("error calling fstat"); return FALSE;
460 } 460 }
461 if (S_ISREG(stat.st_mode) && stat.st_size > 0)
462 d->input.fileLength = stat.st_size;
463 else
464 d->input.fileLength = 0;
465
466#if defined(HAVE_MMAP)
461 if (S_ISREG(stat.st_mode) && stat.st_size > 0) { 467 if (S_ISREG(stat.st_mode) && stat.st_size > 0) {
462 d->input.length = stat.st_size; 468 d->input.length = stat.st_size;
463 d->input.fdm = map_file(d->input.fd, &d->input.length); 469 d->input.fdm = map_file(d->input.fd, &d->input.length);
464 if (d->input.fdm == 0) { 470 if (d->input.fdm == 0) {
465 qDebug("error mmapping file"); return FALSE; 471 qDebug("error mmapping file"); return FALSE;
466 } 472 }
467 d->input.data = (unsigned char *)d->input.fdm; 473 d->input.data = (unsigned char *)d->input.fdm;
468 } 474 }
469#endif 475#endif
470 476
471 if (d->input.data == 0) { 477 if (d->input.data == 0) {
472 d->input.data = (unsigned char *)malloc( bufferSize /*MPEG_BUFFER_SIZE*/); 478 d->input.data = (unsigned char *)malloc( bufferSize /*MPEG_BUFFER_SIZE*/);
473 if (d->input.data == 0) { 479 if (d->input.data == 0) {
474 qDebug("error allocating input buffer"); 480 qDebug("error allocating input buffer");
475 return FALSE; 481 return FALSE;
476 } 482 }
477 d->input.length = 0; 483 d->input.length = 0;
478 } 484 }
479 485
480 d->input.eof = 0; 486 d->input.eof = 0;
481 487
482 mad_stream_init(&d->stream); 488 mad_stream_init(&d->stream);
483 mad_frame_init(&d->frame); 489 mad_frame_init(&d->frame);
484 mad_synth_init(&d->synth); 490 mad_synth_init(&d->synth);
485 491
486 return TRUE; 492 return TRUE;
487} 493}
488 494
489 495
490bool LibMadPlugin::close() { 496bool LibMadPlugin::close() {
491 debugMsg( "LibMadPlugin::close" ); 497 debugMsg( "LibMadPlugin::close" );
492 498
493 int result = TRUE; 499 int result = TRUE;
494 500
495 mad_synth_finish(&d->synth); 501 mad_synth_finish(&d->synth);
496 mad_frame_finish(&d->frame); 502 mad_frame_finish(&d->frame);
497 mad_stream_finish(&d->stream); 503 mad_stream_finish(&d->stream);
498 504
499#if defined(HAVE_MMAP) 505#if defined(HAVE_MMAP)
500 if (d->input.fdm) { 506 if (d->input.fdm) {
501 if (unmap_file(d->input.fdm, d->input.length) == -1) { 507 if (unmap_file(d->input.fdm, d->input.length) == -1) {
502 qDebug("error munmapping file"); 508 qDebug("error munmapping file");
503 result = FALSE; 509 result = FALSE;
504 } 510 }
505 d->input.fdm = 0; 511 d->input.fdm = 0;
506 d->input.data = 0; 512 d->input.data = 0;
507 } 513 }
508#endif 514#endif
509 515
510 if (d->input.data) { 516 if (d->input.data) {
511 free(d->input.data); 517 free(d->input.data);
512 d->input.data = 0; 518 d->input.data = 0;
513 } 519 }
514 520
515 if (::close(d->input.fd) == -1) { 521 if (::close(d->input.fd) == -1) {
516 qDebug("error closing file %s", d->input.path); 522 qDebug("error closing file %s", d->input.path);
517 result = FALSE; 523 result = FALSE;
518 } 524 }
519 525
520 d->input.fd = 0; 526 d->input.fd = 0;
521 527
522 return result; 528 return result;
523} 529}
524 530
525 531
526bool LibMadPlugin::isOpen() { 532bool LibMadPlugin::isOpen() {
527 debugMsg( "LibMadPlugin::isOpen" ); 533 debugMsg( "LibMadPlugin::isOpen" );
528 return ( d->input.fd != 0 ); 534 return ( d->input.fd != 0 );
529} 535}
530 536
531 537
532int LibMadPlugin::audioStreams() { 538int LibMadPlugin::audioStreams() {
533 debugMsg( "LibMadPlugin::audioStreams" ); 539 debugMsg( "LibMadPlugin::audioStreams" );
534 return 1; 540 return 1;
535} 541}
536 542
537 543
538int LibMadPlugin::audioChannels( int ) { 544int LibMadPlugin::audioChannels( int ) {
539 debugMsg( "LibMadPlugin::audioChannels" ); 545 debugMsg( "LibMadPlugin::audioChannels" );
540/* 546/*
541 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); 547 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 );
542 qDebug( "LibMadPlugin::audioChannels: %i", d->frame.header.mode > 0 ? 2 : 1 ); 548 qDebug( "LibMadPlugin::audioChannels: %i", d->frame.header.mode > 0 ? 2 : 1 );
543 return d->frame.header.mode > 0 ? 2 : 1; 549 return d->frame.header.mode > 0 ? 2 : 1;
544*/ 550*/
545 return 2; 551 return 2;
546} 552}
547 553
548 554
549int LibMadPlugin::audioFrequency( int ) { 555int LibMadPlugin::audioFrequency( int ) {
550 debugMsg( "LibMadPlugin::audioFrequency" ); 556 debugMsg( "LibMadPlugin::audioFrequency" );
551 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); 557 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 );
552 qDebug( "LibMadPlugin::audioFrequency: %i", d->frame.header.samplerate ); 558 qDebug( "LibMadPlugin::audioFrequency: %i", d->frame.header.samplerate );
553 return d->frame.header.samplerate; 559 return d->frame.header.samplerate;
554} 560}
555 561
556 562
557int LibMadPlugin::audioSamples( int ) { 563int LibMadPlugin::audioSamples( int ) {
558 debugMsg( "LibMadPlugin::audioSamples" ); 564 debugMsg( "LibMadPlugin::audioSamples" );
565
566 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 );
567 mad_header_decode( (struct mad_header *)&d->frame.header, &d->stream );
568/*
569 qDebug( "LibMadPlugin::audioSamples: %i*%i", d->frame.header.duration.seconds,
570 d->frame.header.samplerate );
571 return d->frame.header.duration.seconds * d->frame.header.samplerate;
572*/
573 if ( d->frame.header.bitrate == 0 )
574 return 0;
575 int samples = (d->input.fileLength / (d->frame.header.bitrate/8)) * d->frame.header.samplerate;
576
577 qDebug( "LibMadPlugin::audioSamples: %i * %i * 8 / %i", (int)d->input.fileLength,
578 (int)d->frame.header.samplerate, (int)d->frame.header.bitrate );
579 qDebug( "LibMadPlugin::audioSamples: %i", samples );
559 580
560 // long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); 581 return samples;
561// mad_header_decode( (struct mad_header *)&d->frame.header, &d->stream );
562// qDebug( "LibMadPlugin::audioSamples: %i*%i", d->frame.header.duration.seconds, d->frame.header.samplerate );
563// return d->frame.header.duration.seconds * d->frame.header.samplerate;
564 582
565 return 10000000; 583// return 10000000;
566} 584}
567 585
568 586
569bool LibMadPlugin::audioSetSample( long, int ) { 587bool LibMadPlugin::audioSetSample( long, int ) {
570 debugMsg( "LibMadPlugin::audioSetSample" ); 588 debugMsg( "LibMadPlugin::audioSetSample" );
589
590// long totalSamples = audioSamples(0);
591// if ( totalSamples <= 1 )
592// return FALSE;
593
594// // Seek to requested position
595// qDebug( "seek pos: %i", (int)((double)pos * d->input.fileLength / totalSamples) );
596// ::lseek( d->input.fd, (long)((double)pos * d->input.fileLength / totalSamples), SEEK_SET );
597// mad_stream_sync(&d->stream);
598
599// mad_stream_init(&d->stream);
600// mad_frame_init(&d->frame);
601// mad_synth_init(&d->synth);
602
603// return TRUE;
604 debugMsg( "LibMadPlugin::audioSetSample" );
571 return FALSE; 605 return FALSE;
572} 606}
573 607
574 608
575long LibMadPlugin::audioGetSample( int ) { 609long LibMadPlugin::audioGetSample( int ) {
576 debugMsg( "LibMadPlugin::audioGetSample" ); 610 debugMsg( "LibMadPlugin::audioGetSample" );
577 return 0; 611 return 0;
578} 612}
579 613
580/* 614/*
581bool LibMadPlugin::audioReadSamples( short *, int, long, int ) { 615bool LibMadPlugin::audioReadSamples( short *, int, long, int ) {
582debugMsg( "LibMadPlugin::audioReadSamples" ); 616debugMsg( "LibMadPlugin::audioReadSamples" );
583return FALSE; 617return FALSE;
584} 618}
585 619
586 620
587bool LibMadPlugin::audioReReadSamples( short *, int, long, int ) { 621bool LibMadPlugin::audioReReadSamples( short *, int, long, int ) {
588debugMsg( "LibMadPlugin::audioReReadSamples" ); 622debugMsg( "LibMadPlugin::audioReReadSamples" );
589 return FALSE; 623 return FALSE;
590 } 624 }
591*/ 625*/
592 626
593bool LibMadPlugin::read() { 627bool LibMadPlugin::read() {
594 debugMsg( "LibMadPlugin::read" ); 628 debugMsg( "LibMadPlugin::read" );
595 int len; 629 int len;
596 630
597 if (d->input.eof) 631 if (d->input.eof)
598 return FALSE; 632 return FALSE;
599 633
600#if defined(HAVE_MMAP) 634#if defined(HAVE_MMAP)
601 if (d->input.fdm) { 635 if (d->input.fdm) {
602 unsigned long skip = 0; 636 unsigned long skip = 0;
603 637
604 if (d->stream.next_frame) { 638 if (d->stream.next_frame) {
605 struct stat stat; 639 struct stat stat;
606 640
607 if (fstat(d->input.fd, &stat) == -1) 641 if (fstat(d->input.fd, &stat) == -1)
608 return FALSE; 642 return FALSE;
609 643
610 if (stat.st_size + MAD_BUFFER_GUARD <= (signed)d->input.length) 644 if (stat.st_size + MAD_BUFFER_GUARD <= (signed)d->input.length)
611 return FALSE; 645 return FALSE;
612 646
613 // file size changed; update memory map 647 // file size changed; update memory map
614 skip = d->stream.next_frame - d->input.data; 648 skip = d->stream.next_frame - d->input.data;
615 649
616 if (unmap_file(d->input.fdm, d->input.length) == -1) { 650 if (unmap_file(d->input.fdm, d->input.length) == -1) {
617 d->input.fdm = 0; 651 d->input.fdm = 0;
618 d->input.data = 0; 652 d->input.data = 0;
619 return FALSE; 653 return FALSE;
620 } 654 }
621 655
622 d->input.length = stat.st_size; 656 d->input.length = stat.st_size;
623 657
624 d->input.fdm = map_file(d->input.fd, &d->input.length); 658 d->input.fdm = map_file(d->input.fd, &d->input.length);
625 if (d->input.fdm == 0) { 659 if (d->input.fdm == 0) {
626 d->input.data = 0; 660 d->input.data = 0;
627 return FALSE; 661 return FALSE;
628 } 662 }
629 663
630 d->input.data = (unsigned char *)d->input.fdm; 664 d->input.data = (unsigned char *)d->input.fdm;
631 } 665 }
632 666
633 mad_stream_buffer(&d->stream, d->input.data + skip, d->input.length - skip); 667 mad_stream_buffer(&d->stream, d->input.data + skip, d->input.length - skip);
634 668
635 } else 669 } else
636#endif 670#endif
637 { 671 {
638 if (d->stream.next_frame) { 672 if (d->stream.next_frame) {
639 memmove(d->input.data, d->stream.next_frame, 673 memmove(d->input.data, d->stream.next_frame,
640 d->input.length = &d->input.data[d->input.length] - d->stream.next_frame); 674 d->input.length = &d->input.data[d->input.length] - d->stream.next_frame);
641 } 675 }
642 676
643 do { 677 do {
644 len = ::read(d->input.fd, d->input.data + d->input.length, bufferSize /* MPEG_BUFFER_SIZE*/ - d->input.length); 678 len = ::read(d->input.fd, d->input.data + d->input.length, bufferSize /* MPEG_BUFFER_SIZE*/ - d->input.length);
645 } 679 }
646 while (len == -1 && errno == EINTR); 680 while (len == -1 && errno == EINTR);
647 681
648 if (len == -1) { 682 if (len == -1) {
649 qDebug("error reading audio"); 683 qDebug("error reading audio");
650 return FALSE; 684 return FALSE;
651 } 685 }
652 else if (len == 0) { 686 else if (len == 0) {
653 d->input.eof = 1; 687 d->input.eof = 1;
654 688
655 assert(bufferSize /*MPEG_BUFFER_SIZE*/ - d->input.length >= MAD_BUFFER_GUARD); 689 assert(bufferSize /*MPEG_BUFFER_SIZE*/ - d->input.length >= MAD_BUFFER_GUARD);
656 690
657 while (len < MAD_BUFFER_GUARD) 691 while (len < MAD_BUFFER_GUARD)
658 d->input.data[d->input.length + len++] = 0; 692 d->input.data[d->input.length + len++] = 0;
659 } 693 }
660 694
661 mad_stream_buffer(&d->stream, d->input.data, d->input.length += len); 695 mad_stream_buffer(&d->stream, d->input.data, d->input.length += len);
662 } 696 }
663 697
664 return TRUE; 698 return TRUE;
665} 699}
666 700
667 701
668static mad_fixed_t left_err, right_err; 702static mad_fixed_t left_err, right_err;
669static const int bits = 16; 703static const int bits = 16;
670static const int shift = MAD_F_FRACBITS + 1 - bits; 704static const int shift = MAD_F_FRACBITS + 1 - bits;
671 705
672 706
673inline long audio_linear_dither( mad_fixed_t sample, mad_fixed_t& error ) { 707inline long audio_linear_dither( mad_fixed_t sample, mad_fixed_t& error ) {
674 sample += error; 708 sample += error;
675 mad_fixed_t quantized = (sample >= MAD_F_ONE) ? MAD_F_ONE - 1 : ( (sample < -MAD_F_ONE) ? -MAD_F_ONE : sample ); 709 mad_fixed_t quantized = (sample >= MAD_F_ONE) ? MAD_F_ONE - 1 : ( (sample < -MAD_F_ONE) ? -MAD_F_ONE : sample );
676 quantized &= ~((1L << shift) - 1); 710 quantized &= ~((1L << shift) - 1);
677 error = sample - quantized; 711 error = sample - quantized;
678 return quantized >> shift; 712 return quantized >> shift;
679} 713}
680 714
681 715
682inline void audio_pcm( short *data, unsigned int nsamples, mad_fixed_t *left, mad_fixed_t *right ) { 716inline void audio_pcm( short *data, unsigned int nsamples, mad_fixed_t *left, mad_fixed_t *right ) {
683 if ( right ) { 717 if ( right ) {
684 while (nsamples--) { 718 while (nsamples--) {
685 data[0] = audio_linear_dither( *left++, left_err ); 719 data[0] = audio_linear_dither( *left++, left_err );
686 data[1] = audio_linear_dither( *right++, right_err ); 720 data[1] = audio_linear_dither( *right++, right_err );
687 data += 2; 721 data += 2;
688 } 722 }
689 } else { 723 } else {
690 while (nsamples--) { 724 while (nsamples--) {
691 data[0] = data[1] = audio_linear_dither( *left++, left_err ); 725 data[0] = data[1] = audio_linear_dither( *left++, left_err );
692 data += 2; 726 data += 2;
693 } 727 }
694 } 728 }
695} 729}
696 730
697 731
698bool LibMadPlugin::decode( short *output, long samples, long& samplesMade ) { 732bool LibMadPlugin::decode( short *output, long samples, long& samplesMade ) {
699 debugMsg( "LibMadPlugin::decode" ); 733 debugMsg( "LibMadPlugin::decode" );
700 734
701 static int buffered = 0; 735 static int buffered = 0;
702 static mad_fixed_t buffer[2][65536 * 2]; 736 static mad_fixed_t buffer[2][65536 * 2];
703 int offset = buffered; 737 int offset = buffered;
704 samplesMade = 0; 738 samplesMade = 0;
705 739
706 static int maxBuffered = 8000; // 65536; 740 static int maxBuffered = 8000; // 65536;
707 741
708 if ( samples > maxBuffered ) { 742 if ( samples > maxBuffered ) {
709 samples = maxBuffered; 743 samples = maxBuffered;
710 } 744 }
711 745
712 if ( d->flush ) { 746 if ( d->flush ) {
713 buffered = 0; 747 buffered = 0;
714 offset = 0; 748 offset = 0;
715 d->flush = FALSE; 749 d->flush = FALSE;
716 } 750 }
717 751
718 while ( buffered < maxBuffered ) { 752 while ( buffered < maxBuffered ) {
719 753
720 while (mad_frame_decode(&d->frame, &d->stream) == -1) { 754 while (mad_frame_decode(&d->frame, &d->stream) == -1) {
721 if (!MAD_RECOVERABLE(d->stream.error)) { 755 if (!MAD_RECOVERABLE(d->stream.error)) {
722 debugMsg( "feed me" ); 756 debugMsg( "feed me" );
723 return FALSE; // Feed me 757 return FALSE; // Feed me
724 } 758 }
725 if ( d->stream.error == MAD_ERROR_BADCRC ) { 759 if ( d->stream.error == MAD_ERROR_BADCRC ) {
726 mad_frame_mute(&d->frame); 760 mad_frame_mute(&d->frame);
727 qDebug( "error decoding, bad crc" ); 761 qDebug( "error decoding, bad crc" );
728 } 762 }
729 } 763 }
730 764
731 mad_synth_frame(&d->synth, &d->frame); 765 mad_synth_frame(&d->synth, &d->frame);
732 int decodedSamples = d->synth.pcm.length; 766 int decodedSamples = d->synth.pcm.length;
733 memcpy( &(buffer[0][offset]), d->synth.pcm.samples[0], decodedSamples * sizeof(mad_fixed_t) ); 767 memcpy( &(buffer[0][offset]), d->synth.pcm.samples[0], decodedSamples * sizeof(mad_fixed_t) );
734 if ( d->synth.pcm.channels == 2 ) 768 if ( d->synth.pcm.channels == 2 )
735 memcpy( &(buffer[1][offset]), d->synth.pcm.samples[1], decodedSamples * sizeof(mad_fixed_t) ); 769 memcpy( &(buffer[1][offset]), d->synth.pcm.samples[1], decodedSamples * sizeof(mad_fixed_t) );
736 offset += decodedSamples; 770 offset += decodedSamples;
737 buffered += decodedSamples; 771 buffered += decodedSamples;
738 } 772 }
739 773
740//qApp->processEvents(); 774//qApp->processEvents();
741 audio_pcm( output, samples, buffer[0], (d->synth.pcm.channels == 2) ? buffer[1] : 0 ); 775 audio_pcm( output, samples, buffer[0], (d->synth.pcm.channels == 2) ? buffer[1] : 0 );
742// audio_pcm( output, samples, buffer[1], buffer[0] ); 776// audio_pcm( output, samples, buffer[1], buffer[0] );
743// audio_pcm( output, samples, buffer[0], buffer[1] ); 777// audio_pcm( output, samples, buffer[0], buffer[1] );
744 samplesMade = samples; 778 samplesMade = samples;
745 memmove( buffer[0], &(buffer[0][samples]), (buffered - samples) * sizeof(mad_fixed_t) ); 779 memmove( buffer[0], &(buffer[0][samples]), (buffered - samples) * sizeof(mad_fixed_t) );
746 if ( d->synth.pcm.channels == 2 ) { 780 if ( d->synth.pcm.channels == 2 ) {
747 memmove( buffer[1], &(buffer[1][samples]), (buffered - samples) * sizeof(mad_fixed_t) ); 781 memmove( buffer[1], &(buffer[1][samples]), (buffered - samples) * sizeof(mad_fixed_t) );
748 } 782 }
749 buffered -= samples; 783 buffered -= samples;
750 784
751 return TRUE; 785 return TRUE;
752} 786}
753 787
754/*bool LibMadPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) { 788/*bool LibMadPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) {
755*/ 789*/
756bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long samples, long& samplesMade, int ) { 790bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long samples, long& samplesMade, int ) {
757 debugMsg( "LibMadPlugin::audioReadStereoSamples" ); 791 debugMsg( "LibMadPlugin::audioReadStereoSamples" );
758 792
759 static bool needInput = TRUE; 793 static bool needInput = TRUE;
760 794
761 if ( samples == 0 ) 795 if ( samples == 0 )
762 return FALSE; 796 return FALSE;
763 797
764 do { 798 do {
765 if ( needInput ) 799 if ( needInput )
766 if ( !read() ) { 800 if ( !read() ) {
767 return FALSE; 801 return FALSE;
768 } 802 }
769 803
770 needInput = FALSE; 804 needInput = FALSE;
771 805
772 if ( decode( output, samples, samplesMade ) ) 806 if ( decode( output, samples, samplesMade ) )
773 return TRUE; 807 return TRUE;
774 else 808 else
775 needInput = TRUE; 809 needInput = TRUE;
776 } 810 }
777 while ( ( samplesMade < samples ) && ( !d->input.eof ) ); 811 while ( ( samplesMade < samples ) && ( !d->input.eof ) );
778 812
779 return FALSE; 813 return FALSE;
780} 814}
781 815
782 816
783double LibMadPlugin::getTime() { 817double LibMadPlugin::getTime() {
784 debugMsg( "LibMadPlugin::getTime" ); 818 debugMsg( "LibMadPlugin::getTime" );
785 return 0.0; 819 return 0.0;
786} 820}
787 821
788 822
789void LibMadPlugin::printID3Tags() { 823void LibMadPlugin::printID3Tags() {
790 qDebug( "LibMadPlugin::printID3Tags" ); 824 qDebug( "LibMadPlugin::printID3Tags" );
791 825
792 char id3v1[128 + 1]; 826 char id3v1[128 + 1];
793 827
794 if ( ::lseek( d->input.fd, -128, SEEK_END ) == -1 ) { 828 if ( ::lseek( d->input.fd, -128, SEEK_END ) == -1 ) {
795 qDebug( "error seeking to id3 tags" ); 829 qDebug( "error seeking to id3 tags" );
796 return; 830 return;
797 } 831 }
798 832
799 if ( ::read( d->input.fd, id3v1, 128 ) != 128 ) { 833 if ( ::read( d->input.fd, id3v1, 128 ) != 128 ) {
800 qDebug( "error reading in id3 tags" ); 834 qDebug( "error reading in id3 tags" );
801 return; 835 return;
802 } 836 }
803 837
804 if ( ::strncmp( (const char *)id3v1, "TAG", 3 ) != 0 ) { 838 if ( ::strncmp( (const char *)id3v1, "TAG", 3 ) != 0 ) {
805 debugMsg( "sorry, no id3 tags" ); 839 debugMsg( "sorry, no id3 tags" );
806 } else { 840 } else {
807 int len[5] = { 30, 30, 30, 4, 30 }; 841 int len[5] = { 30, 30, 30, 4, 30 };
808 QString label[5] = { tr( "Title" ), tr( "Artist" ), tr( "Album" ), tr( "Year" ), tr( "Comment" ) }; 842 QString label[5] = { tr( "Title" ), tr( "Artist" ), tr( "Album" ), tr( "Year" ), tr( "Comment" ) };
809 char *ptr = id3v1 + 3, *ptr2 = ptr + len[0]; 843 char *ptr = id3v1 + 3, *ptr2 = ptr + len[0];
810 qDebug( "ID3 tags in file:" ); 844 qDebug( "ID3 tags in file:" );
811 info = ""; 845 info = "";
812 for ( int i = 0; i < 5; ptr += len[i], i++, ptr2 += len[i] ) { 846 for ( int i = 0; i < 5; ptr += len[i], i++, ptr2 += len[i] ) {
813 char push = *ptr2; 847 char push = *ptr2;
814 *ptr2 = '\0'; 848 *ptr2 = '\0';
815 char *ptr3 = ptr2; 849 char *ptr3 = ptr2;
816 while ( ptr3-1 >= ptr && isspace(ptr3[-1]) ) ptr3--; 850 while ( ptr3-1 >= ptr && isspace(ptr3[-1]) ) ptr3--;
817 char push2 = *ptr3; *ptr3 = '\0'; 851 char push2 = *ptr3; *ptr3 = '\0';
818 if ( strcmp( ptr, "" ) ) { 852 if ( strcmp( ptr, "" ) ) {
819 if( ((QString)ptr).find(" ") == -1) // don't add anything that has blanks 853 if( ((QString)ptr).find(" ") == -1) // don't add anything that has blanks
820 info += ( i != 0 ? ", " : "" ) + label[i] + ": " + ptr; 854 info += ( i != 0 ? ", " : "" ) + label[i] + ": " + ptr;
821 } 855 }
822// qDebug( info.latin1() ); 856// qDebug( info.latin1() );
823 *ptr3 = push2; 857 *ptr3 = push2;
824 *ptr2 = push; 858 *ptr2 = push;
825 } 859 }
826 if (id3v1[126] == 0 && id3v1[127] != 0) 860 if (id3v1[126] == 0 && id3v1[127] != 0)