//**************************************************************************
//*                     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:playlist main

#include <malloc.h>
#include "newfunc\newfunc.h"
#include "control\control.h"
#include "display\display.h"
#include "playlist.h"

static void playlist_allocate_memworkarea(void);
static void playlist_buildlist_all(struct playlist_side_info *psi);

extern mainvars mvps;
extern char *drivescanletters,*id3tagset[I3I_MAX+1];
extern unsigned int outmode,playcontrol,playrand,playstartsong;
extern unsigned int refdisp,writeid3tag,playlistload;
extern unsigned int playlist_max_filenum_list;

static char *memworkarea;
static unsigned int playlist_max_filenum_browser;

void mpxplay_playlist_init(struct mainvars *mvp)
{
 struct playlist_side_info *psi0=mvp->psi0,*psi1=psi0+1;

 if(playlist_max_filenum_list<512)
  playlist_max_filenum_list=512;
 if(playlist_max_filenum_list>99999999)
  playlist_max_filenum_list=99999999;

 playlist_max_filenum_browser=playlist_max_filenum_list/5;
 if(playlist_max_filenum_browser<512)
  playlist_max_filenum_browser=512;
 if(playlist_max_filenum_browser>4096)
  playlist_max_filenum_browser=4096;

 if(playlistload&PLL_DOOMBOX){
  funcbit_disable(psi0->editsidetype,PLT_DIRECTORY);
  funcbit_enable(psi1->editsidetype,PLT_DOOMQUEUE);
 }

 playlist_allocate_memworkarea();
 playlist_init_pointers(mvp);
 mpxplay_playlist_textconv_init();
 playlist_sortlist_init(mvp);
 playlist_close_infile(mvp->frp0,mvp);
}

static void playlist_allocate_memworkarea(void)
{
 unsigned int allfilenums,pointerssize,filenamessize,id3memsize,memworkareasize;
 allfilenums  =playlist_max_filenum_browser+playlist_max_filenum_list;      //1999+9999=11998
 pointerssize =allfilenums*sizeof(struct playlist_entry_info);//  11998*64
 filenamessize=allfilenums*FILENAMELENGTH;                    // +11998*64
 id3memsize   =allfilenums*ID3LENGTH;                         // +11998*64
 memworkareasize=pointerssize+filenamessize+id3memsize+32768; // =2336384

 memworkarea=malloc(memworkareasize);
 if(memworkarea==NULL)
  mpxplay_close_program(MPXERROR_XMS_MEM);
 pds_memset(memworkarea,0,memworkareasize);
}

void mpxplay_playlist_close(void)
{
 playlist_id3list_close();
 mpxplay_playlist_textconv_close();
 if(memworkarea){
  free(memworkarea);
  memworkarea=NULL;
 }
}

void playlist_init_pointers(struct mainvars *mvp)
{
 struct playlist_side_info *psi0=mvp->psi0,*psi1=psi0+1;
 char *workarea=memworkarea;

 if(playlistload&PLL_DOOMBOX){
  psi0->allfilenum=playlist_max_filenum_list;
  psi1->allfilenum=playlist_max_filenum_browser;
 }else{
  psi0->allfilenum=playlist_max_filenum_browser;
  psi1->allfilenum=playlist_max_filenum_list;
 }

 mvp->pei0=(struct playlist_entry_info *)workarea; // 767872 (11998*64)
  workarea+=(playlist_max_filenum_browser+playlist_max_filenum_list)*sizeof(struct playlist_entry_info);
  workarea+=1024;

 mvp->pei0->filename=workarea; // current song's infos
  workarea+=MAX_PATHNAMELEN+MAX_ID3LEN+(1024-MAX_PATHNAMELEN); // 2048 (1024+1024)

 psi0->filenamesbeginp=workarea;
 psi0->filenameslastp=workarea;            // 127936 (1999*64)
  workarea+=psi0->allfilenum*FILENAMELENGTH;
 psi0->filenamesendp=workarea-MAX_PATHNAMELEN;

 psi1->filenamesbeginp=workarea;
 psi1->filenameslastp=workarea;            // 639936 (9999*64)
  workarea+=psi1->allfilenum*FILENAMELENGTH;
 psi1->filenamesendp=workarea-MAX_PATHNAMELEN;
  workarea+=1024;

 psi0->id3infobeginp=workarea;
 psi0->id3infolastp=workarea;              // 127936 (1999*64)
  workarea+=psi0->allfilenum*ID3LENGTH;
 psi0->id3infoendp=workarea-512;

 psi1->id3infobeginp=workarea;
 psi1->id3infolastp=workarea;              // 639936 (9999*64)
  workarea+=psi1->allfilenum*ID3LENGTH;
 psi1->id3infoendp=workarea-256;           //-----------------
					   //2305664

 psi0->firstentry=psi0->firstsong=psi0->editorhighline=mvp->pei0+1;
 psi0->lastentry=psi0->firstentry-1;
 psi0->endentry=psi0->firstentry+(psi0->allfilenum-2);

 psi1->firstentry=psi1->firstsong=psi1->editorhighline=psi0->firstentry+psi0->allfilenum;
 psi1->lastentry=psi1->firstentry-1;
 psi1->endentry=psi1->firstentry+(psi1->allfilenum-1);

 mvp->aktfilenum=psi1->lastentry;
}

//-------------------------------------------------------------------------
void playlist_peimyself_reset(struct playlist_side_info *psi,struct playlist_entry_info *firstentry,struct playlist_entry_info *lastentry)
{
 struct playlist_entry_info *pei;
 if(!firstentry)
  firstentry=psi->firstentry;
 if(!lastentry)
  lastentry=psi->endentry;
 if(lastentry>=firstentry){
  pei=firstentry;
  do{
   pei->myself=pei;
  }while((++pei)<=lastentry);
 }
}

struct playlist_entry_info *playlist_peimyself_search(struct playlist_side_info *psi,struct playlist_entry_info *pei_src)
{
 struct playlist_entry_info *pei_dest=psi->firstentry,*lastentry=psi->lastentry;
 if(lastentry>=pei_dest){
  do{
   if(pei_dest->myself==pei_src)
    return pei_dest;
  }while((++pei_dest)<=lastentry);
 }
 return NULL;
}

//------------------------------------------------------------------------
void playlist_enable_side(struct playlist_side_info *psi)
{
 if(!(psi->editsidetype&PLT_ENABLED)){
  psi->editsidetype|=PLT_ENABLED;
  playlist_peimyself_reset(psi,NULL,NULL);
  refdisp|=RDT_RESET_EDIT;
 }
}

void playlist_disable_side_partial(struct playlist_side_info *psi)
{
 struct mainvars *mvp=psi->mvp;

 playlist_editorhighline_set(psi,psi->firstentry);

 psi->firstsong=psi->firstentry;
 psi->lastentry=psi->firstentry-1;

 psi->filenameslastp=psi->filenamesbeginp;
 psi->id3infolastp=psi->id3infobeginp;

 psi->selected_files=0;

 playlist_fulltime_clearside(psi);

 if(psi==mvp->psip){
  mvp->aktfilenum=psi->firstentry-1;
  mvp->newfilenum=NULL;
  playlist_randlist_clearall(psi);
  if(!(playcontrol&PLAYC_RUNNING))
   mpxplay_stop_and_clear(mvp,0);
 }
 if(psi==mvp->psie)
  playlist_change_editorside(mvp);
 playlist_chkfile_stop(psi);
 funcbit_disable(psi->editsidetype,PLT_ENABLED|PLT_EXTENDED);
}

void playlist_disable_side_list(struct playlist_side_info *psi)
{
 struct mainvars *mvp=psi->mvp;
 if(psi==mvp->psil){
  playlist_loadsub_sublist_clear(psi);
  playlist_clear_freeopts();
  funcbit_disable(playlistload,PLL_LISTS_ALL);
 }
}

void playlist_disable_side_full(struct playlist_side_info *psi)
{
 playlist_disable_side_partial(psi);
 playlist_disable_side_list(psi);
}

void playlist_clear_side(struct playlist_side_info *psi)
{
 struct mainvars *mvp=psi->mvp;

 playlist_editorhighline_set(psi,psi->firstentry);

 psi->firstsong=psi->firstentry;
 psi->lastentry=psi->firstentry-1;

 psi->filenameslastp=psi->filenamesbeginp;
 psi->id3infolastp=psi->id3infobeginp;

 psi->selected_files=0;

 pds_memset(psi->firstentry,0,psi->allfilenum*sizeof(struct playlist_entry_info));
 playlist_fulltime_clearside(psi);

 if(psi==mvp->psip){
  mvp->aktfilenum=psi->firstentry-1;
  mvp->newfilenum=NULL;
  playlist_randlist_clearall(psi);
 }
 playlist_chkfile_stop(psi);
 funcbit_disable(psi->editsidetype,PLT_ENABLED|PLT_EXTENDED);
}

void playlist_reset_side(struct playlist_side_info *psi)
{
 psi->editsidetype=0;
}

void playlist_clear_freeopts(void)
{
 unsigned int optcount=OPT_INPUTFILE+1;
 while((optcount<MAXFREEOPTS) && freeopts[optcount])
  freeopts[optcount++]=NULL;
}

//------------------------------------------------------------------------
static unsigned int startdrive;
static char startdir[MAX_PATHNAMELEN];

void mpxplay_save_startdir(struct mainvars *mvp)
{
 struct playlist_side_info *psi;
 unsigned int i;

 pds_getcwd(startdir);
 startdrive=pds_getdrive();

 psi=mvp->psi0;
 for(i=0;i<PLAYLIST_MAX_SIDES;i++,psi++){
  psi->currdrive=startdrive;
  pds_strcpy(psi->currdir,startdir);
 }
}

void mpxplay_restore_startdir(void)
{
 pds_setdrive(startdrive);
 pds_chdir(startdir);
}

//------------------------------------------------------------------------
void listline_slice(char **listparts,char *cutchars,char *listline)
{
 char *lastpart=listline,*nextpart=NULL;
 int i,ccn=(int)pds_strlen(cutchars);
 for(i=0;i<ccn;){
  listparts[i]=lastpart;
  do{
   nextpart=pds_strchr(lastpart,cutchars[i]);
   if(nextpart){
    *nextpart++=0;
    lastpart=nextpart;
   }
   i++;
  }while(!nextpart && i<ccn);
 }
}

//-------------------------------------------------------------------------
void start_sideplay(struct mainvars *mvp,struct playlist_side_info *psi)
{
 if(!(playcontrol&PLAYC_RUNNING) && (psi->editsidetype&PLT_ENABLED)){
  mvp->psip=psi;
  if(psi->editsidetype&PLT_DOOMQUEUE){
   playlist_editorhighline_set(psi,psi->firstentry);
   mvp->aktfilenum=psi->firstentry-1;
   mvp->adone=ADONE_RESTART;
  }else{
   if(playrand)
    mvp->newsong=playlist_randlist_getnext(psi);
   else
    mvp->newsong=psi->firstsong;
  }
  playcontrol|=PLAYC_STARTNEXT;
 }
}

//*************************************************************************

void playlist_get_allfilenames(struct mainvars *mvp)
{
 struct playlist_side_info *psi0=mvp->psi0,*psi1=psi0+1;

 if(!(mvp->psil->editsidetype&PLT_DIRECTORY))
  playlist_buildlist_all(mvp->psil);

 if(!(mvp->psil->editsidetype&PLT_ENABLED)){ // playlist not loaded
  struct playlist_side_info *psilo=mvp->psil->psio;
  if(!(psilo->editsidetype&PLT_ENABLED))
   funcbit_enable(psi0->editsidetype,PLT_DIRECTORY);
  funcbit_disable(playlistload,PLL_LISTS_CMDL);
 }

 if(psi0->editsidetype&PLT_DIRECTORY){
  mvp->psil=psi1;
  playlist_loaddir_buildbrowser(psi0);
 }

 if(psi1->editsidetype&PLT_DIRECTORY)
  playlist_loaddir_buildbrowser(psi1);
 else
  playlist_loadlist_load_autosaved_list(mvp);

 if(!(psi0->editsidetype&PLT_ENABLED) && !(psi1->editsidetype&PLT_ENABLED))
  mpxplay_close_program(MPXERROR_NOFILE);
}

unsigned int playlist_buildlist_one(struct playlist_side_info *psi,char *listfile,unsigned int loadtype,char *dslp)
{
 unsigned int result=0;
 if((loadtype&PLL_STDIN) || (playlist_loadlist_check_extension(listfile) && !pds_strchr(listfile,'*') && !pds_strchr(listfile,'?'))){
  funcbit_enable(playlistload,PLL_LOADLIST);
  funcbit_disable(playlistload,(PLL_DRIVESCAN|PLL_DIRSCAN));//|PLL_STDIN));
  if(playlist_loadlist_mainload(psi,listfile,loadtype))
   result=PLL_LOADLIST;
 }else{
  struct playlist_entry_info *beginentry=psi->lastentry+1;
  funcbit_enable(playlistload,PLL_DIRSCAN);
  if(dslp)
   funcbit_enable(playlistload,PLL_DRIVESCAN);
  else
   funcbit_disable(playlistload,PLL_DRIVESCAN);
  funcbit_disable(playlistload,PLL_LOADLIST);
  playlist_loaddir_scandrives(psi,listfile,dslp);
  playlist_order_filenames_block(psi,beginentry,psi->lastentry);
  result=PLL_DIRSCAN;
 }
 return result;
}

static void playlist_buildlist_all(struct playlist_side_info *psi)
{
 unsigned int savedrive;
 char savedir[MAX_PATHNAMELEN];

 // first input file
 if(!playlist_loadsub_buildlist(psi,playlistload,drivescanletters))
  return;

 // multiply input file
 if(!(outmode&OUTMODE_TYPE_FILE) && freeopts[OPT_INPUTFILE+1]){
  unsigned int optcount=OPT_INPUTFILE+1;
  unsigned int allextended=psi->editsidetype&PLT_EXTENDED;
  pds_dir_save(&savedrive,savedir);
  mpxplay_restore_startdir();
  while((optcount<MAXFREEOPTS) && freeopts[optcount]){
   unsigned int result=playlist_buildlist_one(psi,freeopts[optcount],0,NULL);
   if(result&PLL_LOADLIST)
    allextended&=(psi->editsidetype&PLT_EXTENDED);
   else
    allextended=0;
   optcount++;
  }
  funcbit_disable(psi->editsidetype,PLT_EXTENDED);
  funcbit_copy(psi->editsidetype,allextended,PLT_EXTENDED); // playlist (side) is extended if all loaded lists are extended (then we don't check the entries)
  pds_dir_restore(savedrive,savedir);
 }

 if((playrand&2) && (psi->editsidetype&PLT_ENABLED)){
  playlist_randlist_randomize_side(psi);
  playrand=0;
 }
}

//*************************************************************************
//set starting playlist side & entry
void playlist_init_playside(struct mainvars *mvp)
{
 struct playlist_side_info *psi0=mvp->psi0,*psi1=psi0+1;

 if(psi1->editsidetype&PLT_DOOMQUEUE){
  mvp->psie=psi0;
  mvp->psip=psi1;
  if((psi1->editsidetype&PLT_ENABLED) && !(psi1->editsidetype&PLT_DIRECTORY))
   funcbit_enable(playcontrol,PLAYC_STARTNEXT);
 }else{
  if((psi1->editsidetype&PLT_ENABLED) && !(psi1->editsidetype&PLT_DIRECTORY)){
   mvp->psie=psi1;
   mvp->psip=psi1;
   if(playlistload)
    funcbit_enable(playcontrol,PLAYC_STARTNEXT);
  }else{
   mvp->psie=psi0;
   mvp->psip=psi0;
  }
 }

 playlist_editorhighline_seek(psi0,0,SEEK_SET);
 playlist_editorhighline_seek(psi1,0,SEEK_SET);
}

void playlist_init_playsong(struct mainvars *mvp)
{
 struct playlist_side_info *psip=mvp->psip;

 mvp->aktfilenum=psip->firstsong;
 if(psip->lastentry>=psip->firstsong){
  if(playstartsong){
   if((mvp->aktfilenum+playstartsong-1)<=psip->lastentry)
    mvp->aktfilenum+=playstartsong-1;
  }else{
   if(playrand){
    struct playlist_entry_info *newfilenum=playlist_randlist_getnext(psip); // start with a random file
    if(newfilenum)
     mvp->aktfilenum=newfilenum;
   }
  }
 }else{
  funcbit_enable(playcontrol,PLAYC_PAUSENEXT); // ???
 }
 playlist_editorhighline_set(psip,((mvp->aktfilenum<=psip->lastentry)? mvp->aktfilenum:psip->firstentry));
}

//**************************************************************************

unsigned int playlist_open_infile(struct frame *frp,struct mainvars *mvp)
{
 struct playlist_entry_info *pei=mvp->aktfilenum;
 struct playlist_side_info *psi=mvp->psip;
 struct mpxplay_infile_info_s *miis=frp->infile_infos;

 mpxplay_infile_close(frp);

 if(pei<psi->firstsong || pei>psi->lastentry)
  return 0;
 if(!pei->filename || !pei->filename[0])
  return 0;

 frp->filetype=GET_HFT(pei->entrytype);
 frp->filesize=pei->filesize;
 frp->infile_funcs=pei->infile_funcs;
 miis->filesize=pei->filesize;
 miis->timemsec=pei->timemsec;

 get_onefileinfos_open(mvp->psip,pei);
 if(pei->entrytype<DFT_AUDIOFILE)
  return 0;

 frp->filetype=GET_HFT(pei->entrytype);
 frp->filesize=pei->filesize;
 frp->infile_funcs=pei->infile_funcs;
 miis->filesize=pei->filesize;
 miis->timemsec=pei->timemsec;

 if(!mpxplay_infile_open(frp,pei->filename))
  return 0;

 funcbit_enable(pei->infobits,PEIF_ENABLED);
 pei->filesize=frp->filesize;
 pei->timemsec=miis->timemsec;
 pei->filesize=miis->filesize;
 pei->infile_funcs=frp->infile_funcs;

 playlist_pei0_set(mvp,pei);

 return 1;
}

void playlist_close_infile(struct frame *frp,struct mainvars *mvp)
{
 struct playlist_entry_info *pei0=mvp->pei0;
 unsigned int i;

 mpxplay_infile_close(frp);

 //pei0 reset
 pds_strcpy(pei0->filename,"No file");
 for(i=0;i<=I3I_MAX;i++)
  pei0->id3info[i]=NULL;
 pei0->pstime=0;
 pei0->petime=0;
 /*pei0->infobits=0;
 pei0->timemsec=0;
 pei0->filesize=0;*/
}

//save infos of current song from playlist (entry)
void playlist_pei0_set(struct mainvars *mvp,struct playlist_entry_info *pei)
{
 struct playlist_entry_info *pei0=mvp->pei0;
 unsigned int i;
 char *sp;

 sp=pei0->filename+pds_strcpy(pei0->filename,pei->filename)+1;
 for(i=0;i<=I3I_MAX;i++){
  if(id3tagset[i])
   pei0->id3info[i]=id3tagset[i];
  else
   if(pei->id3info[i] && (sp<(pei0->filename+MAX_PATHNAMELEN+MAX_ID3LEN))){
    pei0->id3info[i]=sp;
    sp+=pds_strcpy(sp,pei->id3info[i])+1;
   }else
    pei0->id3info[i]=NULL;
 }
 pei0->pstime=pei->pstime;
 pei0->petime=pei->petime;
 /*pei0->infobits=pei->infobits;
 pei0->timemsec=pei->timemsec;
 pei0->filesize=pei->filesize;*/
}

//*************************************************************************

void playlist_editorhighline_check(struct playlist_side_info *psi)
{
 struct playlist_entry_info *pei=psi->editorhighline;

 if(pei>psi->lastentry)
  pei=psi->lastentry;
 if(pei<psi->firstentry)
  pei=psi->firstentry;
 psi->editorhighline=pei;
 mpxplay_display_center_editorhighline(psi,0);
}

void playlist_editorhighline_seek(struct playlist_side_info *psi,long offset,int whence)
{
 switch(whence){
  case SEEK_SET:psi->editorhighline=psi->firstentry+offset;break;
  case SEEK_CUR:psi->editorhighline+=offset;break;
  case SEEK_END:psi->editorhighline=psi->lastentry-offset;break;
 }
 playlist_editorhighline_check(psi);
}

void playlist_editorhighline_set(struct playlist_side_info *psi,struct playlist_entry_info *pei)
{
 if((pei>=psi->firstentry) && (pei<=psi->lastentry)){
  psi->editorhighline=pei;
  mpxplay_display_center_editorhighline(psi,0);
 }
}

void playlist_editorhighline_set_nocenter(struct playlist_side_info *psi,struct playlist_entry_info *pei)
{
 if((pei>=psi->firstentry) && (pei<=psi->lastentry))
  psi->editorhighline=pei;
}

//-------------------------------------------------------------------------
void playlist_change_editorside(struct mainvars *mvp)
{
 struct playlist_side_info *psie=mvp->psie;
 if(psie->psio->editsidetype&PLT_ENABLED){
  psie=psie->psio;
  mvp->psie=psie;
  if(psie->editsidetype&PLT_DIRECTORY){
   pds_setdrive(psie->currdrive);
   pds_chdir(psie->currdir);
  }
  refdisp|=RDT_INIT_EDIT;
 }
}

//*************************************************************************
playlist_entry_info *playlist_search_filename(struct playlist_side_info *psi,char *filename,long timempos,struct playlist_entry_info *pei)
{
 if(!filename || !filename[0])
  return NULL;
 while(*filename==' ')
  filename++;
 if(!*filename)
  return NULL;
 if(!pei)
  pei=psi->firstentry;
 while(pei<=psi->lastentry){
  if(pds_stricmp(pei->filename,filename)==0){
   if((timempos<0) || !(pei->infobits&PEIF_INDEXED))
    return pei;
   if((timempos>=pei->pstime) && (!pei->petime || (timempos<pei->petime)))
    return pei;
  }
  pei++;
 }
 return NULL;
}

/*playlist_entry_info *playlist_search_filename(struct playlist_side_info *psi,char *filename,long timempos)
{
 struct playlist_entry_info *pei;

 if(!filename || !filename[0])
  return NULL;
 while(*filename==' ')
  filename++;
 if(!*filename)
  return NULL;
 for(pei=psi->firstentry;pei<=psi->lastentry;pei++){
  if(pds_stricmp(pei->filename,filename)==0){
   if((timempos<0) || !(pei->infobits&PEIF_INDEXED))
    return pei;
   if((timempos>=pei->pstime) && (!pei->petime || (timempos<pei->petime)))
    return pei;
  }
 }
 return NULL;
}*/

//move the cursor to the subdir/list where you came from
void playlist_search_lastdir(struct playlist_side_info *psi,char *lastdir)
{
 struct playlist_entry_info *pei_set;

 pei_set=playlist_search_filename(psi,lastdir,-1,NULL);
 if(!pei_set)
  pei_set=psi->firstentry;
 playlist_editorhighline_set(psi,pei_set);
}

void playlist_search_firstsong(struct playlist_side_info *psi)
{
 struct playlist_entry_info *pei;
 psi->firstsong=psi->lastentry+1;
 for(pei=psi->firstentry;pei<=psi->lastentry;pei++)
  if(GET_HFT(pei->entrytype)!=HFT_DFT){
   psi->firstsong=pei;
   break;
  }
}

//-------------------------------------------------------------------------
void playlist_change_sublist_or_directory(struct playlist_side_info *psi,unsigned long head)
{
 if(GET_HFT(head)==HFT_DFT){
  if(head&DFTM_PLAYLIST)
   psi=playlist_loadsub_sublist_change(psi,head);
  else
   psi=playlist_loaddir_changedir(psi,head);
  playlist_chkfile_start_norm(psi,0);
 }
}

//-------------------------------------------------------------------------
void playlist_reload_side(struct mainvars *mvp,struct playlist_side_info *psi)
{
 if((psi->editsidetype&PLT_DIRECTORY) && !psi->sublistlevel)
  playlist_loaddir_buildbrowser(psi);
 else
  if(!(psi->editsidetype&PLT_DOOMQUEUE))
   playlist_buildlist_all(psi);
  else
   return;

 if((psi==mvp->psip) && !(playcontrol&PLAYC_RUNNING)){
  mpxplay_stop_and_clear(mvp,0);
  mvp->adone=ADONE_RESTART;
 }
 playlist_chkfile_start_norm(psi,0);
}

//-------------------------------------------------------------------------
void write_id3tags(struct mainvars *mvp)
{
 struct frame *frp;
 struct playlist_side_info *psi;
 struct playlist_entry_info *pei;
 int error;
 char *shortfname;
 char sout[128];

 if(!writeid3tag)
  return;

 frp=mvp->frp0+2;
 psi=mvp->psil;

 for(pei=psi->firstsong;pei<=psi->lastentry;pei++){
  frp->filetype=GET_HFT(pei->entrytype);
  frp->filesize=pei->filesize;
  frp->infile_funcs=pei->infile_funcs;
  frp->infile_infos->timemsec=pei->timemsec;
  error=mpxplay_infile_write_id3tag(frp,pei->filename,&pei->id3info[0]);
  shortfname=pds_getfilename_from_fullname(pei->filename);
  switch(error){
   case MPXPLAY_ERROR_INFILE_OK               :sprintf(sout,"%.15s  %-30.30s : %-30.30s",shortfname,pei->id3info[I3I_ARTIST],pei->id3info[I3I_TITLE]);break;
   case MPXPLAY_ERROR_INFILE_CANTOPEN         :sprintf(sout,"ID3TAG write error at %.25s (read-only or not exists)!",shortfname);break;
   case MPXPLAY_ERROR_INFILE_WRITETAG_FILETYPE:sprintf(sout,"ID3TAG write is not supported for this filetype (%.25s)",shortfname);break;
   case MPXPLAY_ERROR_INFILE_WRITETAG_TAGTYPE :sprintf(sout,"ID3TAG wrong or unsupported tagtype (%.20s)",shortfname);break;
   default:sprintf(sout,"ID3TAG write error at %.20s (unknown error)!",shortfname);break;
  }
  pds_textdisplay_printf(sout);
 }
 mpxplay_close_program(0);
}
