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