//**************************************************************************
//*                     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:id3 (tag) list routines (load,assign,save)

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

typedef char *ID3LISTTYPE[MAX_ID3LISTPARTS];
static ID3LISTTYPE *id3list;
static char *id3listdataarea;
static unsigned int id3listlength;
static struct playlist_side_info *id3listloadside;

extern char *id3loadname,*id3savename;
extern unsigned int loadid3list,saveid3list,id3savefields;
extern unsigned int writeid3tag,id3textconv;

static unsigned int open_id3list(struct playlist_side_info *psi,FILE **id3loadfile)
{
 id3listloadside=NULL;
 id3listlength=0;
 *id3loadfile=pds_fopen(id3loadname,"rt");
 if(!(*id3loadfile))
  return 0;
 if(!id3list){
  id3list=malloc(psi->allfilenum*MAX_ID3LISTPARTS*sizeof(char *));
  if(!id3list)
   return 0;
 }
 if(id3listdataarea)
  free(id3listdataarea);
 id3listdataarea=malloc(filelength((*id3loadfile)->_handle));
 if(!id3listdataarea)
  return 0;
 pds_memset(id3list,0,psi->allfilenum*MAX_ID3LISTPARTS*sizeof(char *));
 return 1;
}

void playlist_id3list_close(void)
{
 if(id3list){
  free(id3list);
  id3list=NULL;
 }
 if(id3listdataarea){
  free(id3listdataarea);
  id3listdataarea=NULL;
 }
}

void playlist_id3list_load(struct mainvars *mvp,struct playlist_side_info *psi)
{
 FILE *id3loadfile;
 char *i3mem,*p2,**id3lp;
 // 3 different possible id3list format with max. 4 line-parts
 char *separators[3]={"°±²\n","°:±\n"," :\n"},*listparts[MAX_ID3LISTPARTS];
 const int sep_lens[3]={4,4,3};
 const int do852s[MAX_ID3LISTPARTS]={0,1,1,0}; // parts: filename,artist,title,time/other
 int id3listcount,i,j,foundparts;
 char strtemp[300];

 if(!loadid3list)
  return;

 if(!psi)
  psi=mvp->psi0+(loadid3list-1);
 else
  if((loadid3list-1)!=(psi-mvp->psi0))
   return;

 if(!open_id3list(psi,&id3loadfile)){
  if(writeid3tag){
   pds_textdisplay_printf("ID3-(info)list loading error! Cannot write ID3-tags...");
   writeid3tag=0;
  }
  return;
 }

 i3mem=id3listdataarea;
 id3lp=&id3list[0][0];
 id3listcount=0;
 while(fgets(strtemp,299,id3loadfile) && id3listcount<psi->allfilenum){
  for(i=0;i<3;i++){
   pds_memset(&(listparts[0]),0,MAX_ID3LISTPARTS*sizeof(char *));
   pds_strcpy(i3mem,strtemp);
   listline_slice(&(listparts[0]),separators[i],i3mem);
   foundparts=0;
   for(j=0;j<sep_lens[i];j++)
    foundparts+=(listparts[j])? 1:0;
   if((foundparts==sep_lens[i]) || (i==2)){
    if(listparts[2]==NULL)   // if no 'title'
     if(listparts[1]!=NULL){
      listparts[2]=listparts[1]; // use 'artist' for title
      listparts[1]=NULL;
     }
    for(j=0;j<sep_lens[i];j++){
     p2=listparts[j];
     if(p2){
      p2=pds_strcutspc(p2);
      if(p2 && do852s[j])
       mpxplay_playlist_textconv_do(p2,pds_strlen(p2),0);
     }
     id3lp[j]=p2;
    }
    i3mem+=pds_strlen(strtemp);
    id3lp+=MAX_ID3LISTPARTS;
    id3listcount++;
    break;
   }
  }
 }
 if(id3listcount>0)
  id3listloadside=psi;  // -il = side0 ; -ig = side1
 id3listlength=id3listcount;
 fclose(id3loadfile);
}

unsigned int get_onefileinfos_from_id3list(struct playlist_side_info *psi,struct playlist_entry_info *pei,unsigned int fastsearch)
{
 char *fname,*id3p,**id3lp;
 unsigned int j,found=0,len;

 // ils==0 && psi==0 : yes
 // ils==0 && psi==1 : no
 // ils==1 && psi==0 : yes
 // ils==1 && psi==1 : yes
 if((id3listloadside>=psi) && (pei>=psi->firstsong) && (pei<=psi->lastentry)){
  id3lp=&id3list[pei-psi->firstsong][0];
  fname=pei->filename;
  if(pds_strricmp(id3lp[0],fname)==0){
   found=EDITLIST_MODE_FILENAME;
  }else
   id3lp=&id3list[0][0];
   for(j=0;j<=id3listlength;j++){
    if(pds_strricmp(id3lp[0],fname)==0){
     found=EDITLIST_MODE_FILENAME;
     break;
    }
    id3lp+=MAX_ID3LISTPARTS;
   }
  if(found){
   found=0;
   if(id3lp[1] || id3lp[2]){
    id3p=psi->id3infolastp;
    if(id3lp[1]){
     len=pds_strlen(id3lp[1])+1;
     if((id3p+len)<psi->id3infoendp){
      pds_strcpy(id3p,id3lp[1]);
      pei->id3info[I3I_ARTIST]=id3p;
      id3p+=len;
     }
    }
    if(id3lp[2]){
     len=pds_strlen(id3lp[2])+1;
     if((id3p+len)<psi->id3infoendp){
      pds_strcpy(id3p,id3lp[2]);
      pei->id3info[I3I_TITLE]=id3p;
      id3p+=len;
     }
    }
    psi->id3infolastp=id3p;
    pei->infobits|=PEIF_ID3EXIST;
    found|=EDITLIST_MODE_ID3;
   }
   if(id3lp[3] && (pei->entrytype==DFT_NOTCHECKED || pei->entrytype==DFT_UNKNOWN) && fastsearch){
    if(id3lp[3][8]!='|'){ // if not old mxu style (v1.42)
     unsigned int timesec=pds_atol16(id3lp[3]);
     if(timesec&MXUFLAG_ENABLED){
      pei->timemsec=(timesec&MXUFLAG_TIMEMASK)*1000;
      pei->infobits|=PEIF_ENABLED;
      pei->entrytype=DFT_NOTCHECKED;
      found|=EDITLIST_MODE_HEAD;
     }
    }
   }
  }
 }
 return found;
}

void playlist_id3list_save(struct mainvars *mvp)
{
 FILE *id3savefile;
 unsigned int songcounter,isf;
 struct frame *frp;
 struct mpxplay_audio_decoder_info_s *adi;
 struct playlist_side_info *psi;
 struct playlist_entry_info *pei;
 char *shortfname,souttext[300],strtemp[300],lastdir[300];
 const char *formats[3][2]={{"%s","%s"},{"%.64s","%.30s"},{"%-28.28s","%-19.19s"}};

 if(!saveid3list || (id3savefile=pds_fopen(id3savename,"wt"))==NULL)
  return;

 pds_textdisplay_printf("Extended playlist save ...");

 isf=id3savefields;
 frp=mvp->frp0+2;
 adi=frp->infile_infos->audio_decoder_infos;
 psi=mvp->psil;
 songcounter=1;
 lastdir[0]=0;

 for(pei=psi->firstentry;pei<=psi->lastentry;pei++){
  get_onefileinfos_is(psi,pei);
  shortfname=pds_getpath_from_fullname(strtemp,pei->filename);
  if(isf&IST_DIRECTORY){
   if(pds_stricmp(lastdir,strtemp)!=0){
    fprintf(id3savefile,"***** %s **********\n",strtemp);
    pds_strcpy(lastdir,strtemp);
    songcounter=1;
   }
  }
  if(isf&IST_FILENAME){
   if(isf&IST_FULLPATH)
    sprintf(souttext,"%-12s  ",pei->filename);
   else
    sprintf(souttext,"%-12s  ",shortfname);
  }else
   sprintf(souttext,"%2d. ",songcounter++);

  if(!pei->id3info[I3I_ARTIST] && !pei->id3info[I3I_TITLE]){
   if(isf&(IST_TIME|IST_BITRATE|IST_FILESIZE)){
    sprintf(strtemp,"%48.48s",(isf&IST_FILENAME)? "":shortfname);
    pds_strcat(souttext,strtemp);
   }
  }else{
   int form;
   if(isf&IST_AT_FIXED)
    form=2;
   else
    if(isf&(IST_TIME|IST_BITRATE|IST_FILESIZE))
     form=1;
    else
     form=0;
   sprintf(strtemp,formats[form][1],((pei->id3info[I3I_ARTIST])? pei->id3info[I3I_ARTIST]:""));
   if(funcbit_test(id3textconv,ID3TEXTCONV_CP_BACK))
    mpxplay_playlist_textconv_back(strtemp,strtemp);
   pds_strcat(souttext,strtemp);
   if(isf&(IST_TIME|IST_BITRATE|IST_FILESIZE)){
    pds_strcat(souttext,":");
    sprintf(strtemp,formats[form][0],((pei->id3info[I3I_TITLE])? pei->id3info[I3I_TITLE]:""));
    if(funcbit_test(id3textconv,ID3TEXTCONV_CP_BACK))
     mpxplay_playlist_textconv_back(strtemp,strtemp);
    pds_strcat(souttext,strtemp);
   }else{
    pds_strcat(souttext," : ");
    if(pei->id3info[I3I_TITLE]){
     sprintf(strtemp,formats[form][0],pei->id3info[I3I_TITLE]);
     if(funcbit_test(id3textconv,ID3TEXTCONV_CP_BACK))
      mpxplay_playlist_textconv_back(strtemp,strtemp);
     pds_strcat(souttext,strtemp);
    }
   }
  }

  if(isf&(IST_TIME|IST_BITRATE|IST_FILESIZE))
   pds_strcat(souttext," ");
  if((pei->infobits&PEIF_ENABLED) || frp->infile_infos->timemsec){
   if(isf&IST_TIME){
    long timesec=(playlist_entry_get_timemsec(pei)+500)/1000;
    sprintf(strtemp,"%d:%2.2d",timesec/60,timesec%60);
    pds_strcat(souttext,strtemp);
   }
   if(isf&IST_BITRATE){
    sprintf(strtemp,"%s%3d",(isf&IST_TIME)? "-":"",(adi->bitrate)? adi->bitrate:adi->bits);
    pds_strcat(souttext,strtemp);
   }
   if(isf&IST_FILESIZE){
    sprintf(strtemp,"%s%1.1fMB",(isf&(IST_TIME|IST_BITRATE))? "-":"",(float)frp->filesize/1048576.0);
    pds_strcat(souttext,strtemp);
   }
  }
  pds_strcat(souttext,"\n");
  fprintf(id3savefile,souttext);
 }
 mpxplay_close_program(0);
}
