player-mp3.c
author nathan
Sat, 29 Dec 2007 14:49:09 +0100
branchtrunk
changeset 2 4c1f7b705009
parent 0 474a1293c3c0
child 6 111ef8181229
permissions -rw-r--r--
release 0.10.1
     1 /*
     2  * MP3/MPlayer plugin to VDR (C++)
     3  *
     4  * (C) 2001-2007 Stefan Huelswitt <s.huelswitt@gmx.de>
     5  *
     6  * This code is free software; you can redistribute it and/or
     7  * modify it under the terms of the GNU General Public License
     8  * as published by the Free Software Foundation; either version 2
     9  * of the License, or (at your option) any later version.
    10  *
    11  * This code is distributed in the hope that it will be useful,
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  * GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License
    17  * along with this program; if not, write to the Free Software
    18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    19  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
    20  */
    21 
    22 #include <stdlib.h>
    23 #include <stdio.h>
    24 #include <sys/ioctl.h>
    25 #include <math.h>
    26 #ifdef WITH_OSS
    27 #include <sys/soundcard.h>
    28 #endif
    29 
    30 #include <mad.h>
    31 #include <id3tag.h>
    32 
    33 #include <vdr/player.h>
    34 #include <vdr/ringbuffer.h>
    35 #include <vdr/thread.h>
    36 #include <vdr/tools.h>
    37 
    38 #include "common.h"
    39 #include "setup-mp3.h"
    40 #include "player-mp3.h"
    41 #include "data-mp3.h"
    42 #include "decoder.h"
    43 #include "decoder-core.h"
    44 
    45 #ifndef NO_DEBUG
    46 //#define DEBUG_MODE      // debug playmode changes
    47 #define DEBUG_BGR       // debug backround scan thread
    48 #define DEBUG_DELAY 300 // debug write/decode delays
    49 //#define ACC_DUMP        // dump limiter lookup table to /tmp/limiter
    50 #endif
    51 
    52 #if !defined(NO_DEBUG) && defined(DEBUG_MODE)
    53 #define dm(x) { (x); }
    54 #else
    55 #define dm(x) ; 
    56 #endif
    57 
    58 #if !defined(NO_DEBUG) && defined(DEBUG_BGR)
    59 #define db(x) { (x); }
    60 #else
    61 #define db(x) ; 
    62 #endif
    63 
    64 // ----------------------------------------------------------------
    65 
    66 #define MP3BUFSIZE (1024*1024)                               // output ringbuffer size
    67 #define OUT_BITS 16                                          // output 16 bit samples to DVB driver
    68 #define OUT_FACT (OUT_BITS/8*2)                              // output factor is 16 bit & 2 channels -> 4 bytes
    69 // cResample
    70 #define MAX_NSAMPLES (1152*7)                                // max. buffer for resampled frame
    71 // cNormalize
    72 #define MIN_GAIN   0.03                                      // min. gain required to launch the normalizer
    73 #define MAX_GAIN   3.0                                       // max. allowed gain
    74 #define USE_FAST_LIMITER
    75 #define LIM_ACC    12                                        // bit, accuracy for lookup table
    76 #define F_LIM_MAX  (mad_fixed_t)((1<<(MAD_F_FRACBITS+2))-1)  // max. value covered by lookup table
    77 #define LIM_SHIFT  (MAD_F_FRACBITS-LIM_ACC)                  // shift value for table lookup
    78 #define F_LIM_JMP  (mad_fixed_t)(1<<LIM_SHIFT)               // lookup table jump between values
    79 // cLevel
    80 #define POW_WIN 100                                          // window width for smoothing power values
    81 #define EPSILON 0.00000000001                                // anything less than EPSILON is considered zero
    82 
    83 // --- cResample ------------------------------------------------------------
    84 
    85 // The resample code has been adapted from the madplay project
    86 // (resample.c) found in the libmad distribution
    87    
    88 class cResample {
    89 private:
    90   mad_fixed_t ratio;
    91   mad_fixed_t step;
    92   mad_fixed_t last;
    93   mad_fixed_t resampled[MAX_NSAMPLES];
    94 public:
    95   bool SetInputRate(unsigned int oldrate, unsigned int newrate);
    96   unsigned int ResampleBlock(unsigned int nsamples, const mad_fixed_t *old);
    97   const mad_fixed_t *Resampled(void) { return resampled; }
    98   };
    99 
   100 bool cResample::SetInputRate(unsigned int oldrate, unsigned int newrate)
   101 {
   102   if(oldrate<8000 || oldrate>newrate*6) { // out of range
   103     esyslog("WARNING: samplerate %d out of range 8000-%d\n",oldrate,newrate*6);
   104     return 0;
   105     }
   106   ratio=mad_f_tofixed((double)oldrate/(double)newrate);
   107   step=0; last=0;
   108 #ifdef DEBUG
   109   static mad_fixed_t oldratio=0;
   110   if(oldratio!=ratio) {
   111     printf("mad: new resample ratio %f (from %d kHz to %d kHz)\n",mad_f_todouble(ratio),oldrate,newrate);
   112     oldratio=ratio;
   113     }
   114 #endif
   115   return ratio!=MAD_F_ONE;
   116 }
   117 
   118 unsigned int cResample::ResampleBlock(unsigned int nsamples, const mad_fixed_t *old)
   119 {
   120   // This resampling algorithm is based on a linear interpolation, which is
   121   // not at all the best sounding but is relatively fast and efficient.
   122   //
   123   // A better algorithm would be one that implements a bandlimited
   124   // interpolation.
   125 
   126   mad_fixed_t *nsam=resampled;
   127   const mad_fixed_t *end=old+nsamples;
   128   const mad_fixed_t *begin=nsam;
   129 
   130   if(step < 0) {
   131     step = mad_f_fracpart(-step);
   132 
   133     while (step < MAD_F_ONE) {
   134       *nsam++ = step ? last+mad_f_mul(*old-last,step) : last;
   135       step += ratio;
   136       if(((step + 0x00000080L) & 0x0fffff00L) == 0)
   137 	step = (step + 0x00000080L) & ~0x0fffffffL;
   138       }
   139     step -= MAD_F_ONE;
   140     }
   141 
   142   while (end - old > 1 + mad_f_intpart(step)) {
   143     old += mad_f_intpart(step);
   144     step = mad_f_fracpart(step);
   145     *nsam++ = step ? *old + mad_f_mul(old[1] - old[0], step) : *old;
   146     step += ratio;
   147     if (((step + 0x00000080L) & 0x0fffff00L) == 0)
   148       step = (step + 0x00000080L) & ~0x0fffffffL;
   149     }
   150 
   151   if (end - old == 1 + mad_f_intpart(step)) {
   152     last = end[-1];
   153     step = -step;
   154     }
   155   else step -= mad_f_fromint(end - old);
   156 
   157   return nsam-begin;
   158 }
   159 
   160 // --- cLevel ----------------------------------------------------------------
   161 
   162 // The normalize algorithm and parts of the code has been adapted from the
   163 // Normalize 0.7 project. (C) 1999-2002, Chris Vaill <cvaill@cs.columbia.edu>
   164 
   165 // A little background on how normalize computes the volume
   166 // of a wav file, in case you want to know just how your
   167 // files are being munged:
   168 //
   169 // The volumes calculated are RMS amplitudes, which corre­
   170 // spond (roughly) to perceived volume. Taking the RMS ampli­
   171 // tude of an entire file would not give us quite the measure
   172 // we want, though, because a quiet song punctuated by short
   173 // loud parts would average out to a quiet song, and the
   174 // adjustment we would compute would make the loud parts
   175 // excessively loud.
   176 //
   177 // What we want is to consider the maximum volume of the
   178 // file, and normalize according to that. We break up the
   179 // signal into 100 chunks per second, and get the signal
   180 // power of each chunk, in order to get an estimation of
   181 // "instantaneous power" over time. This "instantaneous
   182 // power" signal varies too much to get a good measure of the
   183 // original signal's maximum sustained power, so we run a
   184 // smoothing algorithm over the power signal (specifically, a
   185 // mean filter with a window width of 100 elements). The max­
   186 // imum point of the smoothed power signal turns out to be a
   187 // good measure of the maximum sustained power of the file.
   188 // We can then take the square root of the power to get maxi­
   189 // mum sustained RMS amplitude.
   190 
   191 class cLevel {
   192 private:
   193   double maxpow;
   194   mad_fixed_t peak;
   195   struct Power {
   196     // smooth
   197     int npow, wpow;
   198     double powsum, pows[POW_WIN];
   199     // sum
   200     unsigned int nsum;
   201     double sum;
   202     } power[2];
   203   //
   204   inline void AddPower(struct Power *p, double pow);
   205 public:
   206   void Init(void);
   207   void GetPower(struct mad_pcm *pcm);
   208   double GetLevel(void);
   209   double GetPeak(void);
   210   };
   211 
   212 void cLevel::Init(void)
   213 {
   214   for(int l=0 ; l<2 ; l++) {
   215     struct Power *p=&power[l];
   216     p->sum=p->powsum=0.0; p->wpow=p->npow=p->nsum=0;
   217     for(int i=POW_WIN-1 ; i>=0 ; i--) p->pows[i]=0.0;
   218     }
   219   maxpow=0.0; peak=0;
   220 }
   221 
   222 void cLevel::GetPower(struct mad_pcm *pcm)
   223 {
   224   for(int i=0 ; i<pcm->channels ; i++) {
   225     struct Power *p=&power[i];
   226     mad_fixed_t *data=pcm->samples[i];
   227     for(int n=pcm->length ; n>0 ; n--) {
   228       if(*data < -peak) peak = -*data;
   229       if(*data >  peak) peak =  *data;
   230       double s=mad_f_todouble(*data++);
   231       p->sum+=(s*s);
   232       if(++(p->nsum)>=pcm->samplerate/100) {
   233         AddPower(p,p->sum/(double)p->nsum);
   234         p->sum=0.0; p->nsum=0;
   235         }
   236       }
   237     }
   238 }
   239 
   240 void cLevel::AddPower(struct Power *p, double pow)
   241 {
   242   p->powsum+=pow;
   243   if(p->npow>=POW_WIN) {
   244     if(p->powsum>maxpow) maxpow=p->powsum;
   245     p->powsum-=p->pows[p->wpow];
   246     }
   247   else p->npow++;
   248   p->pows[p->wpow]=pow;
   249   p->wpow=(p->wpow+1) % POW_WIN;
   250 }
   251 
   252 double cLevel::GetLevel(void)
   253 {
   254   if(maxpow<EPSILON) {
   255     // Either this whole file has zero power, or was too short to ever
   256     // fill the smoothing buffer.  In the latter case, we need to just
   257     // get maxpow from whatever data we did collect.
   258 
   259     if(power[0].powsum>maxpow) maxpow=power[0].powsum;
   260     if(power[1].powsum>maxpow) maxpow=power[1].powsum;
   261     }
   262   double level=sqrt(maxpow/(double)POW_WIN);     // adjust for the smoothing window size and root
   263   d(printf("norm: new volumen level=%f peak=%f\n",level,mad_f_todouble(peak)))
   264   return level;
   265 }
   266 
   267 double cLevel::GetPeak(void)
   268 {
   269   return mad_f_todouble(peak);
   270 }
   271 
   272 // --- cNormalize ------------------------------------------------------------
   273 
   274 class cNormalize {
   275 private:
   276   mad_fixed_t gain;
   277   double d_limlvl, one_limlvl;
   278   mad_fixed_t limlvl;
   279   bool dogain, dolimit;
   280 #ifdef DEBUG
   281   // stats
   282   unsigned long limited, clipped, total;
   283   mad_fixed_t peak;
   284 #endif
   285   // limiter
   286 #ifdef USE_FAST_LIMITER
   287   mad_fixed_t *table, tablestart;
   288   int tablesize;
   289   inline mad_fixed_t FastLimiter(mad_fixed_t x);
   290 #endif
   291   inline mad_fixed_t Limiter(mad_fixed_t x);
   292 public:
   293   cNormalize(void);
   294   ~cNormalize();
   295   void Init(double Level, double Peak);
   296   void Stats(void);
   297   void AddGain(struct mad_pcm *pcm);
   298   };
   299 
   300 cNormalize::cNormalize(void)
   301 {
   302   d_limlvl=(double)MP3Setup.LimiterLevel/100.0;
   303   one_limlvl=1-d_limlvl;
   304   limlvl=mad_f_tofixed(d_limlvl);
   305   d(printf("norm: lim_lev=%f lim_acc=%d\n",d_limlvl,LIM_ACC))
   306 
   307 #ifdef USE_FAST_LIMITER
   308   mad_fixed_t start=limlvl & ~(F_LIM_JMP-1);
   309   tablestart=start;
   310   tablesize=(unsigned int)(F_LIM_MAX-start)/F_LIM_JMP + 2;
   311   table=new mad_fixed_t[tablesize];
   312   if(table) {
   313     d(printf("norm: table size=%d start=%08x jump=%08x\n",tablesize,start,F_LIM_JMP))
   314     for(int i=0 ; i<tablesize ; i++) {
   315       table[i]=Limiter(start);
   316       start+=F_LIM_JMP;
   317       }
   318     tablesize--; // avoid a -1 in FastLimiter()
   319 
   320     // do a quick accuracy check, just to be sure that FastLimiter() is working
   321     // as expected :-)
   322 #ifdef ACC_DUMP
   323     FILE *out=fopen("/tmp/limiter","w");
   324 #endif
   325     mad_fixed_t maxdiff=0;
   326     for(mad_fixed_t x=F_LIM_MAX ; x>=limlvl ; x-=mad_f_tofixed(1e-4)) {
   327       mad_fixed_t diff=mad_f_abs(Limiter(x)-FastLimiter(x));
   328       if(diff>maxdiff) maxdiff=diff;
   329 #ifdef ACC_DUMP
   330       fprintf(out,"%0.10f\t%0.10f\t%0.10f\t%0.10f\t%0.10f\n",
   331         mad_f_todouble(x),mad_f_todouble(Limiter(x)),mad_f_todouble(FastLimiter(x)),mad_f_todouble(diff),mad_f_todouble(maxdiff));
   332       if(ferror(out)) break;
   333 #endif
   334       }
   335 #ifdef ACC_DUMP
   336     fclose(out);
   337 #endif
   338     d(printf("norm: accuracy %.12f\n",mad_f_todouble(maxdiff)))
   339     if(mad_f_todouble(maxdiff)>1e-6) {
   340       esyslog("ERROR: accuracy check failed, normalizer disabled");
   341       delete table; table=0;
   342       }
   343     }
   344   else esyslog("ERROR: no memory for lookup table, normalizer disabled");
   345 #endif // USE_FAST_LIMITER
   346 }
   347 
   348 cNormalize::~cNormalize()
   349 {
   350 #ifdef USE_FAST_LIMITER
   351   delete[] table;
   352 #endif
   353 }
   354 
   355 void cNormalize::Init(double Level, double Peak)
   356 {
   357   double Target=(double)MP3Setup.TargetLevel/100.0;
   358   double dgain=Target/Level;
   359   if(dgain>MAX_GAIN) dgain=MAX_GAIN;
   360   gain=mad_f_tofixed(dgain);
   361   // Check if we actually need to apply a gain
   362   dogain=(Target>0.0 && fabs(1-dgain)>MIN_GAIN);
   363 #ifdef USE_FAST_LIMITER
   364   if(!table) dogain=false;
   365 #endif
   366   // Check if we actually need to do limiting:
   367   // we have to if limiter is enabled, if gain>1 and if the peaks will clip.
   368   dolimit=(d_limlvl<1.0 && dgain>1.0 && Peak*dgain>1.0);
   369 #ifdef DEBUG
   370   printf("norm: gain=%f dogain=%d dolimit=%d (target=%f level=%f peak=%f)\n",dgain,dogain,dolimit,Target,Level,Peak);
   371   limited=clipped=total=0; peak=0;
   372 #endif
   373 }
   374 
   375 void cNormalize::Stats(void)
   376 {
   377 #ifdef DEBUG
   378   if(total)
   379     printf("norm: stats tot=%ld lim=%ld/%.3f%% clip=%ld/%.3f%% peak=%.3f\n",
   380            total,limited,(double)limited/total*100.0,clipped,(double)clipped/total*100.0,mad_f_todouble(peak));
   381 #endif
   382 }
   383 
   384 mad_fixed_t cNormalize::Limiter(mad_fixed_t x)
   385 {
   386 // Limiter function:
   387 //
   388 //        / x                                                (for x <= lev)
   389 //   x' = |
   390 //        \ tanh((x - lev) / (1-lev)) * (1-lev) + lev        (for x > lev)
   391 //
   392 // call only with x>=0. For negative samples, preserve sign outside this function
   393 //
   394 // With limiter level = 0, this is equivalent to a tanh() function;
   395 // with limiter level = 1, this is equivalent to clipping.
   396 
   397   if(x>limlvl) {
   398 #ifdef DEBUG
   399     if(x>MAD_F_ONE) clipped++;
   400     limited++;
   401 #endif
   402     x=mad_f_tofixed(tanh((mad_f_todouble(x)-d_limlvl) / one_limlvl) * one_limlvl + d_limlvl);
   403     }
   404   return x;
   405 }
   406 
   407 #ifdef USE_FAST_LIMITER
   408 mad_fixed_t cNormalize::FastLimiter(mad_fixed_t x)
   409 {
   410 // The fast algorithm is based on a linear interpolation between the
   411 // the values in the lookup table. Relays heavly on libmads fixed point format.
   412 
   413   if(x>limlvl) {
   414     int i=(unsigned int)(x-tablestart)/F_LIM_JMP;
   415 #ifdef DEBUG
   416     if(x>MAD_F_ONE) clipped++;
   417     limited++;
   418     if(i>=tablesize) printf("norm: overflow x=%f x-ts=%f i=%d tsize=%d\n",
   419                             mad_f_todouble(x),mad_f_todouble(x-tablestart),i,tablesize);
   420 #endif
   421     mad_fixed_t r=x & (F_LIM_JMP-1);
   422     x=MAD_F_ONE;
   423     if(i<tablesize) {
   424       mad_fixed_t *ptr=&table[i];
   425       x=*ptr;
   426       mad_fixed_t d=*(ptr+1)-x;
   427       //x+=mad_f_mul(d,r)<<LIM_ACC;                // this is not accurate as mad_f_mul() does >>MAD_F_FRACBITS
   428                                                    // which is senseless in the case of following <<LIM_ACC.
   429       x+=((long long)d*(long long)r)>>LIM_SHIFT;   // better, don't know if works on all machines
   430       }
   431     }
   432   return x;
   433 }
   434 #endif
   435 
   436 #ifdef USE_FAST_LIMITER
   437 #define LIMITER_FUNC FastLimiter
   438 #else
   439 #define LIMITER_FUNC Limiter
   440 #endif
   441 
   442 void cNormalize::AddGain(struct mad_pcm *pcm)
   443 {
   444   if(dogain) {
   445     for(int i=0 ; i<pcm->channels ; i++) {
   446       mad_fixed_t *data=pcm->samples[i];
   447 #ifdef DEBUG
   448       total+=pcm->length;
   449 #endif
   450       if(dolimit) {
   451         for(int n=pcm->length ; n>0 ; n--) {
   452           mad_fixed_t s=mad_f_mul(*data,gain);
   453           if(s<0) {
   454             s=-s;
   455 #ifdef DEBUG
   456             if(s>peak) peak=s;
   457 #endif
   458             s=LIMITER_FUNC(s);
   459             s=-s;
   460             }
   461           else {
   462 #ifdef DEBUG
   463             if(s>peak) peak=s;
   464 #endif
   465             s=LIMITER_FUNC(s);
   466             }
   467           *data++=s;
   468           }
   469         }
   470       else {
   471         for(int n=pcm->length ; n>0 ; n--) {
   472           mad_fixed_t s=mad_f_mul(*data,gain);
   473 #ifdef DEBUG
   474           if(s>peak) peak=s;
   475           else if(-s>peak) peak=-s;
   476 #endif
   477           if(s>MAD_F_ONE) s=MAD_F_ONE;   // do clipping
   478           if(s<-MAD_F_ONE) s=-MAD_F_ONE;
   479           *data++=s;
   480           }
   481         }
   482       }
   483     }
   484 }
   485 
   486 // --- cScale ----------------------------------------------------------------
   487 
   488 // The dither code has been adapted from the madplay project
   489 // (audio.c) found in the libmad distribution
   490 
   491 enum eAudioMode { amRoundBE, amDitherBE, amRoundLE, amDitherLE };
   492 
   493 class cScale {
   494 private:
   495   enum { MIN=-MAD_F_ONE, MAX=MAD_F_ONE - 1 };
   496 #ifdef DEBUG
   497   // audio stats
   498   unsigned long clipped_samples;
   499   mad_fixed_t peak_clipping;
   500   mad_fixed_t peak_sample;
   501 #endif
   502   // dither
   503   struct dither {
   504     mad_fixed_t error[3];
   505     mad_fixed_t random;
   506     } leftD, rightD;
   507   //
   508   inline mad_fixed_t Clip(mad_fixed_t sample, bool stats=true);
   509   inline unsigned long Prng(unsigned long state);
   510   signed long LinearRound(mad_fixed_t sample);
   511   signed long LinearDither(mad_fixed_t sample, struct dither *dither);
   512 public:
   513   void Init(void);
   514   void Stats(void);
   515   unsigned int ScaleBlock(unsigned char *data, unsigned int size, unsigned int &nsamples, const mad_fixed_t * &left, const mad_fixed_t * &right, eAudioMode mode);
   516   };
   517 
   518 void cScale::Init(void)
   519 {
   520 #ifdef DEBUG
   521   clipped_samples=0; peak_clipping=peak_sample=0;
   522 #endif
   523   memset(&leftD,0,sizeof(leftD));
   524   memset(&rightD,0,sizeof(rightD));
   525 }
   526 
   527 void cScale::Stats(void)
   528 {
   529 #ifdef DEBUG
   530   printf("mp3: scale stats clipped=%ld peak_clip=%f peak=%f\n",
   531          clipped_samples,mad_f_todouble(peak_clipping),mad_f_todouble(peak_sample));
   532 #endif
   533 }
   534 
   535 // gather signal statistics while clipping
   536 mad_fixed_t cScale::Clip(mad_fixed_t sample, bool stats)
   537 {
   538 #ifndef DEBUG
   539   if (sample > MAX) sample = MAX;
   540   if (sample < MIN) sample = MIN;
   541 #else
   542   if(!stats) {
   543     if (sample > MAX) sample = MAX;
   544     if (sample < MIN) sample = MIN;
   545     }
   546   else {
   547     if (sample >= peak_sample) {
   548       if (sample > MAX) {
   549         ++clipped_samples;
   550         if (sample - MAX > peak_clipping)
   551 	  peak_clipping = sample - MAX;
   552         sample = MAX;
   553         }
   554       peak_sample = sample;
   555       }
   556     else if (sample < -peak_sample) {
   557       if (sample < MIN) {
   558         ++clipped_samples;
   559         if (MIN - sample > peak_clipping)
   560 	  peak_clipping = MIN - sample;
   561         sample = MIN;
   562         }
   563       peak_sample = -sample;
   564       }
   565     }
   566 #endif
   567   return sample;
   568 }
   569 
   570 // generic linear sample quantize routine
   571 signed long cScale::LinearRound(mad_fixed_t sample)
   572 {
   573   // round
   574   sample += (1L << (MAD_F_FRACBITS - OUT_BITS));
   575   // clip
   576   sample=Clip(sample);
   577   // quantize and scale
   578   return sample >> (MAD_F_FRACBITS + 1 - OUT_BITS);
   579 }
   580 
   581 // 32-bit pseudo-random number generator
   582 unsigned long cScale::Prng(unsigned long state)
   583 {
   584   return (state * 0x0019660dL + 0x3c6ef35fL) & 0xffffffffL;
   585 }
   586 
   587 // generic linear sample quantize and dither routine
   588 signed long cScale::LinearDither(mad_fixed_t sample, struct dither *dither)
   589 {
   590   // noise shape
   591   sample += dither->error[0] - dither->error[1] + dither->error[2];
   592   dither->error[2] = dither->error[1];
   593   dither->error[1] = dither->error[0] / 2;
   594   // bias
   595   mad_fixed_t output = sample + (1L << (MAD_F_FRACBITS + 1 - OUT_BITS - 1));
   596   const int scalebits = MAD_F_FRACBITS + 1 - OUT_BITS;
   597   const mad_fixed_t mask = (1L << scalebits) - 1;
   598   // dither
   599   const mad_fixed_t random = Prng(dither->random);
   600   output += (random & mask) - (dither->random & mask);
   601   dither->random = random;
   602   // clip
   603   output=Clip(output);
   604   sample=Clip(sample,false);
   605   // quantize
   606   output &= ~mask;
   607   // error feedback
   608   dither->error[0] = sample - output;
   609   // scale
   610   return output >> scalebits;
   611 }
   612 
   613 #define PUT_BE(data,sample) { *data++=(sample)>>8; *data++=(sample)>>0; }
   614 #define PUT_LE(data,sample) { *data++=(sample)>>0; *data++=(sample)>>8; }
   615 
   616 // write a block of signed 16-bit PCM samples
   617 unsigned int cScale::ScaleBlock(unsigned char *data, unsigned int size, unsigned int &nsamples, const mad_fixed_t * &left, const mad_fixed_t * &right, eAudioMode mode)
   618 {
   619   unsigned int len=size/OUT_FACT;
   620   if(len>nsamples) { len=nsamples; size=len*OUT_FACT; }
   621   nsamples-=len;
   622   switch(mode) {
   623     case amRoundBE:
   624       while(len--) {
   625         signed int sample=LinearRound(*left++);
   626         PUT_BE(data,sample);
   627         if(right) sample=LinearRound(*right++);
   628         PUT_BE(data,sample);
   629         }
   630       break;
   631     case amDitherBE:
   632       while(len--) {
   633 	signed int sample=LinearDither(*left++,&leftD);
   634         PUT_BE(data,sample);
   635 	if(right) sample=LinearDither(*right++,&rightD);
   636         PUT_BE(data,sample);
   637         }
   638       break;
   639     case amRoundLE:
   640       while(len--) {
   641         signed int sample=LinearRound(*left++);
   642         PUT_LE(data,sample);
   643         if(right) sample=LinearRound(*right++);
   644         PUT_LE(data,sample);
   645         }
   646       break;
   647     case amDitherLE:
   648       while(len--) {
   649 	signed int sample=LinearDither(*left++,&leftD);
   650         PUT_LE(data,sample);
   651 	if(right) sample=LinearDither(*right++,&rightD);
   652         PUT_LE(data,sample);
   653         }
   654       break;
   655     }
   656  return size;
   657 }
   658 
   659 // --- cShuffle ----------------------------------------------------------------
   660 
   661 class cShuffle {
   662 private:
   663   int *shuffle, max;
   664   unsigned int seed;
   665   //
   666   int Index(int pos);
   667 public:
   668   cShuffle(void);
   669   ~cShuffle();
   670   void Shuffle(int num, int curr);
   671   void Del(int pos);
   672   void Flush(void);
   673   int First(void);
   674   int Next(int curr);
   675   int Prev(int curr);
   676   int Goto(int pos, int curr);
   677   };
   678 
   679 cShuffle::cShuffle(void)
   680 {
   681   shuffle=0; max=0;
   682   seed=time(0);
   683 }
   684 
   685 cShuffle::~cShuffle(void)
   686 {
   687   Flush();
   688 }
   689 
   690 void cShuffle::Flush(void)
   691 {
   692   delete shuffle; shuffle=0;
   693   max=0;
   694 }
   695 
   696 int cShuffle::Index(int pos)
   697 {
   698   if(pos>=0)
   699     for(int i=0; i<max; i++) if(shuffle[i]==pos) return i;
   700   return -1;
   701 }
   702 
   703 void cShuffle::Shuffle(int num, int curr)
   704 {
   705   int oldmax=0;
   706   if(num!=max) {
   707     int *ns=new int[num];
   708     if(shuffle) {
   709       if(num>max) {
   710         memcpy(ns,shuffle,max*sizeof(int));
   711         oldmax=max;
   712         }
   713       delete shuffle;
   714       }
   715     shuffle=ns; max=num;
   716     }
   717   if(!oldmax) curr=-1;
   718   for(int i=oldmax ; i<max ; i++) shuffle[i]=i;
   719 
   720   int in=Index(curr)+1; if(in<0) in=0;
   721   if((max-in)>=2) {
   722     for(int i=in ; i<max ; i++) {
   723       int ran=(rand_r(&seed) % ((max-in)*4-4))/4; ran+=((ran+in) >= i);
   724       int t=shuffle[i];
   725       shuffle[i]=shuffle[ran+in];
   726       shuffle[ran+in]=t;
   727       }
   728     }
   729 #ifdef DEBUG
   730   printf("shuffle: order (%d , %d -> %d) ",num,curr,in);
   731   for(int i=0 ; i<max ; i++) printf("%d ",shuffle[i]);
   732   printf("\n");
   733 #endif
   734 }
   735 
   736 void cShuffle::Del(int pos)
   737 {
   738   int i=Index(pos);
   739   if(i>=0) {
   740     if(i+1<max) memmove(&shuffle[i],&shuffle[i+1],(max-i-1)*sizeof(int));
   741     max--;
   742     }
   743 }
   744 
   745 int cShuffle::First(void)
   746 {
   747   return shuffle[0];
   748 }
   749 
   750 int cShuffle::Next(int curr)
   751 {
   752   int i=Index(curr);
   753   return (i>=0 && i+1<max) ? shuffle[i+1] : -1;
   754 }
   755 
   756 int cShuffle::Prev(int curr)
   757 {
   758   int i=Index(curr);
   759   return (i>0) ? shuffle[i-1] : -1;
   760 }
   761 
   762 int cShuffle::Goto(int pos, int curr)
   763 {
   764   int i=Index(curr);
   765   int g=Index(pos);
   766   if(g>=0) {
   767     if(g<i) {
   768       for(int l=g; l<i; l++) shuffle[l]=shuffle[l+1];
   769       shuffle[i]=pos;
   770       }
   771     else if(g>i) {
   772       for(int l=g; l>i+1; l--) shuffle[l]=shuffle[l-1];
   773       shuffle[i+1]=pos;
   774       }
   775 #ifdef DEBUG
   776     printf("shuffle: goto order (%d -> %d , %d -> %d) ",pos,g,curr,i);
   777     for(int i=0 ; i<max ; i++) printf("%d ",shuffle[i]);
   778     printf("\n");
   779 #endif
   780     return pos;
   781     }
   782   return -1;
   783 }
   784 
   785 // --- cPlayManager ------------------------------------------------------------
   786 
   787 #define SCANNED_ID3 1
   788 #define SCANNED_LVL 2
   789 
   790 cPlayManager *mgr=0;
   791 
   792 cPlayManager::cPlayManager(void)
   793 {
   794   curr=0; currIndex=-1;
   795   scan=0; stopscan=throttle=pass2=release=false;
   796   play=0; playNew=eol=false;
   797   shuffle=new cShuffle;
   798   loopMode=(MP3Setup.InitLoopMode>0);
   799   shuffleMode=(MP3Setup.InitShuffleMode>0);
   800 }
   801 
   802 cPlayManager::~cPlayManager()
   803 {
   804   Flush();
   805   Release();
   806   listMutex.Lock();
   807   stopscan=true; bgCond.Broadcast();
   808   listMutex.Unlock();
   809   Cancel(2);
   810   delete shuffle;
   811 }
   812 
   813 void cPlayManager::ThrottleWait(void)
   814 {
   815   while(!stopscan && !release && throttle) {
   816     db(printf("mgr: background scan throttled\n"))
   817     bgCond.Wait(listMutex);
   818     db(printf("mgr: background scan throttle wakeup\n"))
   819     }
   820 }
   821 
   822 void cPlayManager::Action(void)
   823 {
   824   db(printf("mgr: background scan thread started (pid=%d)\n", getpid()))
   825   nice(5);
   826   listMutex.Lock();
   827   while(!stopscan) {
   828     for(scan=list.First(); !stopscan && !release && scan; scan=list.Next(scan)) {
   829       ThrottleWait();
   830       listMutex.Unlock();
   831       if(!(scan->user & SCANNED_ID3)) {
   832         db(printf("mgr: scanning (id3) %s\n",scan->Name()))
   833         cSongInfo *si=scan->Info(true);
   834         if(si && si->Level>0.0) scan->user|=SCANNED_LVL;
   835         scan->user|=SCANNED_ID3;
   836         }
   837       listMutex.Lock();
   838       }
   839     if(MP3Setup.BgrScan>1) {
   840       pass2=true;
   841       for(scan=list.First(); !stopscan && !release && scan; scan=list.Next(scan)) {
   842         if(scan==curr) continue;
   843         ThrottleWait();
   844         listMutex.Unlock();
   845         if(!(scan->user & SCANNED_LVL)) {
   846           cDecoder *dec=scan->Decoder();
   847           if(dec) {
   848             cSongInfo *si=scan->Info(false);
   849             if(!dec->IsStream() && (!si || si->Level<=0.0) && dec->Start()) {
   850               db(printf("mgr: scanning (lvl) %s\n",scan->Name()))
   851               cLevel level;
   852               level.Init();
   853               bool go=true;
   854               while(go && !release) {
   855                 if(throttle) {
   856                   listMutex.Lock(); ThrottleWait(); listMutex.Unlock();
   857                   continue;
   858                   }
   859                 struct Decode *ds=dec->Decode();
   860                 switch(ds->status) {
   861                   case dsPlay:
   862                     level.GetPower(ds->pcm);
   863                     break;
   864                   case dsSkip:
   865                   case dsSoftError:
   866                     break;
   867                   case dsEof:
   868                     {
   869                     double l=level.GetLevel();
   870                     if(l>0.0) {
   871                       cSongInfo *si=dec->SongInfo(false);
   872                       cFileInfo *fi=dec->FileInfo();
   873                       if(si && fi) {
   874                         si->Level=l;
   875                         si->Peak=level.GetPeak();
   876                         InfoCache.Cache(si,fi);
   877                         }
   878                       }
   879                     }
   880                     //fall through
   881                   case dsOK:
   882                   case dsError:
   883                     scan->user|=SCANNED_LVL;
   884                     go=false;
   885                     break;
   886                   }
   887                 }
   888               }
   889             else scan->user|=SCANNED_LVL;
   890             dec->Stop();
   891             }
   892           }
   893         listMutex.Lock();
   894         }
   895       pass2=false;
   896       }
   897     do {
   898       scan=0; release=false; fgCond.Broadcast();
   899       db(printf("mgr: background scan idle\n"))
   900       bgCond.Wait(listMutex);
   901       db(printf("mgr: background scan idle wakeup\n"))
   902       } while(!stopscan && (release || throttle));
   903     }
   904   listMutex.Unlock();
   905   db(printf("mgr: background scan thread ended (pid=%d)\n", getpid()))
   906 }
   907 
   908 void cPlayManager::Throttle(bool thr)
   909 {
   910   if(MP3Setup.BgrScan) {
   911     if(!thr && throttle) {
   912       db(printf("mgr: bgr-scan -> run (%d)\n",time_ms()))
   913       listMutex.Lock();
   914       throttle=false; bgCond.Broadcast();
   915       listMutex.Unlock();
   916       }
   917     if(thr && !throttle) {
   918       db(printf("mgr: bgr-scan -> throttle (%d)\n",time_ms()))
   919       throttle=true;
   920       }
   921     }
   922 }
   923 
   924 void cPlayManager::ToggleShuffle(void)
   925 {
   926   shuffleMode=!shuffleMode;
   927   d(printf("mgr: shuffle mode toggled : %d\n",shuffleMode))
   928   if(shuffleMode && !eol) {
   929     curr=0; currIndex=-1;
   930     shuffle->Shuffle(maxIndex+1,-1);
   931     Next();
   932     }
   933 }
   934 
   935 void cPlayManager::ToggleLoop(void)
   936 {
   937   loopMode=!loopMode;
   938   d(printf("mgr: loop mode toggled : %d\n",loopMode))
   939 }
   940 
   941 bool cPlayManager::Info(int num, cMP3PlayInfo *pi)
   942 {
   943   cSong *s;
   944   int idx=num-1;
   945   if(idx<0) { idx=currIndex; s=curr; }
   946   else      { s=list.Get(idx); }
   947   memset(pi,0,sizeof(*pi));
   948   pi->Num=idx+1;
   949   pi->MaxNum=maxIndex+1;
   950   pi->Loop=loopMode;
   951   pi->Shuffle=shuffleMode;
   952   bool res=false;
   953   if(s) {
   954     strn0cpy(pi->Title,s->Name(),sizeof(pi->Title));
   955     strn0cpy(pi->Filename,s->FullPath(),sizeof(pi->Filename));
   956     cSongInfo *si=s->Info(false);
   957     if(si && si->HasInfo()) {
   958       static char *modestr[] = { "Mono","Dual","Joint-Stereo","Stereo" };
   959 
   960       if(si->Title)  strn0cpy(pi->Title,si->Title,sizeof(pi->Title));
   961       if(si->Artist) strn0cpy(pi->Artist,si->Artist,sizeof(pi->Artist));
   962       if(si->Album)  strn0cpy(pi->Album,si->Album,sizeof(pi->Album));
   963       strn0cpy(pi->SMode,modestr[si->ChMode],sizeof(pi->SMode));
   964       pi->Year=si->Year;
   965       pi->SampleFreq=si->SampleFreq;
   966       pi->Bitrate=si->Bitrate;
   967       pi->MaxBitrate=si->MaxBitrate;
   968       res=true;
   969       }
   970     }
   971   pi->Hash=MakeHashBuff((char *)pi,(char *)&pi->Loop-(char *)pi);
   972   return res;
   973 }
   974 
   975 void cPlayManager::Add(cPlayList *pl)
   976 {
   977   cMutexLock lock(&listMutex);
   978   bool real=false;
   979   for(cSong *song=pl->First(); song; song=pl->cList<cSong>::Next(song)) {
   980     cSong *ns=new cSong(song);
   981     list.Add(ns);
   982     real=true;
   983     }
   984   if(real) {
   985     if(MP3Setup.BgrScan) { stopscan=false; if(!Active()) Start(); }
   986     else stopscan=true;
   987     bgCond.Broadcast();
   988     maxIndex=list.Count()-1;
   989     if(shuffleMode) shuffle->Shuffle(maxIndex+1,currIndex);
   990     if(!curr) Next();
   991     }
   992 }
   993 
   994 void cPlayManager::Flush(void)
   995 {
   996   cMutexLock lock(&listMutex);
   997   Halt();
   998   list.Clear();
   999   shuffle->Flush();
  1000 }
  1001 
  1002 void cPlayManager::Halt(void)
  1003 {
  1004   cMutexLock lock(&listMutex);
  1005   curr=0; currIndex=-1;
  1006   playNew=true;
  1007   stopscan=true; bgCond.Broadcast();
  1008   NoScan(0);
  1009   NoPlay(0);
  1010 }
  1011 
  1012 void cPlayManager::NoScan(cSong *nono)
  1013 {
  1014   // call with listMutex locked!!
  1015   while((nono && pass2 && scan==nono) || (!nono && scan)) {
  1016     release=true; bgCond.Broadcast();
  1017     d(printf("mgr: waiting for bgr release ... (pass2=%d nono=%p scan=%p)\n",pass2,nono,scan))
  1018     fgCond.Wait(listMutex);
  1019     }
  1020 }
  1021 
  1022 void cPlayManager::NoPlay(cSong *nono)
  1023 {
  1024   // call with listMutex locked!!
  1025   while((nono && play==nono) || (!nono && play)) {
  1026     playNew=true;
  1027     fgCond.Wait(listMutex);
  1028     }
  1029 }
  1030 
  1031 bool cPlayManager::Next(void)
  1032 {
  1033   cMutexLock lock(&listMutex);
  1034   int ni;
  1035   cSong *n;
  1036   if(shuffleMode) {
  1037     if(curr) {
  1038       ni=shuffle->Next(currIndex);
  1039       if(ni<0) {
  1040         if(loopMode || eol) {
  1041           shuffle->Shuffle(maxIndex+1,-1);
  1042           ni=shuffle->First();
  1043           }
  1044         else eol=true;
  1045         }
  1046       }
  1047     else
  1048       ni=shuffle->First();
  1049     n=(ni>=0) ? list.Get(ni) : 0;
  1050     }
  1051   else {
  1052     if(curr) {
  1053       n=list.cList<cSong>::Next(curr);
  1054       if(!n) {
  1055         if(loopMode || eol) n=list.First();
  1056         else eol=true;
  1057         }
  1058       }
  1059     else
  1060       n=list.First();
  1061     ni=n ? n->Index() : -1;
  1062     }
  1063   if(n) {
  1064     curr=n; currIndex=ni;
  1065     playNew=true; eol=false;
  1066     d(printf("mgr: next -> %d\n",currIndex))
  1067     return true;
  1068     }
  1069   return false;
  1070 }
  1071 
  1072 bool cPlayManager::Prev(void)
  1073 {
  1074   cMutexLock lock(&listMutex);
  1075   int ni;
  1076   cSong *n;
  1077   if(shuffleMode) {
  1078     ni=shuffle->Prev(currIndex);
  1079     n=(ni>=0) ? list.Get(ni) : 0;
  1080     }
  1081   else {
  1082     n=list.cList<cSong>::Prev(curr);
  1083     ni=n ? n->Index() : -1;
  1084     }
  1085   if(n) {
  1086     curr=n; currIndex=ni;
  1087     playNew=true; eol=false;
  1088     d(printf("mgr: prev -> %d\n",currIndex))
  1089     return true;
  1090     }
  1091   return false;
  1092 }
  1093 
  1094 void cPlayManager::Goto(int num)
  1095 {
  1096   cMutexLock lock(&listMutex);
  1097   if(num>0 && num<=maxIndex+1) {
  1098     int idx=num-1;
  1099     if(shuffleMode) {
  1100       if(eol) {
  1101         shuffle->Shuffle(maxIndex+1,-1);
  1102         currIndex=shuffle->Goto(idx,-1);
  1103         }
  1104       else
  1105         currIndex=shuffle->Goto(idx,currIndex);
  1106       }
  1107     else
  1108       currIndex=idx;
  1109     curr=(currIndex>=0) ? list.Get(currIndex) : 0;
  1110     playNew=true; eol=false;
  1111     d(printf("mgr: goto -> %d\n",currIndex))
  1112     }
  1113 }
  1114 
  1115 cSong *cPlayManager::Current(void)
  1116 {
  1117   cMutexLock lock(&listMutex);
  1118   if(!play) {
  1119     NoScan(curr);
  1120     play=curr;
  1121     playNew=false;
  1122     if(play) d(printf("mgr: playing %s\n",play->Name()))
  1123     else d(printf("mgr: nothing to play\n"))
  1124     fgCond.Broadcast();
  1125     }
  1126   return play;
  1127 }
  1128 
  1129 bool cPlayManager::NextCurrent(void)
  1130 {
  1131   cMutexLock lock(&listMutex);
  1132   return (!eol && (playNew || Next()));
  1133 }
  1134 
  1135 bool cPlayManager::NewCurrent(void)
  1136 {
  1137   return playNew;
  1138 }
  1139 
  1140 void cPlayManager::Release(void)
  1141 {
  1142   cMutexLock lock(&listMutex);
  1143   play=0;
  1144   fgCond.Broadcast();
  1145 }
  1146 
  1147 // --- cOutput -----------------------------------------------------------------
  1148 
  1149 struct FrameHeader {
  1150   unsigned int samplerate;
  1151   };
  1152 #define FHS sizeof(struct FrameHeader)
  1153 
  1154 class cOutput {
  1155 protected:
  1156   cMP3Player *player;
  1157   cScale scale;
  1158 public:
  1159   cOutput(cMP3Player *Player);
  1160   virtual ~cOutput() {}
  1161   virtual void Init(void);
  1162   virtual unsigned int SampleRate(unsigned int PcmSampleRate)=0;
  1163   virtual cFrame *MakeFrame(unsigned int & Samples, const mad_fixed_t **Data, int index, int sr)=0;
  1164   virtual int Output(const unsigned char *Data, int Len, bool SOF)=0;
  1165   virtual bool Poll(void)=0;
  1166   virtual void Play(void)=0;
  1167   virtual void Pause(void)=0;
  1168 #ifdef DEBUG
  1169   virtual void Stats(void);
  1170 #endif
  1171   };
  1172 
  1173 cOutput::cOutput(cMP3Player *Player)
  1174 {
  1175   player=Player;
  1176 }
  1177 
  1178 void cOutput::Init(void)
  1179 {
  1180   scale.Init();
  1181 }
  1182 
  1183 #ifdef DEBUG
  1184 void cOutput::Stats(void)
  1185 {
  1186   scale.Stats();
  1187 }
  1188 #endif
  1189 
  1190 // --- cOutputDvb --------------------------------------------------------------
  1191 
  1192 /*
  1193 struct LPCMHeader { int id:8;              // id
  1194                     int frame_count:8;     // number of frames
  1195                     int access_ptr:16;     // first acces unit pointer, i.e. start of audio frame
  1196                     bool emphasis:1;       // audio emphasis on-off
  1197                     bool mute:1;           // audio mute on-off
  1198                     bool reserved:1;       // reserved
  1199                     int frame_number:5;    // audio frame number
  1200                     int quant_wlen:2;      // quantization word length
  1201                     int sample_freq:2;     // audio sampling frequency (48khz=0, 96khz=1, 44,1khz=2, 32khz=3)
  1202                     bool reserved2:1;      // reserved
  1203                     int chan_count:3;      // number of audio channels - 1 (e.g. stereo = 1)
  1204                     int dyn_range_ctrl:8;  // dynamic range control (0x80 if off)
  1205                     };
  1206 */
  1207 
  1208 #define FRAMESIZE 2048 // max. frame size allowed for DVB driver
  1209 
  1210 class cOutputDvb : public cOutput {
  1211 private:
  1212   cPoller poll;
  1213   unsigned int outSr;
  1214   bool only48khz;
  1215 public:
  1216   cOutputDvb(cMP3Player *Player);
  1217   virtual unsigned int SampleRate(unsigned int PcmSampleRate);
  1218   virtual cFrame *MakeFrame(unsigned int & Samples, const mad_fixed_t **Data, int index, int sr);
  1219   virtual int Output(const unsigned char *Data, int Len, bool SOF);
  1220   virtual bool Poll(void);
  1221   virtual void Play(void);
  1222   virtual void Pause(void);
  1223   };
  1224 
  1225 cOutputDvb::cOutputDvb(cMP3Player *Player)
  1226 :cOutput(Player)
  1227 {
  1228   only48khz=MP3Setup.Only48kHz;
  1229   outSr=0;
  1230 #if APIVERSNUM == 10318
  1231   cDevice::PrimaryDevice()->SetCurrentAudioTrack(ttDolbyFirst);
  1232 #elif APIVERSNUM >= 10319
  1233   cDevice::PrimaryDevice()->SetCurrentAudioTrack(ttAudio);
  1234 #endif
  1235   d(printf("mp3-dvb: using DVB output\n"))
  1236 }
  1237 
  1238 unsigned int cOutputDvb::SampleRate(unsigned int PcmSampleRate)
  1239 {
  1240   unsigned int samplerate=48000;
  1241   if(!only48khz) {
  1242     switch(PcmSampleRate) { // If one of the supported frequencies, do it without resampling.
  1243       case 96000:           // Select a "even" upsampling frequency if possible, too.
  1244         samplerate=96000;
  1245         break;
  1246       //case 48000: // this is already the default ...
  1247       //  samplerate=48000;
  1248       //  break;
  1249       case 11025:
  1250       case 22050:
  1251       case 44100:
  1252         samplerate=44100;
  1253         break;
  1254       case 8000:
  1255       case 16000:
  1256       case 32000:
  1257         samplerate=32000;
  1258         break;
  1259       }
  1260     }
  1261   return samplerate;
  1262 }
  1263 
  1264 cFrame *cOutputDvb::MakeFrame(unsigned int & Samples, const mad_fixed_t **Data, int index, int sr)
  1265 {
  1266   static const unsigned char header[] = {
  1267     0x00, // PES header
  1268     0x00,
  1269     0x01,
  1270     0xBD, // private stream
  1271     0x00,
  1272     0x00,
  1273     0x87, // mpeg2, aligned, copyright, original
  1274     0x00, // no pts/dts
  1275     0x00, // PES header data len
  1276     0xA0, // aLPCM header
  1277     0xFF,
  1278     0x00,
  1279     0x04,
  1280     0x00,
  1281     0x01, // 2-channel stereo (n-1)
  1282     0x80  // neutral dynamic range
  1283     };
  1284   cFrame *f=0;
  1285   unsigned char *buff=MALLOC(uchar,FRAMESIZE);
  1286   if(buff) {
  1287     struct FrameHeader *fh=(struct FrameHeader *)buff;
  1288     fh->samplerate=sr;
  1289     memcpy(buff+FHS,header,sizeof(header));
  1290     int srMode;
  1291     switch(sr) {
  1292       default:
  1293       case 48000: srMode=0<<4; break;
  1294       case 96000: srMode=1<<4; break;
  1295       case 44100: srMode=2<<4; break;
  1296       case 32000: srMode=3<<4; break;
  1297       }
  1298     buff[14+FHS]|=srMode;
  1299     unsigned int outlen=scale.ScaleBlock(buff+sizeof(header)+FHS,FRAMESIZE-sizeof(header)-FHS,Samples,Data[0],Data[1],MP3Setup.AudioMode?amDitherBE:amRoundBE);
  1300     if(outlen) { 
  1301       // lPCM has 600 fps which is 80 samples at 48kHz per channel
  1302       // Frame size = (sample_rate * quantization * channels)/4800
  1303       buff[10+FHS]=outlen*(4800/16/2)/sr;
  1304       outlen+=(sizeof(header)-6);
  1305       buff[4+FHS]=outlen>>8;
  1306       buff[5+FHS]=outlen;
  1307       f=new cFrame(buff,-(outlen+6+FHS),ftUnknown,index);
  1308       }
  1309     if(!f) free(buff);
  1310     }
  1311   return f;
  1312 }
  1313 
  1314 #ifdef BROKEN_PCM
  1315 #include "player-mp3-sample.c"
  1316 #endif
  1317 
  1318 int cOutputDvb::Output(const unsigned char *Data, int Len, bool SOF)
  1319 {
  1320   int n=0;
  1321   if(SOF) {
  1322 #ifdef BROKEN_PCM
  1323     struct FrameHeader *fh=(struct FrameHeader *)Data;
  1324     if(fh->samplerate!=outSr) {
  1325       if(outSr) {
  1326         // at this point we would need access to AUDIO_STOP/AUDIO_PLAY
  1327         // ioctl, but unfortunaly VDR's API doesn't provides this.
  1328         // So we have to do magic to make the driver switch samplerate.
  1329         const unsigned char *p=testAudio;
  1330         int pc=sizeof(testAudio);
  1331         int r;
  1332         do {
  1333 #if APIVERSNUM < 10318
  1334           r=player->PlayVideo(p,pc);
  1335 #else
  1336           r=player->PlayPes(p,pc);
  1337 #endif
  1338           if(r>0) { p+=r; pc-=r; }
  1339           if(r==0) Poll();
  1340           } while(r>=0 && pc>0);
  1341         }
  1342       outSr=fh->samplerate;
  1343       d(printf("mp3-dvb: output samplerate now %d\n",outSr))
  1344       }
  1345 #endif
  1346     n=FHS;
  1347     Data+=n; Len-=n;
  1348     }
  1349 #if APIVERSNUM < 10318
  1350   int r=player->PlayVideo(Data,Len);
  1351 #else
  1352   int r=player->PlayPes(Data,Len);
  1353 #endif
  1354   return (r>=0 ? r+n : -1);
  1355 }
  1356 
  1357 bool cOutputDvb::Poll(void)
  1358 {
  1359   return player->DevicePoll(poll,500);
  1360 }
  1361 
  1362 void cOutputDvb::Play(void)
  1363 {
  1364 #ifndef BROKEN_PCM
  1365   player->DevicePlay();
  1366 #endif
  1367 }
  1368 
  1369 void cOutputDvb::Pause(void)
  1370 {
  1371 #ifndef BROKEN_PCM
  1372   player->DeviceFreeze();
  1373 #endif
  1374 }
  1375 
  1376 // --- cOutputOss --------------------------------------------------------------
  1377 
  1378 #ifdef WITH_OSS
  1379 
  1380 const char *dspdevice="/dev/dsp";
  1381 
  1382 class cOutputOss : public cOutput {
  1383 private:
  1384   int fd;
  1385   cPoller poll;
  1386   unsigned int outSr;
  1387   unsigned char buff[8192];
  1388   //
  1389   bool Reset(unsigned int sr);
  1390 public:
  1391   cOutputOss(cMP3Player *Player);
  1392   virtual ~cOutputOss();
  1393   virtual void Init(void);
  1394   virtual unsigned int SampleRate(unsigned int PcmSampleRate);
  1395   virtual cFrame *MakeFrame(unsigned int & Samples, const mad_fixed_t **Data, int index, int sr);
  1396   virtual int Output(const unsigned char *Data, int Len, bool SOF);
  1397   virtual bool Poll(void);
  1398   virtual void Play(void);
  1399   virtual void Pause(void);
  1400   };
  1401 
  1402 cOutputOss::cOutputOss(cMP3Player *Player)
  1403 :cOutput(Player)
  1404 {
  1405   fd=-1; outSr=0;
  1406   d(printf("mp3-oss: using OSS output\n"))
  1407 }
  1408 
  1409 cOutputOss::~cOutputOss()
  1410 {
  1411   close(fd);
  1412 }
  1413 
  1414 void cOutputOss::Init(void)
  1415 {
  1416   if(fd<0) {
  1417     fd=open(dspdevice,O_WRONLY|O_NONBLOCK);
  1418     if(fd>=0) poll.Add(fd,true);
  1419     else esyslog("ERROR: Cannot open dsp device '%s': %s!",dspdevice,strerror(errno));
  1420     }
  1421   cOutput::Init();
  1422 }
  1423 
  1424 bool cOutputOss::Reset(unsigned int sr)
  1425 {
  1426   if(fd>=0) {
  1427     CHECK(ioctl(fd,SNDCTL_DSP_SYNC,0));
  1428     int format=AFMT_S16_LE;
  1429     CHECK(ioctl(fd,SNDCTL_DSP_SETFMT,&format));
  1430     if(format==AFMT_S16_LE) {
  1431       int channels=2;
  1432       CHECK(ioctl(fd,SNDCTL_DSP_CHANNELS,&channels));
  1433       if(channels==2) {
  1434         int real=sr;
  1435         CHECK(ioctl(fd,SNDCTL_DSP_SPEED,&real));
  1436         d(printf("oss: DSP samplerate now %d\n",real))
  1437         if(abs(real-sr)<sr/50) {
  1438           outSr=sr;
  1439           d(printf("mp3-oss: DSP reset done\n"))
  1440           return true;
  1441           }
  1442         else {
  1443           d(printf("mp3-oss: driver can't handle samplerate %d, got %d\n",sr,real))
  1444           esyslog("ERROR: OSS driver can't handle samplerate %d, got %d\n",sr,real);
  1445           }
  1446         }
  1447       else {
  1448         d(printf("mp3-oss: 2-channel stereo not supported\n"))
  1449         esyslog("ERROR: OSS driver doesn't support 2-channel stereo.");
  1450         }
  1451       }
  1452     else {
  1453       d(printf("mp3-oss: little-endian samples not supported\n"))
  1454       esyslog("ERROR: OSS driver doesn't support 16-bit little-endian samples.");
  1455       }
  1456     close(fd); fd=-1;
  1457     }
  1458   return false;
  1459 }
  1460 
  1461 unsigned int cOutputOss::SampleRate(unsigned int PcmSampleRate)
  1462 {
  1463   return PcmSampleRate;
  1464 }
  1465 
  1466 cFrame *cOutputOss::MakeFrame(unsigned int & Samples, const mad_fixed_t **Data, int index, int sr)
  1467 {
  1468   struct FrameHeader *fh=(struct FrameHeader *)buff;
  1469   fh->samplerate=sr;
  1470   cFrame *f=0;
  1471   unsigned int outlen=scale.ScaleBlock(buff+FHS,sizeof(buff)-FHS,Samples,Data[0],Data[1],MP3Setup.AudioMode?amDitherLE:amRoundLE);
  1472   if(outlen) 
  1473     f=new cFrame(buff,outlen+FHS,ftUnknown,index);
  1474   return f;
  1475 }
  1476 
  1477 int cOutputOss::Output(const unsigned char *Data, int Len, bool SOF)
  1478 {
  1479   if(fd>=0) {
  1480     int n=0;
  1481     if(SOF) {
  1482       struct FrameHeader *fh=(struct FrameHeader *)Data;
  1483       if(fh->samplerate!=outSr) Reset(fh->samplerate);
  1484       n=FHS;
  1485       Data+=n; Len-=n;
  1486       }
  1487     int r=write(fd,Data,Len);
  1488     if(r<0 && !FATALERRNO) r=0;
  1489     if(r>=0) return n+r;
  1490     }
  1491   return -1;
  1492 }
  1493 
  1494 bool cOutputOss::Poll(void)
  1495 {
  1496   return fd>=0 ? poll.Poll(500) : false;
  1497 }
  1498 
  1499 void cOutputOss::Play(void)
  1500 {
  1501 }
  1502 
  1503 void cOutputOss::Pause(void)
  1504 {
  1505   CHECK(ioctl(fd,SNDCTL_DSP_POST,0));
  1506 }
  1507 
  1508 #endif
  1509 
  1510 // --- cMP3Player --------------------------------------------------------------
  1511 
  1512 cMP3Player::cMP3Player()
  1513 :cPlayer(MP3Setup.BackgrMode==1 ? pmAudioOnly : pmAudioOnlyBlack)
  1514 {
  1515   active=true; started=false; isStream=false;
  1516   ringBuffer=new cRingBufferFrame(MP3BUFSIZE);
  1517   rframe=0; pframe=0; decoder=0; output=0;
  1518   playMode=pmStartup; state=msStop;
  1519   playindex=total=0;
  1520 }
  1521 
  1522 cMP3Player::~cMP3Player()
  1523 {
  1524   Detach();
  1525   delete ringBuffer;
  1526 }
  1527 
  1528 void cMP3Player::Activate(bool On)
  1529 {
  1530   if(On) {
  1531     d(printf("mp3: player active true requested...\n"))
  1532     if(!started) {
  1533       playMode=pmStartup; Start(); started=true;
  1534       playModeMutex.Lock();
  1535       WaitPlayMode(pmStartup,true); // wait for the decoder to become ready
  1536       playModeMutex.Unlock();
  1537       Lock();
  1538       Play();
  1539       Unlock();
  1540       }
  1541     d(printf("mp3: player active true done\n"))
  1542     }
  1543   else if(started && active) {
  1544     d(printf("mp3: player active false requested...\n"))
  1545     Lock(); StopPlay(); Unlock();
  1546     active=false;
  1547     SetPlayMode(pmStartup);
  1548     Cancel(2);
  1549     d(printf("mp3: player active false done\n"))
  1550     }
  1551 }
  1552 
  1553 void cMP3Player::SetPlayMode(ePlayMode mode)
  1554 {
  1555   playModeMutex.Lock();
  1556   if(mode!=playMode) {
  1557     playMode=mode;
  1558     dm(printf("mp3: setting mode=%d (pid=%d)\n",mode,getpid()))
  1559     playModeCond.Broadcast();
  1560     }
  1561   playModeMutex.Unlock();
  1562 }
  1563 
  1564 void cMP3Player::WaitPlayMode(ePlayMode mode, bool inv)
  1565 {
  1566   // must be called with playModeMutex LOCKED !!!
  1567 
  1568   while(active && ((!inv && mode!=playMode) || (inv && mode==playMode))) {
  1569     dm(printf("mp3: entering wait for mode%s%d with mode=%d (pid=%d)\n",inv?"!=":"==",mode,playMode,getpid()))
  1570     playModeCond.Wait(playModeMutex);
  1571     dm(printf("mp3: returning from wait with mode=%d (pid=%d)\n",playMode,getpid()))
  1572     }
  1573 }
  1574 
  1575 void cMP3Player::Action(void)
  1576 {
  1577   cSong *playing=0;
  1578   struct mad_pcm *pcm=0;
  1579   cResample resample[2];
  1580   unsigned int nsamples[2];
  1581   const mad_fixed_t *data[2];
  1582   cLevel level;
  1583   cNormalize norm;
  1584   bool haslevel=false;
  1585   const unsigned char *p=0;
  1586   int pc=0, readindex=0;
  1587   bool imageValid=true;
  1588   int imageCheck=0;
  1589 #ifdef DEBUG
  1590   int beat=0;
  1591 #endif
  1592 #ifdef DEBUG_DELAY
  1593   int lastwrite=0;
  1594 #endif
  1595 
  1596   dsyslog("mp3: player thread started (pid=%d)", getpid());
  1597   state=msStop;
  1598   SetPlayMode(pmStopped);
  1599 
  1600   delete output; output=0;
  1601 #ifdef WITH_OSS
  1602   if(MP3Setup.AudioOutMode==AUDIOOUTMODE_OSS) output=new cOutputOss(this);
  1603 #endif
  1604   if(MP3Setup.AudioOutMode==AUDIOOUTMODE_DVB) output=new cOutputDvb(this);
  1605   if(!output) {
  1606     d(printf("mp3: audiooutmode mismatch or no output driver\n"))
  1607     esyslog("ERROR: no audio output driver. balling out");
  1608     goto abort;
  1609     }
  1610 
  1611   while(active) {
  1612 #ifdef DEBUG
  1613     {
  1614     int now=time(0);
  1615     if(now>=beat) {
  1616       int avail=ringBuffer->Available();
  1617       printf("mp3: heartbeat buffer=%d now=%d\n",avail,now&4095);
  1618       //output->Stats(); if(haslevel) norm.Stats();
  1619       beat=now+(avail>(MP3BUFSIZE*10/100) ? (avail<(MP3BUFSIZE*50/100) ? 2 : 20) : 1);
  1620       }
  1621     }
  1622 #endif
  1623 
  1624     Lock();
  1625 
  1626 next:
  1627     if(!pframe && playing && !imageValid && imageCheck<time_ms()) {
  1628       unsigned char *mem;
  1629       int len;
  1630       imageCheck=time_ms()+250;
  1631       imageValid=playing->Image(mem,len);
  1632       if(mem) {
  1633         if(playindex) SLEEP(80); // stillpicture ioctl freezes without this
  1634         DeviceStillPicture(mem,len);
  1635         free(mem);
  1636         }
  1637       }
  1638 
  1639     bool SOF=false;
  1640     if(!pframe && playMode==pmPlay) {
  1641       pframe=ringBuffer->Get();
  1642       if(pframe) {
  1643         playindex=pframe->Index();
  1644         p=pframe->Data();
  1645         pc=pframe->Count();
  1646         SOF=true;
  1647         }
  1648       }
  1649 
  1650     if(pframe) {
  1651 #ifdef DEBUG_DELAY
  1652       {
  1653       int now=time_ms();
  1654       if(lastwrite && lastwrite<now-(DEBUG_DELAY+50))
  1655         printf("mp3: write delayed %d ms\n",now-lastwrite);
  1656       lastwrite=now;
  1657       }
  1658 #endif
  1659       int w=output->Output(p,pc,SOF);
  1660       if(w>0) {
  1661         p+=w; pc-=w;
  1662         if(pc<=0) {
  1663           ringBuffer->Drop(pframe);
  1664           pframe=0;
  1665           goto next;
  1666           }
  1667         }
  1668       else if(w<0 && FATALERRNO) {
  1669         LOG_ERROR;
  1670         d(printf("mp3: output failed: %s\n",strerror(errno)))
  1671         Unlock();
  1672         goto abort;
  1673         }
  1674       }
  1675 
  1676     if(mgr->NewCurrent() && playMode==pmPlay && state!=msStart) {
  1677       Empty();
  1678       state=msRestart;
  1679       d(printf("mp3: stale song change, restart.\n"))
  1680       }
  1681 
  1682     if(!rframe && playMode==pmPlay) {
  1683       switch(state) {
  1684         case msStart:
  1685           d(printf("mp3: starting play\n"))
  1686           mgr->Throttle(true);
  1687           playindex=readindex=total=0;
  1688           playing=mgr->Current();
  1689           if(playing) {
  1690             if((decoder=playing->Decoder()) && decoder->Start()) {
  1691               isStream=decoder->IsStream(); levelgood=!isStream; haslevel=false;
  1692               cSongInfo *si=playing->Info(true);
  1693               if(si) {
  1694                 if(si->Level>0.0) {
  1695                   d(printf("mp3: found song level=%f peak=%f\n",si->Level,si->Peak))
  1696                   haslevel=true;
  1697                   norm.Init(si->Level,si->Peak);
  1698                   }
  1699                 if(si->HasInfo())
  1700                   total=SecondsToFrames(si->Total);
  1701                 }
  1702               d(printf("mp3: isStream=%d levelgood=%d haslevel=%d\n",isStream,levelgood,haslevel))
  1703               output->Init();
  1704               level.Init();
  1705               if(MP3Setup.BackgrMode==2) imageValid=false;
  1706               state=msDecode;
  1707               break;
  1708               }
  1709             else
  1710               esyslog("ERROR: playlist entry %s is not a valid file",playing->Name());
  1711             }
  1712           else
  1713             d(printf("mp3: no current on start play\n"))
  1714           state=msEof;
  1715           break;
  1716         case msDecode:
  1717           {
  1718 #ifdef DEBUG_DELAY
  1719           int now=time_ms();
  1720 #endif
  1721           struct Decode *ds=decoder->Decode();
  1722 #ifdef DEBUG_DELAY
  1723           now=time_ms()-now;
  1724           if(now>DEBUG_DELAY) printf("mp3: decode delayed %d ms\n",now);
  1725 #endif
  1726           switch(ds->status) {
  1727             case dsPlay:
  1728               pcm=ds->pcm;
  1729               readindex=ds->index;
  1730               state=msNormalize;
  1731               break;
  1732             case dsSkip:
  1733             case dsSoftError:
  1734               // skipping, state unchanged, next decode
  1735               break;
  1736             case dsEof:
  1737               if(!haslevel && levelgood) { // save level & peak to infocache on eof
  1738                 double l=level.GetLevel();
  1739                 if(l>0.0) {
  1740                   cSongInfo *si=decoder->SongInfo(false);
  1741                   cFileInfo *fi=decoder->FileInfo();
  1742                   if(si && fi) {
  1743                     si->Level=l;
  1744                     si->Peak=level.GetPeak();
  1745                     InfoCache.Cache(si,fi);
  1746                     }
  1747                   }
  1748                 }
  1749               state=msEof;
  1750               break;
  1751             case dsOK:
  1752             case dsError:
  1753               state=msError;
  1754               break;
  1755             }
  1756           break;
  1757           }
  1758         case msNormalize:
  1759           if(!haslevel) { if(levelgood) level.GetPower(pcm); }
  1760           else norm.AddGain(pcm);
  1761           state=msResample;
  1762           break;
  1763         case msResample:
  1764 #ifdef DEBUG
  1765           {
  1766           static unsigned int oldrate=0;
  1767           if(oldrate!=pcm->samplerate) {
  1768             printf("mp3: new input sample rate %d\n",pcm->samplerate);
  1769             oldrate=pcm->samplerate;
  1770             }
  1771           }
  1772 #endif
  1773           nsamples[0]=nsamples[1]=pcm->length;
  1774           data[0]=pcm->samples[0];
  1775           data[1]=pcm->channels>1 ? pcm->samples[1]:0;
  1776 
  1777           dvbSampleRate=output->SampleRate(pcm->samplerate);
  1778           if(dvbSampleRate!=pcm->samplerate) {
  1779             if(resample[0].SetInputRate(pcm->samplerate,dvbSampleRate)) {
  1780               nsamples[0]=resample[0].ResampleBlock(nsamples[0],data[0]);
  1781               data[0]    =resample[0].Resampled();
  1782               }
  1783             if(data[1] && resample[1].SetInputRate(pcm->samplerate,dvbSampleRate)) {
  1784               nsamples[1]=resample[1].ResampleBlock(nsamples[1],data[1]);
  1785               data[1]    =resample[1].Resampled();
  1786               }
  1787             }
  1788           state=msOutput;
  1789           break;
  1790         case msOutput:
  1791           if(nsamples[0]>0) rframe=output->MakeFrame(nsamples[0],data,readindex,dvbSampleRate);
  1792           else state=msDecode;
  1793           break;
  1794         case msError:
  1795         case msEof:
  1796           d(printf("mp3: eof or error\n"))
  1797           state=msWait;
  1798           // fall through
  1799         case msRestart:
  1800         case msStop:
  1801           d(printf("mp3: stopping play\n"))
  1802           if(decoder) { decoder->Stop(); decoder=0; }
  1803           mgr->Release(); playing=0; imageValid=true;
  1804           levelgood=false;
  1805 #ifdef DEBUG
  1806           output->Stats(); if(haslevel) norm.Stats();
  1807 #endif
  1808           if(state==msStop) SetPlayMode(pmStopped);
  1809           if(state==msRestart) state=msStart;
  1810           break;
  1811         case msWait:
  1812           if(ringBuffer->Available()==0) {
  1813             if(mgr->NextCurrent()) {
  1814               d(printf("mp3: playing next\n"))
  1815               state=msStart;
  1816               }
  1817             else {
  1818               d(printf("mp3: end of playlist\n"))
  1819               if(MP3Setup.AbortAtEOL) {
  1820                 active=false;
  1821                 d(printf("mp3: aborting player...\n"))
  1822                 }
  1823               else d(printf("mp3: player idle...\n"))
  1824               SetPlayMode(pmStopped);
  1825               }
  1826             }
  1827           break;
  1828         }
  1829       }
  1830 
  1831     if(rframe && ringBuffer->Put(rframe)) rframe=0;
  1832 
  1833     Unlock();
  1834 
  1835     if((rframe || state==msWait) && pframe) {
  1836       mgr->Throttle(false);
  1837       output->Poll();
  1838       }
  1839     else if(playMode!=pmPlay) {
  1840       mgr->Throttle(false);
  1841       if(!imageValid)
  1842         SLEEP(100);
  1843       else {
  1844         playModeMutex.Lock();
  1845         if(playMode!=pmPlay) WaitPlayMode(playMode,true);
  1846         playModeMutex.Unlock();
  1847         }
  1848 #ifdef DEBUG_DELAY
  1849       lastwrite=0;
  1850 #endif
  1851       }
  1852     else if(state!=msWait && ringBuffer->Available()<(MP3BUFSIZE*50/100)) {
  1853       mgr->Throttle(true);
  1854       }
  1855     }
  1856 
  1857 abort:
  1858   Lock();
  1859   delete rframe;
  1860   delete output; output=0;
  1861   if(decoder) { decoder->Stop(); decoder=0; }
  1862   mgr->Release(); playing=0;
  1863   SetPlayMode(pmStopped);
  1864   Unlock();
  1865   active=false;
  1866 
  1867   dsyslog("mp3: player thread ended (pid=%d)", getpid());
  1868 }
  1869 
  1870 void cMP3Player::Empty(void)
  1871 {
  1872   Lock();
  1873   delete rframe; rframe=0; pframe=0;
  1874   ringBuffer->Clear();
  1875   DeviceClear();
  1876   Unlock();
  1877 }
  1878 
  1879 void cMP3Player::StopPlay(void) // StopPlay() must be called in locked state!!!
  1880 {
  1881   if(playMode!=pmStopped) {
  1882     Empty();
  1883     state=msStop;
  1884     SetPlayMode(pmPlay);
  1885     Unlock();                 // let the decode thread process the stop signal
  1886     playModeMutex.Lock();
  1887     WaitPlayMode(pmStopped,false);
  1888     playModeMutex.Unlock();
  1889     Lock();
  1890     }
  1891 }
  1892 
  1893 void cMP3Player::Pause(void)
  1894 {
  1895   Lock();
  1896   if(playMode==pmPaused) Play();
  1897   else if(playMode==pmPlay && !isStream) {
  1898     d(printf("mp3: pause\n"))
  1899     if(output) output->Pause();
  1900     SetPlayMode(pmPaused);
  1901     }
  1902   Unlock();
  1903 }
  1904 
  1905 void cMP3Player::Play(void)
  1906 {
  1907   Lock();
  1908   if(playMode!=pmPlay) {
  1909     d(printf("mp3: play\n"))
  1910     if(playMode==pmStopped) state=msStart;
  1911     if(output) output->Play();
  1912     SetPlayMode(pmPlay);
  1913     }
  1914   Unlock();
  1915 }
  1916 
  1917 bool cMP3Player::PrevCheck(void)
  1918 {
  1919   bool res=false;
  1920   Lock();
  1921   if(playindex>=2000 && !isStream) {
  1922     state=msRestart; res=true;
  1923     Empty();
  1924     d(printf("mp3: skip to start of song\n"))
  1925     }
  1926   Unlock();
  1927   return res;
  1928 }
  1929 
  1930 void cMP3Player::SkipSeconds(int secs)
  1931 {
  1932   if(playMode!=pmStopped && !isStream) {
  1933     Lock();
  1934     d(printf("mp3: skip secs %d\n",secs))
  1935     if(playMode==pmPaused) SetPlayMode(pmPlay);
  1936     float bufsecs=(float)ringBuffer->Available() / (float)(dvbSampleRate*OUT_FACT);
  1937     d(printf("mp3: ringbuffer available %f secs\n",bufsecs))
  1938     if(secs>0 && bufsecs>=(float)secs) {
  1939       // clear intermediate queue
  1940       if(pframe) {
  1941         ringBuffer->Drop(pframe);
  1942         pframe=0;
  1943         }
  1944       DeviceClear();
  1945       // skip inside ringbuffer
  1946       int skipindex=playindex+secs*1000;
  1947       d(printf("mp3: skipping play=%d skip=%d ...",playindex,skipindex))
  1948       cFrame *f;
  1949       do {
  1950         f=ringBuffer->Get();
  1951         if(f) {
  1952           playindex=f->Index();
  1953           ringBuffer->Drop(f);
  1954           d(printf("*"))
  1955           }
  1956         } while(f && playindex<skipindex);
  1957       d(printf("\nmp3: skipped play=%d skip=%d\n",playindex,skipindex))
  1958       }
  1959     else {
  1960       if(decoder && decoder->Skip(secs,bufsecs)) levelgood=false;
  1961       Empty();
  1962       }
  1963     Unlock();
  1964     }
  1965 }
  1966 
  1967 bool cMP3Player::GetIndex(int &Current, int &Total, bool SnapToIFrame)
  1968 {
  1969   Current=SecondsToFrames(playindex/1000); Total=total;
  1970   return total>=0;
  1971 }
  1972 
  1973 bool cMP3Player::GetReplayMode(bool &Play, bool &Forward, int &Speed)
  1974 {
  1975   Play=(playMode==pmPlay);
  1976   Forward=true;
  1977   Speed=-1;
  1978   return true;
  1979 }