summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/multimedia/opieplayer/audiodevice.cpp37
-rw-r--r--core/multimedia/opieplayer/loopcontrol_threaded.cpp33
2 files changed, 35 insertions, 35 deletions
diff --git a/core/multimedia/opieplayer/audiodevice.cpp b/core/multimedia/opieplayer/audiodevice.cpp
index 6a38fc9..d296d27 100644
--- a/core/multimedia/opieplayer/audiodevice.cpp
+++ b/core/multimedia/opieplayer/audiodevice.cpp
@@ -1,322 +1,323 @@
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// L.J.Potter added better error code Fri 02-15-2002 14:37:47 20// L.J.Potter added better error code Fri 02-15-2002 14:37:47
21 21
22 22
23#include <stdlib.h> 23#include <stdlib.h>
24#include <stdio.h> 24#include <stdio.h>
25#include <qpe/qpeapplication.h> 25#include <qpe/qpeapplication.h>
26#include <qpe/config.h> 26#include <qpe/config.h>
27#include <qpe/custom.h>
27#include <qmessagebox.h> 28#include <qmessagebox.h>
28 29
29#include "audiodevice.h" 30#include "audiodevice.h"
30 31
31 32
32#include <errno.h> 33#include <errno.h>
33 34
34#if ( defined Q_WS_QWS || defined(_WS_QWS_) ) && !defined(QT_NO_COP) 35#if !defined(QT_NO_COP)
35#include "qpe/qcopenvelope_qws.h" 36#include <qpe/qcopenvelope_qws.h>
36#endif 37#endif
37 38
38#if defined(Q_WS_X11) || defined(Q_WS_QWS) 39#if defined(Q_WS_X11) || defined(Q_WS_QWS)
39#include <fcntl.h> 40#include <fcntl.h>
40#include <sys/ioctl.h> 41#include <sys/ioctl.h>
41#include <sys/soundcard.h> 42#include <sys/soundcard.h>
42#include <sys/stat.h> 43#include <sys/stat.h>
43#include <sys/time.h> 44#include <sys/time.h>
44#include <sys/types.h> 45#include <sys/types.h>
45#include <unistd.h> 46#include <unistd.h>
46#endif 47#endif
47 48
48# if defined(QT_QWS_IPAQ) 49#ifdef OPIE_SOUND_FRAGMENT_SHIFT
49static const int sound_fragment_shift = 14; 50static const int sound_fragment_shift = OPIE_SOUND_FRAGMENT_SHIFT;
50# else 51#else
51static const int sound_fragment_shift = 16; 52static const int sound_fragment_shift = 16;
52# endif 53#endif
53static const int sound_fragment_bytes = (1<<sound_fragment_shift); 54static const int sound_fragment_bytes = (1<<sound_fragment_shift);
54//#endif 55//#endif
55 56
56 57
57class AudioDevicePrivate { 58class AudioDevicePrivate {
58public: 59public:
59 int handle; 60 int handle;
60 unsigned int frequency; 61 unsigned int frequency;
61 unsigned int channels; 62 unsigned int channels;
62 unsigned int bytesPerSample; 63 unsigned int bytesPerSample;
63 unsigned int bufferSize; 64 unsigned int bufferSize;
64//#ifndef Q_OS_WIN32 65//#ifndef Q_OS_WIN32
65 bool can_GETOSPACE; 66 bool can_GETOSPACE;
66 char* unwrittenBuffer; 67 char* unwrittenBuffer;
67 unsigned int unwritten; 68 unsigned int unwritten;
68//#endif 69//#endif
69 70
70 static int dspFd; 71 static int dspFd;
71 static bool muted; 72 static bool muted;
72 static unsigned int leftVolume; 73 static unsigned int leftVolume;
73 static unsigned int rightVolume; 74 static unsigned int rightVolume;
74}; 75};
75 76
76 77
77#ifdef Q_WS_QWS 78#ifdef Q_WS_QWS
78// This is for keeping the device open in-between playing files when 79// This is for keeping the device open in-between playing files when
79// the device makes clicks and it starts to drive you insane! :) 80// the device makes clicks and it starts to drive you insane! :)
80// Best to have the device not open when not using it though 81// Best to have the device not open when not using it though
81//#define KEEP_DEVICE_OPEN 82//#define KEEP_DEVICE_OPEN
82#endif 83#endif
83 84
84 85
85int AudioDevicePrivate::dspFd = 0; 86int AudioDevicePrivate::dspFd = 0;
86bool AudioDevicePrivate::muted = FALSE; 87bool AudioDevicePrivate::muted = FALSE;
87unsigned int AudioDevicePrivate::leftVolume = 0; 88unsigned int AudioDevicePrivate::leftVolume = 0;
88unsigned int AudioDevicePrivate::rightVolume = 0; 89unsigned int AudioDevicePrivate::rightVolume = 0;
89 90
90 91
91void AudioDevice::getVolume( unsigned int& leftVolume, unsigned int& rightVolume, bool &muted ) { 92void AudioDevice::getVolume( unsigned int& leftVolume, unsigned int& rightVolume, bool &muted ) {
92 muted = AudioDevicePrivate::muted; 93 muted = AudioDevicePrivate::muted;
93 unsigned int volume; 94 unsigned int volume;
94#ifdef QT_QWS_DEVFS 95#ifdef QT_QWS_DEVFS
95 int mixerHandle = open( "/dev/sound/mixer", O_RDWR ); 96 int mixerHandle = open( "/dev/sound/mixer", O_RDWR );
96#else 97#else
97 int mixerHandle = open( "/dev/mixer", O_RDWR ); 98 int mixerHandle = open( "/dev/mixer", O_RDWR );
98#endif 99#endif
99 if ( mixerHandle >= 0 ) { 100 if ( mixerHandle >= 0 ) {
100 if(ioctl( mixerHandle, MIXER_READ(0), &volume )==-1) 101 if(ioctl( mixerHandle, MIXER_READ(0), &volume )==-1)
101 perror("ioctl(\"MIXER_READ\")"); 102 perror("ioctl(\"MIXER_READ\")");
102 close( mixerHandle ); 103 close( mixerHandle );
103 } else 104 } else
104 perror("open(\"/dev/mixer\")"); 105 perror("open(\"/dev/mixer\")");
105 leftVolume = ((volume & 0x00FF) << 16) / 101; 106 leftVolume = ((volume & 0x00FF) << 16) / 101;
106 rightVolume = ((volume & 0xFF00) << 8) / 101; 107 rightVolume = ((volume & 0xFF00) << 8) / 101;
107} 108}
108 109
109 110
110void AudioDevice::setVolume( unsigned int leftVolume, unsigned int rightVolume, bool muted ) { 111void AudioDevice::setVolume( unsigned int leftVolume, unsigned int rightVolume, bool muted ) {
111 AudioDevicePrivate::muted = muted; 112 AudioDevicePrivate::muted = muted;
112 if ( muted ) { 113 if ( muted ) {
113 AudioDevicePrivate::leftVolume = leftVolume; 114 AudioDevicePrivate::leftVolume = leftVolume;
114 AudioDevicePrivate::rightVolume = rightVolume; 115 AudioDevicePrivate::rightVolume = rightVolume;
115 leftVolume = 0; 116 leftVolume = 0;
116 rightVolume = 0; 117 rightVolume = 0;
117 } else { 118 } else {
118 leftVolume = ( (int) leftVolume < 0 ) ? 0 : (( leftVolume > 0xFFFF ) ? 0xFFFF : leftVolume ); 119 leftVolume = ( (int) leftVolume < 0 ) ? 0 : (( leftVolume > 0xFFFF ) ? 0xFFFF : leftVolume );
119 rightVolume = ( (int)rightVolume < 0 ) ? 0 : (( rightVolume > 0xFFFF ) ? 0xFFFF : rightVolume ); 120 rightVolume = ( (int)rightVolume < 0 ) ? 0 : (( rightVolume > 0xFFFF ) ? 0xFFFF : rightVolume );
120 } 121 }
121 // Volume can be from 0 to 100 which is 101 distinct values 122 // Volume can be from 0 to 100 which is 101 distinct values
122 unsigned int rV = (rightVolume * 101) >> 16; 123 unsigned int rV = (rightVolume * 101) >> 16;
123 124
124# if 0 125# if 0
125 unsigned int lV = (leftVolume * 101) >> 16; 126 unsigned int lV = (leftVolume * 101) >> 16;
126 unsigned int volume = ((rV << 8) & 0xFF00) | (lV & 0x00FF); 127 unsigned int volume = ((rV << 8) & 0xFF00) | (lV & 0x00FF);
127 int mixerHandle = 0; 128 int mixerHandle = 0;
128#ifdef QT_QWS_DEVFS 129#ifdef QT_QWS_DEVFS
129 if ( ( mixerHandle = open( "/dev/sound/mixer", O_RDWR ) ) >= 0 ) { 130 if ( ( mixerHandle = open( "/dev/sound/mixer", O_RDWR ) ) >= 0 ) {
130#else 131#else
131 if ( ( mixerHandle = open( "/dev/mixer", O_RDWR ) ) >= 0 ) { 132 if ( ( mixerHandle = open( "/dev/mixer", O_RDWR ) ) >= 0 ) {
132#endif 133#endif
133 if(ioctl( mixerHandle, MIXER_WRITE(0), &volume ) ==-1) 134 if(ioctl( mixerHandle, MIXER_WRITE(0), &volume ) ==-1)
134 perror("ioctl(\"MIXER_WRITE\")"); 135 perror("ioctl(\"MIXER_WRITE\")");
135 close( mixerHandle ); 136 close( mixerHandle );
136 } else 137 } else
137 perror("open(\"/dev/mixer\")"); 138 perror("open(\"/dev/mixer\")");
138 139
139# else 140# else
140 // This is the way this has to be done now I guess, doesn't allow for 141 // This is the way this has to be done now I guess, doesn't allow for
141 // independant right and left channel setting, or setting for different outputs 142 // independant right and left channel setting, or setting for different outputs
142 Config cfg("qpe"); // qtopia is "Sound" 143 Config cfg("qpe"); // qtopia is "Sound"
143 cfg.setGroup("Volume"); // qtopia is "Settings" 144 cfg.setGroup("Volume"); // qtopia is "Settings"
144 cfg.writeEntry("VolumePercent",(int)rV); //qtopia is Volume 145 cfg.writeEntry("VolumePercent",(int)rV); //qtopia is Volume
145# endif 146# endif
146 147
147//#endif 148//#endif
148// qDebug( "setting volume to: 0x%x", volume ); 149// qDebug( "setting volume to: 0x%x", volume );
149#if ( defined Q_WS_QWS || defined(_WS_QWS_) ) && !defined(QT_NO_COP) 150#if ( defined Q_WS_QWS || defined(_WS_QWS_) ) && !defined(QT_NO_COP)
150 // Send notification that the volume has changed 151 // Send notification that the volume has changed
151 QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << muted; 152 QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << muted;
152#endif 153#endif
153} 154}
154 155
155 156
156 157
157AudioDevice::AudioDevice( unsigned int f, unsigned int chs, unsigned int bps ) { 158AudioDevice::AudioDevice( unsigned int f, unsigned int chs, unsigned int bps ) {
158 // qDebug("creating new audio device"); 159 // qDebug("creating new audio device");
159// QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << TRUE; 160// QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << TRUE;
160 d = new AudioDevicePrivate; 161 d = new AudioDevicePrivate;
161 d->frequency = f; 162 d->frequency = f;
162 d->channels = chs; 163 d->channels = chs;
163 d->bytesPerSample = bps; 164 d->bytesPerSample = bps;
164 // qDebug("%d",bps); 165 // qDebug("%d",bps);
165 int format=0; 166 int format=0;
166 if( bps == 8) format = AFMT_U8; 167 if( bps == 8) format = AFMT_U8;
167 else if( bps <= 0) format = AFMT_S16_LE; 168 else if( bps <= 0) format = AFMT_S16_LE;
168 else format = AFMT_S16_LE; 169 else format = AFMT_S16_LE;
169 // qDebug("AD- freq %d, channels %d, b/sample %d, bitrate %d",f,chs,bps,format); 170 // qDebug("AD- freq %d, channels %d, b/sample %d, bitrate %d",f,chs,bps,format);
170 connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( volumeChanged(bool) ) ); 171 connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( volumeChanged(bool) ) );
171 172
172 int fragments = 0x10000 * 8 + sound_fragment_shift; 173 int fragments = 0x10000 * 8 + sound_fragment_shift;
173 int capabilities = 0; 174 int capabilities = 0;
174 175
175 176
176#ifdef KEEP_DEVICE_OPEN 177#ifdef KEEP_DEVICE_OPEN
177 if ( AudioDevicePrivate::dspFd == 0 ) { 178 if ( AudioDevicePrivate::dspFd == 0 ) {
178#endif 179#endif
179#ifdef QT_QWS_DEVFS 180#ifdef QT_QWS_DEVFS
180 if ( ( d->handle = ::open( "/dev/sound/dsp", O_WRONLY ) ) < 0 ) { 181 if ( ( d->handle = ::open( "/dev/sound/dsp", O_WRONLY ) ) < 0 ) {
181#else 182#else
182 if ( ( d->handle = ::open( "/dev/dsp", O_WRONLY ) ) < 0 ) { 183 if ( ( d->handle = ::open( "/dev/dsp", O_WRONLY ) ) < 0 ) {
183#endif 184#endif
184 185
185 perror("open(\"/dev/dsp\")"); 186 perror("open(\"/dev/dsp\")");
186 QString errorMsg=tr("Somethin's wrong with\nyour sound device.\nopen(\"/dev/dsp\")\n")+(QString)strerror(errno)+tr("\n\nClosing player now."); 187 QString errorMsg=tr("Somethin's wrong with\nyour sound device.\nopen(\"/dev/dsp\")\n")+(QString)strerror(errno)+tr("\n\nClosing player now.");
187 QMessageBox::critical(0, "Vmemo", errorMsg, tr("Abort")); 188 QMessageBox::critical(0, "Vmemo", errorMsg, tr("Abort"));
188 exit(-1); //harsh? 189 exit(-1); //harsh?
189 } 190 }
190#ifdef KEEP_DEVICE_OPEN 191#ifdef KEEP_DEVICE_OPEN
191 AudioDevicePrivate::dspFd = d->handle; 192 AudioDevicePrivate::dspFd = d->handle;
192 } else { 193 } else {
193 d->handle = AudioDevicePrivate::dspFd; 194 d->handle = AudioDevicePrivate::dspFd;
194 } 195 }
195#endif 196#endif
196 197
197 if(ioctl( d->handle, SNDCTL_DSP_GETCAPS, &capabilities )==-1) 198 if(ioctl( d->handle, SNDCTL_DSP_GETCAPS, &capabilities )==-1)
198 perror("ioctl(\"SNDCTL_DSP_GETCAPS\")"); 199 perror("ioctl(\"SNDCTL_DSP_GETCAPS\")");
199 if(ioctl( d->handle, SNDCTL_DSP_SETFRAGMENT, &fragments )==-1) 200 if(ioctl( d->handle, SNDCTL_DSP_SETFRAGMENT, &fragments )==-1)
200 perror("ioctl(\"SNDCTL_DSP_SETFRAGMENT\")"); 201 perror("ioctl(\"SNDCTL_DSP_SETFRAGMENT\")");
201 if(ioctl( d->handle, SNDCTL_DSP_SETFMT, & format )==-1) 202 if(ioctl( d->handle, SNDCTL_DSP_SETFMT, & format )==-1)
202 perror("ioctl(\"SNDCTL_DSP_SETFMT\")"); 203 perror("ioctl(\"SNDCTL_DSP_SETFMT\")");
203 // qDebug("freq %d", d->frequency); 204 // qDebug("freq %d", d->frequency);
204 if(ioctl( d->handle, SNDCTL_DSP_SPEED, &d->frequency )==-1) 205 if(ioctl( d->handle, SNDCTL_DSP_SPEED, &d->frequency )==-1)
205 perror("ioctl(\"SNDCTL_DSP_SPEED\")"); 206 perror("ioctl(\"SNDCTL_DSP_SPEED\")");
206 // qDebug("channels %d",d->channels); 207 // qDebug("channels %d",d->channels);
207 if ( ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels ) == -1 ) { 208 if ( ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels ) == -1 ) {
208 d->channels = ( d->channels == 1 ) ? 2 : d->channels; 209 d->channels = ( d->channels == 1 ) ? 2 : d->channels;
209 if(ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels )==-1) 210 if(ioctl( d->handle, SNDCTL_DSP_CHANNELS, &d->channels )==-1)
210 perror("ioctl(\"SNDCTL_DSP_CHANNELS\")"); 211 perror("ioctl(\"SNDCTL_DSP_CHANNELS\")");
211 } 212 }
212// QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << FALSE; 213// QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << FALSE;
213 214
214 d->bufferSize = sound_fragment_bytes; 215 d->bufferSize = sound_fragment_bytes;
215 d->unwrittenBuffer = new char[d->bufferSize]; 216 d->unwrittenBuffer = new char[d->bufferSize];
216 d->unwritten = 0; 217 d->unwritten = 0;
217 d->can_GETOSPACE = TRUE; // until we find otherwise 218 d->can_GETOSPACE = TRUE; // until we find otherwise
218 219
219 //if ( chs != d->channels ) qDebug( "Wanted %d, got %d channels", chs, d->channels ); 220 //if ( chs != d->channels ) qDebug( "Wanted %d, got %d channels", chs, d->channels );
220 //if ( f != d->frequency ) qDebug( "wanted %dHz, got %dHz", f, d->frequency ); 221 //if ( f != d->frequency ) qDebug( "wanted %dHz, got %dHz", f, d->frequency );
221 //if ( capabilities & DSP_CAP_BATCH ) qDebug( "Sound card has local buffer" ); 222 //if ( capabilities & DSP_CAP_BATCH ) qDebug( "Sound card has local buffer" );
222 //if ( capabilities & DSP_CAP_REALTIME )qDebug( "Sound card has realtime sync" ); 223 //if ( capabilities & DSP_CAP_REALTIME )qDebug( "Sound card has realtime sync" );
223 //if ( capabilities & DSP_CAP_TRIGGER ) qDebug( "Sound card has precise trigger" ); 224 //if ( capabilities & DSP_CAP_TRIGGER ) qDebug( "Sound card has precise trigger" );
224 //if ( capabilities & DSP_CAP_MMAP ) qDebug( "Sound card can mmap" ); 225 //if ( capabilities & DSP_CAP_MMAP ) qDebug( "Sound card can mmap" );
225 226
226} 227}
227 228
228 229
229AudioDevice::~AudioDevice() { 230AudioDevice::~AudioDevice() {
230 // qDebug("destryo audiodevice"); 231 // qDebug("destryo audiodevice");
231// QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << TRUE; 232// QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << TRUE;
232 233
233# ifndef KEEP_DEVICE_OPEN 234# ifndef KEEP_DEVICE_OPEN
234 close( d->handle ); // Now it should be safe to shut the handle 235 close( d->handle ); // Now it should be safe to shut the handle
235# endif 236# endif
236 delete d->unwrittenBuffer; 237 delete d->unwrittenBuffer;
237 delete d; 238 delete d;
238// QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << FALSE; 239// QCopEnvelope( "QPE/System", "volumeChange(bool)" ) << FALSE;
239 240
240} 241}
241 242
242 243
243void AudioDevice::volumeChanged( bool muted ) 244void AudioDevice::volumeChanged( bool muted )
244{ 245{
245 AudioDevicePrivate::muted = muted; 246 AudioDevicePrivate::muted = muted;
246} 247}
247 248
248 249
249void AudioDevice::write( char *buffer, unsigned int length ) 250void AudioDevice::write( char *buffer, unsigned int length )
250{ 251{
251 int t = ::write( d->handle, buffer, length ); 252 int t = ::write( d->handle, buffer, length );
252 if ( t<0 ) t = 0; 253 if ( t<0 ) t = 0;
253 if ( t != (int)length) { 254 if ( t != (int)length) {
254 // qDebug("Ahhh!! memcpys 1"); 255 // qDebug("Ahhh!! memcpys 1");
255 memcpy(d->unwrittenBuffer,buffer+t,length-t); 256 memcpy(d->unwrittenBuffer,buffer+t,length-t);
256 d->unwritten = length-t; 257 d->unwritten = length-t;
257 } 258 }
258//#endif 259//#endif
259} 260}
260 261
261 262
262unsigned int AudioDevice::channels() const 263unsigned int AudioDevice::channels() const
263{ 264{
264 return d->channels; 265 return d->channels;
265} 266}
266 267
267 268
268unsigned int AudioDevice::frequency() const 269unsigned int AudioDevice::frequency() const
269{ 270{
270 return d->frequency; 271 return d->frequency;
271} 272}
272 273
273 274
274unsigned int AudioDevice::bytesPerSample() const 275unsigned int AudioDevice::bytesPerSample() const
275{ 276{
276 return d->bytesPerSample; 277 return d->bytesPerSample;
277} 278}
278 279
279 280
280unsigned int AudioDevice::bufferSize() const 281unsigned int AudioDevice::bufferSize() const
281{ 282{
282 return d->bufferSize; 283 return d->bufferSize;
283} 284}
284 285
285unsigned int AudioDevice::canWrite() const 286unsigned int AudioDevice::canWrite() const
286{ 287{
287 audio_buf_info info; 288 audio_buf_info info;
288 if ( d->can_GETOSPACE && ioctl(d->handle,SNDCTL_DSP_GETOSPACE,&info) ) { 289 if ( d->can_GETOSPACE && ioctl(d->handle,SNDCTL_DSP_GETOSPACE,&info) ) {
289 d->can_GETOSPACE = FALSE; 290 d->can_GETOSPACE = FALSE;
290 fcntl( d->handle, F_SETFL, O_NONBLOCK ); 291 fcntl( d->handle, F_SETFL, O_NONBLOCK );
291 } 292 }
292 if ( d->can_GETOSPACE ) { 293 if ( d->can_GETOSPACE ) {
293 int t = info.fragments * sound_fragment_bytes; 294 int t = info.fragments * sound_fragment_bytes;
294 return QMIN(t,(int)bufferSize()); 295 return QMIN(t,(int)bufferSize());
295 } else { 296 } else {
296 if ( d->unwritten ) { 297 if ( d->unwritten ) {
297 int t = ::write( d->handle, d->unwrittenBuffer, d->unwritten ); 298 int t = ::write( d->handle, d->unwrittenBuffer, d->unwritten );
298 if ( t<0 ) t = 0; 299 if ( t<0 ) t = 0;
299 if ( (unsigned)t!=d->unwritten ) { 300 if ( (unsigned)t!=d->unwritten ) {
300 memcpy(d->unwrittenBuffer,d->unwrittenBuffer+t,d->unwritten-t); 301 memcpy(d->unwrittenBuffer,d->unwrittenBuffer+t,d->unwritten-t);
301 d->unwritten -= t; 302 d->unwritten -= t;
302 } else { 303 } else {
303 d->unwritten = 0; 304 d->unwritten = 0;
304 } 305 }
305 } 306 }
306 if ( d->unwritten ) 307 if ( d->unwritten )
307 return 0; 308 return 0;
308 else 309 else
309 return d->bufferSize; 310 return d->bufferSize;
310 } 311 }
311} 312}
312 313
313 314
314int AudioDevice::bytesWritten() { 315int AudioDevice::bytesWritten() {
315 int buffered = 0; 316 int buffered = 0;
316 if ( ioctl( d->handle, SNDCTL_DSP_GETODELAY, &buffered ) ) { 317 if ( ioctl( d->handle, SNDCTL_DSP_GETODELAY, &buffered ) ) {
317 // qDebug( "failed to get audio device position" ); 318 // qDebug( "failed to get audio device position" );
318 return -1; 319 return -1;
319 } 320 }
320 return buffered; 321 return buffered;
321} 322}
322 323
diff --git a/core/multimedia/opieplayer/loopcontrol_threaded.cpp b/core/multimedia/opieplayer/loopcontrol_threaded.cpp
index 364e77b..3796549 100644
--- a/core/multimedia/opieplayer/loopcontrol_threaded.cpp
+++ b/core/multimedia/opieplayer/loopcontrol_threaded.cpp
@@ -1,625 +1,624 @@
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#define _REENTRANT 20#define _REENTRANT
21 21
22#include <qpe/qpeapplication.h> 22#include <qpe/qpeapplication.h>
23#include <qpe/custom.h>
23#include <qimage.h> 24#include <qimage.h>
24#include <qpainter.h> 25#include <qpainter.h>
25#ifdef Q_WS_QWS 26#if !defined(QT_NO_COP)
26#include <qpe/qcopenvelope_qws.h> 27#include <qpe/qcopenvelope_qws.h>
27#endif 28#endif
28#include "mediaplayerplugininterface.h" 29#include "mediaplayerplugininterface.h"
29#include <stdio.h> 30#include <stdio.h>
30#include <stdlib.h> 31#include <stdlib.h>
31#include <string.h> 32#include <string.h>
32#include <time.h> 33#include <time.h>
33#include <unistd.h> 34#include <unistd.h>
34#include <pthread.h> 35#include <pthread.h>
35#include "loopcontrol.h" 36#include "loopcontrol.h"
36#include "audiodevice.h" 37#include "audiodevice.h"
37#include "videowidget.h" 38#include "videowidget.h"
38#include "audiowidget.h" 39#include "audiowidget.h"
39#include "mediaplayerstate.h" 40#include "mediaplayerstate.h"
40 41
41 42
42#if defined(QT_QWS_SL5XXX) || defined(QT_QWS_IPAQ) || defined(QT_QWS_RAMSES) 43
43#define USE_REALTIME_AUDIO_THREAD
44#endif
45 44
46 45
47extern VideoWidget *videoUI; // now only needed to tell it to play a frame 46extern VideoWidget *videoUI; // now only needed to tell it to play a frame
48extern MediaPlayerState *mediaPlayerState; 47extern MediaPlayerState *mediaPlayerState;
49 48
50 49
51#define DecodeLoopDebug(x) qDebug x 50#define DecodeLoopDebug(x) qDebug x
52//#define DecodeLoopDebug(x) 51//#define DecodeLoopDebug(x)
53 52
54 53
55static char *audioBuffer = NULL; 54static char *audioBuffer = NULL;
56static AudioDevice *audioDevice = NULL; 55static AudioDevice *audioDevice = NULL;
57static bool disabledSuspendScreenSaver = FALSE; 56static bool disabledSuspendScreenSaver = FALSE;
58 57
59 58
60pthread_t video_tid; 59pthread_t video_tid;
61pthread_attr_t video_attr; 60pthread_attr_t video_attr;
62pthread_t audio_tid; 61pthread_t audio_tid;
63pthread_attr_t audio_attr; 62pthread_attr_t audio_attr;
64 63
65 64
66bool emitPlayFinished = FALSE; 65bool emitPlayFinished = FALSE;
67bool emitChangePos = FALSE; 66bool emitChangePos = FALSE;
68 67
69 68
70class Mutex { 69class Mutex {
71public: 70public:
72 Mutex() { 71 Mutex() {
73 pthread_mutexattr_t attr; 72 pthread_mutexattr_t attr;
74 pthread_mutexattr_init( &attr ); 73 pthread_mutexattr_init( &attr );
75 pthread_mutex_init( &mutex, &attr ); 74 pthread_mutex_init( &mutex, &attr );
76 pthread_mutexattr_destroy( &attr ); 75 pthread_mutexattr_destroy( &attr );
77 } 76 }
78 77
79 ~Mutex() { 78 ~Mutex() {
80 pthread_mutex_destroy( &mutex ); 79 pthread_mutex_destroy( &mutex );
81 } 80 }
82 81
83 void lock() { 82 void lock() {
84 pthread_mutex_lock( &mutex ); 83 pthread_mutex_lock( &mutex );
85 } 84 }
86 85
87 void unlock() { 86 void unlock() {
88 pthread_mutex_unlock( &mutex ); 87 pthread_mutex_unlock( &mutex );
89 } 88 }
90/* 89/*
91 bool locked() { 90 bool locked() {
92 switch ( pthread_mutex_trylock( &mutex ) ) { 91 switch ( pthread_mutex_trylock( &mutex ) ) {
93 case EBUSY: 92 case EBUSY:
94 return TRUE; 93 return TRUE;
95 case 0: 94 case 0:
96 pthread_mutex_unlock( &mutex ); 95 pthread_mutex_unlock( &mutex );
97 default: 96 default:
98 return FALSE; 97 return FALSE;
99 } 98 }
100 } 99 }
101*/ 100*/
102private: 101private:
103 pthread_mutex_t mutex; 102 pthread_mutex_t mutex;
104}; 103};
105 104
106 105
107class currentFrameObj { 106class currentFrameObj {
108public: 107public:
109 currentFrameObj() : value( 0 ) { } 108 currentFrameObj() : value( 0 ) { }
110 void set( long f ) { 109 void set( long f ) {
111 mutex.lock(); 110 mutex.lock();
112 value = f; 111 value = f;
113 mediaPlayerState->curDecoder()->videoSetFrame( f, 0 ); 112 mediaPlayerState->curDecoder()->videoSetFrame( f, 0 );
114 mutex.unlock(); 113 mutex.unlock();
115 } 114 }
116 long get() { 115 long get() {
117 return value; 116 return value;
118 } 117 }
119private: 118private:
120 long value; 119 long value;
121 Mutex mutex; 120 Mutex mutex;
122}; 121};
123 122
124 123
125Mutex *videoMutex; 124Mutex *videoMutex;
126Mutex *audioMutex; 125Mutex *audioMutex;
127Mutex *globalMutex; 126Mutex *globalMutex;
128 127
129 128
130clock_t begin; 129clock_t begin;
131 130
132 131
133LoopControl::LoopControl( QObject *parent, const char *name ) 132LoopControl::LoopControl( QObject *parent, const char *name )
134 : QObject( parent, name ) { 133 : QObject( parent, name ) {
135 isMuted = FALSE; 134 isMuted = FALSE;
136 connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( setMute(bool) ) ); 135 connect( qApp, SIGNAL( volumeChanged(bool) ), this, SLOT( setMute(bool) ) );
137 timerid = startTimer( 200 ); 136 timerid = startTimer( 200 );
138 videoMutex = new Mutex; 137 videoMutex = new Mutex;
139 audioMutex = new Mutex; 138 audioMutex = new Mutex;
140 globalMutex = new Mutex; 139 globalMutex = new Mutex;
141 //begin = clock(); 140 //begin = clock();
142} 141}
143 142
144 143
145LoopControl::~LoopControl() { 144LoopControl::~LoopControl() {
146 stop(); 145 stop();
147 killTimer( timerid ); 146 killTimer( timerid );
148} 147}
149 148
150 149
151static bool sendingNewPos = FALSE; 150static bool sendingNewPos = FALSE;
152static long prev_frame = 0; 151static long prev_frame = 0;
153static int currentSample = 0; 152static int currentSample = 0;
154 153
155 154
156void LoopControl::timerEvent( QTimerEvent* ) { 155void LoopControl::timerEvent( QTimerEvent* ) {
157 // We need to emit playFinished from the main thread, not one of the 156 // We need to emit playFinished from the main thread, not one of the
158 // decoding threads else we'll have all kinds of yucky things happen (reentrance). 157 // decoding threads else we'll have all kinds of yucky things happen (reentrance).
159 // playFinished will eventually call stop() which stops these threads. 158 // playFinished will eventually call stop() which stops these threads.
160 if ( emitPlayFinished ) { 159 if ( emitPlayFinished ) {
161 emitPlayFinished = FALSE; 160 emitPlayFinished = FALSE;
162 mediaPlayerState->setPlaying( FALSE ); 161 mediaPlayerState->setPlaying( FALSE );
163 } 162 }
164 163
165 if ( emitChangePos ) { 164 if ( emitChangePos ) {
166 165
167 emitChangePos = FALSE; 166 emitChangePos = FALSE;
168 167
169 if ( hasVideoChannel && hasAudioChannel ) { 168 if ( hasVideoChannel && hasAudioChannel ) {
170 sendingNewPos = TRUE; 169 sendingNewPos = TRUE;
171 mediaPlayerState->setPosition( current_frame ); 170 mediaPlayerState->setPosition( current_frame );
172 } else if ( hasVideoChannel ) { 171 } else if ( hasVideoChannel ) {
173 sendingNewPos = TRUE; 172 sendingNewPos = TRUE;
174 mediaPlayerState->setPosition( current_frame ); 173 mediaPlayerState->setPosition( current_frame );
175 } else if ( hasAudioChannel ) { 174 } else if ( hasAudioChannel ) {
176 sendingNewPos = TRUE; 175 sendingNewPos = TRUE;
177 mediaPlayerState->setPosition( audioSampleCounter ); 176 mediaPlayerState->setPosition( audioSampleCounter );
178 } 177 }
179 178
180 } 179 }
181} 180}
182 181
183 182
184 183
185 184
186void LoopControl::setPosition( long pos ) { 185void LoopControl::setPosition( long pos ) {
187 if ( sendingNewPos ) { 186 if ( sendingNewPos ) {
188 sendingNewPos = FALSE; 187 sendingNewPos = FALSE;
189 return; 188 return;
190 } 189 }
191 190
192 if ( hasVideoChannel && hasAudioChannel ) { 191 if ( hasVideoChannel && hasAudioChannel ) {
193 videoMutex->lock(); 192 videoMutex->lock();
194 audioMutex->lock(); 193 audioMutex->lock();
195 //qDebug("setting position"); 194 //qDebug("setting position");
196 playtime.restart(); 195 playtime.restart();
197 playtime = playtime.addMSecs( -pos * 1000 / framerate ); 196 playtime = playtime.addMSecs( -pos * 1000 / framerate );
198 //begin = clock() - (double)pos * CLOCKS_PER_SEC / framerate; 197 //begin = clock() - (double)pos * CLOCKS_PER_SEC / framerate;
199 current_frame = pos + 1; 198 current_frame = pos + 1;
200 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); 199 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream );
201 prev_frame = current_frame - 1; 200 prev_frame = current_frame - 1;
202 currentSample = (int)( current_frame * freq / framerate ); 201 currentSample = (int)( current_frame * freq / framerate );
203 mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream ); 202 mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream );
204 audioSampleCounter = currentSample - 1; 203 audioSampleCounter = currentSample - 1;
205 audioMutex->unlock(); 204 audioMutex->unlock();
206 videoMutex->unlock(); 205 videoMutex->unlock();
207 } else if ( hasVideoChannel ) { 206 } else if ( hasVideoChannel ) {
208 videoMutex->lock(); 207 videoMutex->lock();
209 playtime.restart(); 208 playtime.restart();
210 playtime = playtime.addMSecs( -pos * 1000 / framerate ); 209 playtime = playtime.addMSecs( -pos * 1000 / framerate );
211 //begin = clock() - (double)pos * CLOCKS_PER_SEC / framerate; 210 //begin = clock() - (double)pos * CLOCKS_PER_SEC / framerate;
212 current_frame = pos + 1; 211 current_frame = pos + 1;
213 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); 212 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream );
214 videoMutex->unlock(); 213 videoMutex->unlock();
215 prev_frame = current_frame - 1; 214 prev_frame = current_frame - 1;
216 } else if ( hasAudioChannel ) { 215 } else if ( hasAudioChannel ) {
217 audioMutex->lock(); 216 audioMutex->lock();
218 playtime.restart(); 217 playtime.restart();
219 playtime = playtime.addMSecs( -pos * 1000 / freq ); 218 playtime = playtime.addMSecs( -pos * 1000 / freq );
220 //begin = clock() - (double)pos * CLOCKS_PER_SEC / freq; 219 //begin = clock() - (double)pos * CLOCKS_PER_SEC / freq;
221 currentSample = pos + 1; // (int)( current_frame * freq / framerate ); 220 currentSample = pos + 1; // (int)( current_frame * freq / framerate );
222 mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream ); 221 mediaPlayerState->curDecoder()->audioSetSample( currentSample, stream );
223 audioSampleCounter = currentSample - 1; 222 audioSampleCounter = currentSample - 1;
224 audioMutex->unlock(); 223 audioMutex->unlock();
225 } 224 }
226} 225}
227 226
228 227
229void *startVideoThread( void *ptr ) { 228void *startVideoThread( void *ptr ) {
230 LoopControl *mpegView = (LoopControl *)ptr; 229 LoopControl *mpegView = (LoopControl *)ptr;
231 mpegView->startVideo(); 230 mpegView->startVideo();
232 return 0; 231 return 0;
233} 232}
234 233
235void *startAudioThread( void *ptr ) { 234void *startAudioThread( void *ptr ) {
236 LoopControl *mpegView = (LoopControl *)ptr; 235 LoopControl *mpegView = (LoopControl *)ptr;
237 mpegView->startAudio(); 236 mpegView->startAudio();
238 return 0; 237 return 0;
239} 238}
240 239
241void LoopControl::startVideo() { 240void LoopControl::startVideo() {
242 moreVideo = TRUE; 241 moreVideo = TRUE;
243 242
244 while ( moreVideo ) { 243 while ( moreVideo ) {
245 244
246 if ( mediaPlayerState->curDecoder() && hasVideoChannel ) { 245 if ( mediaPlayerState->curDecoder() && hasVideoChannel ) {
247 246
248 if ( hasAudioChannel && !isMuted ) { 247 if ( hasAudioChannel && !isMuted ) {
249 248
250 bool done = FALSE; 249 bool done = FALSE;
251 250
252 do { 251 do {
253 252
254 253
255/* 254/*
256 videoMutex->lock(); 255 videoMutex->lock();
257 current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); 256 current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 );
258 //current_frame = ( clock() - begin ) * (double)framerate / CLOCKS_PER_SEC; 257 //current_frame = ( clock() - begin ) * (double)framerate / CLOCKS_PER_SEC;
259 258
260 // Sync to Audio 259 // Sync to Audio
261// current_frame = (long)((double)(audioSampleCounter - 1000) * framerate / (double)freq); 260// current_frame = (long)((double)(audioSampleCounter - 1000) * framerate / (double)freq);
262 261
263 long mSecsToNextFrame = 0; 262 long mSecsToNextFrame = 0;
264 263
265 if ( current_frame == prev_frame ) { 264 if ( current_frame == prev_frame ) {
266 int nf = current_frame + 1; 265 int nf = current_frame + 1;
267 if ( nf > 0 && nf != total_video_frames ) 266 if ( nf > 0 && nf != total_video_frames )
268 // mSecsToNextFrame = long(double(nf * CLOCKS_PER_SEC) / framerate) - ( clock() - begin ); 267 // mSecsToNextFrame = long(double(nf * CLOCKS_PER_SEC) / framerate) - ( clock() - begin );
269 mSecsToNextFrame = long(double(nf * 1000) / framerate) - ( playtime.elapsed() ); 268 mSecsToNextFrame = long(double(nf * 1000) / framerate) - ( playtime.elapsed() );
270 } 269 }
271 videoMutex->unlock(); 270 videoMutex->unlock();
272 271
273 if ( mSecsToNextFrame ) { 272 if ( mSecsToNextFrame ) {
274 usleep( mSecsToNextFrame ); // wait a bit 273 usleep( mSecsToNextFrame ); // wait a bit
275 274
276 videoMutex->lock(); 275 videoMutex->lock();
277 // This should now be the next frame 276 // This should now be the next frame
278 current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); 277 current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 );
279 //current_frame = ( clock() - begin ) * (double)framerate / CLOCKS_PER_SEC; 278 //current_frame = ( clock() - begin ) * (double)framerate / CLOCKS_PER_SEC;
280 videoMutex->unlock(); 279 videoMutex->unlock();
281 } 280 }
282 281
283 videoMutex->lock(); 282 videoMutex->lock();
284 done = current_frame >= prev_frame; 283 done = current_frame >= prev_frame;
285 videoMutex->unlock(); 284 videoMutex->unlock();
286*/ 285*/
287 videoMutex->lock(); 286 videoMutex->lock();
288 current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 ); 287 current_frame = int( (double)playtime.elapsed() * (double)framerate / 1000.0 );
289 done = current_frame >= prev_frame; 288 done = current_frame >= prev_frame;
290 videoMutex->unlock(); 289 videoMutex->unlock();
291 if ( !done ) 290 if ( !done )
292 usleep( 1000 ); // wait a bit 291 usleep( 1000 ); // wait a bit
293 292
294 } while ( !done ); 293 } while ( !done );
295 294
296// qDebug("elapsed: %i %i (%f)", int( playtime.elapsed() ), current_frame, framerate ); 295// qDebug("elapsed: %i %i (%f)", int( playtime.elapsed() ), current_frame, framerate );
297 296
298 } else { 297 } else {
299 videoMutex->lock(); 298 videoMutex->lock();
300 current_frame++; 299 current_frame++;
301 videoMutex->unlock(); 300 videoMutex->unlock();
302 } 301 }
303 302
304 videoMutex->lock(); 303 videoMutex->lock();
305 bool check = current_frame && current_frame > prev_frame; 304 bool check = current_frame && current_frame > prev_frame;
306 videoMutex->unlock(); 305 videoMutex->unlock();
307 306
308 if ( check ) { 307 if ( check ) {
309 videoMutex->lock(); 308 videoMutex->lock();
310 if ( current_frame > prev_frame + 1 ) { 309 if ( current_frame > prev_frame + 1 ) {
311 // qDebug("skipped a frame"); 310 // qDebug("skipped a frame");
312 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream ); 311 mediaPlayerState->curDecoder()->videoSetFrame( current_frame, stream );
313 } 312 }
314 prev_frame = current_frame; 313 prev_frame = current_frame;
315 if ( moreVideo = videoUI->playVideo() ) 314 if ( moreVideo = videoUI->playVideo() )
316 emitChangePos = TRUE; 315 emitChangePos = TRUE;
317 videoMutex->unlock(); 316 videoMutex->unlock();
318 } 317 }
319 318
320 } else 319 } else
321 moreVideo = FALSE; 320 moreVideo = FALSE;
322 321
323 } 322 }
324 323
325 if ( !moreVideo && !moreAudio ) 324 if ( !moreVideo && !moreAudio )
326 emitPlayFinished = TRUE; 325 emitPlayFinished = TRUE;
327 326
328 pthread_exit(NULL); 327 pthread_exit(NULL);
329} 328}
330 329
331void LoopControl::startAudio() { 330void LoopControl::startAudio() {
332 moreAudio = TRUE; 331 moreAudio = TRUE;
333 332
334 while ( moreAudio ) { 333 while ( moreAudio ) {
335 334
336 if ( !isMuted && mediaPlayerState->curDecoder() && hasAudioChannel ) { 335 if ( !isMuted && mediaPlayerState->curDecoder() && hasAudioChannel ) {
337 336
338 audioMutex->lock(); 337 audioMutex->lock();
339 currentSample = mediaPlayerState->curDecoder()->audioGetSample( stream ); 338 currentSample = mediaPlayerState->curDecoder()->audioGetSample( stream );
340 339
341 if ( currentSample == 0 ) 340 if ( currentSample == 0 )
342 currentSample = audioSampleCounter + 1; 341 currentSample = audioSampleCounter + 1;
343 342
344// if ( currentSample != audioSampleCounter + 1 ) 343// if ( currentSample != audioSampleCounter + 1 )
345// qDebug("out of sync with decoder %i %i", currentSample, audioSampleCounter); 344// qDebug("out of sync with decoder %i %i", currentSample, audioSampleCounter);
346 audioMutex->unlock(); 345 audioMutex->unlock();
347 346
348/* 347/*
349 int sampleWeShouldBeAt = int( playtime.elapsed() ) * freq / 1000; 348 int sampleWeShouldBeAt = int( playtime.elapsed() ) * freq / 1000;
350 349
351 if ( sampleWeShouldBeAt - currentSample > 20000 ) { 350 if ( sampleWeShouldBeAt - currentSample > 20000 ) {
352 mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream ); 351 mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream );
353 currentSample = sampleWeShouldBeAt; 352 currentSample = sampleWeShouldBeAt;
354 } 353 }
355*/ 354*/
356 long samplesRead = 0; 355 long samplesRead = 0;
357 356
358 const long samples = 1024; 357 const long samples = 1024;
359 358
360 moreAudio = !mediaPlayerState->curDecoder()->audioReadSamples( (short*)audioBuffer, channels, samples, samplesRead, stream ); 359 moreAudio = !mediaPlayerState->curDecoder()->audioReadSamples( (short*)audioBuffer, channels, samples, samplesRead, stream );
361 360
362 audioMutex->lock(); 361 audioMutex->lock();
363 long sampleWeShouldBeAt = long( playtime.elapsed() ) * freq / 1000; 362 long sampleWeShouldBeAt = long( playtime.elapsed() ) * freq / 1000;
364 //long sampleWeShouldBeAt = long( clock() - begin ) * (double) freq / CLOCKS_PER_SEC; 363 //long sampleWeShouldBeAt = long( clock() - begin ) * (double) freq / CLOCKS_PER_SEC;
365 long sampleWaitTime = currentSample - sampleWeShouldBeAt; 364 long sampleWaitTime = currentSample - sampleWeShouldBeAt;
366 audioMutex->unlock(); 365 audioMutex->unlock();
367 366
368 if ( sampleWaitTime >= 0 && sampleWaitTime <= 2000 ) { 367 if ( sampleWaitTime >= 0 && sampleWaitTime <= 2000 ) {
369 //qDebug("sampleWaitTime: %i", sampleWaitTime); 368 //qDebug("sampleWaitTime: %i", sampleWaitTime);
370 usleep( ( sampleWaitTime * 1000000 ) / ( freq ) ); 369 usleep( ( sampleWaitTime * 1000000 ) / ( freq ) );
371 } else { 370 } else {
372 audioMutex->lock(); 371 audioMutex->lock();
373 if ( sampleWaitTime <= -2000 ) { 372 if ( sampleWaitTime <= -2000 ) {
374 // qDebug("need to catch up by: %li (%i,%li)", -sampleWaitTime, currentSample, sampleWeShouldBeAt ); 373 // qDebug("need to catch up by: %li (%i,%li)", -sampleWaitTime, currentSample, sampleWeShouldBeAt );
375 mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream ); 374 mediaPlayerState->curDecoder()->audioSetSample( sampleWeShouldBeAt, stream );
376 currentSample = sampleWeShouldBeAt; 375 currentSample = sampleWeShouldBeAt;
377 } 376 }
378 audioMutex->unlock(); 377 audioMutex->unlock();
379 } 378 }
380 379
381 audioDevice->write( audioBuffer, samplesRead * 2 * channels ); 380 audioDevice->write( audioBuffer, samplesRead * 2 * channels );
382 381
383 audioMutex->lock(); 382 audioMutex->lock();
384// audioSampleCounter += samplesRead; 383// audioSampleCounter += samplesRead;
385 audioSampleCounter = currentSample + samplesRead - 1; 384 audioSampleCounter = currentSample + samplesRead - 1;
386 audioMutex->unlock(); 385 audioMutex->unlock();
387 386
388 if ( !hasVideoChannel ) 387 if ( !hasVideoChannel )
389 emitChangePos = TRUE; 388 emitChangePos = TRUE;
390 389
391 //qDebug("currentSample: %i audioSampleCounter: %i total_audio_samples: %i", currentSample, audioSampleCounter, total_audio_samples); 390 //qDebug("currentSample: %i audioSampleCounter: %i total_audio_samples: %i", currentSample, audioSampleCounter, total_audio_samples);
392// qDebug("current: %i counter: %i total: %i", currentSample, audioSampleCounter, (int)total_audio_samples); 391// qDebug("current: %i counter: %i total: %i", currentSample, audioSampleCounter, (int)total_audio_samples);
393 moreAudio = audioSampleCounter <= total_audio_samples; 392 moreAudio = audioSampleCounter <= total_audio_samples;
394 393
395 } else { 394 } else {
396 395
397 if ( mediaPlayerState->curDecoder() && hasAudioChannel ) 396 if ( mediaPlayerState->curDecoder() && hasAudioChannel )
398 usleep( 100000 ); // Check every 1/10 sec to see if mute is off 397 usleep( 100000 ); // Check every 1/10 sec to see if mute is off
399 else 398 else
400 moreAudio = FALSE; 399 moreAudio = FALSE;
401 400
402 } 401 }
403 } 402 }
404 403
405 // qDebug( "End of file" ); 404 // qDebug( "End of file" );
406 405
407 if ( !moreVideo && !moreAudio ) 406 if ( !moreVideo && !moreAudio )
408 emitPlayFinished = TRUE; 407 emitPlayFinished = TRUE;
409 408
410 pthread_exit(NULL); 409 pthread_exit(NULL);
411} 410}
412 411
413void LoopControl::killTimers() { 412void LoopControl::killTimers() {
414 if ( hasVideoChannel ) { 413 if ( hasVideoChannel ) {
415 if ( pthread_self() != video_tid ) { 414 if ( pthread_self() != video_tid ) {
416 if ( pthread_cancel(video_tid) == 0 ) { 415 if ( pthread_cancel(video_tid) == 0 ) {
417 void *thread_result = 0; 416 void *thread_result = 0;
418 if ( pthread_join(video_tid,&thread_result) != 0 ) 417 if ( pthread_join(video_tid,&thread_result) != 0 )
419 // qDebug("thread join error 1"); 418 // qDebug("thread join error 1");
420 pthread_attr_destroy(&video_attr); 419 pthread_attr_destroy(&video_attr);
421 } 420 }
422 } 421 }
423 } 422 }
424 if ( hasAudioChannel ) { 423 if ( hasAudioChannel ) {
425 if ( pthread_self() != audio_tid ) { 424 if ( pthread_self() != audio_tid ) {
426 if ( pthread_cancel(audio_tid) == 0 ) { 425 if ( pthread_cancel(audio_tid) == 0 ) {
427 void *thread_result = 0; 426 void *thread_result = 0;
428 if ( pthread_join(audio_tid,&thread_result) != 0 ) 427 if ( pthread_join(audio_tid,&thread_result) != 0 )
429 // qDebug("thread join error 2"); 428 // qDebug("thread join error 2");
430 pthread_attr_destroy(&audio_attr); 429 pthread_attr_destroy(&audio_attr);
431 } 430 }
432 } 431 }
433 } 432 }
434} 433}
435 434
436void LoopControl::startTimers() { 435void LoopControl::startTimers() {
437 moreVideo = FALSE; 436 moreVideo = FALSE;
438 moreAudio = FALSE; 437 moreAudio = FALSE;
439 438
440 if ( hasVideoChannel ) { 439 if ( hasVideoChannel ) {
441 moreVideo = TRUE; 440 moreVideo = TRUE;
442 pthread_attr_init(&video_attr); 441 pthread_attr_init(&video_attr);
443 pthread_create(&video_tid, &video_attr, (void * (*)(void *))startVideoThread, this); 442 pthread_create(&video_tid, &video_attr, (void * (*)(void *))startVideoThread, this);
444 } 443 }
445 444
446 if ( hasAudioChannel ) { 445 if ( hasAudioChannel ) {
447 moreAudio = TRUE; 446 moreAudio = TRUE;
448 pthread_attr_init(&audio_attr); 447 pthread_attr_init(&audio_attr);
449#ifdef USE_REALTIME_AUDIO_THREAD 448#ifdef USE_REALTIME_AUDIO_THREAD
450 pthread_attr_setschedpolicy(&audio_attr,SCHED_RR); // Real-time round robin 449 pthread_attr_setschedpolicy(&audio_attr,SCHED_RR); // Real-time round robin
451 //qDebug("min: %i, max: %i", sched_get_priority_min( SCHED_RR ), sched_get_priority_max( SCHED_RR ) ); 450 //qDebug("min: %i, max: %i", sched_get_priority_min( SCHED_RR ), sched_get_priority_max( SCHED_RR ) );
452 sched_param params; 451 sched_param params;
453 params.sched_priority = 50; 452 params.sched_priority = 50;
454 pthread_attr_setschedparam(&audio_attr,&params); 453 pthread_attr_setschedparam(&audio_attr,&params);
455#endif 454#endif
456 pthread_create(&audio_tid, &audio_attr, (void * (*)(void *))startAudioThread, this); 455 pthread_create(&audio_tid, &audio_attr, (void * (*)(void *))startAudioThread, this);
457 } 456 }
458} 457}
459 458
460 459
461 460
462 461
463void LoopControl::setPaused( bool pause ) { 462void LoopControl::setPaused( bool pause ) {
464 static int whenPaused = 0; 463 static int whenPaused = 0;
465 464
466 if ( !mediaPlayerState->curDecoder() || !mediaPlayerState->curDecoder()->isOpen() ) 465 if ( !mediaPlayerState->curDecoder() || !mediaPlayerState->curDecoder()->isOpen() )
467 return; 466 return;
468 467
469 if ( pause ) { 468 if ( pause ) {
470 // Remember where we are 469 // Remember where we are
471 whenPaused = playtime.elapsed(); 470 whenPaused = playtime.elapsed();
472 killTimers(); 471 killTimers();
473 } else { 472 } else {
474 // Just like we never stopped 473 // Just like we never stopped
475 playtime.restart(); 474 playtime.restart();
476 playtime = playtime.addMSecs( -whenPaused ); 475 playtime = playtime.addMSecs( -whenPaused );
477 whenPaused = 0; 476 whenPaused = 0;
478 startTimers(); 477 startTimers();
479 } 478 }
480} 479}
481 480
482 481
483void LoopControl::stop( bool willPlayAgainShortly ) { 482void LoopControl::stop( bool willPlayAgainShortly ) {
484 483
485#if defined(Q_WS_QWS) && !defined(QT_NO_COP) 484#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
486 if ( !willPlayAgainShortly && disabledSuspendScreenSaver ) { 485 if ( !willPlayAgainShortly && disabledSuspendScreenSaver ) {
487 disabledSuspendScreenSaver = FALSE; 486 disabledSuspendScreenSaver = FALSE;
488 // Re-enable the suspend mode 487 // Re-enable the suspend mode
489 QCopEnvelope("QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable; 488 QCopEnvelope("QPE/System", "setScreenSaverMode(int)" ) << QPEApplication::Enable;
490 } 489 }
491#endif 490#endif
492 491
493 if ( mediaPlayerState->curDecoder() && mediaPlayerState->curDecoder()->isOpen() ) { 492 if ( mediaPlayerState->curDecoder() && mediaPlayerState->curDecoder()->isOpen() ) {
494 493
495 killTimers(); 494 killTimers();
496 495
497 mediaPlayerState->curDecoder()->close(); 496 mediaPlayerState->curDecoder()->close();
498 497
499 if ( audioDevice ) { 498 if ( audioDevice ) {
500 delete audioDevice; 499 delete audioDevice;
501 delete audioBuffer; 500 delete audioBuffer;
502 audioDevice = 0; 501 audioDevice = 0;
503 audioBuffer = 0; 502 audioBuffer = 0;
504 } 503 }
505 504
506 } 505 }
507} 506}
508 507
509 508
510bool LoopControl::init( const QString& filename ) { 509bool LoopControl::init( const QString& filename ) {
511 stop(); 510 stop();
512 fileName = filename; 511 fileName = filename;
513 stream = 0; // only play stream 0 for now 512 stream = 0; // only play stream 0 for now
514 current_frame = total_video_frames = total_audio_samples = 0; 513 current_frame = total_video_frames = total_audio_samples = 0;
515 514
516 // qDebug( "Using the %s decoder", mediaPlayerState->curDecoder()->pluginName() ); 515 // qDebug( "Using the %s decoder", mediaPlayerState->curDecoder()->pluginName() );
517 516
518 // ### Hack to use libmpeg3plugin to get the number of audio samples if we are using the libmad plugin 517 // ### Hack to use libmpeg3plugin to get the number of audio samples if we are using the libmad plugin
519 if ( mediaPlayerState->curDecoder()->pluginName() == QString("LibMadPlugin") ) { 518 if ( mediaPlayerState->curDecoder()->pluginName() == QString("LibMadPlugin") ) {
520 if ( mediaPlayerState->libMpeg3Decoder() && mediaPlayerState->libMpeg3Decoder()->open( filename ) ) { 519 if ( mediaPlayerState->libMpeg3Decoder() && mediaPlayerState->libMpeg3Decoder()->open( filename ) ) {
521 total_audio_samples = mediaPlayerState->libMpeg3Decoder()->audioSamples( 0 ); 520 total_audio_samples = mediaPlayerState->libMpeg3Decoder()->audioSamples( 0 );
522 mediaPlayerState->libMpeg3Decoder()->close(); 521 mediaPlayerState->libMpeg3Decoder()->close();
523 } 522 }
524 } 523 }
525 524
526 if ( !mediaPlayerState->curDecoder()|| !mediaPlayerState->curDecoder()->open( filename ) ) 525 if ( !mediaPlayerState->curDecoder()|| !mediaPlayerState->curDecoder()->open( filename ) )
527 return FALSE; 526 return FALSE;
528 527
529 hasAudioChannel = mediaPlayerState->curDecoder()->audioStreams() > 0; 528 hasAudioChannel = mediaPlayerState->curDecoder()->audioStreams() > 0;
530 hasVideoChannel = mediaPlayerState->curDecoder()->videoStreams() > 0; 529 hasVideoChannel = mediaPlayerState->curDecoder()->videoStreams() > 0;
531 530
532 if ( hasAudioChannel ) { 531 if ( hasAudioChannel ) {
533 int astream = 0; 532 int astream = 0;
534 533
535 channels = mediaPlayerState->curDecoder()->audioChannels( astream ); 534 channels = mediaPlayerState->curDecoder()->audioChannels( astream );
536 DecodeLoopDebug(( "channels = %d\n", channels )); 535 DecodeLoopDebug(( "channels = %d\n", channels ));
537 536
538 if ( !total_audio_samples ) 537 if ( !total_audio_samples )
539 total_audio_samples = mediaPlayerState->curDecoder()->audioSamples( astream ); 538 total_audio_samples = mediaPlayerState->curDecoder()->audioSamples( astream );
540 539
541 mediaPlayerState->setLength( total_audio_samples ); 540 mediaPlayerState->setLength( total_audio_samples );
542 541
543 freq = mediaPlayerState->curDecoder()->audioFrequency( astream ); 542 freq = mediaPlayerState->curDecoder()->audioFrequency( astream );
544 DecodeLoopDebug(( "frequency = %d\n", freq )); 543 DecodeLoopDebug(( "frequency = %d\n", freq ));
545 544
546 audioSampleCounter = 0; 545 audioSampleCounter = 0;
547 546
548 static const int bytes_per_sample = 2; //16 bit 547 static const int bytes_per_sample = 2; //16 bit
549 548
550 audioDevice = new AudioDevice( freq, channels, bytes_per_sample ); 549 audioDevice = new AudioDevice( freq, channels, bytes_per_sample );
551 audioBuffer = new char[ audioDevice->bufferSize() ]; 550 audioBuffer = new char[ audioDevice->bufferSize() ];
552 channels = audioDevice->channels(); 551 channels = audioDevice->channels();
553 552
554 //### must check which frequency is actually used. 553 //### must check which frequency is actually used.
555 static const int size = 1; 554 static const int size = 1;
556 short int buf[size]; 555 short int buf[size];
557 long samplesRead = 0; 556 long samplesRead = 0;
558 mediaPlayerState->curDecoder()->audioReadSamples( buf, channels, size, samplesRead, stream ); 557 mediaPlayerState->curDecoder()->audioReadSamples( buf, channels, size, samplesRead, stream );
559 } 558 }
560 559
561 if ( hasVideoChannel ) { 560 if ( hasVideoChannel ) {
562 total_video_frames = mediaPlayerState->curDecoder()->videoFrames( stream ); 561 total_video_frames = mediaPlayerState->curDecoder()->videoFrames( stream );
563 562
564 mediaPlayerState->setLength( total_video_frames ); 563 mediaPlayerState->setLength( total_video_frames );
565 564
566 framerate = mediaPlayerState->curDecoder()->videoFrameRate( stream ); 565 framerate = mediaPlayerState->curDecoder()->videoFrameRate( stream );
567 DecodeLoopDebug(( "Frame rate %g total %ld", framerate, total_video_frames )); 566 DecodeLoopDebug(( "Frame rate %g total %ld", framerate, total_video_frames ));
568 567
569 if ( framerate <= 1.0 ) { 568 if ( framerate <= 1.0 ) {
570 DecodeLoopDebug(( "Crazy frame rate, resetting to sensible" )); 569 DecodeLoopDebug(( "Crazy frame rate, resetting to sensible" ));
571 framerate = 25; 570 framerate = 25;
572 } 571 }
573 572
574 if ( total_video_frames == 1 ) { 573 if ( total_video_frames == 1 ) {
575 DecodeLoopDebug(( "Cannot seek to frame" )); 574 DecodeLoopDebug(( "Cannot seek to frame" ));
576 } 575 }
577 576
578 } 577 }
579 578
580 videoMutex->lock(); 579 videoMutex->lock();
581 current_frame = 0; 580 current_frame = 0;
582 prev_frame = -1; 581 prev_frame = -1;
583 videoMutex->unlock(); 582 videoMutex->unlock();
584 583
585 connect( mediaPlayerState, SIGNAL( positionChanged( long ) ), this, SLOT( setPosition( long ) ) ); 584 connect( mediaPlayerState, SIGNAL( positionChanged( long ) ), this, SLOT( setPosition( long ) ) );
586 connect( mediaPlayerState, SIGNAL( pausedToggled( bool ) ), this, SLOT( setPaused( bool ) ) ); 585 connect( mediaPlayerState, SIGNAL( pausedToggled( bool ) ), this, SLOT( setPaused( bool ) ) );
587 586
588 //setBackgroundColor( black ); 587 //setBackgroundColor( black );
589 return TRUE; 588 return TRUE;
590} 589}
591 590
592 591
593void LoopControl::play() { 592void LoopControl::play() {
594 593
595#if defined(Q_WS_QWS) && !defined(QT_NO_COP) 594#if defined(Q_WS_QWS) && !defined(QT_NO_COP)
596 if ( !disabledSuspendScreenSaver ) { 595 if ( !disabledSuspendScreenSaver ) {
597 disabledSuspendScreenSaver = TRUE; 596 disabledSuspendScreenSaver = TRUE;
598 // Stop the screen from blanking and power saving state 597 // Stop the screen from blanking and power saving state
599 QCopEnvelope("QPE/System", "setScreenSaverMode(int)" ) 598 QCopEnvelope("QPE/System", "setScreenSaverMode(int)" )
600 << ( hasVideoChannel ? QPEApplication::Disable : QPEApplication::DisableSuspend ); 599 << ( hasVideoChannel ? QPEApplication::Disable : QPEApplication::DisableSuspend );
601 } 600 }
602#endif 601#endif
603 602
604 //begin = clock(); 603 //begin = clock();
605 playtime.start(); 604 playtime.start();
606 startTimers(); 605 startTimers();
607 //updateGeometry(); 606 //updateGeometry();
608} 607}
609 608
610 609
611void LoopControl::setMute( bool on ) { 610void LoopControl::setMute( bool on ) {
612 if ( isMuted != on ) { 611 if ( isMuted != on ) {
613 isMuted = on; 612 isMuted = on;
614 if ( isMuted ) { 613 if ( isMuted ) {
615 } else { 614 } else {
616 int frame = current_frame; // mediaPlayerState->curDecoder()->videoGetFrame( stream ); 615 int frame = current_frame; // mediaPlayerState->curDecoder()->videoGetFrame( stream );
617 playtime.restart(); 616 playtime.restart();
618 playtime = playtime.addMSecs( -frame * 1000 / framerate ); 617 playtime = playtime.addMSecs( -frame * 1000 / framerate );
619 //begin = clock() - (double)frame * CLOCKS_PER_SEC / framerate; 618 //begin = clock() - (double)frame * CLOCKS_PER_SEC / framerate;
620 mediaPlayerState->curDecoder()->audioSetSample( frame*freq/framerate, stream ); 619 mediaPlayerState->curDecoder()->audioSetSample( frame*freq/framerate, stream );
621 } 620 }
622 } 621 }
623} 622}
624 623
625 624