//**************************************************************************
//*                     This file is part of the                           *
//*                      Mpxplay - audio player.                           *
//*                  The source code of Mpxplay is                         *
//*        (C) copyright 1998-2006 by PDSoft (Attila Padar)                *
//*                    http://mpxplay.cjb.net                              *
//*                  email: mpxplay@freemail.hu                            *
//**************************************************************************
//*  This program is distributed in the hope that it will be useful,       *
//*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *
//*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                  *
//*  Please contact with the author (with me) if you want to use           *
//*  or modify this source.                                                *
//**************************************************************************
//function:check playlist entries

#include "newfunc\newfunc.h"
#include "control\control.h"
#include "display\display.h"
#include "deparser\tagging.h"
#include "playlist.h"
#include "mpxinbuf.h"

static void get_fileinfos_under_play(struct mainvars *mvp);
static unsigned int get_onefileinfos(struct playlist_side_info *,struct playlist_entry_info *,unsigned int);
static unsigned int get_onefileinfos_from_tagset(struct playlist_entry_info *pei_dest);
static unsigned int get_onefileinfos_from_otherside(struct playlist_side_info *psi,struct playlist_entry_info *pei_dest,unsigned int fastsearch);
static void create_id3infos_from_filename(struct playlist_side_info *psi,struct playlist_entry_info *pei);

extern char *id3tagset[I3I_MAX+1];
extern unsigned int playcontrol,playrand,preloadinfo,loadid3tag,id3textconv;
extern unsigned int textscreen_maxy,refdisp,fullelapstime,timemode;

void get_allfileinfos(struct mainvars *mvp)
{
 struct playlist_side_info *psi=mvp->psi0;
 struct playlist_entry_info *pei,*dispend;
 int side,allsongs;
 char sout[64];

 for(side=0;side<PLAYLIST_MAX_SIDES;side++,psi++){
  if(psi->editsidetype&PLT_ENABLED){
   if(psi->editsidetype&PLT_EXTENDED){
    playlist_order_side(psi);
    playlist_fulltime_getside(psi);
    funcbit_disable(psi->editsidetype,PLT_EXTENDED);
   }else{
    switch(preloadinfo){
     case PLI_PRELOAD:  // -irl
	  pei=psi->firstsong;
	  dispend=pei+textscreen_maxy;
	  allsongs=psi->lastentry-pei+1;
	  while(pei<=psi->lastentry){
           if(pds_kbhit())
            if(pds_extgetch()==KEY_ESC)
             break;
	   sprintf(sout,"Preloading file informations (%2d/%d) ",pei-psi->firstsong+1,allsongs);
	   display_message(0,0,sout);
           display_message(1,0,"(press ESC to terminate it)");
	   get_onefileinfos_check(psi,pei);
	   playlist_order_entry(psi,pei);
	   if(psi==mvp->psip)
	    draw_browserbox(mvp,pei);
	   if(pei<dispend)
	    draweditor(mvp);
           pei++;
	  }
	  clear_message();
	  if(pei<=psi->lastentry)
	   playlist_chkfile_start_norm(psi,pei);
          break;
     case PLI_PLAYLOAD: // -ipl
          playlist_chkfile_start_norm(psi,0);
          break;
    }
   }
  }
 }
 if(preloadinfo==PLI_PRELOAD) // !!!
  preloadinfo=PLI_DISPLOAD;   //
}

static void get_fileinfos_under_play(struct mainvars *mvp)
{
 unsigned int fastfound,fastcount,side;
 struct playlist_side_info *psi=mvp->psi0;
 struct playlist_entry_info *pei;
 char sout[64];

 side=0;
 do{
  if(psi->chkfilenum_begin)
   break;
  if(++side>=PLAYLIST_MAX_SIDES){
   mpxplay_timer_deletefunc(&get_fileinfos_under_play);
   return;
  }
  psi++;
 }while(1);

 pei=psi->chkfilenum_begin;
 if(pei<=psi->chkfilenum_end){
  fastcount=5;
  do{
   fastfound=get_onefileinfos_check(psi,pei);
   playlist_order_entry(psi,pei);
   pei++;
  }while(fastfound && (--fastcount) && (pei<=psi->chkfilenum_end));
  psi->chkfilenum_begin=pei;
  if(!(playcontrol&PLAYC_RUNNING) && fastcount && (pei<=psi->chkfilenum_end)){
   sprintf(sout,"Loading file informations (%2d/%d)",pei-psi->firstsong,psi->lastentry-psi->firstsong+1);
   display_message(0,0,sout);
   display_message(1,0,"");
  }
 }else{
  playlist_chkfile_stop(psi);
  if(psi==mvp->psip)
   refdisp|=RDT_BROWSER;
 }
 refdisp|=RDT_EDITOR;
}

//--------------------------------------------------------------------------

void get_onefileinfos_open(struct playlist_side_info *psi,struct playlist_entry_info *pei)
{
 if(pei->entrytype==DFT_NOTCHECKED){
  pei->entrytype=DFT_UNKNOWN;
  get_onefileinfos(psi,pei,0);
  mpxplay_infile_close(psi->mvp->frp0+2);
 }
}

unsigned int get_onefileinfos_check(struct playlist_side_info *psi,struct playlist_entry_info *pei)
{
 unsigned int fastfound=get_onefileinfos(psi,pei,1);
 mpxplay_infile_close(psi->mvp->frp0+2);
 return fastfound;
}

void get_onefileinfos_is(struct playlist_side_info *psi,struct playlist_entry_info *pei)
{
 if(pei->entrytype==DFT_NOTCHECKED)
  pei->entrytype=DFT_UNKNOWN;
 get_onefileinfos(psi,pei,0);
}

static unsigned int get_onefileinfos(struct playlist_side_info *psi,struct playlist_entry_info *pei,unsigned int fastsearch)
{
 unsigned int found=0;

 playlist_fulltime_del(psi,pei);
 if((pei->entrytype!=DFT_UNKNOWN) && (pei->infobits&PEIF_ENABLED))
  found|=EDITLIST_MODE_HEAD;
 if((pei->infobits&PEIF_ID3EXIST) || !loadid3tag)
  found|=EDITLIST_MODE_ID3;
 if(found!=(EDITLIST_MODE_HEAD|EDITLIST_MODE_ID3)){
  found|=get_onefileinfos_from_tagset(pei);
  if(loadid3tag&ID3LOADMODE_LIST)
   found|=get_onefileinfos_from_id3list(psi,pei,fastsearch);
  if(found!=(EDITLIST_MODE_HEAD|EDITLIST_MODE_ID3))
   found|=get_onefileinfos_from_otherside(psi,pei,fastsearch);
  if(!(found&EDITLIST_MODE_HEAD))
   get_onefileinfos_from_file(psi,pei,found);
  create_id3infos_from_filename(psi,pei);
 }
 playlist_fulltime_add(psi,pei);

 return (found&EDITLIST_MODE_HEAD);
}

static unsigned int get_onefileinfos_from_tagset(struct playlist_entry_info *pei_dest)
{
 unsigned int i;

 for(i=0;i<=I3I_MAX;i++)
  if(id3tagset[i])
   pei_dest->id3info[i]=id3tagset[i];

 if(pei_dest->id3info[I3I_ARTIST] || pei_dest->id3info[I3I_TITLE])
  return EDITLIST_MODE_ID3;

 return 0;
}

static unsigned int get_onefileinfos_from_otherside(struct playlist_side_info *psi_dest,struct playlist_entry_info *pei_dest,unsigned int fastsearch)
{
 struct playlist_side_info *psi_src=psi_dest->psio;
 struct playlist_entry_info *pei_src;
 unsigned int modify;

 if(!(psi_src->editsidetype&PLT_ENABLED) || (psi_src->lastentry<psi_src->firstsong))
  return 0;
 modify=0;
 for(pei_src=psi_src->firstsong;pei_src<=psi_src->lastentry;pei_src++){
  if(pds_stricmp(pei_src->filename,pei_dest->filename)==0){
   if((pei_dest->entrytype==DFT_NOTCHECKED || pei_dest->entrytype==DFT_UNKNOWN) && (pei_src->entrytype!=DFT_UNKNOWN) && (pei_src->entrytype!=DFT_NOTCHECKED || fastsearch) && (pei_src->infobits&PEIF_ENABLED) && !(pei_src->infobits&PEIF_INDEXED))
    modify|=EDITLIST_MODE_HEAD;
   if(pei_src->infobits&PEIF_ID3EXIST)
    if( (!(pei_dest->infobits&PEIF_ID3EXIST) || ((pei_src->infobits&PEIF_ID3MASK) > (pei_dest->infobits&PEIF_ID3MASK)) ) && !(pei_src->infobits&PEIF_INDEXED))
     modify|=EDITLIST_MODE_ID3;
   if(modify)
    modify=playlist_editlist_addfile_one(psi_src,NULL,pei_src,pei_dest,modify);
   break;
  }
 }
 return modify;
}

void get_onefileinfos_from_file(struct playlist_side_info *psi,struct playlist_entry_info *pei,unsigned int found)
{
 unsigned int i;
 struct frame *frp=psi->mvp->frp0+2;
 struct mpxplay_infile_info_s *miis;
 struct mpxplay_audio_decoder_info_s *adi;
 struct playlist_entry_info *pei_tmp;
 char *id3p_old,*id3p_new;
 struct playlist_entry_info pei_save;

 // is file playlist?
 if(playlist_loadlist_get_header_by_ext(pei,psi,pei->filename))
  return;

 // is file audio?
 if(!mpxplay_infile_get_header_by_ext(frp,pei->filename))
  return;

 miis=frp->infile_infos;
 adi=miis->audio_decoder_infos;

 if(frp->filetype && frp->infile_funcs && miis->timemsec){
  pei->filesize=frp->filesize;
  pei->timemsec=miis->timemsec;
  pei->infile_funcs=frp->infile_funcs;
  pei->infobits|=PEIF_ENABLED;
  pei->entrytype=((unsigned long)frp->filetype<<28);
 }else{
  mpxplay_infile_close(frp);
  pei->entrytype=DFT_UNKNOWN;
  funcbit_disable(pei->infobits,PEIF_ENABLED);
  return;
 }

 //we have to run get_headerinfo (to open infile) before get_id3tag (it's done above)
 if((loadid3tag&ID3LOADMODE_FILE) && (!(found&EDITLIST_MODE_ID3) || !(pei->infobits&PEIF_ID3LOADED))){
  id3p_old=psi->id3infolastp;
  if((id3p_old<psi->id3infoendp) && (psi->lastentry<psi->endentry)){
   psi->lastentry++;
   pei_tmp=psi->lastentry;

   pds_memcpy(&pei_save,pei_tmp,sizeof(struct playlist_entry_info));
   pds_memcpy(pei_tmp,pei,sizeof(struct playlist_entry_info));
   pds_memset(&pei_tmp->id3info[0],0,(I3I_MAX+1)*sizeof(char *));

   id3p_new=mpxplay_infile_get_id3tag(frp,&pei_tmp->id3info[0],id3p_old);                // load tag infos from audio file

   // keep old (if new doesn't exist), delete old (if new exists), add new id3infos (MXU/EXTM3U/id3list vs. file-tags (ID3v1,v2,APETAG,etc.))
   if(id3p_new>id3p_old){                        // audio file has id3-tag
    pei->infobits|=PEIF_ID3EXIST|PEIF_ID3LOADED;
    psi->id3infolastp=id3p_new;
    for(i=0;i<=I3I_MAX;i++)
     if(!pei_tmp->id3info[i] || (pei->id3info[i] && ((loadid3tag&ID3LOADMODE_PREFER_LIST) || (pei->infobits&PEIF_INDEXED))))
      pds_memxch((char *)&pei_tmp->id3info[i],(char *)&pei->id3info[i],sizeof(char *));

    playlist_editlist_delfile_one(psi,pei,EDITLIST_MODE_ID3); // delete old (duplicated,non-used) id3-infos

    pds_memcpy((char *)&pei->id3info[0],(char *)&pei_tmp->id3info[0],(I3I_MAX+1)*sizeof(char *));
   }
   pds_memcpy(pei_tmp,&pei_save,sizeof(struct playlist_entry_info));
   psi->lastentry--;
  }else{
   if(!pei->id3info[I3I_ARTIST] && !pei->id3info[I3I_TITLE]){
    playlist_editlist_delfile_one(psi,pei,EDITLIST_MODE_ID3);
    if(psi->id3infolastp<psi->id3infoendp)
     psi->id3infolastp=mpxplay_infile_get_id3tag(frp,&pei->id3info[0],id3p_old); // load tag infos from audio file
   }
  }
 }
}

static void ciff_add_id3info(struct playlist_side_info *psi,struct playlist_entry_info *pei,unsigned int i3i,char *str)
{
 if(!pei->id3info[i3i]){
  char *id3p=psi->id3infolastp;
  unsigned int len=pds_strcpy(id3p,str);
  if(len){
   if(!(id3textconv&ID3TEXTCONV_FILENAME))
    len=mpxplay_playlist_textconv_do(id3p,len,0);
   if(len){
    pei->id3info[i3i]=id3p;
    psi->id3infolastp+=len+1;
    funcbit_enable(pei->infobits,PEIF_ID3EXIST);
   }
  }
 }
}

static long ciff_add_tracknum(struct playlist_side_info *psi,struct playlist_entry_info *pei,char *str)
{
 long tracknum=pds_atol(str);
 if(!pei->id3info[I3I_TRACKNUM]){
  char *id3p=psi->id3infolastp;
  if(tracknum>0){
   pei->id3info[I3I_TRACKNUM]=id3p;
   id3p+=sprintf(id3p,"%d",tracknum)+1;
   psi->id3infolastp=id3p;
  }
 }
 return tracknum;
}

static void create_id3infos_from_filename(struct playlist_side_info *psi,struct playlist_entry_info *pei)
{
 char *a,*t,*album,*t2,*e,*ext;
 long tracknum;
 char filename[MAX_PATHNAMELEN],updirname[MAX_PATHNAMELEN];

 if(!(loadid3tag&ID3LOADMODE_CLFN))
  return;
 if(pei->id3info[I3I_ARTIST] && pei->id3info[I3I_TITLE])
  return;
 if((pei->entrytype>=DFTM_DFT) && (pei->entrytype<DFT_AUDIOFILE))
  return;
 a=pds_strrchr(pei->filename,PDS_DIRECTORY_SEPARATOR_CHAR);
 if(a)
  a++;
 else
  a=pei->filename;

 tracknum=ciff_add_tracknum(psi,pei,a);

 while((a[0]>='0' && a[0]<='9') || a[0]=='.') // skip numbers and dots
  a++;
 if(!a[0])
  return;
 while(a[0]==' ' || a[0]=='-' || a[0]=='_')  // skip spaces,'-','_'
  a++;
 if(!a[0])
  return;

 pds_strcpy(filename,a);      // artist

 ext=pds_strrchr(filename,'.'); // cut file extension
 if(!ext)
  return;
 *ext=0;

 t=&filename[0];
 do{
  if(t[0]=='_')  // convert all underlines to spaces
   t[0]=' ';
  t++;
 }while(t[0]);

 t=pds_strchr(filename,'-');
 if(t){
  a=&filename[0]; // possible artist
  e=t;            // end of artist
  t++;            // title
  if(tracknum<=0){
   t2=pds_strchr(t,'-');    // check "artist - NN - title" format
   if(t2){
    tracknum=ciff_add_tracknum(psi,pei,t);
    if(tracknum>0)
     t=t2+1;      // title
   }
  }else
   t2=NULL;
  while(t[0] && t[0]==32) // title: cut spaces from begin
   t++;

  //fprintf(stdout,"a:%c t:%c\n",a[0],t[0]);
  if(t[0] || (t2 && tracknum))
   if(((a[0]>='A') && (a[0]<='Z') && (t[0]>='A') && (t[0]<='Z')) || (((a[0]<'A') || (a[0]>'Z')) && ((t[0]<'A') || (t[0]>'Z'))) || (t2 && tracknum)){ // case of begin char is same or artist-NN-title
    *e--=0;
    while(e[0] && e[0]==32 && e>a) // artist: cut spaces from end
     *e--=0;
    ciff_add_id3info(psi,pei,I3I_ARTIST,a);
   }else
    t=a;
 }else
  t=&filename[0];             // title only

 if((tracknum>0) || pei->id3info[I3I_ARTIST]) // tracknum or artist loaded
  if((tracknum>0 && pei->id3info[I3I_ARTIST]) || (ext-t)>8 || !pds_chkstr_uppercase(t)) // title is lfn like
   ciff_add_id3info(psi,pei,I3I_TITLE,t);

 if(!pei->id3info[I3I_ARTIST]){   // get artist from updir name
  pds_strcpy(updirname,pei->filename);
  e=pds_strrchr(updirname,PDS_DIRECTORY_SEPARATOR_CHAR);
  if(e){
   *e=0;
   a=pds_strrchr(updirname,PDS_DIRECTORY_SEPARATOR_CHAR); // artist
   if(a){
    a++;
    album=pds_strchr(a,'-');      // album
    if(album){
     *album=0;
     if(album[-1]==' ')
      album[-1]=0;
     do{
      album++;
     }while(*album==' ');
     ciff_add_id3info(psi,pei,I3I_ALBUM,album);
     ciff_add_id3info(psi,pei,I3I_ARTIST,a);
     ciff_add_id3info(psi,pei,I3I_TITLE,t);
    }else{
     if(pei->id3info[I3I_TITLE] && (tracknum>0) && (e-a)>=2)// || !pds_chkstr_uppercase(a)))
      ciff_add_id3info(psi,pei,I3I_ARTIST,a);
    }
   }
  }
 }

 return;
}

//-------------------------------------------------------------------------
void playlist_chkfile_start_norm(struct playlist_side_info *psi,struct playlist_entry_info *startsong)
{
 if(psi->editsidetype&PLT_ENABLED){
  struct mainvars *mvp=psi->mvp;
  if((psi==mvp->psip) && !(psi->editsidetype&PLT_DOOMQUEUE) && (mvp->aktfilenum<psi->firstsong)){
   struct playlist_entry_info *pei;
   struct frame *frp=mvp->frp0;
   long timempos=(frp->allframes)? ((long)((float)frp->infile_infos->timemsec*(float)frp->frameNum/(float)frp->allframes)):-1;

   pei=playlist_search_filename(psi,mvp->pei0->filename,timempos,NULL);
   if(pei){
    mvp->aktfilenum=pei;
    get_onefileinfos_check(psi,pei);
    playlist_randlist_pushq(psi,pei);
    mpxplay_calculate_index_start_end(frp,mvp,pei); // switch between cue and other playlist
    if((psi==mvp->psie) && (psi->editorhighline>=psi->firstentry) && (psi->editorhighline<=psi->lastentry) && !psi->editorhighline->entrytype)
     playlist_loadlist_get_header_by_ext(psi->editorhighline,psi,psi->editorhighline->filename);
    if((psi!=mvp->psie) || (psi->editorhighline<psi->firstentry) || (GET_HFT(psi->editorhighline->entrytype)!=HFT_DFT))
     playlist_editorhighline_set(psi,pei);
   }
  }
  if((psi->editsidetype&PLT_EXTENDED) && !psi->chkfilenum_begin){
   playlist_order_side(psi);
   playlist_fulltime_getside(psi);
   funcbit_disable(psi->editsidetype,PLT_EXTENDED);
   refdisp|=RDT_BROWSER|RDT_EDITOR; // ???
  }else{
   switch(preloadinfo){
    case PLI_PLAYLOAD:
      if(startsong<psi->firstsong)
       startsong=psi->firstsong;
      if(!psi->chkfilenum_begin || startsong<psi->chkfilenum_begin)
       psi->chkfilenum_begin=startsong;
      psi->chkfilenum_end=psi->lastentry;
      mpxplay_timer_addfunc(&get_fileinfos_under_play,mvp,MPXPLAY_TIMERTYPE_REPEAT|MPXPLAY_TIMERFLAG_INDOS|MPXPLAY_TIMERFLAG_LOWPRIOR,0);
      break;
    case PLI_PRELOAD :
    case PLI_DISPLOAD:
      refdisp|=RDT_RESET_EDIT;
      break;
   }
  }
 }
}

void playlist_chkfile_start_disp(struct playlist_side_info *psi,struct playlist_entry_info *startsong,struct playlist_entry_info *endsong)
{
 if((preloadinfo==PLI_DISPLOAD) && (psi->editsidetype&PLT_ENABLED)){
  if(startsong<psi->firstsong)
   startsong=psi->firstsong;
  psi->chkfilenum_begin=startsong;
  if(!endsong || (endsong>psi->lastentry))
   endsong=psi->lastentry;
  psi->chkfilenum_end=endsong;
  mpxplay_timer_addfunc(&get_fileinfos_under_play,psi->mvp,MPXPLAY_TIMERTYPE_REPEAT|MPXPLAY_TIMERFLAG_INDOS|MPXPLAY_TIMERFLAG_LOWPRIOR,0);
 }
}

void playlist_chkfile_start_ehline(struct playlist_side_info *psi,struct playlist_entry_info *pei)
{
 if((preloadinfo==PLI_EHLINELOAD) && (psi->editsidetype&PLT_ENABLED)){
  if(pei>=psi->firstsong && pei<=psi->lastentry){
   struct mainvars *mvp=psi->mvp;
   if(((mvp->aui->card_infobits&AUINFOS_CARDINFOBIT_DMAFULL) && (mvp->frp0->buffertype&PREBUFTYPE_FILLED)) || !(playcontrol&PLAYC_RUNNING)){
    get_onefileinfos_check(psi,pei);
    playlist_order_entry(psi,pei);
    //if(psi->id3ordertype[0])
    // get_onefileinfos_check(psi,pei);
   }else
    refdisp|=RDT_EDITOR;
  }
 }
}

void playlist_chkfile_stop(struct playlist_side_info *psi)
{
 psi->chkfilenum_begin=NULL;
 psi->chkfilenum_end=NULL;
 if(!(playcontrol&PLAYC_RUNNING))
  clear_message();
}

//------------------------------------------------------------------------
unsigned long playlist_entry_get_timemsec(struct playlist_entry_info *pei)
{
 unsigned long timemsec;

 if(pei->infobits&PEIF_INDEXED){
  timemsec=(pei->petime)? pei->petime:pei->timemsec;
  if(pei->pstime<=timemsec)
   timemsec-=pei->pstime;
 }else
  timemsec=pei->timemsec;

 return timemsec;
}

void playlist_fulltime_add(struct playlist_side_info *psi,struct playlist_entry_info *pei)
{
 if(pei->infobits&PEIF_ENABLED){
  if(!(pei->infobits&PEIF_FULLTIMEADDED)){
   struct mainvars *mvp;
   unsigned long timesec=(playlist_entry_get_timemsec(pei)+500)/1000;

   psi->fulltimesec+=timesec;
   funcbit_enable(pei->infobits,PEIF_FULLTIMEADDED);

   mvp=psi->mvp;
   if(!playrand && (psi==mvp->psip) && ((pei<mvp->aktfilenum) || (mvp->aktfilenum<psi->firstsong)))
    fullelapstime+=timesec;
  }
 }
}

void playlist_fulltime_del(struct playlist_side_info *psi,struct playlist_entry_info *pei)
{
 unsigned long timesec=(playlist_entry_get_timemsec(pei)+500)/1000;

 if(pei->infobits&PEIF_FULLTIMEADDED){
  psi->fulltimesec-=timesec;
  funcbit_disable(pei->infobits,PEIF_FULLTIMEADDED);

  if(playrand){
   if(pei->infobits&PEIF_RNDPLAYED)
    fullelapstime-=timesec;
  }else{
   struct mainvars *mvp=psi->mvp;
   if((psi==mvp->psip) && ((pei<mvp->aktfilenum) || (mvp->aktfilenum<psi->firstsong)))
    fullelapstime-=timesec;
  }
 }
}

void playlist_fulltime_clearside(struct playlist_side_info *psi)
{
 psi->fulltimesec=0;
 if(psi==psi->mvp->psip)
  fullelapstime=0;
}

void playlist_fulltime_getside(struct playlist_side_info *psi)
{
 struct playlist_entry_info *pei;
 mpxp_int64_t loc_fulltime=0;

 for(pei=psi->firstsong;pei<=psi->lastentry;pei++){
  if(pei->infobits&PEIF_ENABLED){
   loc_fulltime+=playlist_entry_get_timemsec(pei);
   funcbit_enable(pei->infobits,PEIF_FULLTIMEADDED);
  }
 }
 psi->fulltimesec=(loc_fulltime+500)/1000;
}

unsigned int playlist_fulltime_getelapsed(struct mainvars *mvp,unsigned int cleartime)
{
 struct playlist_side_info *psip;
 struct playlist_entry_info *pei;
 struct playlist_entry_info *end;

 if(cleartime)
  fullelapstime=0;

 if(timemode>=2 && !fullelapstime){
  psip=mvp->psip;
  if(psip->chkfilenum_begin)
   end=psip->chkfilenum_begin;
  else
   end=psip->lastentry;
  if(end>=psip->firstsong){
   mpxp_int64_t loc_fullelapstime=0;
   if(playrand){
    for(pei=psip->firstsong;pei<=end;pei++)
     if((pei->infobits&PEIF_RNDPLAYED) && (pei->infobits&PEIF_ENABLED))
      loc_fullelapstime+=playlist_entry_get_timemsec(pei);
    if(mvp->aktfilenum>=psip->firstsong)
     loc_fullelapstime-=playlist_entry_get_timemsec(mvp->aktfilenum);
   }else{
    if(end>=mvp->aktfilenum)
     end=mvp->aktfilenum-1;
    for(pei=psip->firstsong;pei<=end;pei++)
     if(pei->infobits&PEIF_ENABLED)
      loc_fullelapstime+=playlist_entry_get_timemsec(pei);
   }
   fullelapstime=(loc_fullelapstime+500)/1000;
  }else{
   fullelapstime=0;
  }
 }
 return fullelapstime;
}
