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