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