player-mp3.c
author nathan
Mon, 17 Aug 2009 20:55:55 +0800
branchtrunk
changeset 28 38d35ff3d93f
parent 23 3b14b8aacaa0
child 29 640ce9201139
permissions -rw-r--r--
update po files
     1 /*
     2  * MP3/MPlayer plugin to VDR (C++)
     3  *
     4  * (C) 2001-2009 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 (%llu)\n",cTimeMs::Now()))
   913       listMutex.Lock();
   914       throttle=false; bgCond.Broadcast();
   915       listMutex.Unlock();
   916       }
   917     if(thr && !throttle) {
   918       db(printf("mgr: bgr-scan -> throttle (%llu)\n",cTimeMs::Now()))
   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 const 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   cDevice::PrimaryDevice()->SetCurrentAudioTrack(ttAudio);
  1231   d(printf("mp3-dvb: using DVB output\n"))
  1232 }
  1233 
  1234 unsigned int cOutputDvb::SampleRate(unsigned int PcmSampleRate)
  1235 {
  1236   unsigned int samplerate=48000;
  1237   if(!only48khz) {
  1238     switch(PcmSampleRate) { // If one of the supported frequencies, do it without resampling.
  1239       case 96000:           // Select a "even" upsampling frequency if possible, too.
  1240         samplerate=96000;
  1241         break;
  1242       //case 48000: // this is already the default ...
  1243       //  samplerate=48000;
  1244       //  break;
  1245       case 11025:
  1246       case 22050:
  1247       case 44100:
  1248         samplerate=44100;
  1249         break;
  1250       case 8000:
  1251       case 16000:
  1252       case 32000:
  1253         samplerate=32000;
  1254         break;
  1255       }
  1256     }
  1257   return samplerate;
  1258 }
  1259 
  1260 cFrame *cOutputDvb::MakeFrame(unsigned int & Samples, const mad_fixed_t **Data, int index, int sr)
  1261 {
  1262   static const unsigned char header[] = {
  1263     0x00, // PES header
  1264     0x00,
  1265     0x01,
  1266     0xBD, // private stream
  1267     0x00,
  1268     0x00,
  1269     0x87, // mpeg2, aligned, copyright, original
  1270     0x00, // no pts/dts
  1271     0x00, // PES header data len
  1272     0xA0, // aLPCM header
  1273     0xFF,
  1274     0x00,
  1275     0x04,
  1276     0x00,
  1277     0x01, // 2-channel stereo (n-1)
  1278     0x80  // neutral dynamic range
  1279     };
  1280   cFrame *f=0;
  1281   unsigned char *buff=MALLOC(uchar,FRAMESIZE);
  1282   if(buff) {
  1283     struct FrameHeader *fh=(struct FrameHeader *)buff;
  1284     fh->samplerate=sr;
  1285     memcpy(buff+FHS,header,sizeof(header));
  1286     int srMode;
  1287     switch(sr) {
  1288       default:
  1289       case 48000: srMode=0<<4; break;
  1290       case 96000: srMode=1<<4; break;
  1291       case 44100: srMode=2<<4; break;
  1292       case 32000: srMode=3<<4; break;
  1293       }
  1294     buff[14+FHS]|=srMode;
  1295     unsigned int outlen=scale.ScaleBlock(buff+sizeof(header)+FHS,FRAMESIZE-sizeof(header)-FHS,Samples,Data[0],Data[1],MP3Setup.AudioMode?amDitherBE:amRoundBE);
  1296     if(outlen) { 
  1297       // lPCM has 600 fps which is 80 samples at 48kHz per channel
  1298       // Frame size = (sample_rate * quantization * channels)/4800
  1299       buff[10+FHS]=outlen*(4800/16/2)/sr;
  1300       outlen+=(sizeof(header)-6);
  1301       buff[4+FHS]=outlen>>8;
  1302       buff[5+FHS]=outlen;
  1303       f=new cFrame(buff,-(outlen+6+FHS),ftUnknown,index);
  1304       }
  1305     if(!f) free(buff);
  1306     }
  1307   return f;
  1308 }
  1309 
  1310 #ifdef BROKEN_PCM
  1311 #include "player-mp3-sample.c"
  1312 #endif
  1313 
  1314 int cOutputDvb::Output(const unsigned char *Data, int Len, bool SOF)
  1315 {
  1316   int n=0;
  1317   if(SOF) {
  1318 #ifdef BROKEN_PCM
  1319     struct FrameHeader *fh=(struct FrameHeader *)Data;
  1320     if(fh->samplerate!=outSr) {
  1321       if(outSr) {
  1322         // at this point we would need access to AUDIO_STOP/AUDIO_PLAY
  1323         // ioctl, but unfortunaly VDR's API doesn't provides this.
  1324         // So we have to do magic to make the driver switch samplerate.
  1325         const unsigned char *p=testAudio;
  1326         int pc=sizeof(testAudio);
  1327         int r;
  1328         do {
  1329           r=player->PlayPes(p,pc);
  1330           if(r>0) { p+=r; pc-=r; }
  1331           if(r==0) Poll();
  1332           } while(r>=0 && pc>0);
  1333         }
  1334       outSr=fh->samplerate;
  1335       d(printf("mp3-dvb: output samplerate now %d\n",outSr))
  1336       }
  1337 #endif
  1338     n=FHS;
  1339     Data+=n; Len-=n;
  1340     }
  1341   int r=player->PlayPes(Data,Len);
  1342   return (r>=0 ? r+n : -1);
  1343 }
  1344 
  1345 bool cOutputDvb::Poll(void)
  1346 {
  1347   return player->DevicePoll(poll,500);
  1348 }
  1349 
  1350 void cOutputDvb::Play(void)
  1351 {
  1352 #ifndef BROKEN_PCM
  1353   player->DevicePlay();
  1354 #endif
  1355 }
  1356 
  1357 void cOutputDvb::Pause(void)
  1358 {
  1359 #ifndef BROKEN_PCM
  1360   player->DeviceFreeze();
  1361 #endif
  1362 }
  1363 
  1364 // --- cOutputOss --------------------------------------------------------------
  1365 
  1366 #ifdef WITH_OSS
  1367 
  1368 const char *dspdevice="/dev/dsp";
  1369 
  1370 class cOutputOss : public cOutput {
  1371 private:
  1372   int fd;
  1373   cPoller poll;
  1374   unsigned int outSr;
  1375   unsigned char buff[8192];
  1376   //
  1377   bool Reset(unsigned int sr);
  1378 public:
  1379   cOutputOss(cMP3Player *Player);
  1380   virtual ~cOutputOss();
  1381   virtual void Init(void);
  1382   virtual unsigned int SampleRate(unsigned int PcmSampleRate);
  1383   virtual cFrame *MakeFrame(unsigned int & Samples, const mad_fixed_t **Data, int index, int sr);
  1384   virtual int Output(const unsigned char *Data, int Len, bool SOF);
  1385   virtual bool Poll(void);
  1386   virtual void Play(void);
  1387   virtual void Pause(void);
  1388   };
  1389 
  1390 cOutputOss::cOutputOss(cMP3Player *Player)
  1391 :cOutput(Player)
  1392 {
  1393   fd=-1; outSr=0;
  1394   d(printf("mp3-oss: using OSS output\n"))
  1395 }
  1396 
  1397 cOutputOss::~cOutputOss()
  1398 {
  1399   if(fd>=0) close(fd);
  1400 }
  1401 
  1402 void cOutputOss::Init(void)
  1403 {
  1404   if(fd<0) {
  1405     fd=open(dspdevice,O_WRONLY|O_NONBLOCK);
  1406     if(fd>=0) {
  1407       if(fcntl(fd,F_SETFL,0)==0)
  1408         poll.Add(fd,true);
  1409       else {
  1410         esyslog("ERROR: Cannot make dsp device '%s' blocking: %s!",dspdevice,strerror(errno));
  1411         close(fd); fd=-1;
  1412         }
  1413       }
  1414     else esyslog("ERROR: Cannot open dsp device '%s': %s!",dspdevice,strerror(errno));
  1415     }
  1416   cOutput::Init();
  1417 }
  1418 
  1419 bool cOutputOss::Reset(unsigned int sr)
  1420 {
  1421   if(fd>=0) {
  1422     CHECK(ioctl(fd,SNDCTL_DSP_SYNC,0));
  1423     int format=AFMT_S16_LE;
  1424     CHECK(ioctl(fd,SNDCTL_DSP_SETFMT,&format));
  1425     if(format==AFMT_S16_LE) {
  1426       int channels=2;
  1427       CHECK(ioctl(fd,SNDCTL_DSP_CHANNELS,&channels));
  1428       if(channels==2) {
  1429         int real=sr;
  1430         CHECK(ioctl(fd,SNDCTL_DSP_SPEED,&real));
  1431         d(printf("oss: DSP samplerate now %d\n",real))
  1432         if(abs(real-sr)<sr/50) {
  1433           outSr=sr;
  1434           d(printf("mp3-oss: DSP reset done\n"))
  1435           return true;
  1436           }
  1437         else {
  1438           d(printf("mp3-oss: driver can't handle samplerate %d, got %d\n",sr,real))
  1439           esyslog("ERROR: OSS driver can't handle samplerate %d, got %d\n",sr,real);
  1440           }
  1441         }
  1442       else {
  1443         d(printf("mp3-oss: 2-channel stereo not supported\n"))
  1444         esyslog("ERROR: OSS driver doesn't support 2-channel stereo.");
  1445         }
  1446       }
  1447     else {
  1448       d(printf("mp3-oss: little-endian samples not supported\n"))
  1449       esyslog("ERROR: OSS driver doesn't support 16-bit little-endian samples.");
  1450       }
  1451     close(fd); fd=-1;
  1452     }
  1453   return false;
  1454 }
  1455 
  1456 unsigned int cOutputOss::SampleRate(unsigned int PcmSampleRate)
  1457 {
  1458   return PcmSampleRate;
  1459 }
  1460 
  1461 cFrame *cOutputOss::MakeFrame(unsigned int & Samples, const mad_fixed_t **Data, int index, int sr)
  1462 {
  1463   struct FrameHeader *fh=(struct FrameHeader *)buff;
  1464   fh->samplerate=sr;
  1465   cFrame *f=0;
  1466   unsigned int outlen=scale.ScaleBlock(buff+FHS,sizeof(buff)-FHS,Samples,Data[0],Data[1],MP3Setup.AudioMode?amDitherLE:amRoundLE);
  1467   if(outlen) 
  1468     f=new cFrame(buff,outlen+FHS,ftUnknown,index);
  1469   return f;
  1470 }
  1471 
  1472 int cOutputOss::Output(const unsigned char *Data, int Len, bool SOF)
  1473 {
  1474   if(fd>=0) {
  1475     int n=0;
  1476     if(SOF) {
  1477       struct FrameHeader *fh=(struct FrameHeader *)Data;
  1478       if(fh->samplerate!=outSr) Reset(fh->samplerate);
  1479       n=FHS;
  1480       Data+=n; Len-=n;
  1481       }
  1482     if(poll.Poll(0)) {
  1483       int r=write(fd,Data,Len);
  1484       if(r<0 && FATALERRNO) return -1;
  1485       if(r>0) n+=r;
  1486       }
  1487     return n;
  1488     }
  1489   return -1;
  1490 }
  1491 
  1492 bool cOutputOss::Poll(void)
  1493 {
  1494   return fd>=0 ? poll.Poll(500) : false;
  1495 }
  1496 
  1497 void cOutputOss::Play(void)
  1498 {
  1499 }
  1500 
  1501 void cOutputOss::Pause(void)
  1502 {
  1503   CHECK(ioctl(fd,SNDCTL_DSP_POST,0));
  1504 }
  1505 
  1506 #endif
  1507 
  1508 // --- cMP3Player --------------------------------------------------------------
  1509 
  1510 cMP3Player::cMP3Player()
  1511 :cPlayer(MP3Setup.BackgrMode==1 ? pmAudioOnly : pmAudioOnlyBlack)
  1512 {
  1513   active=true; started=false; isStream=false;
  1514   ringBuffer=new cRingBufferFrame(MP3BUFSIZE);
  1515   rframe=0; pframe=0; decoder=0; output=0;
  1516   playMode=pmStartup; state=msStop;
  1517   playindex=total=0;
  1518 }
  1519 
  1520 cMP3Player::~cMP3Player()
  1521 {
  1522   Detach();
  1523   delete ringBuffer;
  1524 }
  1525 
  1526 void cMP3Player::Activate(bool On)
  1527 {
  1528   if(On) {
  1529     d(printf("mp3: player active true requested...\n"))
  1530     if(!started) {
  1531       playMode=pmStartup; Start(); started=true;
  1532       playModeMutex.Lock();
  1533       WaitPlayMode(pmStartup,true); // wait for the decoder to become ready
  1534       playModeMutex.Unlock();
  1535       Lock();
  1536       Play();
  1537       Unlock();
  1538       }
  1539     d(printf("mp3: player active true done\n"))
  1540     }
  1541   else if(started && active) {
  1542     d(printf("mp3: player active false requested...\n"))
  1543     Lock(); StopPlay(); Unlock();
  1544     active=false;
  1545     SetPlayMode(pmStartup);
  1546     Cancel(2);
  1547     d(printf("mp3: player active false done\n"))
  1548     }
  1549 }
  1550 
  1551 void cMP3Player::SetPlayMode(ePlayMode mode)
  1552 {
  1553   playModeMutex.Lock();
  1554   if(mode!=playMode) {
  1555     playMode=mode;
  1556     dm(printf("mp3: setting mode=%d (pid=%d)\n",mode,getpid()))
  1557     playModeCond.Broadcast();
  1558     }
  1559   playModeMutex.Unlock();
  1560 }
  1561 
  1562 void cMP3Player::WaitPlayMode(ePlayMode mode, bool inv)
  1563 {
  1564   // must be called with playModeMutex LOCKED !!!
  1565 
  1566   while(active && ((!inv && mode!=playMode) || (inv && mode==playMode))) {
  1567     dm(printf("mp3: entering wait for mode%s%d with mode=%d (pid=%d)\n",inv?"!=":"==",mode,playMode,getpid()))
  1568     playModeCond.Wait(playModeMutex);
  1569     dm(printf("mp3: returning from wait with mode=%d (pid=%d)\n",playMode,getpid()))
  1570     }
  1571 }
  1572 
  1573 void cMP3Player::Action(void)
  1574 {
  1575   cSong *playing=0;
  1576   struct mad_pcm *pcm=0;
  1577   cResample resample[2];
  1578   unsigned int nsamples[2];
  1579   const mad_fixed_t *data[2];
  1580   cLevel level;
  1581   cNormalize norm;
  1582   bool haslevel=false;
  1583   const unsigned char *p=0;
  1584   int pc=0, readindex=0;
  1585   bool imageValid=true;
  1586   cTimeMs imageCheck;
  1587 #ifdef DEBUG
  1588   int beat=0;
  1589 #endif
  1590 #ifdef DEBUG_DELAY
  1591   cTimeMs lastwrite(2000000);
  1592 #endif
  1593 
  1594   dsyslog("mp3: player thread started (pid=%d)", getpid());
  1595   state=msStop;
  1596   SetPlayMode(pmStopped);
  1597 
  1598   delete output; output=0;
  1599 #ifdef WITH_OSS
  1600   if(MP3Setup.AudioOutMode==AUDIOOUTMODE_OSS) output=new cOutputOss(this);
  1601 #endif
  1602   if(MP3Setup.AudioOutMode==AUDIOOUTMODE_DVB) output=new cOutputDvb(this);
  1603   if(!output) {
  1604     d(printf("mp3: audiooutmode mismatch or no output driver\n"))
  1605     esyslog("ERROR: no audio output driver. balling out");
  1606     goto abort;
  1607     }
  1608 
  1609   while(active) {
  1610 #ifdef DEBUG
  1611     {
  1612     int now=time(0);
  1613     if(now>=beat) {
  1614       int avail=ringBuffer->Available();
  1615       printf("mp3: heartbeat buffer=%d now=%d\n",avail,now&4095);
  1616       //output->Stats(); if(haslevel) norm.Stats();
  1617       beat=now+(avail>(MP3BUFSIZE*10/100) ? (avail<(MP3BUFSIZE*50/100) ? 2 : 20) : 1);
  1618       }
  1619     }
  1620 #endif
  1621 
  1622     Lock();
  1623 
  1624 next:
  1625     if(!pframe && playing && !imageValid && imageCheck.Elapsed()) {
  1626       unsigned char *mem;
  1627       int len;
  1628       imageCheck.Set(250);
  1629       imageValid=playing->Image(mem,len);
  1630       if(mem) {
  1631         if(playindex) cCondWait::SleepMs(80); // stillpicture ioctl freezes without this
  1632         DeviceStillPicture(mem,len);
  1633         free(mem);
  1634         }
  1635       }
  1636 
  1637     bool SOF=false;
  1638     if(!pframe && playMode==pmPlay) {
  1639       pframe=ringBuffer->Get();
  1640       if(pframe) {
  1641         playindex=pframe->Index();
  1642         p=pframe->Data();
  1643         pc=pframe->Count();
  1644         SOF=true;
  1645         }
  1646       }
  1647 
  1648     if(pframe) {
  1649 #ifdef DEBUG_DELAY
  1650       {
  1651       if(lastwrite.TimedOut())
  1652         printf("mp3: write delayed %llu ms\n",lastwrite.Elapsed());
  1653       lastwrite.Set(DEBUG_DELAY+50);
  1654       }
  1655 #endif
  1656       int w=output->Output(p,pc,SOF);
  1657       if(w>0) {
  1658         p+=w; pc-=w;
  1659         if(pc<=0) {
  1660           ringBuffer->Drop(pframe);
  1661           pframe=0;
  1662           goto next;
  1663           }
  1664         }
  1665       else if(w<0 && FATALERRNO) {
  1666         LOG_ERROR;
  1667         d(printf("mp3: output failed: %s\n",strerror(errno)))
  1668         Unlock();
  1669         goto abort;
  1670         }
  1671       }
  1672 
  1673     if(mgr->NewCurrent() && playMode==pmPlay && state!=msStart) {
  1674       Empty();
  1675       state=msRestart;
  1676       d(printf("mp3: stale song change, restart.\n"))
  1677       }
  1678 
  1679     if(!rframe && playMode==pmPlay) {
  1680       switch(state) {
  1681         case msStart:
  1682           d(printf("mp3: starting play\n"))
  1683           mgr->Throttle(true);
  1684           playindex=readindex=total=0;
  1685           playing=mgr->Current();
  1686           if(playing) {
  1687             if((decoder=playing->Decoder()) && decoder->Start()) {
  1688               isStream=decoder->IsStream(); levelgood=!isStream; haslevel=false;
  1689               cSongInfo *si=playing->Info(true);
  1690               if(si) {
  1691                 if(si->Level>0.0) {
  1692                   d(printf("mp3: found song level=%f peak=%f\n",si->Level,si->Peak))
  1693                   haslevel=true;
  1694                   norm.Init(si->Level,si->Peak);
  1695                   }
  1696                 if(si->HasInfo())
  1697                   total=SecondsToFrames(si->Total);
  1698                 }
  1699               d(printf("mp3: isStream=%d levelgood=%d haslevel=%d\n",isStream,levelgood,haslevel))
  1700               output->Init();
  1701               level.Init();
  1702               if(MP3Setup.BackgrMode==2) imageValid=false;
  1703               state=msDecode;
  1704               break;
  1705               }
  1706             else
  1707               esyslog("ERROR: playlist entry %s is not a valid file",playing->Name());
  1708             }
  1709           else
  1710             d(printf("mp3: no current on start play\n"))
  1711           state=msEof;
  1712           break;
  1713         case msDecode:
  1714           {
  1715 #ifdef DEBUG_DELAY
  1716           cTimeMs check(DEBUG_DELAY);
  1717 #endif
  1718           struct Decode *ds=decoder->Decode();
  1719 #ifdef DEBUG_DELAY
  1720           if(check.TimedOut()) printf("mp3: decode delayed %llu ms\n",check.Elapsed());
  1721 #endif
  1722           switch(ds->status) {
  1723             case dsPlay:
  1724               pcm=ds->pcm;
  1725               readindex=ds->index;
  1726               state=msNormalize;
  1727               break;
  1728             case dsSkip:
  1729             case dsSoftError:
  1730               // skipping, state unchanged, next decode
  1731               break;
  1732             case dsEof:
  1733               if(!haslevel && levelgood) { // save level & peak to infocache on eof
  1734                 double l=level.GetLevel();
  1735                 if(l>0.0) {
  1736                   cSongInfo *si=decoder->SongInfo(false);
  1737                   cFileInfo *fi=decoder->FileInfo();
  1738                   if(si && fi) {
  1739                     si->Level=l;
  1740                     si->Peak=level.GetPeak();
  1741                     InfoCache.Cache(si,fi);
  1742                     }
  1743                   }
  1744                 }
  1745               state=msEof;
  1746               break;
  1747             case dsOK:
  1748             case dsError:
  1749               state=msError;
  1750               break;
  1751             }
  1752           break;
  1753           }
  1754         case msNormalize:
  1755           if(!haslevel) { if(levelgood) level.GetPower(pcm); }
  1756           else norm.AddGain(pcm);
  1757           state=msResample;
  1758           break;
  1759         case msResample:
  1760 #ifdef DEBUG
  1761           {
  1762           static unsigned int oldrate=0;
  1763           if(oldrate!=pcm->samplerate) {
  1764             printf("mp3: new input sample rate %d\n",pcm->samplerate);
  1765             oldrate=pcm->samplerate;
  1766             }
  1767           }
  1768 #endif
  1769           nsamples[0]=nsamples[1]=pcm->length;
  1770           data[0]=pcm->samples[0];
  1771           data[1]=pcm->channels>1 ? pcm->samples[1]:0;
  1772 
  1773           dvbSampleRate=output->SampleRate(pcm->samplerate);
  1774           if(dvbSampleRate!=pcm->samplerate) {
  1775             if(resample[0].SetInputRate(pcm->samplerate,dvbSampleRate)) {
  1776               nsamples[0]=resample[0].ResampleBlock(nsamples[0],data[0]);
  1777               data[0]    =resample[0].Resampled();
  1778               }
  1779             if(data[1] && resample[1].SetInputRate(pcm->samplerate,dvbSampleRate)) {
  1780               nsamples[1]=resample[1].ResampleBlock(nsamples[1],data[1]);
  1781               data[1]    =resample[1].Resampled();
  1782               }
  1783             }
  1784           state=msOutput;
  1785           break;
  1786         case msOutput:
  1787           if(nsamples[0]>0) rframe=output->MakeFrame(nsamples[0],data,readindex,dvbSampleRate);
  1788           else state=msDecode;
  1789           break;
  1790         case msError:
  1791         case msEof:
  1792           d(printf("mp3: eof or error\n"))
  1793           state=msWait;
  1794           // fall through
  1795         case msRestart:
  1796         case msStop:
  1797           d(printf("mp3: stopping play\n"))
  1798           if(decoder) { decoder->Stop(); decoder=0; }
  1799           mgr->Release(); playing=0; imageValid=true;
  1800           levelgood=false;
  1801 #ifdef DEBUG
  1802           output->Stats(); if(haslevel) norm.Stats();
  1803 #endif
  1804           if(state==msStop) SetPlayMode(pmStopped);
  1805           if(state==msRestart) state=msStart;
  1806           break;
  1807         case msWait:
  1808           if(ringBuffer->Available()==0) {
  1809             if(mgr->NextCurrent()) {
  1810               d(printf("mp3: playing next\n"))
  1811               state=msStart;
  1812               }
  1813             else {
  1814               d(printf("mp3: end of playlist\n"))
  1815               if(MP3Setup.AbortAtEOL) {
  1816                 active=false;
  1817                 d(printf("mp3: aborting player...\n"))
  1818                 }
  1819               else d(printf("mp3: player idle...\n"))
  1820               SetPlayMode(pmStopped);
  1821               }
  1822             }
  1823           break;
  1824         }
  1825       }
  1826 
  1827     if(rframe && ringBuffer->Put(rframe)) rframe=0;
  1828 
  1829     Unlock();
  1830 
  1831     if((rframe || state==msWait) && pframe) {
  1832       mgr->Throttle(false);
  1833       output->Poll();
  1834       }
  1835     else if(playMode!=pmPlay) {
  1836       mgr->Throttle(false);
  1837       if(!imageValid)
  1838         cCondWait::SleepMs(100);
  1839       else {
  1840         playModeMutex.Lock();
  1841         if(playMode!=pmPlay) WaitPlayMode(playMode,true);
  1842         playModeMutex.Unlock();
  1843         }
  1844 #ifdef DEBUG_DELAY
  1845       lastwrite.Set(2000000);
  1846 #endif
  1847       }
  1848     else if(state!=msWait && ringBuffer->Available()<(MP3BUFSIZE*50/100)) {
  1849       mgr->Throttle(true);
  1850       }
  1851     }
  1852 
  1853 abort:
  1854   Lock();
  1855   delete rframe;
  1856   delete output; output=0;
  1857   if(decoder) { decoder->Stop(); decoder=0; }
  1858   mgr->Release(); playing=0;
  1859   SetPlayMode(pmStopped);
  1860   Unlock();
  1861   active=false;
  1862 
  1863   dsyslog("mp3: player thread ended (pid=%d)", getpid());
  1864 }
  1865 
  1866 void cMP3Player::Empty(void)
  1867 {
  1868   Lock();
  1869   delete rframe; rframe=0; pframe=0;
  1870   ringBuffer->Clear();
  1871   DeviceClear();
  1872   Unlock();
  1873 }
  1874 
  1875 void cMP3Player::StopPlay(void) // StopPlay() must be called in locked state!!!
  1876 {
  1877   if(playMode!=pmStopped) {
  1878     Empty();
  1879     state=msStop;
  1880     SetPlayMode(pmPlay);
  1881     Unlock();                 // let the decode thread process the stop signal
  1882     playModeMutex.Lock();
  1883     WaitPlayMode(pmStopped,false);
  1884     playModeMutex.Unlock();
  1885     Lock();
  1886     }
  1887 }
  1888 
  1889 void cMP3Player::Pause(void)
  1890 {
  1891   Lock();
  1892   if(playMode==pmPaused) Play();
  1893   else if(playMode==pmPlay && !isStream) {
  1894     d(printf("mp3: pause\n"))
  1895     if(output) output->Pause();
  1896     SetPlayMode(pmPaused);
  1897     }
  1898   Unlock();
  1899 }
  1900 
  1901 void cMP3Player::Play(void)
  1902 {
  1903   Lock();
  1904   if(playMode!=pmPlay) {
  1905     d(printf("mp3: play\n"))
  1906     if(playMode==pmStopped) state=msStart;
  1907     if(output) output->Play();
  1908     SetPlayMode(pmPlay);
  1909     }
  1910   Unlock();
  1911 }
  1912 
  1913 bool cMP3Player::PrevCheck(void)
  1914 {
  1915   bool res=false;
  1916   Lock();
  1917   if(playindex>=2000 && !isStream) {
  1918     state=msRestart; res=true;
  1919     Empty();
  1920     d(printf("mp3: skip to start of song\n"))
  1921     }
  1922   Unlock();
  1923   return res;
  1924 }
  1925 
  1926 void cMP3Player::SkipSeconds(int secs)
  1927 {
  1928   if(playMode!=pmStopped && !isStream) {
  1929     Lock();
  1930     d(printf("mp3: skip secs %d\n",secs))
  1931     if(playMode==pmPaused) SetPlayMode(pmPlay);
  1932     float bufsecs=(float)ringBuffer->Available() / (float)(dvbSampleRate*OUT_FACT);
  1933     d(printf("mp3: ringbuffer available %f secs\n",bufsecs))
  1934     if(secs>0 && bufsecs>=(float)secs) {
  1935       // clear intermediate queue
  1936       if(pframe) {
  1937         ringBuffer->Drop(pframe);
  1938         pframe=0;
  1939         }
  1940       DeviceClear();
  1941       // skip inside ringbuffer
  1942       int skipindex=playindex+secs*1000;
  1943       d(printf("mp3: skipping play=%d skip=%d ...",playindex,skipindex))
  1944       cFrame *f;
  1945       do {
  1946         f=ringBuffer->Get();
  1947         if(f) {
  1948           playindex=f->Index();
  1949           ringBuffer->Drop(f);
  1950           d(printf("*"))
  1951           }
  1952         } while(f && playindex<skipindex);
  1953       d(printf("\nmp3: skipped play=%d skip=%d\n",playindex,skipindex))
  1954       }
  1955     else {
  1956       if(decoder && decoder->Skip(secs,bufsecs)) levelgood=false;
  1957       Empty();
  1958       }
  1959     Unlock();
  1960     }
  1961 }
  1962 
  1963 bool cMP3Player::GetIndex(int &Current, int &Total, bool SnapToIFrame)
  1964 {
  1965   Current=SecondsToFrames(playindex/1000); Total=total;
  1966   return total>=0;
  1967 }
  1968 
  1969 bool cMP3Player::GetReplayMode(bool &Play, bool &Forward, int &Speed)
  1970 {
  1971   Play=(playMode==pmPlay);
  1972   Forward=true;
  1973   Speed=-1;
  1974   return true;
  1975 }