summaryrefslogtreecommitdiff
authorbipolar <bipolar>2002-02-01 18:41:28 (UTC)
committer bipolar <bipolar>2002-02-01 18:41:28 (UTC)
commit190a0111ccd874923bf88dac938531a18f52e698 (patch) (unidiff)
tree422dcb8c17724eb061624f442f0fa6a3116d789b
parent9a8990097aa35d28a9c758f730c5c8b5fa59560a (diff)
downloadopie-190a0111ccd874923bf88dac938531a18f52e698.zip
opie-190a0111ccd874923bf88dac938531a18f52e698.tar.gz
opie-190a0111ccd874923bf88dac938531a18f52e698.tar.bz2
Mediaplayer hang fix
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/libmad/libmadplugin.cpp8
-rw-r--r--core/multimedia/opieplayer/loopcontrol.cpp4
-rw-r--r--core/multimedia/opieplayer/wavplugin/wavplugin.cpp2
3 files changed, 7 insertions, 7 deletions
diff --git a/core/multimedia/opieplayer/libmad/libmadplugin.cpp b/core/multimedia/opieplayer/libmad/libmadplugin.cpp
index b2b876f..9d04f7e 100644
--- a/core/multimedia/opieplayer/libmad/libmadplugin.cpp
+++ b/core/multimedia/opieplayer/libmad/libmadplugin.cpp
@@ -1,578 +1,578 @@
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 <stdio.h> 20#include <stdio.h>
21#include <stdarg.h> 21#include <stdarg.h>
22#include <stdlib.h> 22#include <stdlib.h>
23#include <sys/types.h> 23#include <sys/types.h>
24#include <sys/stat.h> 24#include <sys/stat.h>
25#include <fcntl.h> 25#include <fcntl.h>
26#include <unistd.h> 26#include <unistd.h>
27#include <string.h> 27#include <string.h>
28#include <ctype.h> 28#include <ctype.h>
29#include <errno.h> 29#include <errno.h>
30#include <time.h> 30#include <time.h>
31#include <locale.h> 31#include <locale.h>
32#include <math.h> 32#include <math.h>
33#include <assert.h> 33#include <assert.h>
34#include <qapplication.h> 34#include <qapplication.h>
35 35
36//#define HAVE_MMAP 36//#define HAVE_MMAP
37 37
38#if defined(HAVE_MMAP) 38#if defined(HAVE_MMAP)
39# include <sys/mman.h> 39# include <sys/mman.h>
40#endif 40#endif
41#include "libmadplugin.h" 41#include "libmadplugin.h"
42 42
43 43
44extern "C" { 44extern "C" {
45#include "mad.h" 45#include "mad.h"
46} 46}
47 47
48 48
49#define MPEG_BUFFER_SIZE 65536 49#define MPEG_BUFFER_SIZE 65536
50 //#define debugMsg(a) qDebug(a) 50 //#define debugMsg(a) qDebug(a)
51#define debugMsg(a) 51#define debugMsg(a)
52 52
53 53
54class Input { 54class Input {
55public: 55public:
56 char const *path; 56 char const *path;
57 int fd; 57 int fd;
58#if defined(HAVE_MMAP) 58#if defined(HAVE_MMAP)
59 void *fdm; 59 void *fdm;
60#endif 60#endif
61 unsigned char *data; 61 unsigned char *data;
62 unsigned long length; 62 unsigned long length;
63 int eof; 63 int eof;
64}; 64};
65 65
66 66
67class Output { 67class Output {
68public: 68public:
69 mad_fixed_t attenuate; 69 mad_fixed_t attenuate;
70 struct filter *filters; 70 struct filter *filters;
71 unsigned int channels_in; 71 unsigned int channels_in;
72 unsigned int channels_out; 72 unsigned int channels_out;
73 unsigned int speed_in; 73 unsigned int speed_in;
74 unsigned int speed_out; 74 unsigned int speed_out;
75 const char *path; 75 const char *path;
76}; 76};
77 77
78 78
79# if defined(HAVE_MMAP) 79# if defined(HAVE_MMAP)
80static void *map_file(int fd, unsigned long *length) 80static void *map_file(int fd, unsigned long *length)
81{ 81{
82 void *fdm; 82 void *fdm;
83 83
84 *length += MAD_BUFFER_GUARD; 84 *length += MAD_BUFFER_GUARD;
85 85
86 fdm = mmap(0, *length, PROT_READ, MAP_SHARED, fd, 0); 86 fdm = mmap(0, *length, PROT_READ, MAP_SHARED, fd, 0);
87 if (fdm == MAP_FAILED) 87 if (fdm == MAP_FAILED)
88 return 0; 88 return 0;
89 89
90# if defined(HAVE_MADVISE) 90# if defined(HAVE_MADVISE)
91 madvise(fdm, *length, MADV_SEQUENTIAL); 91 madvise(fdm, *length, MADV_SEQUENTIAL);
92# endif 92# endif
93 93
94 return fdm; 94 return fdm;
95} 95}
96 96
97 97
98static int unmap_file(void *fdm, unsigned long length) 98static int unmap_file(void *fdm, unsigned long length)
99{ 99{
100 if (munmap(fdm, length) == -1) 100 if (munmap(fdm, length) == -1)
101 return -1; 101 return -1;
102 102
103 return 0; 103 return 0;
104} 104}
105# endif 105# endif
106 106
107 107
108static inline QString tr( const char *str ) { 108static inline QString tr( const char *str ) {
109 // Apparently this is okay from a plugin as it runs in the process space of the owner of the plugin 109 // Apparently this is okay from a plugin as it runs in the process space of the owner of the plugin
110 return qApp->translate( "MediaPlayer", str, "libmad strings for mp3 file info" ); 110 return qApp->translate( "MediaPlayer", str, "libmad strings for mp3 file info" );
111} 111}
112 112
113 113
114class LibMadPluginData { 114class LibMadPluginData {
115public: 115public:
116 Input input; 116 Input input;
117 Output output; 117 Output output;
118 int bad_last_frame; 118 int bad_last_frame;
119 struct mad_stream stream; 119 struct mad_stream stream;
120 struct mad_frame frame; 120 struct mad_frame frame;
121 struct mad_synth synth; 121 struct mad_synth synth;
122 bool flush; 122 bool flush;
123}; 123};
124 124
125 125
126LibMadPlugin::LibMadPlugin() { 126LibMadPlugin::LibMadPlugin() {
127 d = new LibMadPluginData; 127 d = new LibMadPluginData;
128 d->input.fd = 0; 128 d->input.fd = 0;
129#if defined(HAVE_MMAP) 129#if defined(HAVE_MMAP)
130 d->input.fdm = 0; 130 d->input.fdm = 0;
131#endif 131#endif
132 d->input.data = 0; 132 d->input.data = 0;
133 d->flush = TRUE; 133 d->flush = TRUE;
134 info = tr( "No Song Open" ); 134 info = tr( "No Song Open" );
135} 135}
136 136
137 137
138LibMadPlugin::~LibMadPlugin() { 138LibMadPlugin::~LibMadPlugin() {
139 close(); 139 close();
140 delete d; 140 delete d;
141} 141}
142 142
143 143
144bool LibMadPlugin::isFileSupported( const QString& path ) { 144bool LibMadPlugin::isFileSupported( const QString& path ) {
145 debugMsg( "LibMadPlugin::isFileSupported" ); 145 debugMsg( "LibMadPlugin::isFileSupported" );
146 146
147 // Mpeg file extensions 147 // Mpeg file extensions
148 //"mp2","mp3","m1v","m2v","m2s","mpg","vob","mpeg","ac3" 148 //"mp2","mp3","m1v","m2v","m2s","mpg","vob","mpeg","ac3"
149 // Other media extensions 149 // Other media extensions
150 // "wav","mid","mod","s3m","ogg","avi","mov","sid" 150 // "wav","mid","mod","s3m","ogg","avi","mov","sid"
151 151
152 char *ext = strrchr( path.latin1(), '.' ); 152 char *ext = strrchr( path.latin1(), '.' );
153 153
154 // Test file extension 154 // Test file extension
155 if ( ext ) { 155 if ( ext ) {
156 if ( strncasecmp(ext, ".mp2", 4) == 0 ) 156 if ( strncasecmp(ext, ".mp2", 4) == 0 )
157 return TRUE; 157 return TRUE;
158 if ( strncasecmp(ext, ".mp3", 4) == 0 ) 158 if ( strncasecmp(ext, ".mp3", 4) == 0 )
159 return TRUE; 159 return TRUE;
160 } 160 }
161 161
162 return FALSE; 162 return FALSE;
163} 163}
164 164
165 165
166bool LibMadPlugin::open( const QString& path ) { 166bool LibMadPlugin::open( const QString& path ) {
167 debugMsg( "LibMadPlugin::open" ); 167 debugMsg( "LibMadPlugin::open" );
168 168
169 d->bad_last_frame = 0; 169 d->bad_last_frame = 0;
170 d->flush = TRUE; 170 d->flush = TRUE;
171 info = QString( "" ); 171 info = QString( "" );
172 172
173 //qDebug( "Opening %s", path.latin1() ); 173 //qDebug( "Opening %s", path.latin1() );
174 174
175 d->input.path = path.latin1(); 175 d->input.path = path.latin1();
176 d->input.fd = ::open( d->input.path, O_RDONLY ); 176 d->input.fd = ::open( d->input.path, O_RDONLY );
177 if (d->input.fd == -1) { 177 if (d->input.fd == -1) {
178 qDebug("error opening %s", d->input.path ); 178 qDebug("error opening %s", d->input.path );
179 return FALSE; 179 return FALSE;
180 } 180 }
181 181
182 printID3Tags(); 182 printID3Tags();
183 183
184#if defined(HAVE_MMAP) 184#if defined(HAVE_MMAP)
185 struct stat stat; 185 struct stat stat;
186 if (fstat(d->input.fd, &stat) == -1) { 186 if (fstat(d->input.fd, &stat) == -1) {
187 qDebug("error calling fstat"); return FALSE; 187 qDebug("error calling fstat"); return FALSE;
188 } 188 }
189 if (S_ISREG(stat.st_mode) && stat.st_size > 0) { 189 if (S_ISREG(stat.st_mode) && stat.st_size > 0) {
190 d->input.length = stat.st_size; 190 d->input.length = stat.st_size;
191 d->input.fdm = map_file(d->input.fd, &d->input.length); 191 d->input.fdm = map_file(d->input.fd, &d->input.length);
192 if (d->input.fdm == 0) { 192 if (d->input.fdm == 0) {
193 qDebug("error mmapping file"); return FALSE; 193 qDebug("error mmapping file"); return FALSE;
194 } 194 }
195 d->input.data = (unsigned char *)d->input.fdm; 195 d->input.data = (unsigned char *)d->input.fdm;
196 } 196 }
197#endif 197#endif
198 198
199 if (d->input.data == 0) { 199 if (d->input.data == 0) {
200 d->input.data = (unsigned char *)malloc(MPEG_BUFFER_SIZE); 200 d->input.data = (unsigned char *)malloc(MPEG_BUFFER_SIZE);
201 if (d->input.data == 0) { 201 if (d->input.data == 0) {
202 qDebug("error allocating input buffer"); 202 qDebug("error allocating input buffer");
203 return FALSE; 203 return FALSE;
204 } 204 }
205 d->input.length = 0; 205 d->input.length = 0;
206 } 206 }
207 207
208 d->input.eof = 0; 208 d->input.eof = 0;
209 209
210 mad_stream_init(&d->stream); 210 mad_stream_init(&d->stream);
211 mad_frame_init(&d->frame); 211 mad_frame_init(&d->frame);
212 mad_synth_init(&d->synth); 212 mad_synth_init(&d->synth);
213 213
214 return TRUE; 214 return TRUE;
215} 215}
216 216
217 217
218bool LibMadPlugin::close() { 218bool LibMadPlugin::close() {
219 debugMsg( "LibMadPlugin::close" ); 219 debugMsg( "LibMadPlugin::close" );
220 220
221 int result = TRUE; 221 int result = TRUE;
222 222
223 mad_synth_finish(&d->synth); 223 mad_synth_finish(&d->synth);
224 mad_frame_finish(&d->frame); 224 mad_frame_finish(&d->frame);
225 mad_stream_finish(&d->stream); 225 mad_stream_finish(&d->stream);
226 226
227#if defined(HAVE_MMAP) 227#if defined(HAVE_MMAP)
228 if (d->input.fdm) { 228 if (d->input.fdm) {
229 if (unmap_file(d->input.fdm, d->input.length) == -1) { 229 if (unmap_file(d->input.fdm, d->input.length) == -1) {
230 qDebug("error munmapping file"); 230 qDebug("error munmapping file");
231 result = FALSE; 231 result = FALSE;
232 } 232 }
233 d->input.fdm = 0; 233 d->input.fdm = 0;
234 d->input.data = 0; 234 d->input.data = 0;
235 } 235 }
236#endif 236#endif
237 237
238 if (d->input.data) { 238 if (d->input.data) {
239 free(d->input.data); 239 free(d->input.data);
240 d->input.data = 0; 240 d->input.data = 0;
241 } 241 }
242 242
243 if (::close(d->input.fd) == -1) { 243 if (::close(d->input.fd) == -1) {
244 qDebug("error closing file %s", d->input.path); 244 qDebug("error closing file %s", d->input.path);
245 result = FALSE; 245 result = FALSE;
246 } 246 }
247 247
248 d->input.fd = 0; 248 d->input.fd = 0;
249 249
250 return result; 250 return result;
251} 251}
252 252
253 253
254bool LibMadPlugin::isOpen() { 254bool LibMadPlugin::isOpen() {
255 debugMsg( "LibMadPlugin::isOpen" ); 255 debugMsg( "LibMadPlugin::isOpen" );
256 return ( d->input.fd != 0 ); 256 return ( d->input.fd != 0 );
257} 257}
258 258
259 259
260int LibMadPlugin::audioStreams() { 260int LibMadPlugin::audioStreams() {
261 debugMsg( "LibMadPlugin::audioStreams" ); 261 debugMsg( "LibMadPlugin::audioStreams" );
262 return 1; 262 return 1;
263} 263}
264 264
265 265
266int LibMadPlugin::audioChannels( int ) { 266int LibMadPlugin::audioChannels( int ) {
267 debugMsg( "LibMadPlugin::audioChannels" ); 267 debugMsg( "LibMadPlugin::audioChannels" );
268/* 268/*
269 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); 269 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 );
270 qDebug( "LibMadPlugin::audioChannels: %i", d->frame.header.mode > 0 ? 2 : 1 ); 270 qDebug( "LibMadPlugin::audioChannels: %i", d->frame.header.mode > 0 ? 2 : 1 );
271 return d->frame.header.mode > 0 ? 2 : 1; 271 return d->frame.header.mode > 0 ? 2 : 1;
272*/ 272*/
273 return 2; 273 return 2;
274} 274}
275 275
276 276
277int LibMadPlugin::audioFrequency( int ) { 277int LibMadPlugin::audioFrequency( int ) {
278 debugMsg( "LibMadPlugin::audioFrequency" ); 278 debugMsg( "LibMadPlugin::audioFrequency" );
279 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); 279 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 );
280 qDebug( "LibMadPlugin::audioFrequency: %i", d->frame.header.samplerate ); 280 qDebug( "LibMadPlugin::audioFrequency: %i", d->frame.header.samplerate );
281 return d->frame.header.samplerate; 281 return d->frame.header.samplerate;
282} 282}
283 283
284 284
285int LibMadPlugin::audioSamples( int ) { 285int LibMadPlugin::audioSamples( int ) {
286 debugMsg( "LibMadPlugin::audioSamples" ); 286 debugMsg( "LibMadPlugin::audioSamples" );
287/* 287/*
288 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 ); 288 long t; short t1[5]; audioReadSamples( t1, 2, 1, t, 0 );
289 mad_header_decode( (struct mad_header *)&d->frame.header, &d->stream ); 289 mad_header_decode( (struct mad_header *)&d->frame.header, &d->stream );
290 qDebug( "LibMadPlugin::audioSamples: %i*%i", d->frame.header.duration.seconds, d->frame.header.samplerate ); 290 qDebug( "LibMadPlugin::audioSamples: %i*%i", d->frame.header.duration.seconds, d->frame.header.samplerate );
291 return d->frame.header.duration.seconds * d->frame.header.samplerate; 291 return d->frame.header.duration.seconds * d->frame.header.samplerate;
292*/ 292*/
293 return 10000000; 293 return 10000000;
294} 294}
295 295
296 296
297bool LibMadPlugin::audioSetSample( long, int ) { 297bool LibMadPlugin::audioSetSample( long, int ) {
298 debugMsg( "LibMadPlugin::audioSetSample" ); 298 debugMsg( "LibMadPlugin::audioSetSample" );
299 return FALSE; 299 return FALSE;
300} 300}
301 301
302 302
303long LibMadPlugin::audioGetSample( int ) { 303long LibMadPlugin::audioGetSample( int ) {
304 debugMsg( "LibMadPlugin::audioGetSample" ); 304 debugMsg( "LibMadPlugin::audioGetSample" );
305 return 0; 305 return 0;
306} 306}
307 307
308/* 308/*
309bool LibMadPlugin::audioReadSamples( short *, int, long, int ) { 309bool LibMadPlugin::audioReadSamples( short *, int, long, int ) {
310 debugMsg( "LibMadPlugin::audioReadSamples" ); 310 debugMsg( "LibMadPlugin::audioReadSamples" );
311 return FALSE; 311 return FALSE;
312} 312}
313 313
314 314
315bool LibMadPlugin::audioReReadSamples( short *, int, long, int ) { 315bool LibMadPlugin::audioReReadSamples( short *, int, long, int ) {
316 debugMsg( "LibMadPlugin::audioReReadSamples" ); 316 debugMsg( "LibMadPlugin::audioReReadSamples" );
317 return FALSE; 317 return FALSE;
318} 318}
319*/ 319*/
320 320
321bool LibMadPlugin::read() { 321bool LibMadPlugin::read() {
322 debugMsg( "LibMadPlugin::read" ); 322 debugMsg( "LibMadPlugin::read" );
323 int len; 323 int len;
324 324
325 if (d->input.eof) 325 if (d->input.eof)
326 return FALSE; 326 return FALSE;
327 327
328#if defined(HAVE_MMAP) 328#if defined(HAVE_MMAP)
329 if (d->input.fdm) { 329 if (d->input.fdm) {
330 unsigned long skip = 0; 330 unsigned long skip = 0;
331 331
332 if (d->stream.next_frame) { 332 if (d->stream.next_frame) {
333 struct stat stat; 333 struct stat stat;
334 334
335 if (fstat(d->input.fd, &stat) == -1) 335 if (fstat(d->input.fd, &stat) == -1)
336 return FALSE; 336 return FALSE;
337 337
338 if (stat.st_size + MAD_BUFFER_GUARD <= (signed)d->input.length) 338 if (stat.st_size + MAD_BUFFER_GUARD <= (signed)d->input.length)
339 return FALSE; 339 return FALSE;
340 340
341 // file size changed; update memory map 341 // file size changed; update memory map
342 skip = d->stream.next_frame - d->input.data; 342 skip = d->stream.next_frame - d->input.data;
343 343
344 if (unmap_file(d->input.fdm, d->input.length) == -1) { 344 if (unmap_file(d->input.fdm, d->input.length) == -1) {
345 d->input.fdm = 0; 345 d->input.fdm = 0;
346 d->input.data = 0; 346 d->input.data = 0;
347 return FALSE; 347 return FALSE;
348 } 348 }
349 349
350 d->input.length = stat.st_size; 350 d->input.length = stat.st_size;
351 351
352 d->input.fdm = map_file(d->input.fd, &d->input.length); 352 d->input.fdm = map_file(d->input.fd, &d->input.length);
353 if (d->input.fdm == 0) { 353 if (d->input.fdm == 0) {
354 d->input.data = 0; 354 d->input.data = 0;
355 return FALSE; 355 return FALSE;
356 } 356 }
357 357
358 d->input.data = (unsigned char *)d->input.fdm; 358 d->input.data = (unsigned char *)d->input.fdm;
359 } 359 }
360 360
361 mad_stream_buffer(&d->stream, d->input.data + skip, d->input.length - skip); 361 mad_stream_buffer(&d->stream, d->input.data + skip, d->input.length - skip);
362 362
363 } else 363 } else
364#endif 364#endif
365 { 365 {
366 if (d->stream.next_frame) { 366 if (d->stream.next_frame) {
367 memmove(d->input.data, d->stream.next_frame, 367 memmove(d->input.data, d->stream.next_frame,
368 d->input.length = &d->input.data[d->input.length] - d->stream.next_frame); 368 d->input.length = &d->input.data[d->input.length] - d->stream.next_frame);
369 } 369 }
370 370
371 do { 371 do {
372 len = ::read(d->input.fd, d->input.data + d->input.length, MPEG_BUFFER_SIZE - d->input.length); 372 len = ::read(d->input.fd, d->input.data + d->input.length, MPEG_BUFFER_SIZE - d->input.length);
373 } 373 }
374 while (len == -1 && errno == EINTR); 374 while (len == -1 && errno == EINTR);
375 375
376 if (len == -1) { 376 if (len == -1) {
377 qDebug("error reading audio"); 377 qDebug("error reading audio");
378 return FALSE; 378 return FALSE;
379 } 379 }
380 else if (len == 0) { 380 else if (len == 0) {
381 d->input.eof = 1; 381 d->input.eof = 1;
382 382
383 assert(MPEG_BUFFER_SIZE - d->input.length >= MAD_BUFFER_GUARD); 383 assert(MPEG_BUFFER_SIZE - d->input.length >= MAD_BUFFER_GUARD);
384 384
385 while (len < MAD_BUFFER_GUARD) 385 while (len < MAD_BUFFER_GUARD)
386 d->input.data[d->input.length + len++] = 0; 386 d->input.data[d->input.length + len++] = 0;
387 } 387 }
388 388
389 mad_stream_buffer(&d->stream, d->input.data, d->input.length += len); 389 mad_stream_buffer(&d->stream, d->input.data, d->input.length += len);
390 } 390 }
391 391
392 return TRUE; 392 return TRUE;
393} 393}
394 394
395 395
396static mad_fixed_t left_err, right_err; 396static mad_fixed_t left_err, right_err;
397static const int bits = 16; 397static const int bits = 16;
398static const int shift = MAD_F_FRACBITS + 1 - bits; 398static const int shift = MAD_F_FRACBITS + 1 - bits;
399 399
400 400
401inline long audio_linear_dither( mad_fixed_t sample, mad_fixed_t& error ) 401inline long audio_linear_dither( mad_fixed_t sample, mad_fixed_t& error )
402{ 402{
403 sample += error; 403 sample += error;
404 mad_fixed_t quantized = (sample >= MAD_F_ONE) ? MAD_F_ONE - 1 : ( (sample < -MAD_F_ONE) ? -MAD_F_ONE : sample ); 404 mad_fixed_t quantized = (sample >= MAD_F_ONE) ? MAD_F_ONE - 1 : ( (sample < -MAD_F_ONE) ? -MAD_F_ONE : sample );
405 quantized &= ~((1L << shift) - 1); 405 quantized &= ~((1L << shift) - 1);
406 error = sample - quantized; 406 error = sample - quantized;
407 return quantized >> shift; 407 return quantized >> shift;
408} 408}
409 409
410 410
411inline void audio_pcm( short *data, unsigned int nsamples, mad_fixed_t *left, mad_fixed_t *right ) 411inline void audio_pcm( short *data, unsigned int nsamples, mad_fixed_t *left, mad_fixed_t *right )
412{ 412{
413 if ( right ) { 413 if ( right ) {
414 while (nsamples--) { 414 while (nsamples--) {
415 data[0] = audio_linear_dither( *left++, left_err ); 415 data[0] = audio_linear_dither( *left++, left_err );
416 data[1] = audio_linear_dither( *right++, right_err ); 416 data[1] = audio_linear_dither( *right++, right_err );
417 data += 2; 417 data += 2;
418 } 418 }
419 } else { 419 } else {
420 while (nsamples--) { 420 while (nsamples--) {
421 data[0] = data[1] = audio_linear_dither( *left++, left_err ); 421 data[0] = data[1] = audio_linear_dither( *left++, left_err );
422 data += 2; 422 data += 2;
423 } 423 }
424 } 424 }
425} 425}
426 426
427 427
428bool LibMadPlugin::decode( short *output, long samples, long& samplesMade ) { 428bool LibMadPlugin::decode( short *output, long samples, long& samplesMade ) {
429 debugMsg( "LibMadPlugin::decode" ); 429 debugMsg( "LibMadPlugin::decode" );
430 430
431 static int buffered = 0; 431 static int buffered = 0;
432 static mad_fixed_t buffer[2][65536 * 2]; 432 static mad_fixed_t buffer[2][65536 * 2];
433 int offset = buffered; 433 int offset = buffered;
434 samplesMade = 0; 434 samplesMade = 0;
435 435
436 static int maxBuffered = 8000; // 65536; 436 static int maxBuffered = 8000; // 65536;
437 437
438 if ( samples > maxBuffered ) 438 if ( samples > maxBuffered )
439 samples = maxBuffered; 439 samples = maxBuffered;
440 440
441 if ( d->flush ) { 441 if ( d->flush ) {
442 buffered = 0; 442 buffered = 0;
443 offset = 0; 443 offset = 0;
444 d->flush = FALSE; 444 d->flush = FALSE;
445 } 445 }
446 446
447 while ( buffered < maxBuffered ) { 447 while ( buffered < maxBuffered ) {
448 448
449 while (mad_frame_decode(&d->frame, &d->stream) == -1) { 449 while (mad_frame_decode(&d->frame, &d->stream) == -1) {
450 if (!MAD_RECOVERABLE(d->stream.error)) { 450 if (!MAD_RECOVERABLE(d->stream.error)) {
451 debugMsg( "feed me" ); 451 debugMsg( "feed me" );
452 return FALSE; // Feed me 452 return FALSE; // Feed me
453 } 453 }
454 if ( d->stream.error == MAD_ERROR_BADCRC ) { 454 if ( d->stream.error == MAD_ERROR_BADCRC ) {
455 mad_frame_mute(&d->frame); 455 mad_frame_mute(&d->frame);
456 qDebug( "error decoding, bad crc" ); 456 qDebug( "error decoding, bad crc" );
457 } 457 }
458 } 458 }
459 459
460 mad_synth_frame(&d->synth, &d->frame); 460 mad_synth_frame(&d->synth, &d->frame);
461 int decodedSamples = d->synth.pcm.length; 461 int decodedSamples = d->synth.pcm.length;
462 memcpy( &(buffer[0][offset]), d->synth.pcm.samples[0], decodedSamples * sizeof(mad_fixed_t) ); 462 memcpy( &(buffer[0][offset]), d->synth.pcm.samples[0], decodedSamples * sizeof(mad_fixed_t) );
463 if ( d->synth.pcm.channels == 2 ) 463 if ( d->synth.pcm.channels == 2 )
464 memcpy( &(buffer[1][offset]), d->synth.pcm.samples[1], decodedSamples * sizeof(mad_fixed_t) ); 464 memcpy( &(buffer[1][offset]), d->synth.pcm.samples[1], decodedSamples * sizeof(mad_fixed_t) );
465 offset += decodedSamples; 465 offset += decodedSamples;
466 buffered += decodedSamples; 466 buffered += decodedSamples;
467 } 467 }
468 468
469 audio_pcm( output, samples, buffer[0], (d->synth.pcm.channels == 2) ? buffer[1] : 0 ); 469 audio_pcm( output, samples, buffer[0], (d->synth.pcm.channels == 2) ? buffer[1] : 0 );
470// audio_pcm( output, samples, buffer[1], buffer[0] ); 470// audio_pcm( output, samples, buffer[1], buffer[0] );
471// audio_pcm( output, samples, buffer[0], buffer[1] ); 471// audio_pcm( output, samples, buffer[0], buffer[1] );
472 samplesMade = samples; 472 samplesMade = samples;
473 memmove( buffer[0], &(buffer[0][samples]), (buffered - samples) * sizeof(mad_fixed_t) ); 473 memmove( buffer[0], &(buffer[0][samples]), (buffered - samples) * sizeof(mad_fixed_t) );
474 if ( d->synth.pcm.channels == 2 ) 474 if ( d->synth.pcm.channels == 2 )
475 memmove( buffer[1], &(buffer[1][samples]), (buffered - samples) * sizeof(mad_fixed_t) ); 475 memmove( buffer[1], &(buffer[1][samples]), (buffered - samples) * sizeof(mad_fixed_t) );
476 buffered -= samples; 476 buffered -= samples;
477 477
478 return TRUE; 478 return TRUE;
479} 479}
480 480
481/* 481/*
482bool LibMadPlugin::audioReadMonoSamples( short *, long, long&, int ) { 482bool LibMadPlugin::audioReadMonoSamples( short *, long, long&, int ) {
483 debugMsg( "LibMadPlugin::audioReadMonoSamples" ); 483 debugMsg( "LibMadPlugin::audioReadMonoSamples" );
484 return FALSE; 484 return FALSE;
485} 485}
486 486
487 487
488bool LibMadPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) { 488bool LibMadPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) {
489*/ 489*/
490bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long samples, long& samplesMade, int ) { 490bool LibMadPlugin::audioReadSamples( short *output, int /*channels*/, long samples, long& samplesMade, int ) {
491 debugMsg( "LibMadPlugin::audioReadStereoSamples" ); 491 debugMsg( "LibMadPlugin::audioReadStereoSamples" );
492 492
493 static bool needInput = TRUE; 493 static bool needInput = TRUE;
494 494
495 if ( samples == 0 ) 495 if ( samples == 0 )
496 return TRUE; 496 return FALSE;
497 497
498 do { 498 do {
499 if ( needInput ) 499 if ( needInput )
500 if ( !read() ) { 500 if ( !read() ) {
501 // if ( d->input.eof ) 501 // if ( d->input.eof )
502 // needInput = FALSE; 502 // needInput = FALSE;
503 // else 503 // else
504 return TRUE; 504 return FALSE;
505 } 505 }
506 506
507 needInput = FALSE; 507 needInput = FALSE;
508 508
509 if ( decode( output, samples, samplesMade ) ) 509 if ( decode( output, samples, samplesMade ) )
510 return FALSE; 510 return TRUE;
511 else 511 else
512 needInput = TRUE; 512 needInput = TRUE;
513 } 513 }
514 while ( ( samplesMade < samples ) && ( !d->input.eof ) ); 514 while ( ( samplesMade < samples ) && ( !d->input.eof ) );
515/* 515/*
516 static bool firstTimeThru = TRUE; 516 static bool firstTimeThru = TRUE;
517 517
518 if ( firstTimeThru ) { 518 if ( firstTimeThru ) {
519 firstTimeThru = FALSE; 519 firstTimeThru = FALSE;
520 decode( output, samples, samplesMade ); 520 decode( output, samples, samplesMade );
521 return FALSE; 521 return FALSE;
522 } else 522 } else
523*/ 523*/
524 return TRUE; 524 return FALSE;
525} 525}
526 526
527 527
528double LibMadPlugin::getTime() { 528double LibMadPlugin::getTime() {
529 debugMsg( "LibMadPlugin::getTime" ); 529 debugMsg( "LibMadPlugin::getTime" );
530 return 0.0; 530 return 0.0;
531} 531}
532 532
533 533
534void LibMadPlugin::printID3Tags() { 534void LibMadPlugin::printID3Tags() {
535 debugMsg( "LibMadPlugin::printID3Tags" ); 535 debugMsg( "LibMadPlugin::printID3Tags" );
536 536
537 char id3v1[128 + 1]; 537 char id3v1[128 + 1];
538 538
539 if ( ::lseek( d->input.fd, -128, SEEK_END ) == -1 ) { 539 if ( ::lseek( d->input.fd, -128, SEEK_END ) == -1 ) {
540 qDebug( "error seeking to id3 tags" ); 540 qDebug( "error seeking to id3 tags" );
541 return; 541 return;
542 } 542 }
543 543
544 if ( ::read( d->input.fd, id3v1, 128 ) != 128 ) { 544 if ( ::read( d->input.fd, id3v1, 128 ) != 128 ) {
545 qDebug( "error reading in id3 tags" ); 545 qDebug( "error reading in id3 tags" );
546 return; 546 return;
547 } 547 }
548 548
549 if ( ::strncmp( (const char *)id3v1, "TAG", 3 ) != 0 ) { 549 if ( ::strncmp( (const char *)id3v1, "TAG", 3 ) != 0 ) {
550 debugMsg( "sorry, no id3 tags" ); 550 debugMsg( "sorry, no id3 tags" );
551 } else { 551 } else {
552 int len[5] = { 30, 30, 30, 4, 30 }; 552 int len[5] = { 30, 30, 30, 4, 30 };
553 QString label[5] = { tr( "Title" ), tr( "Artist" ), tr( "Album" ), tr( "Year" ), tr( "Comment" ) }; 553 QString label[5] = { tr( "Title" ), tr( "Artist" ), tr( "Album" ), tr( "Year" ), tr( "Comment" ) };
554 char *ptr = id3v1 + 3, *ptr2 = ptr + len[0]; 554 char *ptr = id3v1 + 3, *ptr2 = ptr + len[0];
555 qDebug( "ID3 tags in file:" ); 555 qDebug( "ID3 tags in file:" );
556 info = ""; 556 info = "";
557 for ( int i = 0; i < 5; ptr += len[i], i++, ptr2 += len[i] ) { 557 for ( int i = 0; i < 5; ptr += len[i], i++, ptr2 += len[i] ) {
558 char push = *ptr2; 558 char push = *ptr2;
559 *ptr2 = '\0'; 559 *ptr2 = '\0';
560 char *ptr3 = ptr2; 560 char *ptr3 = ptr2;
561 while ( ptr3-1 >= ptr && isspace(ptr3[-1]) ) ptr3--; 561 while ( ptr3-1 >= ptr && isspace(ptr3[-1]) ) ptr3--;
562 char push2 = *ptr3; *ptr3 = '\0'; 562 char push2 = *ptr3; *ptr3 = '\0';
563 if ( strcmp( ptr, "" ) ) 563 if ( strcmp( ptr, "" ) )
564 info += ( i != 0 ? ", " : "" ) + label[i] + ": " + ptr; 564 info += ( i != 0 ? ", " : "" ) + label[i] + ": " + ptr;
565 //qDebug( info.latin1() ); 565 //qDebug( info.latin1() );
566 *ptr3 = push2; 566 *ptr3 = push2;
567 *ptr2 = push; 567 *ptr2 = push;
568 } 568 }
569 if (id3v1[126] == 0 && id3v1[127] != 0) 569 if (id3v1[126] == 0 && id3v1[127] != 0)
570 info += tr( ", Track: " ) + id3v1[127]; 570 info += tr( ", Track: " ) + id3v1[127];
571 } 571 }
572 572
573 if ( ::lseek(d->input.fd, 0, SEEK_SET) == -1 ) { 573 if ( ::lseek(d->input.fd, 0, SEEK_SET) == -1 ) {
574 qDebug( "error seeking back to beginning" ); 574 qDebug( "error seeking back to beginning" );
575 return; 575 return;
576 } 576 }
577} 577}
578 578
diff --git a/core/multimedia/opieplayer/loopcontrol.cpp b/core/multimedia/opieplayer/loopcontrol.cpp
index 93a6e3f..6dfd057 100644
--- a/core/multimedia/opieplayer/loopcontrol.cpp
+++ b/core/multimedia/opieplayer/loopcontrol.cpp
@@ -1,464 +1,464 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000 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 <qpe/qpeapplication.h> 20#include <qpe/qpeapplication.h>
21#ifdef Q_WS_QWS 21#ifdef Q_WS_QWS
22#include <qpe/qcopenvelope_qws.h> 22#include <qpe/qcopenvelope_qws.h>
23#endif 23#endif
24#include <stdio.h> 24#include <stdio.h>
25#include <stdlib.h> 25#include <stdlib.h>
26#include <string.h> 26#include <string.h>
27#include <pthread.h> 27#include <pthread.h>
28#include <errno.h> 28#include <errno.h>
29#include <unistd.h> 29#include <unistd.h>
30#include "loopcontrol.h" 30#include "loopcontrol.h"
31#include "videowidget.h" 31#include "videowidget.h"
32#include "audiodevice.h" 32#include "audiodevice.h"
33#include "mediaplayerplugininterface.h" 33#include "mediaplayerplugininterface.h"
34#include "mediaplayerstate.h" 34#include "mediaplayerstate.h"
35 35
36 36
37extern VideoWidget *videoUI; // now only needed to tell it to play a frame 37extern VideoWidget *videoUI; // now only needed to tell it to play a frame
38extern MediaPlayerState *mediaPlayerState; 38extern MediaPlayerState *mediaPlayerState;
39 39
40 40
41//#define DecodeLoopDebug(x) qDebug x 41//#define DecodeLoopDebug(x) qDebug x
42#define DecodeLoopDebug(x) 42#define DecodeLoopDebug(x)
43 43
44 44
45 static char *audioBuffer = NULL; 45 static char *audioBuffer = NULL;
46static AudioDevice *audioDevice = NULL; 46static AudioDevice *audioDevice = NULL;
47 static bool disabledSuspendScreenSaver = FALSE; 47 static bool disabledSuspendScreenSaver = FALSE;
48 static bool previousSuspendMode = FALSE; 48 static bool previousSuspendMode = FALSE;
49 49
50 50
51 pthread_taudio_tid; 51 pthread_taudio_tid;
52pthread_attr_t audio_attr; 52pthread_attr_t audio_attr;
53bool threadOkToGo = FALSE; 53bool threadOkToGo = FALSE;
54 54
55 55
56class Mutex { 56class Mutex {
57public: 57public:
58 Mutex() { 58 Mutex() {
59 pthread_mutexattr_t attr; 59 pthread_mutexattr_t attr;
60 pthread_mutexattr_init( &attr ); 60 pthread_mutexattr_init( &attr );
61 pthread_mutex_init( &mutex, &attr ); 61 pthread_mutex_init( &mutex, &attr );
62 pthread_mutexattr_destroy( &attr ); 62 pthread_mutexattr_destroy( &attr );
63 } 63 }
64 64
65 ~Mutex() { 65 ~Mutex() {
66 pthread_mutex_destroy( &mutex ); 66 pthread_mutex_destroy( &mutex );
67 } 67 }
68 68
69 void lock() { 69 void lock() {
70 pthread_mutex_lock( &mutex ); 70 pthread_mutex_lock( &mutex );
71 } 71 }
72 72
73 void unlock() { 73 void unlock() {
74 pthread_mutex_unlock( &mutex ); 74 pthread_mutex_unlock( &mutex );
75 } 75 }
76private: 76private:
77 pthread_mutex_t mutex; 77 pthread_mutex_t mutex;
78}; 78};
79 79
80 80
81void *startAudioThread( void *ptr ) { 81void *startAudioThread( void *ptr ) {
82 LoopControl *mpegView = (LoopControl *)ptr; 82 LoopControl *mpegView = (LoopControl *)ptr;
83 while ( TRUE ) { 83 while ( TRUE ) {
84 if ( threadOkToGo && mpegView->moreAudio ) 84 if ( threadOkToGo && mpegView->moreAudio )
85 mpegView->startAudio(); 85 mpegView->startAudio();
86 else 86 else
87 usleep( 10000 ); // Semi-buzy-wait till we are playing again 87 usleep( 10000 ); // Semi-buzy-wait till we are playing again
88 } 88 }
89 return 0; 89 return 0;
90} 90}
91 91
92 92
93Mutex *audioMutex; 93Mutex *audioMutex;
94 94
95 95
96LoopControl::LoopControl( QObject *parent, const char *name ) 96LoopControl::LoopControl( QObject *parent, const char *name )
97 : QObject( parent, name ) { 97 : QObject( parent, name ) {
98 isMuted = FALSE; 98 isMuted = FALSE;
99 connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( setMute(bool) ) ); 99 connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( setMute(bool) ) );
100 100
101 audioMutex = new Mutex; 101 audioMutex = new Mutex;
102 102
103 pthread_attr_init(&audio_attr); 103 pthread_attr_init(&audio_attr);
104#define USE_REALTIME_AUDIO_THREAD 104#define USE_REALTIME_AUDIO_THREAD
105#ifdef USE_REALTIME_AUDIO_THREAD 105#ifdef USE_REALTIME_AUDIO_THREAD
106 // Attempt to set it to real-time round robin 106 // Attempt to set it to real-time round robin
107 if ( pthread_attr_setschedpolicy( &audio_attr, SCHED_RR ) == 0 ) { 107 if ( pthread_attr_setschedpolicy( &audio_attr, SCHED_RR ) == 0 ) {
108 sched_param params; 108 sched_param params;
109 params.sched_priority = 50; 109 params.sched_priority = 50;
110 pthread_attr_setschedparam(&audio_attr,&params); 110 pthread_attr_setschedparam(&audio_attr,&params);
111 } else { 111 } else {
112 qDebug( "Error setting up a realtime thread, reverting to using a normal thread." ); 112 qDebug( "Error setting up a realtime thread, reverting to using a normal thread." );
113 pthread_attr_destroy(&audio_attr); 113 pthread_attr_destroy(&audio_attr);
114 pthread_attr_init(&audio_attr); 114 pthread_attr_init(&audio_attr);
115 } 115 }
116#endif 116#endif
117 pthread_create(&audio_tid, &audio_attr, (void * (*)(void *))startAudioThread, this); 117 pthread_create(&audio_tid, &audio_attr, (void * (*)(void *))startAudioThread, this);
118} 118}
119 119
120 120
121LoopControl::~LoopControl() { 121LoopControl::~LoopControl() {
122 stop(); 122 stop();
123} 123}
124 124
125 125
126static long prev_frame = 0; 126static long prev_frame = 0;
127static int currentSample = 0; 127static int currentSample = 0;
128 128
129 129
130void LoopControl::timerEvent( QTimerEvent *te ) { 130void LoopControl::timerEvent( QTimerEvent *te ) {
131 131
132 if ( te->timerId() == videoId ) 132 if ( te->timerId() == videoId )
133 startVideo(); 133 startVideo();
134 134
135 if ( te->timerId() == sliderId ) { 135 if ( te->timerId() == sliderId ) {
136 if ( hasAudioChannel && !hasVideoChannel && moreAudio ) { 136 if ( hasAudioChannel && !hasVideoChannel && moreAudio ) {
137 mediaPlayerState->updatePosition( audioSampleCounter ); 137 mediaPlayerState->updatePosition( audioSampleCounter );
138 } else if ( hasVideoChannel && moreVideo ) { 138 } else if ( hasVideoChannel && moreVideo ) {
139 mediaPlayerState->updatePosition( current_frame ); 139 mediaPlayerState->updatePosition( current_frame );
140 } 140 }
141 } 141 }
142 142
143 if ( !moreVideo && !moreAudio ) { 143 if ( !moreVideo && !moreAudio ) {
144 mediaPlayerState->setPlaying( FALSE ); 144 mediaPlayerState->setPlaying( FALSE );
145 mediaPlayerState->setNext(); 145 mediaPlayerState->setNext();
146 } 146 }
147} 147}
148 148
149 149
150void LoopControl::setPosition( long pos ) { 150void LoopControl::setPosition( long pos ) {
151 audioMutex->lock(); 151 audioMutex->lock();
152 152
153 if ( hasVideoChannel && hasAudioChannel ) { 153 if ( hasVideoChannel && hasAudioChannel ) {
154 playtime.restart(); 154 playtime.restart();
155 playtime = playtime.addMSecs( long((double)-pos * 1000.0 / framerate) ); 155 playtime = playtime.addMSecs( long((double)-pos * 1000.0 / framerate) );
156 current_frame = pos + 1; 156 current_frame = pos + 1;
157 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); 157 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream );
158 prev_frame = current_frame - 1; 158 prev_frame = current_frame - 1;
159 currentSample = (int)( (double)current_frame * freq / framerate ); 159 currentSample = (int)( (double)current_frame * freq / framerate );
160 mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream ); 160 mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream );
161 audioSampleCounter = currentSample - 1; 161 audioSampleCounter = currentSample - 1;
162 } else if ( hasVideoChannel ) { 162 } else if ( hasVideoChannel ) {
163 playtime.restart(); 163 playtime.restart();
164 playtime = playtime.addMSecs( long((double)-pos * 1000.0 / framerate) ); 164 playtime = playtime.addMSecs( long((double)-pos * 1000.0 / framerate) );
165 current_frame = pos + 1; 165 current_frame = pos + 1;
166 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); 166 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream );
167 prev_frame = current_frame - 1; 167 prev_frame = current_frame - 1;
168 } else if ( hasAudioChannel ) { 168 } else if ( hasAudioChannel ) {
169 playtime.restart(); 169 playtime.restart();
170 playtime = playtime.addMSecs( long((double)-pos * 1000.0 / freq) ); 170 playtime = playtime.addMSecs( long((double)-pos * 1000.0 / freq) );
171 currentSample = pos + 1; 171 currentSample = pos + 1;
172 mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream ); 172 mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream );
173 audioSampleCounter = currentSample - 1; 173 audioSampleCounter = currentSample - 1;
174 } 174 }
175 175
176 audioMutex->unlock(); 176 audioMutex->unlock();
177} 177}
178 178
179 179
180void LoopControl::startVideo() { 180void LoopControl::startVideo() {
181 181
182 if ( moreVideo ) { 182 if ( moreVideo ) {
183 183
184 if ( mediaPlayerState->curDecoder() ) { 184 if ( mediaPlayerState->curDecoder() ) {
185 185
186 if ( hasAudioChannel && !isMuted ) { 186 if ( hasAudioChannel && !isMuted ) {
187 187
188 current_frame = long( playtime.elapsed() * framerate / 1000 ); 188 current_frame = long( playtime.elapsed() * framerate / 1000 );
189 189
190 if ( prev_frame != -1 && current_frame <= prev_frame ) 190 if ( prev_frame != -1 && current_frame <= prev_frame )
191 return; 191 return;
192 192
193 } else { 193 } else {
194 // Don't skip 194 // Don't skip
195 current_frame++; 195 current_frame++;
196 } 196 }
197 197
198 if ( prev_frame == -1 || current_frame > prev_frame ) { 198 if ( prev_frame == -1 || current_frame > prev_frame ) {
199 if ( current_frame > prev_frame + 1 ) { 199 if ( current_frame > prev_frame + 1 ) {
200 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); 200 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream );
201 } 201 }
202 moreVideo = videoUI->playVideo(); 202 moreVideo = videoUI->playVideo();
203 prev_frame = current_frame; 203 prev_frame = current_frame;
204 } 204 }
205 205
206 } else { 206 } else {
207 207
208 moreVideo = FALSE; 208 moreVideo = FALSE;
209 killTimer( videoId ); 209 killTimer( videoId );
210 210
211 } 211 }
212 212
213 } 213 }
214} 214}
215 215
216 216
217void LoopControl::startAudio() { 217void LoopControl::startAudio() {
218 218
219 audioMutex->lock(); 219 audioMutex->lock();
220 220
221 if ( moreAudio ) { 221 if ( moreAudio ) {
222 222
223 if ( !isMuted && mediaPlayerState->curDecoder() ) { 223 if ( !isMuted && mediaPlayerState->curDecoder() ) {
224 224
225 currentSample = audioSampleCounter + 1; 225 currentSample = audioSampleCounter + 1;
226 226
227 if ( currentSample != audioSampleCounter + 1 ) 227 if ( currentSample != audioSampleCounter + 1 )
228 qDebug("out of sync with decoder %i %i", currentSample, audioSampleCounter); 228 qDebug("out of sync with decoder %i %i", currentSample, audioSampleCounter);
229 229
230 long samplesRead = 0; 230 long samplesRead = 0;
231 mediaPlayerState->curDecoder()->audioReadSamples( (short*)audioBuffer, channels, 1024, samplesRead, stream ); 231 bool readOk=mediaPlayerState->curDecoder()->audioReadSamples( (short*)audioBuffer, channels, 1024, samplesRead, stream );
232 long sampleWeShouldBeAt = long( playtime.elapsed() ) * freq / 1000; 232 long sampleWeShouldBeAt = long( playtime.elapsed() ) * freq / 1000;
233 long sampleWaitTime = currentSample - sampleWeShouldBeAt; 233 long sampleWaitTime = currentSample - sampleWeShouldBeAt;
234 234
235 if ( ( sampleWaitTime > 2000 ) && ( sampleWaitTime < 20000 ) ) { 235 if ( ( sampleWaitTime > 2000 ) && ( sampleWaitTime < 20000 ) ) {
236 usleep( (long)((double)sampleWaitTime * 1000000.0 / freq) ); 236 usleep( (long)((double)sampleWaitTime * 1000000.0 / freq) );
237 } else if ( sampleWaitTime <= -5000 ) { 237 } else if ( sampleWaitTime <= -5000 ) {
238 qDebug("need to catch up by: %li (%i,%li)", -sampleWaitTime, currentSample, sampleWeShouldBeAt ); 238 qDebug("need to catch up by: %li (%i,%li)", -sampleWaitTime, currentSample, sampleWeShouldBeAt );
239 //mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream ); 239 //mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream );
240 currentSample = sampleWeShouldBeAt; 240 currentSample = sampleWeShouldBeAt;
241 } 241 }
242 242
243 audioDevice->write( audioBuffer, samplesRead * 2 * channels ); 243 audioDevice->write( audioBuffer, samplesRead * 2 * channels );
244 audioSampleCounter = currentSample + samplesRead - 1; 244 audioSampleCounter = currentSample + samplesRead - 1;
245 245
246 moreAudio = audioSampleCounter <= total_audio_samples; 246 moreAudio = readOk && (audioSampleCounter <= total_audio_samples);
247 247
248 } else { 248 } else {
249 249
250 moreAudio = FALSE; 250 moreAudio = FALSE;
251 251
252 } 252 }
253 253
254 } 254 }
255 255
256 audioMutex->unlock(); 256 audioMutex->unlock();
257} 257}
258 258
259 259
260void LoopControl::killTimers() { 260void LoopControl::killTimers() {
261 261
262 audioMutex->lock(); 262 audioMutex->lock();
263 263
264 if ( hasVideoChannel ) 264 if ( hasVideoChannel )
265 killTimer( videoId ); 265 killTimer( videoId );
266 killTimer( sliderId ); 266 killTimer( sliderId );
267 threadOkToGo = FALSE; 267 threadOkToGo = FALSE;
268 268
269 audioMutex->unlock(); 269 audioMutex->unlock();
270} 270}
271 271
272 272
273void LoopControl::startTimers() { 273void LoopControl::startTimers() {
274 274
275 audioMutex->lock(); 275 audioMutex->lock();
276 276
277 moreVideo = FALSE; 277 moreVideo = FALSE;
278 moreAudio = FALSE; 278 moreAudio = FALSE;
279 279
280 if ( hasVideoChannel ) { 280 if ( hasVideoChannel ) {
281 moreVideo = TRUE; 281 moreVideo = TRUE;
282 int mSecsBetweenFrames = (int)(100 / framerate); // 10% of the real value 282 int mSecsBetweenFrames = (int)(100 / framerate); // 10% of the real value
283 videoId = startTimer( mSecsBetweenFrames ); 283 videoId = startTimer( mSecsBetweenFrames );
284 } 284 }
285 285
286 if ( hasAudioChannel ) { 286 if ( hasAudioChannel ) {
287 moreAudio = TRUE; 287 moreAudio = TRUE;
288 threadOkToGo = TRUE; 288 threadOkToGo = TRUE;
289 } 289 }
290 290
291 sliderId = startTimer( 300 ); // update slider every 1/3 second 291 sliderId = startTimer( 300 ); // update slider every 1/3 second
292 292
293 audioMutex->unlock(); 293 audioMutex->unlock();
294} 294}
295 295
296 296
297void LoopControl::setPaused( bool pause ) { 297void LoopControl::setPaused( bool pause ) {
298 298
299 if ( !mediaPlayerState->curDecoder() || !mediaPlayerState->curDecoder()->isOpen() ) 299 if ( !mediaPlayerState->curDecoder() || !mediaPlayerState->curDecoder()->isOpen() )
300 return; 300 return;
301 301
302 if ( pause ) { 302 if ( pause ) {
303 killTimers(); 303 killTimers();
304 } else { 304 } else {
305 // Force an update of the position 305 // Force an update of the position
306 mediaPlayerState->setPosition( mediaPlayerState->position() + 1 ); 306 mediaPlayerState->setPosition( mediaPlayerState->position() + 1 );
307 mediaPlayerState->setPosition( mediaPlayerState->position() - 1 ); 307 mediaPlayerState->setPosition( mediaPlayerState->position() - 1 );
308 // Just like we never stopped 308 // Just like we never stopped
309 startTimers(); 309 startTimers();
310 } 310 }
311} 311}
312 312
313 313
314void LoopControl::stop( bool willPlayAgainShortly ) { 314void LoopControl::stop( bool willPlayAgainShortly ) {
315 315
316#if defined(Q_WS_QWS) && !defined(QT_NO_COP) 316#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
317 if ( !willPlayAgainShortly && disabledSuspendScreenSaver ) { 317 if ( !willPlayAgainShortly && disabledSuspendScreenSaver ) {
318 disabledSuspendScreenSaver = FALSE; 318 disabledSuspendScreenSaver = FALSE;
319 // Re-enable the suspend mode 319 // Re-enable the suspend mode
320 QCopEnvelope("QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable; 320 QCopEnvelope("QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable;
321 } 321 }
322#endif 322#endif
323 323
324 if ( mediaPlayerState->curDecoder() && mediaPlayerState->curDecoder()->isOpen() ) { 324 if ( mediaPlayerState->curDecoder() && mediaPlayerState->curDecoder()->isOpen() ) {
325 325
326 killTimers(); 326 killTimers();
327 327
328 audioMutex->lock(); 328 audioMutex->lock();
329 329
330 mediaPlayerState->curDecoder()->close(); 330 mediaPlayerState->curDecoder()->close();
331 331
332 if ( audioDevice ) { 332 if ( audioDevice ) {
333 delete audioDevice; 333 delete audioDevice;
334 delete audioBuffer; 334 delete audioBuffer;
335 audioDevice = 0; 335 audioDevice = 0;
336 audioBuffer = 0; 336 audioBuffer = 0;
337 } 337 }
338 338
339 audioMutex->unlock(); 339 audioMutex->unlock();
340 340
341 } 341 }
342} 342}
343 343
344 344
345bool LoopControl::init( const QString& filename ) { 345bool LoopControl::init( const QString& filename ) {
346 stop(); 346 stop();
347 347
348 audioMutex->lock(); 348 audioMutex->lock();
349 349
350 fileName = filename; 350 fileName = filename;
351 stream = 0; // only play stream 0 for now 351 stream = 0; // only play stream 0 for now
352 current_frame = total_video_frames = total_audio_samples = 0; 352 current_frame = total_video_frames = total_audio_samples = 0;
353 353
354 qDebug( "Using the %s decoder", mediaPlayerState->curDecoder()->pluginName() ); 354 qDebug( "Using the %s decoder", mediaPlayerState->curDecoder()->pluginName() );
355 355
356 // ### Hack to use libmpeg3plugin to get the number of audio samples if we are using the libmad plugin 356 // ### Hack to use libmpeg3plugin to get the number of audio samples if we are using the libmad plugin
357 if ( mediaPlayerState->curDecoder()->pluginName() == QString("LibMadPlugin") ) { 357 if ( mediaPlayerState->curDecoder()->pluginName() == QString("LibMadPlugin") ) {
358 if ( mediaPlayerState->libMpeg3Decoder() && mediaPlayerState->libMpeg3Decoder()->open( filename ) ) { 358 if ( mediaPlayerState->libMpeg3Decoder() && mediaPlayerState->libMpeg3Decoder()->open( filename ) ) {
359 total_audio_samples = mediaPlayerState->libMpeg3Decoder()->audioSamples( 0 ); 359 total_audio_samples = mediaPlayerState->libMpeg3Decoder()->audioSamples( 0 );
360 mediaPlayerState->libMpeg3Decoder()->close(); 360 mediaPlayerState->libMpeg3Decoder()->close();
361 } 361 }
362 } 362 }
363 363
364 if ( !mediaPlayerState->curDecoder()|| !mediaPlayerState->curDecoder()->open( filename ) ) { 364 if ( !mediaPlayerState->curDecoder()|| !mediaPlayerState->curDecoder()->open( filename ) ) {
365 audioMutex->unlock(); 365 audioMutex->unlock();
366 return FALSE; 366 return FALSE;
367 } 367 }
368 368
369 hasAudioChannel = mediaPlayerState->curDecoder()->audioStreams() > 0; 369 hasAudioChannel = mediaPlayerState->curDecoder()->audioStreams() > 0;
370 hasVideoChannel = mediaPlayerState->curDecoder()->videoStreams() > 0; 370 hasVideoChannel = mediaPlayerState->curDecoder()->videoStreams() > 0;
371 371
372 if ( hasAudioChannel ) { 372 if ( hasAudioChannel ) {
373 int astream = 0; 373 int astream = 0;
374 374
375 channels = mediaPlayerState->curDecoder()->audioChannels( astream ); 375 channels = mediaPlayerState->curDecoder()->audioChannels( astream );
376 DecodeLoopDebug(( "channels = %d\n", channels )); 376 DecodeLoopDebug(( "channels = %d\n", channels ));
377 377
378 if ( !total_audio_samples ) 378 if ( !total_audio_samples )
379 total_audio_samples = mediaPlayerState->curDecoder()->audioSamples( astream ); 379 total_audio_samples = mediaPlayerState->curDecoder()->audioSamples( astream );
380 380
381 total_audio_samples += 1000; 381 total_audio_samples += 1000;
382 382
383 mediaPlayerState->setLength( total_audio_samples ); 383 mediaPlayerState->setLength( total_audio_samples );
384 384
385 freq = mediaPlayerState->curDecoder()->audioFrequency( astream ); 385 freq = mediaPlayerState->curDecoder()->audioFrequency( astream );
386 DecodeLoopDebug(( "frequency = %d\n", freq )); 386 DecodeLoopDebug(( "frequency = %d\n", freq ));
387 387
388 audioSampleCounter = 0; 388 audioSampleCounter = 0;
389 389
390 static const int bytes_per_sample = 2; //16 bit 390 static const int bytes_per_sample = 2; //16 bit
391 391
392 audioDevice = new AudioDevice( freq, channels, bytes_per_sample ); 392 audioDevice = new AudioDevice( freq, channels, bytes_per_sample );
393 audioBuffer = new char[ audioDevice->bufferSize() ]; 393 audioBuffer = new char[ audioDevice->bufferSize() ];
394 channels = audioDevice->channels(); 394 channels = audioDevice->channels();
395 395
396 //### must check which frequency is actually used. 396 //### must check which frequency is actually used.
397 static const int size = 1; 397 static const int size = 1;
398 short int buf[size]; 398 short int buf[size];
399 long samplesRead = 0; 399 long samplesRead = 0;
400 mediaPlayerState->curDecoder()->audioReadSamples( buf, channels, size, samplesRead, stream ); 400 mediaPlayerState->curDecoder()->audioReadSamples( buf, channels, size, samplesRead, stream );
401 } 401 }
402 402
403 if ( hasVideoChannel ) { 403 if ( hasVideoChannel ) {
404 total_video_frames = mediaPlayerState->curDecoder()->videoFrames( stream ); 404 total_video_frames = mediaPlayerState->curDecoder()->videoFrames( stream );
405 405
406 mediaPlayerState->setLength( total_video_frames ); 406 mediaPlayerState->setLength( total_video_frames );
407 407
408 framerate = mediaPlayerState->curDecoder()->videoFrameRate( stream ); 408 framerate = mediaPlayerState->curDecoder()->videoFrameRate( stream );
409 DecodeLoopDebug(( "Frame rate %g total %ld", framerate, total_video_frames )); 409 DecodeLoopDebug(( "Frame rate %g total %ld", framerate, total_video_frames ));
410 410
411 if ( framerate <= 1.0 ) { 411 if ( framerate <= 1.0 ) {
412 DecodeLoopDebug(( "Crazy frame rate, resetting to sensible" )); 412 DecodeLoopDebug(( "Crazy frame rate, resetting to sensible" ));
413 framerate = 25; 413 framerate = 25;
414 } 414 }
415 415
416 if ( total_video_frames == 1 ) { 416 if ( total_video_frames == 1 ) {
417 DecodeLoopDebug(( "Cannot seek to frame" )); 417 DecodeLoopDebug(( "Cannot seek to frame" ));
418 } 418 }
419 419
420 } 420 }
421 421
422 current_frame = 0; 422 current_frame = 0;
423 prev_frame = -1; 423 prev_frame = -1;
424 424
425 connect( mediaPlayerState, SIGNAL( positionChanged( long ) ), this, SLOT( setPosition( long ) ) ); 425 connect( mediaPlayerState, SIGNAL( positionChanged( long ) ), this, SLOT( setPosition( long ) ) );
426 connect( mediaPlayerState, SIGNAL( pausedToggled( bool ) ), this, SLOT( setPaused( bool ) ) ); 426 connect( mediaPlayerState, SIGNAL( pausedToggled( bool ) ), this, SLOT( setPaused( bool ) ) );
427 427
428 audioMutex->unlock(); 428 audioMutex->unlock();
429 429
430 return TRUE; 430 return TRUE;
431} 431}
432 432
433 433
434void LoopControl::play() { 434void LoopControl::play() {
435 435
436#if defined(Q_WS_QWS) && !defined(QT_NO_COP) 436#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
437 if ( !disabledSuspendScreenSaver || previousSuspendMode != hasVideoChannel ) { 437 if ( !disabledSuspendScreenSaver || previousSuspendMode != hasVideoChannel ) {
438 disabledSuspendScreenSaver = TRUE; 438 disabledSuspendScreenSaver = TRUE;
439 previousSuspendMode = hasVideoChannel; 439 previousSuspendMode = hasVideoChannel;
440 // Stop the screen from blanking and power saving state 440 // Stop the screen from blanking and power saving state
441 QCopEnvelope("QPE/System", "setScreenSaverMode(int)" ) 441 QCopEnvelope("QPE/System", "setScreenSaverMode(int)" )
442 << ( hasVideoChannel ? QPEApplication::Disable : QPEApplication::DisableSuspend ); 442 << ( hasVideoChannel ? QPEApplication::Disable : QPEApplication::DisableSuspend );
443 } 443 }
444#endif 444#endif
445 445
446 playtime.start(); 446 playtime.start();
447 startTimers(); 447 startTimers();
448} 448}
449 449
450 450
451void LoopControl::setMute( bool on ) { 451void LoopControl::setMute( bool on ) {
452 if ( on != isMuted ) { 452 if ( on != isMuted ) {
453 isMuted = on; 453 isMuted = on;
454 if ( !on ) { 454 if ( !on ) {
455 // Force an update of the position 455 // Force an update of the position
456 mediaPlayerState->setPosition( mediaPlayerState->position() + 1 ); 456 mediaPlayerState->setPosition( mediaPlayerState->position() + 1 );
457 mediaPlayerState->setPosition( mediaPlayerState->position() - 1 ); 457 mediaPlayerState->setPosition( mediaPlayerState->position() - 1 );
458 // Resume playing audio 458 // Resume playing audio
459 moreAudio = TRUE; 459 moreAudio = TRUE;
460 } 460 }
461 } 461 }
462} 462}
463 463
464 464
diff --git a/core/multimedia/opieplayer/wavplugin/wavplugin.cpp b/core/multimedia/opieplayer/wavplugin/wavplugin.cpp
index 60a0024..a6bd974 100644
--- a/core/multimedia/opieplayer/wavplugin/wavplugin.cpp
+++ b/core/multimedia/opieplayer/wavplugin/wavplugin.cpp
@@ -1,334 +1,334 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000 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 <stdio.h> 20#include <stdio.h>
21#include <stdarg.h> 21#include <stdarg.h>
22#include <stdlib.h> 22#include <stdlib.h>
23#include <errno.h> 23#include <errno.h>
24#include <unistd.h> 24#include <unistd.h>
25#include <qfile.h> 25#include <qfile.h>
26#include "wavplugin.h" 26#include "wavplugin.h"
27 27
28 28
29 //#define debugMsg(a) qDebug(a) 29 //#define debugMsg(a) qDebug(a)
30#define debugMsg(a) 30#define debugMsg(a)
31 31
32 32
33struct RiffChunk { 33struct RiffChunk {
34 char id[4]; 34 char id[4];
35 Q_UINT32 size; 35 Q_UINT32 size;
36 char data[4]; 36 char data[4];
37}; 37};
38 38
39 39
40struct ChunkData { 40struct ChunkData {
41 Q_INT16 formatTag; 41 Q_INT16 formatTag;
42 Q_INT16 channels; 42 Q_INT16 channels;
43 Q_INT32 samplesPerSec; 43 Q_INT32 samplesPerSec;
44 Q_INT32 avgBytesPerSec; 44 Q_INT32 avgBytesPerSec;
45 Q_INT16 blockAlign; 45 Q_INT16 blockAlign;
46 Q_INT16 wBitsPerSample; 46 Q_INT16 wBitsPerSample;
47}; 47};
48 48
49 49
50const int sound_buffer_size = 4096; 50const int sound_buffer_size = 4096;
51 51
52 52
53class WavPluginData { 53class WavPluginData {
54public: 54public:
55 QFile *input; 55 QFile *input;
56 56
57 int wavedata_remaining; 57 int wavedata_remaining;
58 ChunkData chunkdata; 58 ChunkData chunkdata;
59 RiffChunk chunk; 59 RiffChunk chunk;
60 uchar data[sound_buffer_size+32]; // +32 to handle badly aligned input data 60 uchar data[sound_buffer_size+32]; // +32 to handle badly aligned input data
61 int out,max; 61 int out,max;
62 int samples_due; 62 int samples_due;
63 int samples; 63 int samples;
64 64
65 WavPluginData() { 65 WavPluginData() {
66 max = out = sound_buffer_size; 66 max = out = sound_buffer_size;
67 wavedata_remaining = 0; 67 wavedata_remaining = 0;
68 samples_due = 0; 68 samples_due = 0;
69 samples = -1; 69 samples = -1;
70 } 70 }
71 71
72 // expands out samples to the frequency of 44kHz 72 // expands out samples to the frequency of 44kHz
73 bool add( short *output, long count, long& done, bool stereo ) 73 bool add( short *output, long count, long& done, bool stereo )
74 { 74 {
75 done = 0; 75 done = 0;
76 76
77 if ( input == 0 ) { 77 if ( input == 0 ) {
78 qDebug("no input"); 78 qDebug("no input");
79 return FALSE; 79 return FALSE;
80 } 80 }
81 81
82 while ( count ) { 82 while ( count ) {
83 int l,r; 83 int l,r;
84 if ( getSample(l, r) == FALSE ) { 84 if ( getSample(l, r) == FALSE ) {
85 qDebug("didn't get sample"); 85 qDebug("didn't get sample");
86 return FALSE; 86 return FALSE;
87 } 87 }
88 samples_due += 44100; 88 samples_due += 44100;
89 while ( count && (samples_due > chunkdata.samplesPerSec) ) { 89 while ( count && (samples_due > chunkdata.samplesPerSec) ) {
90 *output++ = l; 90 *output++ = l;
91 if ( stereo ) 91 if ( stereo )
92 *output++ = r; 92 *output++ = r;
93 samples_due -= chunkdata.samplesPerSec; 93 samples_due -= chunkdata.samplesPerSec;
94 count--; 94 count--;
95 done++; 95 done++;
96 } 96 }
97 } 97 }
98 98
99 return TRUE; 99 return TRUE;
100 } 100 }
101 101
102 bool initialise() { 102 bool initialise() {
103 if ( input == 0 ) 103 if ( input == 0 )
104 return FALSE; 104 return FALSE;
105 105
106 wavedata_remaining = -1; 106 wavedata_remaining = -1;
107 107
108 while ( wavedata_remaining == -1 ) { 108 while ( wavedata_remaining == -1 ) {
109 // Keep reading chunks... 109 // Keep reading chunks...
110 const int n = sizeof(chunk) - sizeof(chunk.data); 110 const int n = sizeof(chunk) - sizeof(chunk.data);
111 int t = input->readBlock( (char*)&chunk, n ); 111 int t = input->readBlock( (char*)&chunk, n );
112 if ( t != n ) { 112 if ( t != n ) {
113 if ( t == -1 ) 113 if ( t == -1 )
114 return FALSE; 114 return FALSE;
115 return TRUE; 115 return TRUE;
116 } 116 }
117 if ( qstrncmp(chunk.id,"data",4) == 0 ) { 117 if ( qstrncmp(chunk.id,"data",4) == 0 ) {
118 samples = wavedata_remaining = chunk.size; 118 samples = wavedata_remaining = chunk.size;
119 } else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) { 119 } else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) {
120 char d[4]; 120 char d[4];
121 if ( input->readBlock(d,4) != 4 ) { 121 if ( input->readBlock(d,4) != 4 ) {
122 return FALSE; 122 return FALSE;
123 } 123 }
124 if ( qstrncmp(d,"WAVE",4) != 0 ) { 124 if ( qstrncmp(d,"WAVE",4) != 0 ) {
125 // skip 125 // skip
126 if ( chunk.size > 1000000000 || !input->at(input->at()+chunk.size-4) ) { 126 if ( chunk.size > 1000000000 || !input->at(input->at()+chunk.size-4) ) {
127 return FALSE; 127 return FALSE;
128 } 128 }
129 } 129 }
130 } else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) { 130 } else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) {
131 if ( input->readBlock((char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) ) { 131 if ( input->readBlock((char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) ) {
132 return FALSE; 132 return FALSE;
133 } 133 }
134#define WAVE_FORMAT_PCM 1 134#define WAVE_FORMAT_PCM 1
135 if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) { 135 if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) {
136 qDebug("WAV file: UNSUPPORTED FORMAT %d",chunkdata.formatTag); 136 qDebug("WAV file: UNSUPPORTED FORMAT %d",chunkdata.formatTag);
137 return FALSE; 137 return FALSE;
138 } 138 }
139 } else { 139 } else {
140 // ignored chunk 140 // ignored chunk
141 if ( chunk.size > 1000000000 || !input->at(input->at()+chunk.size) ) { 141 if ( chunk.size > 1000000000 || !input->at(input->at()+chunk.size) ) {
142 return FALSE; 142 return FALSE;
143 } 143 }
144 } 144 }
145 } // while 145 } // while
146 146
147 return TRUE; 147 return TRUE;
148 } 148 }
149 149
150 150
151 // gets a sample from the file 151 // gets a sample from the file
152 bool getSample(int& l, int& r) 152 bool getSample(int& l, int& r)
153 { 153 {
154 l = r = 0; 154 l = r = 0;
155 155
156 if ( input == 0 ) 156 if ( input == 0 )
157 return FALSE; 157 return FALSE;
158 158
159 if ( (wavedata_remaining < 0) || !max ) 159 if ( (wavedata_remaining < 0) || !max )
160 return FALSE; 160 return FALSE;
161 161
162 if ( out >= max ) { 162 if ( out >= max ) {
163 max = input->readBlock( (char*)data, (uint)QMIN(sound_buffer_size,wavedata_remaining) ); 163 max = input->readBlock( (char*)data, (uint)QMIN(sound_buffer_size,wavedata_remaining) );
164 164
165 wavedata_remaining -= max; 165 wavedata_remaining -= max;
166 166
167 out = 0; 167 out = 0;
168 if ( max <= 0 ) { 168 if ( max <= 0 ) {
169 max = 0; 169 max = 0;
170 return TRUE; 170 return TRUE;
171 } 171 }
172 } 172 }
173 if ( chunkdata.wBitsPerSample == 8 ) { 173 if ( chunkdata.wBitsPerSample == 8 ) {
174 l = (data[out++] - 128) * 128; 174 l = (data[out++] - 128) * 128;
175 } else { 175 } else {
176 l = ((short*)data)[out/2]; 176 l = ((short*)data)[out/2];
177 out += 2; 177 out += 2;
178 } 178 }
179 if ( chunkdata.channels == 1 ) { 179 if ( chunkdata.channels == 1 ) {
180 r = l; 180 r = l;
181 } else { 181 } else {
182 if ( chunkdata.wBitsPerSample == 8 ) { 182 if ( chunkdata.wBitsPerSample == 8 ) {
183 r = (data[out++] - 128) * 128; 183 r = (data[out++] - 128) * 128;
184 } else { 184 } else {
185 r = ((short*)data)[out/2]; 185 r = ((short*)data)[out/2];
186 out += 2; 186 out += 2;
187 } 187 }
188 } 188 }
189 return TRUE; 189 return TRUE;
190 } // getSample 190 } // getSample
191 191
192}; 192};
193 193
194 194
195WavPlugin::WavPlugin() { 195WavPlugin::WavPlugin() {
196 d = new WavPluginData; 196 d = new WavPluginData;
197 d->input = 0; 197 d->input = 0;
198} 198}
199 199
200 200
201WavPlugin::~WavPlugin() { 201WavPlugin::~WavPlugin() {
202 close(); 202 close();
203 delete d; 203 delete d;
204} 204}
205 205
206 206
207bool WavPlugin::isFileSupported( const QString& path ) { 207bool WavPlugin::isFileSupported( const QString& path ) {
208 debugMsg( "WavPlugin::isFileSupported" ); 208 debugMsg( "WavPlugin::isFileSupported" );
209 209
210 char *ext = strrchr( path.latin1(), '.' ); 210 char *ext = strrchr( path.latin1(), '.' );
211 211
212 // Test file extension 212 // Test file extension
213 if ( ext ) { 213 if ( ext ) {
214 if ( strncasecmp(ext, ".raw", 4) == 0 ) 214 if ( strncasecmp(ext, ".raw", 4) == 0 )
215 return TRUE; 215 return TRUE;
216 if ( strncasecmp(ext, ".wav", 4) == 0 ) 216 if ( strncasecmp(ext, ".wav", 4) == 0 )
217 return TRUE; 217 return TRUE;
218 if ( strncasecmp(ext, ".wave", 4) == 0 ) 218 if ( strncasecmp(ext, ".wave", 4) == 0 )
219 return TRUE; 219 return TRUE;
220 } 220 }
221 221
222 return FALSE; 222 return FALSE;
223} 223}
224 224
225 225
226bool WavPlugin::open( const QString& path ) { 226bool WavPlugin::open( const QString& path ) {
227 debugMsg( "WavPlugin::open" ); 227 debugMsg( "WavPlugin::open" );
228 228
229 d->max = d->out = sound_buffer_size; 229 d->max = d->out = sound_buffer_size;
230 d->wavedata_remaining = 0; 230 d->wavedata_remaining = 0;
231 d->samples_due = 0; 231 d->samples_due = 0;
232 232
233 d->input = new QFile( path ); 233 d->input = new QFile( path );
234 if ( d->input->open(IO_ReadOnly) == FALSE ) { 234 if ( d->input->open(IO_ReadOnly) == FALSE ) {
235 qDebug("couldn't open file"); 235 qDebug("couldn't open file");
236 delete d->input; 236 delete d->input;
237 d->input = 0; 237 d->input = 0;
238 return FALSE; 238 return FALSE;
239 } 239 }
240 240
241 d->initialise(); 241 d->initialise();
242 242
243 return TRUE; 243 return TRUE;
244} 244}
245 245
246 246
247bool WavPlugin::close() { 247bool WavPlugin::close() {
248 debugMsg( "WavPlugin::close" ); 248 debugMsg( "WavPlugin::close" );
249 249
250 d->input->close(); 250 d->input->close();
251 delete d->input; 251 delete d->input;
252 d->input = 0; 252 d->input = 0;
253 return TRUE; 253 return TRUE;
254} 254}
255 255
256 256
257bool WavPlugin::isOpen() { 257bool WavPlugin::isOpen() {
258 debugMsg( "WavPlugin::isOpen" ); 258 debugMsg( "WavPlugin::isOpen" );
259 return ( d->input != 0 ); 259 return ( d->input != 0 );
260} 260}
261 261
262 262
263int WavPlugin::audioStreams() { 263int WavPlugin::audioStreams() {
264 debugMsg( "WavPlugin::audioStreams" ); 264 debugMsg( "WavPlugin::audioStreams" );
265 return 1; 265 return 1;
266} 266}
267 267
268 268
269int WavPlugin::audioChannels( int ) { 269int WavPlugin::audioChannels( int ) {
270 debugMsg( "WavPlugin::audioChannels" ); 270 debugMsg( "WavPlugin::audioChannels" );
271 return 2; // ### Always scale audio to stereo samples 271 return 2; // ### Always scale audio to stereo samples
272} 272}
273 273
274 274
275int WavPlugin::audioFrequency( int ) { 275int WavPlugin::audioFrequency( int ) {
276 debugMsg( "WavPlugin::audioFrequency" ); 276 debugMsg( "WavPlugin::audioFrequency" );
277 return 44100; // ### Always scale to frequency of 44100 277 return 44100; // ### Always scale to frequency of 44100
278} 278}
279 279
280 280
281int WavPlugin::audioSamples( int ) { 281int WavPlugin::audioSamples( int ) {
282 debugMsg( "WavPlugin::audioSamples" ); 282 debugMsg( "WavPlugin::audioSamples" );
283 return d->samples * 2 / d->chunkdata.channels; // ### Scaled samples will be made stereo, 283 return d->samples * 2 / d->chunkdata.channels; // ### Scaled samples will be made stereo,
284 // Therefore if source is mono we will double the number of samples 284 // Therefore if source is mono we will double the number of samples
285} 285}
286 286
287 287
288bool WavPlugin::audioSetSample( long, int ) { 288bool WavPlugin::audioSetSample( long, int ) {
289 debugMsg( "WavPlugin::audioSetSample" ); 289 debugMsg( "WavPlugin::audioSetSample" );
290 return FALSE; 290 return FALSE;
291} 291}
292 292
293 293
294long WavPlugin::audioGetSample( int ) { 294long WavPlugin::audioGetSample( int ) {
295 debugMsg( "WavPlugin::audioGetSample" ); 295 debugMsg( "WavPlugin::audioGetSample" );
296 return 0; 296 return 0;
297} 297}
298 298
299/* 299/*
300bool WavPlugin::audioReadSamples( short *, int, long, int ) { 300bool WavPlugin::audioReadSamples( short *, int, long, int ) {
301 debugMsg( "WavPlugin::audioReadSamples" ); 301 debugMsg( "WavPlugin::audioReadSamples" );
302 return FALSE; 302 return FALSE;
303} 303}
304 304
305 305
306bool WavPlugin::audioReReadSamples( short *, int, long, int ) { 306bool WavPlugin::audioReReadSamples( short *, int, long, int ) {
307 debugMsg( "WavPlugin::audioReReadSamples" ); 307 debugMsg( "WavPlugin::audioReReadSamples" );
308 return FALSE; 308 return FALSE;
309} 309}
310 310
311 311
312bool WavPlugin::audioReadMonoSamples( short *output, long samples, long& samplesMade, int ) { 312bool WavPlugin::audioReadMonoSamples( short *output, long samples, long& samplesMade, int ) {
313 debugMsg( "WavPlugin::audioReadMonoSamples" ); 313 debugMsg( "WavPlugin::audioReadMonoSamples" );
314 return !d->add( output, samples, samplesMade, FALSE ); 314 return !d->add( output, samples, samplesMade, FALSE );
315} 315}
316 316
317 317
318bool WavPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) { 318bool WavPlugin::audioReadStereoSamples( short *output, long samples, long& samplesMade, int ) {
319 debugMsg( "WavPlugin::audioReadStereoSamples" ); 319 debugMsg( "WavPlugin::audioReadStereoSamples" );
320 return !d->add( output, samples, samplesMade, TRUE ); 320 return !d->add( output, samples, samplesMade, TRUE );
321} 321}
322*/ 322*/
323 323
324bool WavPlugin::audioReadSamples( short *output, int channels, long samples, long& samplesMade, int ) { 324bool WavPlugin::audioReadSamples( short *output, int channels, long samples, long& samplesMade, int ) {
325 debugMsg( "WavPlugin::audioReadSamples" ); 325 debugMsg( "WavPlugin::audioReadSamples" );
326 return !d->add( output, samples, samplesMade, channels != 1 ); 326 return d->add( output, samples, samplesMade, channels != 1 );
327} 327}
328 328
329double WavPlugin::getTime() { 329double WavPlugin::getTime() {
330 debugMsg( "WavPlugin::getTime" ); 330 debugMsg( "WavPlugin::getTime" );
331 return 0.0; 331 return 0.0;
332} 332}
333 333
334 334