summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/libmad/libmad.pro2
-rw-r--r--core/multimedia/opieplayer/libmad/libmadplugin.cpp59
2 files changed, 42 insertions, 19 deletions
diff --git a/core/multimedia/opieplayer/libmad/libmad.pro b/core/multimedia/opieplayer/libmad/libmad.pro
index eddf242..679242b 100644
--- a/core/multimedia/opieplayer/libmad/libmad.pro
+++ b/core/multimedia/opieplayer/libmad/libmad.pro
@@ -1,25 +1,25 @@
1TEMPLATE = lib 1TEMPLATE = lib
2CONFIG += qt warn_on release 2CONFIG += qt warn_on release
3HEADERS = libmad_version.h fixed.h bit.h timer.h stream.h frame.h synth.h decoder.h \ 3HEADERS = libmad_version.h fixed.h bit.h timer.h stream.h frame.h synth.h decoder.h \
4 layer12.h layer3.h huffman.h libmad_global.h mad.h libmadplugin.h libmadpluginimpl.h 4 layer12.h layer3.h huffman.h libmad_global.h mad.h libmadplugin.h libmadpluginimpl.h
5SOURCES = version.c fixed.c bit.c timer.c stream.c frame.c synth.c decoder.c \ 5SOURCES = version.c fixed.c bit.c timer.c stream.c frame.c synth.c decoder.c \
6 layer12.c layer3.c huffman.c libmadplugin.cpp libmadpluginimpl.cpp 6 layer12.c layer3.c huffman.c libmadplugin.cpp libmadpluginimpl.cpp
7TARGET = madplugin 7TARGET = madplugin
8DESTDIR = ../../plugins/codecs 8DESTDIR = ../../../plugins/codecs
9INCLUDEPATH += $(OPIEDIR)/include .. 9INCLUDEPATH += $(OPIEDIR)/include ..
10DEPENDPATH += ../$(OPIEDIR)/include .. 10DEPENDPATH += ../$(OPIEDIR)/include ..
11LIBS += -lqpe -lm 11LIBS += -lqpe -lm
12VERSION = 1.0.0 12VERSION = 1.0.0
13 13
14TRANSLATIONS = ../../i18n/pt_BR/libmadplugin.ts 14TRANSLATIONS = ../../i18n/pt_BR/libmadplugin.ts
15TRANSLATIONS += ../../i18n/de/libmadplugin.ts 15TRANSLATIONS += ../../i18n/de/libmadplugin.ts
16TRANSLATIONS += ../../i18n/en/libmadplugin.ts 16TRANSLATIONS += ../../i18n/en/libmadplugin.ts
17TRANSLATIONS += ../../i18n/hu/libmadplugin.ts 17TRANSLATIONS += ../../i18n/hu/libmadplugin.ts
18TRANSLATIONS += ../../i18n/sl/libmadplugin.ts 18TRANSLATIONS += ../../i18n/sl/libmadplugin.ts
19TRANSLATIONS += ../../i18n/ja/libmadplugin.ts 19TRANSLATIONS += ../../i18n/ja/libmadplugin.ts
20TRANSLATIONS += ../../i18n/pl/libmadplugin.ts 20TRANSLATIONS += ../../i18n/pl/libmadplugin.ts
21TRANSLATIONS += ../../i18n/ko/libmadplugin.ts 21TRANSLATIONS += ../../i18n/ko/libmadplugin.ts
22TRANSLATIONS += ../../i18n/no/libmadplugin.ts 22TRANSLATIONS += ../../i18n/no/libmadplugin.ts
23TRANSLATIONS += ../../i18n/zh_CN/libmadplugin.ts 23TRANSLATIONS += ../../i18n/zh_CN/libmadplugin.ts
24TRANSLATIONS += ../../i18n/zh_TW/libmadplugin.ts 24TRANSLATIONS += ../../i18n/zh_TW/libmadplugin.ts
25TRANSLATIONS += ../../i18n/fr/libmadplugin.ts 25TRANSLATIONS += ../../i18n/fr/libmadplugin.ts
diff --git a/core/multimedia/opieplayer/libmad/libmadplugin.cpp b/core/multimedia/opieplayer/libmad/libmadplugin.cpp
index 46f2450..4665408 100644
--- a/core/multimedia/opieplayer/libmad/libmadplugin.cpp
+++ b/core/multimedia/opieplayer/libmad/libmadplugin.cpp
@@ -1,591 +1,614 @@
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>
21#include <qpe/config.h>
22#include <qmessagebox.h>
23#include <qstring.h>
24
20#include <stdio.h> 25#include <stdio.h>
21#include <stdarg.h> 26#include <stdarg.h>
22#include <stdlib.h> 27#include <stdlib.h>
23#include <sys/types.h> 28#include <sys/types.h>
24#include <sys/stat.h> 29#include <sys/stat.h>
25#include <fcntl.h> 30#include <fcntl.h>
26#include <unistd.h> 31#include <unistd.h>
27#include <string.h> 32#include <string.h>
28#include <ctype.h> 33#include <ctype.h>
29#include <errno.h> 34#include <errno.h>
30#include <time.h> 35#include <time.h>
31#include <locale.h> 36#include <locale.h>
32#include <math.h> 37#include <math.h>
33#include <assert.h> 38#include <assert.h>
34#include <qapplication.h> 39
35#include <qpe/config.h>
36 40
37// for network handling 41// for network handling
38#include <netinet/in.h> 42#include <netinet/in.h>
39#include <netdb.h> 43#include <netdb.h>
40#include <sys/socket.h> 44#include <sys/socket.h>
41#include <arpa/inet.h> 45#include <arpa/inet.h>
42#include <unistd.h> 46#include <unistd.h>
43 47
44 48
45//#define HAVE_MMAP 49//#define HAVE_MMAP
46 50
47#if defined(HAVE_MMAP) 51#if defined(HAVE_MMAP)
48# include <sys/mman.h> 52# include <sys/mman.h>
49#endif 53#endif
50#include "libmadplugin.h" 54#include "libmadplugin.h"
51 55
52 56
53extern "C" { 57extern "C" {
54#include "mad.h" 58#include "mad.h"
55} 59}
56 60
57 61
58#define MPEG_BUFFER_SIZE 65536 62#define MPEG_BUFFER_SIZE 65536
59//#define MPEG_BUFFER_SIZE 32768 //16384 // 8192 63//#define MPEG_BUFFER_SIZE 32768 //16384 // 8192
60//#define debugMsg(a) qDebug(a) 64//#define debugMsg(a) qDebug(a)
61#define debugMsg(a) 65#define debugMsg(a)
62 66
63 67
64class Input { 68class Input {
65public: 69public:
66 char const *path; 70 char const *path;
67 int fd; 71 int fd;
68#if defined(HAVE_MMAP) 72#if defined(HAVE_MMAP)
69 void *fdm; 73 void *fdm;
70#endif 74#endif
71 unsigned char *data; 75 unsigned char *data;
72 unsigned long length; 76 unsigned long length;
73 int eof; 77 int eof;
74}; 78};
75 79
76 80
77class Output { 81class Output {
78public: 82public:
79 mad_fixed_t attenuate; 83 mad_fixed_t attenuate;
80 struct filter *filters; 84 struct filter *filters;
81 unsigned int channels_in; 85 unsigned int channels_in;
82 unsigned int channels_out; 86 unsigned int channels_out;
83 unsigned int speed_in; 87 unsigned int speed_in;
84 unsigned int speed_out; 88 unsigned int speed_out;
85 const char *path; 89 const char *path;
86}; 90};
87 91
88 92
89# if defined(HAVE_MMAP) 93# if defined(HAVE_MMAP)
90static void *map_file(int fd, unsigned long *length) 94static void *map_file(int fd, unsigned long *length)
91{ 95{
92 void *fdm; 96 void *fdm;
93 97
94 *length += MAD_BUFFER_GUARD; 98 *length += MAD_BUFFER_GUARD;
95 99
96 fdm = mmap(0, *length, PROT_READ, MAP_SHARED, fd, 0); 100 fdm = mmap(0, *length, PROT_READ, MAP_SHARED, fd, 0);
97 if (fdm == MAP_FAILED) 101 if (fdm == MAP_FAILED)
98 return 0; 102 return 0;
99 103
100# if defined(HAVE_MADVISE) 104# if defined(HAVE_MADVISE)
101 madvise(fdm, *length, MADV_SEQUENTIAL); 105 madvise(fdm, *length, MADV_SEQUENTIAL);
102# endif 106# endif
103 107
104 return fdm; 108 return fdm;
105} 109}
106 110
107 111
108static int unmap_file(void *fdm, unsigned long length) 112static int unmap_file(void *fdm, unsigned long length)
109{ 113{
110 if (munmap(fdm, length) == -1) 114 if (munmap(fdm, length) == -1)
111 return -1; 115 return -1;
112 116
113 return 0; 117 return 0;
114} 118}
115# endif 119# endif
116 120
117 121
118static inline QString tr( const char *str ) { 122static inline QString tr( const char *str ) {
119 // 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
120 return qApp->translate( "OpiePlayer", str, "libmad strings for mp3 file info" ); 124 return qApp->translate( "OpiePlayer", str, "libmad strings for mp3 file info" );
121} 125}
122 126
123 127
124class LibMadPluginData { 128class LibMadPluginData {
125public: 129public:
126 Input input; 130 Input input;
127 Output output; 131 Output output;
128 int bad_last_frame; 132 int bad_last_frame;
129 struct mad_stream stream; 133 struct mad_stream stream;
130 struct mad_frame frame; 134 struct mad_frame frame;
131 struct mad_synth synth; 135 struct mad_synth synth;
132 bool flush; 136 bool flush;
133}; 137};
134 138
135 139
136LibMadPlugin::LibMadPlugin() { 140LibMadPlugin::LibMadPlugin() {
137 d = new LibMadPluginData; 141 d = new LibMadPluginData;
138 d->input.fd = 0; 142 d->input.fd = 0;
139#if defined(HAVE_MMAP) 143#if defined(HAVE_MMAP)
140 d->input.fdm = 0; 144 d->input.fdm = 0;
141#endif 145#endif
142 d->input.data = 0; 146 d->input.data = 0;
143 d->flush = TRUE; 147 d->flush = TRUE;
144 info = tr( "No Song Open" ); 148 info = tr( "No Song Open" );
145} 149}
146 150
147 151
148LibMadPlugin::~LibMadPlugin() { 152LibMadPlugin::~LibMadPlugin() {
149 close(); 153 close();
150 delete d; 154 delete d;
151} 155}
152 156
153 157
154bool LibMadPlugin::isFileSupported( const QString& path ) { 158bool LibMadPlugin::isFileSupported( const QString& path ) {
155 debugMsg( "LibMadPlugin::isFileSupported" ); 159 debugMsg( "LibMadPlugin::isFileSupported" );
156 160
157 // Mpeg file extensions 161 // Mpeg file extensions
158 // "mp2","mp3","m1v","m2v","m2s","mpg","vob","mpeg","ac3" 162 // "mp2","mp3","m1v","m2v","m2s","mpg","vob","mpeg","ac3"
159 // Other media extensions 163 // Other media extensions
160 // "wav","mid","mod","s3m","ogg","avi","mov","sid" 164 // "wav","mid","mod","s3m","ogg","avi","mov","sid"
161 165
162 char *ext = strrchr( path.latin1(), '.' ); 166 char *ext = strrchr( path.latin1(), '.' );
163 167
164 // Test file extension 168 // Test file extension
165 if ( ext ) { 169 if ( ext ) {
166 if ( strncasecmp(ext, ".mp2", 4) == 0 ) 170 if ( strncasecmp(ext, ".mp2", 4) == 0 )
167 return TRUE; 171 return TRUE;
168 if ( strncasecmp(ext, ".mp3", 4) == 0 ) 172 if ( strncasecmp(ext, ".mp3", 4) == 0 )
169 return TRUE; 173 return TRUE;
170 } 174 }
171 // UGLY - just for fast testing 175 // UGLY - just for fast testing
172 if ( path.left(4) == "http") { 176 if ( path.left(4) == "http") {
173 return TRUE; 177 return TRUE;
174 } 178 }
175 179
176 180
177 return FALSE; 181 return FALSE;
178} 182}
179 183
180 184
181int LibMadPlugin::tcp_open(char *address, int port) { 185int LibMadPlugin::tcp_open(char *address, int port) {
182 struct sockaddr_in stAddr; 186 struct sockaddr_in stAddr;
183 struct hostent *host; 187 struct hostent *host;
184 int sock; 188 int sock;
185 struct linger l; 189 struct linger l;
186 190
187 memset(&stAddr, 0, sizeof(stAddr)); 191 memset(&stAddr, 0, sizeof(stAddr));
188 stAddr.sin_family = AF_INET; 192 stAddr.sin_family = AF_INET;
189 stAddr.sin_port = htons(port); 193 stAddr.sin_port = htons(port);
190 194
191 if ((host = gethostbyname(address)) == NULL) 195 if ((host = gethostbyname(address)) == NULL)
192 return (0); 196 return (0);
193 197
194 stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]); 198 stAddr.sin_addr = *((struct in_addr *)host->h_addr_list[0]);
195 199
196 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) 200 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
197 return (0); 201 return (0);
198 202
199 l.l_onoff = 1; 203 l.l_onoff = 1;
200 l.l_linger = 5; 204 l.l_linger = 5;
201 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)
202 return (0); 206 return (0);
203 207
204 if (connect(sock, (struct sockaddr *)&stAddr, sizeof(stAddr)) < 0) 208 if (connect(sock, (struct sockaddr *)&stAddr, sizeof(stAddr)) < 0)
205 return (0); 209 return (0);
206 210
207 return (sock); 211 return (sock);
208} 212}
209 213
210 214
211/** 215/**
212 * Read a http line header. 216 * Read a http line header.
213 * This function read character by character. 217 * This function read character by character.
214 * @param tcp_sock the socket use to read the stream 218 * @param tcp_sock the socket use to read the stream
215 * @param buf a buffer to receive the data 219 * @param buf a buffer to receive the data
216 * @param size size of the buffer 220 * @param size size of the buffer
217 * @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
218 */ 222 */
219int LibMadPlugin::http_read_line(int tcp_sock, char *buf, int size) { 223int LibMadPlugin::http_read_line(int tcp_sock, char *buf, int size) {
220 int offset = 0; 224 int offset = 0;
221 225
222 do 226 do
223 { 227 {
224 if (std::read(tcp_sock, buf + offset, 1) < 0) 228 if (std::read(tcp_sock, buf + offset, 1) < 0)
225 return -1; 229 return -1;
226 if (buf[offset] != '\r') /* Strip \r from answer */ 230 if (buf[offset] != '\r') /* Strip \r from answer */
227 offset++; 231 offset++;
228 } 232 }
229 while (offset < size - 1 && buf[offset - 1] != '\n'); 233 while (offset < size - 1 && buf[offset - 1] != '\n');
230 234
231 buf[offset] = 0; 235 buf[offset] = 0;
232 return offset; 236 return offset;
233} 237}
234 238
235int LibMadPlugin::http_open(const QString& path ) { 239int LibMadPlugin::http_open(const QString& path ) {
240 qDebug("Open http");
236 char *host; 241 char *host;
237 int port; 242 int port;
238 char *request; 243 char *request;
239 int tcp_sock; 244 int tcp_sock;
240 char http_request[PATH_MAX]; 245 char http_request[PATH_MAX];
241 char filename[PATH_MAX]; 246 char filename[PATH_MAX];
242 char c; 247 char c;
243 char *arg =strdup(path.latin1()); 248 char *arg =strdup(path.latin1());
244 249
250 QString errorMsg;
251
245 /* Check for URL syntax */ 252 /* Check for URL syntax */
246 if (strncmp(arg, "http://", strlen("http://"))) 253// if (strncmp(arg, "http://", strlen("http://"))) {
247 return (0); 254// qDebug("Url syntax error");
255// return (0);
256// }
248 257
249 /* Parse URL */ 258 qDebug("Parse URL");
250 port = 80; 259 port = 80;
251 host = arg + strlen("http://"); 260 host = arg + strlen("http://");
252 if ((request = strchr(host, '/')) == NULL) 261 if ((request = strchr(host, '/')) == NULL) {
262 qDebug("Url syntax 2error %s", host);
253 return (0); 263 return (0);
264 }
254 *request++ = 0; 265 *request++ = 0;
255 266
256 if (strchr(host, ':') != NULL) /* port is specified */ 267 if (strchr(host, ':') != NULL) /* port is specified */
257 { 268 {
258 port = atoi(strchr(host, ':') + 1); 269 port = atoi(strchr(host, ':') + 1);
259 *strchr(host, ':') = 0; 270 *strchr(host, ':') = 0;
260 } 271 }
261 272
262 /* Open a TCP socket */ 273 qDebug("Open a TCP socket");
263 if (!(tcp_sock = tcp_open(host, port))) 274 if (!(tcp_sock = tcp_open(host, port))) {
264 { 275 perror("http_open");
265 perror("http_open"); 276 errorMsg="http_open "+(QString)strerror(errno);
277 QMessageBox::message("OPiePlayer",errorMsg);
266 return (0); 278 return (0);
267 } 279 }
268 280
269 snprintf(filename, sizeof(filename) - strlen(host) - 75, "%s", request); 281 snprintf(filename, sizeof(filename) - strlen(host) - 75, "%s", request);
270 282
271 /* Send HTTP GET request */ 283 /* Send HTTP GET request */
272 /* Please don't use a Agent know by shoutcast (Lynx, Mozilla) seems to be reconized and print 284 /* Please don't use a Agent know by shoutcast (Lynx, Mozilla) seems to be reconized and print
273 * a html page and not the stream */ 285 * a html page and not the stream */
274 snprintf(http_request, sizeof(http_request), "GET /%s HTTP/1.0\r\n" 286 snprintf(http_request, sizeof(http_request), "GET /%s HTTP/1.0\r\n"
275/* "User-Agent: Mozilla/2.0 (Win95; I)\r\n" */ 287/* "User-Agent: Mozilla/2.0 (Win95; I)\r\n" */
276 "Pragma: no-cache\r\n" "Host: %s\r\n" "Accept: */*\r\n" "\r\n", filename, host); 288 "Pragma: no-cache\r\n" "Host: %s\r\n" "Accept: */*\r\n" "\r\n", filename, host);
277 289 qDebug("send");
278 send(tcp_sock, http_request, strlen(http_request), 0); 290 send(tcp_sock, http_request, strlen(http_request), 0);
279 291
280 /* Parse server reply */ 292 qDebug("Parse server reply");
281#if 0 293#if 0
294 qDebug("do 0");
282 do 295 do
283 read(tcp_sock, &c, sizeof(char)); 296 read(tcp_sock, &c, sizeof(char));
284 while (c != ' '); 297 while (c != ' ');
285 read(tcp_sock, http_request, 4 * sizeof(char)); 298 read(tcp_sock, http_request, 4 * sizeof(char));
286 http_request[4] = 0; 299 http_request[4] = 0;
287 if (strcmp(http_request, "200 ")) 300 if (strcmp(http_request, "200 "))
288 { 301 {
289 fprintf(stderr, "http_open: "); 302 fprintf(stderr, "http_open: ");
290 do 303 do
291 { 304 {
292 read(tcp_sock, &c, sizeof(char)); 305 read(tcp_sock, &c, sizeof(char));
293 fprintf(stderr, "%c", c); 306 fprintf(stderr, "%c", c);
294 } 307 }
295 while (c != '\r'); 308 while (c != '\r');
296 fprintf(stderr, "\n"); 309 fprintf(stderr, "\n");
297 return (0); 310 return (0);
298 } 311 }
299#endif 312#endif
300 313
301 do 314 do
302 { 315 {
303 int len; 316 int len;
304 317
305 len = http_read_line(tcp_sock, http_request, sizeof(http_request)); 318 len = http_read_line(tcp_sock, http_request, sizeof(http_request));
306 319
307 if (len == -1) 320 if (len == -1)
308 { 321 {
309 fprintf(stderr, "http_open: %s\n", strerror(errno)); 322 fprintf(stderr, "http_open: %s\n", strerror(errno));
310 return 0; 323 return 0;
311 } 324 }
312 325
313 if (strncmp(http_request, "Location:", 9) == 0) 326 if (strncmp(http_request, "Location:", 9) == 0)
314 { 327 {
315 /* redirect */ 328 qDebug("redirect");
316 std::close(tcp_sock); 329 std::close(tcp_sock);
317 330
318 http_request[strlen(http_request) - 1] = '\0'; 331 http_request[strlen(http_request) - 1] = '\0';
319 332
320 return http_open(&http_request[10]); 333 return http_open(&http_request[10]);
321 } 334 }
322 335
323 if (strncmp(http_request, "ICY ", 4) == 0) 336 if (strncmp(http_request, "ICY ", 4) == 0)
324 { 337 {
325 /* This is icecast streaming */ 338 qDebug(" This is icecast streaming");
326 if (strncmp(http_request + 4, "200 ", 4)) 339 if (strncmp(http_request + 4, "200 ", 4))
327 { 340 {
328 fprintf(stderr, "http_open: %s\n", http_request); 341 fprintf(stderr, "http_open: %s\n", http_request);
329 return 0; 342 return 0;
330 } 343 }
331 } 344 }
332 else if (strncmp(http_request, "icy-", 4) == 0) 345 else if (strncmp(http_request, "icy-", 4) == 0)
333 { 346 {
334 /* we can have: icy-noticeX, icy-name, icy-genre, icy-url, icy-pub, icy-metaint, icy-br */ 347 /* we can have: icy-noticeX, icy-name, icy-genre, icy-url, icy-pub, icy-metaint, icy-br */
335 /* Don't print these - mpg123 doesn't */ 348 /* Don't print these - mpg123 doesn't */
336 /* fprintf(stderr,"%s\n",http_request); */ 349 /* fprintf(stderr,"%s\n",http_request); */
337 } 350 }
338 } 351 }
339 while (strcmp(http_request, "\n") != 0); 352 while (strcmp(http_request, "\n") != 0);
340 353
341 return (tcp_sock); 354 return (tcp_sock);
342} 355}
343 356
344 357
345bool LibMadPlugin::open( const QString& path ) { 358bool LibMadPlugin::open( const QString& path ) {
346 debugMsg( "LibMadPlugin::open" ); 359 debugMsg( "LibMadPlugin::open" );
347 Config cfg("OpiePlayer"); 360 Config cfg("OpiePlayer");
348 cfg.setGroup("Options"); 361 cfg.setGroup("Options");
349 bufferSize = cfg.readNumEntry("MPeg_BufferSize",MPEG_BUFFER_SIZE); 362 bufferSize = cfg.readNumEntry("MPeg_BufferSize",MPEG_BUFFER_SIZE);
350 qDebug("buffer size is %d", bufferSize); 363 qDebug("buffer size is %d", bufferSize);
351 d->bad_last_frame = 0; 364 d->bad_last_frame = 0;
352 d->flush = TRUE; 365 d->flush = TRUE;
353 info = QString( "" ); 366 info = QString( "" );
354 367
355 //qDebug( "Opening %s", path.latin1() ); 368 qDebug( "Opening %s", path.latin1() );
356
357 369
370 bool isStream=FALSE;
358 if (path.left( 4 ) == "http" ) { 371 if (path.left( 4 ) == "http" ) {
359 d->input.fd = http_open(path); 372 d->input.fd = http_open(path);
373 if(d->input.fd == 0) {
374 qDebug("http_open error");
375 }
376 isStream=TRUE;
377 qDebug("Opened ok");
360 378
361 } else { 379 } else {
362 d->input.path = path.latin1(); 380 d->input.path = path.latin1();
363 d->input.fd = ::open( d->input.path, O_RDONLY ); 381 d->input.fd = ::open( d->input.path, O_RDONLY );
364 } 382 }
365 if (d->input.fd == -1) { 383 if (d->input.fd == -1) {
366 qDebug("error opening %s", d->input.path ); 384 qDebug("error opening %s", d->input.path );
367 return FALSE; 385 return FALSE;
368 } 386 }
369 387 if(!isStream) {
370 printID3Tags(); 388 qDebug("Print ID#tags");
389 printID3Tags();
390 }
371 391
372#if defined(HAVE_MMAP) 392#if defined(HAVE_MMAP)
373 struct stat stat; 393 struct stat stat;
374 if (fstat(d->input.fd, &stat) == -1) { 394 if (fstat(d->input.fd, &stat) == -1) {
375 qDebug("error calling fstat"); return FALSE; 395 qDebug("error calling fstat"); return FALSE;
376 } 396 }
377 if (S_ISREG(stat.st_mode) && stat.st_size > 0) { 397 if (S_ISREG(stat.st_mode) && stat.st_size > 0) {
378 d->input.length = stat.st_size; 398 d->input.length = stat.st_size;
379 d->input.fdm = map_file(d->input.fd, &d->input.length); 399 d->input.fdm = map_file(d->input.fd, &d->input.length);
380 if (d->input.fdm == 0) { 400 if (d->input.fdm == 0) {
381 qDebug("error mmapping file"); return FALSE; 401 qDebug("error mmapping file"); return FALSE;
382 } 402 }
383 d->input.data = (unsigned char *)d->input.fdm; 403 d->input.data = (unsigned char *)d->input.fdm;
384 } 404 }
385#endif 405#endif
386 406
387 if (d->input.data == 0) { 407 if (d->input.data == 0) {
388 d->input.data = (unsigned char *)malloc( bufferSize /*MPEG_BUFFER_SIZE*/); 408 d->input.data = (unsigned char *)malloc( bufferSize /*MPEG_BUFFER_SIZE*/);
389 if (d->input.data == 0) { 409 if (d->input.data == 0) {
390 qDebug("error allocating input buffer"); 410 qDebug("error allocating input buffer");
391 return FALSE; 411 return FALSE;
392 } 412 }
393 d->input.length = 0; 413 d->input.length = 0;
394 } 414 }
395 415
396 d->input.eof = 0; 416 d->input.eof = 0;
397 417
418qDebug("about to mad_stream");
398 mad_stream_init(&d->stream); 419 mad_stream_init(&d->stream);
420qDebug("mad_frame");
399 mad_frame_init(&d->frame); 421 mad_frame_init(&d->frame);
422qDebug("mad_synth");
400 mad_synth_init(&d->synth); 423 mad_synth_init(&d->synth);
401 424
402 return TRUE; 425 return TRUE;
403} 426}
404 427
405 428
406bool LibMadPlugin::close() { 429bool LibMadPlugin::close() {
407 debugMsg( "LibMadPlugin::close" ); 430 debugMsg( "LibMadPlugin::close" );
408 431
409 int result = TRUE; 432 int result = TRUE;
410 433
411 mad_synth_finish(&d->synth); 434 mad_synth_finish(&d->synth);
412 mad_frame_finish(&d->frame); 435 mad_frame_finish(&d->frame);
413 mad_stream_finish(&d->stream); 436 mad_stream_finish(&d->stream);
414 437
415#if defined(HAVE_MMAP) 438#if defined(HAVE_MMAP)
416 if (d->input.fdm) { 439 if (d->input.fdm) {
417 if (unmap_file(d->input.fdm, d->input.length) == -1) { 440 if (unmap_file(d->input.fdm, d->input.length) == -1) {
418 qDebug("error munmapping file"); 441 qDebug("error munmapping file");
419 result = FALSE; 442 result = FALSE;
420 } 443 }
421 d->input.fdm = 0; 444 d->input.fdm = 0;
422 d->input.data = 0; 445 d->input.data = 0;
423 } 446 }
424#endif 447#endif
425 448
426 if (d->input.data) { 449 if (d->input.data) {
427 free(d->input.data); 450 free(d->input.data);
428 d->input.data = 0; 451 d->input.data = 0;
429 } 452 }
430 453
431 if (::close(d->input.fd) == -1) { 454 if (::close(d->input.fd) == -1) {
432 qDebug("error closing file %s", d->input.path); 455 qDebug("error closing file %s", d->input.path);
433 result = FALSE; 456 result = FALSE;
434 } 457 }
435 458
436 d->input.fd = 0; 459 d->input.fd = 0;
437 460
438 return result; 461 return result;
439} 462}
440 463
441 464
442bool LibMadPlugin::isOpen() { 465bool LibMadPlugin::isOpen() {
443 debugMsg( "LibMadPlugin::isOpen" ); 466 debugMsg( "LibMadPlugin::isOpen" );
444 return ( d->input.fd != 0 ); 467 return ( d->input.fd != 0 );
445} 468}
446 469
447 470
448int LibMadPlugin::audioStreams() { 471int LibMadPlugin::audioStreams() {
449 debugMsg( "LibMadPlugin::audioStreams" ); 472 debugMsg( "LibMadPlugin::audioStreams" );
450 return 1; 473 return 1;
451} 474}
452 475
453 476
454int LibMadPlugin::audioChannels( int ) { 477int LibMadPlugin::audioChannels( int ) {
455 debugMsg( "LibMadPlugin::audioChannels" ); 478 debugMsg( "LibMadPlugin::audioChannels" );
456/* 479/*
457 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); 480 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 );
458 qDebug( "LibMadPlugin::audioChannels: %i", d->frame.header.mode > 0 ? 2 : 1 ); 481 qDebug( "LibMadPlugin::audioChannels: %i", d->frame.header.mode > 0 ? 2 : 1 );
459 return d->frame.header.mode > 0 ? 2 : 1; 482 return d->frame.header.mode > 0 ? 2 : 1;
460*/ 483*/
461 return 2; 484 return 2;
462} 485}
463 486
464 487
465int LibMadPlugin::audioFrequency( int ) { 488int LibMadPlugin::audioFrequency( int ) {
466 debugMsg( "LibMadPlugin::audioFrequency" ); 489 debugMsg( "LibMadPlugin::audioFrequency" );
467 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); 490 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 );
468 qDebug( "LibMadPlugin::audioFrequency: %i", d->frame.header.samplerate ); 491 qDebug( "LibMadPlugin::audioFrequency: %i", d->frame.header.samplerate );
469 return d->frame.header.samplerate; 492 return d->frame.header.samplerate;
470} 493}
471 494
472 495
473int LibMadPlugin::audioSamples( int ) { 496int LibMadPlugin::audioSamples( int ) {
474 debugMsg( "LibMadPlugin::audioSamples" ); 497 debugMsg( "LibMadPlugin::audioSamples" );
475/* 498/*
476 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); 499 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 );
477 mad_header_decode( (struct mad_header *)&d->frame.header, &d->stream ); 500 mad_header_decode( (struct mad_header *)&d->frame.header, &d->stream );
478 qDebug( "LibMadPlugin::audioSamples: %i*%i", d->frame.header.duration.seconds, d->frame.header.samplerate ); 501 qDebug( "LibMadPlugin::audioSamples: %i*%i", d->frame.header.duration.seconds, d->frame.header.samplerate );
479 return d->frame.header.duration.seconds * d->frame.header.samplerate; 502 return d->frame.header.duration.seconds * d->frame.header.samplerate;
480*/ 503*/
481 return 10000000; 504 return 10000000;
482} 505}
483 506
484 507
485bool LibMadPlugin::audioSetSample( long, int ) { 508bool LibMadPlugin::audioSetSample( long, int ) {
486 debugMsg( "LibMadPlugin::audioSetSample" ); 509 debugMsg( "LibMadPlugin::audioSetSample" );
487 return FALSE; 510 return FALSE;
488} 511}
489 512
490 513
491long LibMadPlugin::audioGetSample( int ) { 514long LibMadPlugin::audioGetSample( int ) {
492 debugMsg( "LibMadPlugin::audioGetSample" ); 515 debugMsg( "LibMadPlugin::audioGetSample" );
493 return 0; 516 return 0;
494} 517}
495 518
496/* 519/*
497bool LibMadPlugin::audioReadSamples( short *, int, long, int ) { 520bool LibMadPlugin::audioReadSamples( short *, int, long, int ) {
498 debugMsg( "LibMadPlugin::audioReadSamples" ); 521 debugMsg( "LibMadPlugin::audioReadSamples" );
499 return FALSE; 522 return FALSE;
500} 523}
501 524
502 525
503bool LibMadPlugin::audioReReadSamples( short *, int, long, int ) { 526bool LibMadPlugin::audioReReadSamples( short *, int, long, int ) {
504 debugMsg( "LibMadPlugin::audioReReadSamples" ); 527 debugMsg( "LibMadPlugin::audioReReadSamples" );
505 return FALSE; 528 return FALSE;
506} 529}
507*/ 530*/
508 531
509bool LibMadPlugin::read() { 532bool LibMadPlugin::read() {
510 debugMsg( "LibMadPlugin::read" ); 533 debugMsg( "LibMadPlugin::read" );
511 int len; 534 int len;
512 535
513 if (d->input.eof) 536 if (d->input.eof)
514 return FALSE; 537 return FALSE;
515 538
516#if defined(HAVE_MMAP) 539#if defined(HAVE_MMAP)
517 if (d->input.fdm) { 540 if (d->input.fdm) {
518 unsigned long skip = 0; 541 unsigned long skip = 0;
519 542
520 if (d->stream.next_frame) { 543 if (d->stream.next_frame) {
521 struct stat stat; 544 struct stat stat;
522 545
523 if (fstat(d->input.fd, &stat) == -1) 546 if (fstat(d->input.fd, &stat) == -1)
524 return FALSE; 547 return FALSE;
525 548
526 if (stat.st_size + MAD_BUFFER_GUARD <= (signed)d->input.length) 549 if (stat.st_size + MAD_BUFFER_GUARD <= (signed)d->input.length)
527 return FALSE; 550 return FALSE;
528 551
529 // file size changed; update memory map 552 // file size changed; update memory map
530 skip = d->stream.next_frame - d->input.data; 553 skip = d->stream.next_frame - d->input.data;
531 554
532 if (unmap_file(d->input.fdm, d->input.length) == -1) { 555 if (unmap_file(d->input.fdm, d->input.length) == -1) {
533 d->input.fdm = 0; 556 d->input.fdm = 0;
534 d->input.data = 0; 557 d->input.data = 0;
535 return FALSE; 558 return FALSE;
536 } 559 }
537 560
538 d->input.length = stat.st_size; 561 d->input.length = stat.st_size;
539 562
540 d->input.fdm = map_file(d->input.fd, &d->input.length); 563 d->input.fdm = map_file(d->input.fd, &d->input.length);
541 if (d->input.fdm == 0) { 564 if (d->input.fdm == 0) {
542 d->input.data = 0; 565 d->input.data = 0;
543 return FALSE; 566 return FALSE;
544 } 567 }
545 568
546 d->input.data = (unsigned char *)d->input.fdm; 569 d->input.data = (unsigned char *)d->input.fdm;
547 } 570 }
548 571
549 mad_stream_buffer(&d->stream, d->input.data + skip, d->input.length - skip); 572 mad_stream_buffer(&d->stream, d->input.data + skip, d->input.length - skip);
550 573
551 } else 574 } else
552#endif 575#endif
553 { 576 {
554 if (d->stream.next_frame) { 577 if (d->stream.next_frame) {
555 memmove(d->input.data, d->stream.next_frame, 578 memmove(d->input.data, d->stream.next_frame,
556 d->input.length = &d->input.data[d->input.length] - d->stream.next_frame); 579 d->input.length = &d->input.data[d->input.length] - d->stream.next_frame);
557 } 580 }
558 581
559 do { 582 do {
560 len = ::read(d->input.fd, d->input.data + d->input.length, bufferSize /* MPEG_BUFFER_SIZE*/ - d->input.length); 583 len = ::read(d->input.fd, d->input.data + d->input.length, bufferSize /* MPEG_BUFFER_SIZE*/ - d->input.length);
561 } 584 }
562 while (len == -1 && errno == EINTR); 585 while (len == -1 && errno == EINTR);
563 586
564 if (len == -1) { 587 if (len == -1) {
565 qDebug("error reading audio"); 588 qDebug("error reading audio");
566 return FALSE; 589 return FALSE;
567 } 590 }
568 else if (len == 0) { 591 else if (len == 0) {
569 d->input.eof = 1; 592 d->input.eof = 1;
570 593
571 assert(bufferSize /*MPEG_BUFFER_SIZE*/ - d->input.length >= MAD_BUFFER_GUARD); 594 assert(bufferSize /*MPEG_BUFFER_SIZE*/ - d->input.length >= MAD_BUFFER_GUARD);
572 595
573 while (len < MAD_BUFFER_GUARD) 596 while (len < MAD_BUFFER_GUARD)
574 d->input.data[d->input.length + len++] = 0; 597 d->input.data[d->input.length + len++] = 0;
575 } 598 }
576 599
577 mad_stream_buffer(&d->stream, d->input.data, d->input.length += len); 600 mad_stream_buffer(&d->stream, d->input.data, d->input.length += len);
578 } 601 }
579 602
580 return TRUE; 603 return TRUE;
581} 604}
582 605
583 606
584static mad_fixed_t left_err, right_err; 607static mad_fixed_t left_err, right_err;
585static const int bits = 16; 608static const int bits = 16;
586static const int shift = MAD_F_FRACBITS + 1 - bits; 609static const int shift = MAD_F_FRACBITS + 1 - bits;
587 610
588 611
589inline long audio_linear_dither( mad_fixed_t sample, mad_fixed_t& error ) 612inline long audio_linear_dither( mad_fixed_t sample, mad_fixed_t& error )
590{ 613{
591 sample += error; 614 sample += error;