//**************************************************************************
//*                     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: file handler routines

#include <share.h>
#include "newfunc.h"
#include "mpxplay.h"
#include "display\display.h"

#ifdef __DOS__
extern unsigned int intsoundcontrol;
extern unsigned int is_lfn_support,uselfn;
extern dosmem_t dm_int2x_1,dm_int2x_2;
static char far *indosptr;
static unsigned int in_filehand;
#endif

extern volatile unsigned long mpxplay_signal_events;

//--------------------------------------------------------------------------
//indos flag

void pds_indosflag_init(void)
{
#ifdef __DOS__
 struct rminfo RMI;
 long selector;

 pds_dpmi_rmi_clear(&RMI);
 RMI.EAX=0x00003400;
 pds_dpmi_realmodeint_call(0x21,&RMI);
 selector=pds_dpmi_segment_to_selector(RMI.ES);
 if(selector>=0)
  indosptr=MK_FP(selector,RMI.EBX);
#endif
}

unsigned int pds_indos_flag(void)
{
#ifdef __DOS
 if(intsoundcontrol&INTSOUND_DOSSHELL) // !!! because it's allways 1 then
  return 0;                            //
 if(indosptr)
  return (unsigned int)(*indosptr);
#endif
 return 0;
}

//-------------------------------------------------------------------------
#ifdef __DOS__

unsigned int pds_filehand_check_infilehand(void)
{
 return in_filehand;
}

unsigned int pds_filehand_check_entrance(void)
{
 if(in_filehand)
  return 1;
 if(intsoundcontrol&INTSOUND_DOSSHELL)
  return 1;
 if(pds_indos_flag())
  return 1;
 return 0;
}

void pds_filehand_lock_entrance(void)
{
 in_filehand=1;
}

void pds_filehand_unlock_entrance(void)
{
 in_filehand=0;
}
#endif

//----------------------------------------------------------------------
#ifdef __DOS__

static int pds_lfn_open_read(char *filename,unsigned int mode)
{
 struct rminfo RMI;
 unsigned int retry=2; // possible DOSLFN bug (not a 100% solution)
 do{
  pds_dpmi_rmi_clear(&RMI);
  RMI.EAX=0x0000716C;
  RMI.EDX=0x01;                    // open, fail if not exist
  RMI.EBX=(mode&0x0f)|SH_DENYNO;   // O_RDONLY|O_BINARY
  RMI.DS =dm_int2x_1.segment;
  funcbit_enable(RMI.flags,RMINFO_FLAG_CARRY);
  pds_strcpy(dm_int2x_1.linearptr,filename);
  pds_dpmi_realmodeint_call(0x21,&RMI);
  if(!funcbit_test(RMI.flags,RMINFO_FLAG_CARRY))
   return (RMI.EAX&0xffff);
 }while(--retry);
 return 0;
}

static int pds_lfn_open_write(char *filename,unsigned int mode)
{
 struct rminfo RMI;

 pds_dpmi_rmi_clear(&RMI);
 RMI.EAX=0x0000716C;
 RMI.EDX=0x01;                    // open, fail if not exist
 RMI.EBX=(mode&0x0f)|SH_DENYWR;   // O_RDWR|O_BINARY
 RMI.DS =dm_int2x_1.segment;
 funcbit_enable(RMI.flags,RMINFO_FLAG_CARRY);
 pds_strcpy(dm_int2x_1.linearptr,filename);
 pds_dpmi_realmodeint_call(0x21,&RMI);
 if(!funcbit_test(RMI.flags,RMINFO_FLAG_CARRY))
  return (RMI.EAX&0xffff);
 return 0;
}

static int pds_lfn_open_create(char *filename,unsigned int mode)
{
 struct rminfo RMI;

 pds_dpmi_rmi_clear(&RMI);
 RMI.EAX=0x0000716C;
 RMI.EDX=0x12;                   // truncate if exist, create if not
 RMI.EBX=(mode&0x0f)|SH_DENYWR;  // O_RDWR|O_BINARY
 RMI.DS =dm_int2x_1.segment;
 funcbit_enable(RMI.flags,RMINFO_FLAG_CARRY);
 pds_strcpy(dm_int2x_1.linearptr,filename);
 pds_dpmi_realmodeint_call(0x21,&RMI);
 if(!funcbit_test(RMI.flags,RMINFO_FLAG_CARRY))
  return (RMI.EAX&0xffff);
 return 0;
}

/*static int pds_dos_open(char *filename,unsigned int mode)
{
 struct rminfo RMI;

 pds_dpmi_rmi_clear(&RMI);
 RMI.EAX=0x00003d00|(mode&0xff);
 RMI.DS =dm_int2x_1.segment;
 funcbit_enable(RMI.flags,RMINFO_FLAG_CARRY);
 pds_strcpy(dm_int2x_1.linearptr,filename);
 pds_dpmi_realmodeint_call(0x21,&RMI);
 //fprintf(stdout,"pds_dos_open fp:%8.8X\n",RMI.EAX);
 if(!funcbit_test(RMI.flags,RMINFO_FLAG_CARRY))
  return (RMI.EAX&0xffff);
 return 0;
}

static int pds_dos_create(char *filename,unsigned int mode)
{
 struct rminfo RMI;

 pds_dpmi_rmi_clear(&RMI);
 RMI.EAX=0x00003c00|(mode&0xff);
 RMI.DS =dm_int2x_1.segment;
 funcbit_enable(RMI.flags,RMINFO_FLAG_CARRY);
 pds_strcpy(dm_int2x_1.linearptr,filename);
 pds_dpmi_realmodeint_call(0x21,&RMI);
 if(!funcbit_test(RMI.flags,RMINFO_FLAG_CARRY))
  return (RMI.EAX&0xffff);
 return 0;
}

static void pds_dos_close(unsigned int handle)
{
 struct rminfo RMI;

 pds_dpmi_rmi_clear(&RMI);
 RMI.EAX=0x00003e00;
 RMI.EBX=handle;
 pds_dpmi_realmodeint_call(0x21,&RMI);
 //fprintf(stdout,"pds_dos_close: fp:%d err:%8.8X \n",handle,RMI.EAX);
}*/

#endif

/*int pds_open_read(char *filename,unsigned int mode)
{
 int filehand=0;
#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return filehand;
 pds_filehand_lock_entrance();
 if(is_lfn_support && uselfn)
  filehand=pds_lfn_open_read(filename,mode);
 else
  filehand=pds_dos_open(filename,mode|SH_DENYNO);
 pds_filehand_unlock_entrance();
#else
 filehand=sopen(filename,mode,SH_DENYNO);
#endif

 funcbit_enable(mpxplay_signal_events,MPXPLAY_SIGNALTYPE_DISKACCESS);

 if(filehand<0)
  filehand=0;
 return filehand;
}

int pds_open_write(char *filename,unsigned int mode)
{
 int filehand=0;

#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return filehand;
 pds_filehand_lock_entrance();
 if(is_lfn_support && uselfn)
  filehand=pds_lfn_open_write(filename,mode);
 else
  filehand=pds_dos_open(filename,mode|SH_DENYWR);
 pds_filehand_unlock_entrance();
#else
 filehand=sopen(filename,mode,SH_DENYWR);
#endif

 funcbit_enable(mpxplay_signal_events,MPXPLAY_SIGNALTYPE_DISKACCESS);

 if(filehand<0)
  filehand=0;

 //fprintf(stdout,"pds_open_write fp:%d\n",filehand);

 return filehand;
}

int pds_open_create(char *filename,unsigned int mode)
{
 int filehand=0;

#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return filehand;
 pds_filehand_lock_entrance();
 if(is_lfn_support && uselfn)
  filehand=pds_lfn_open_create(filename,mode);
 else
  filehand=pds_dos_create(filename,mode|SH_DENYWR);
 pds_filehand_unlock_entrance();
#else
 filehand=sopen(filename,mode|O_CREAT|O_TRUNC,SH_DENYWR,S_IREAD|S_IWRITE);
#endif

 funcbit_enable(mpxplay_signal_events,MPXPLAY_SIGNALTYPE_DISKACCESS);

 if(filehand<0)
  filehand=0;
 return filehand;
}

void pds_close(int filehand)
{
 if(filehand<1)
  return;
#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return;
 pds_filehand_lock_entrance();
 pds_dos_close(filehand);
 pds_filehand_unlock_entrance();
#else
 close(filehand);
#endif
 //fprintf(stdout,"pds_close fp:%d\n",filehand);
 funcbit_enable(mpxplay_signal_events,MPXPLAY_SIGNALTYPE_DISKACCESS);
}*/

int pds_open_read(char *filename,unsigned int mode)
{
 int filehand=0;
#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return filehand;
 pds_filehand_lock_entrance();
 if(is_lfn_support && uselfn)
  filehand=pds_lfn_open_read(filename,mode);
 else
#endif
  filehand=sopen(filename,mode,SH_DENYNO);

#ifdef __DOS__
 pds_filehand_unlock_entrance();
#endif

 funcbit_enable(mpxplay_signal_events,MPXPLAY_SIGNALTYPE_DISKACCESS);

 if(filehand<0)
  filehand=0;
 return filehand;
}

int pds_open_write(char *filename,unsigned int mode)
{
 int filehand=0;

#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return filehand;
 pds_filehand_lock_entrance();
 if(is_lfn_support && uselfn)
  filehand=pds_lfn_open_write(filename,mode);
 else
#endif
  filehand=sopen(filename,mode,SH_DENYWR);

#ifdef __DOS__
 pds_filehand_unlock_entrance();
#endif

 funcbit_enable(mpxplay_signal_events,MPXPLAY_SIGNALTYPE_DISKACCESS);

 if(filehand<0)
  filehand=0;

 //fprintf(stdout,"open fp:%d\n",filehand);

 return filehand;
}

int pds_open_create(char *filename,unsigned int mode)
{
 int filehand=0;

#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return filehand;
 pds_filehand_lock_entrance();
#endif
 funcbit_enable(mpxplay_signal_events,MPXPLAY_SIGNALTYPE_DISKACCESS);
#ifdef __DOS__
 if(is_lfn_support && uselfn)
  filehand=pds_lfn_open_create(filename,mode);
 else
#endif
  filehand=sopen(filename,mode|O_CREAT|O_TRUNC,SH_DENYWR,S_IREAD|S_IWRITE);

#ifdef __DOS__
 pds_filehand_unlock_entrance();
#endif

 if(filehand<0)
  filehand=0;
 return filehand;
}

void pds_close(int filehand)
{
 if(filehand<1)
  return;
#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return;
 pds_filehand_lock_entrance();
#endif
 funcbit_enable(mpxplay_signal_events,MPXPLAY_SIGNALTYPE_DISKACCESS);
#ifdef __DOS__
 if(is_lfn_support && uselfn)
  _dos_close(filehand);
 else
#endif
  close(filehand);
 //fprintf(stdout,"pds_close fp:%d\n",filehand);
#ifdef __DOS__
 pds_filehand_unlock_entrance();
#endif
}

/*int pds_dos_read(int filehand,char *buf,unsigned int len)
{
 int b;
 if(filehand<1)
  return 0;
#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return 0;
 pds_filehand_lock_entrance();
 if(_dos_read(filehand,buf,len,(unsigned int *)&b)!=0)
  b=0;
 pds_filehand_unlock_entrance();
#else
 b=read(filehand,buf,len);
#endif

 funcbit_enable(mpxplay_signal_events,MPXPLAY_SIGNALTYPE_DISKACCESS);

 return b;
}

int pds_dos_write(int filehand,char *buf,unsigned int len)
{
 int b;
 if(filehand<1)
  return 0;
#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return 0;
 pds_filehand_lock_entrance();
 if(_dos_write(filehand,buf,len,(unsigned int *)&b)!=0)
  b=0;
 pds_filehand_unlock_entrance();
#else
 b=write(filehand,buf,len);
#endif

 funcbit_enable(mpxplay_signal_events,MPXPLAY_SIGNALTYPE_DISKACCESS);

 return b;
}*/

int pds_dos_read(int filehand,char *buf,unsigned int len)
{
 int b;
 if(filehand<1)
  return 0;
#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return 0;
 pds_filehand_lock_entrance();
#endif
 funcbit_enable(mpxplay_signal_events,MPXPLAY_SIGNALTYPE_DISKACCESS);
#ifdef __DOS__
 if(is_lfn_support && uselfn){
  if(_dos_read(filehand,buf,len,(unsigned int *)&b)!=0)
   b=0;
 }else
#endif
  b=read(filehand,buf,len);

#ifdef __DOS__
 pds_filehand_unlock_entrance();
#endif

 return b;
}

int pds_dos_write(int filehand,char *buf,unsigned int len)
{
 int b;
 if(filehand<1)
  return 0;
#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return 0;
 pds_filehand_lock_entrance();
#endif
 funcbit_enable(mpxplay_signal_events,MPXPLAY_SIGNALTYPE_DISKACCESS);
#ifdef __DOS__
 if(is_lfn_support && uselfn){
  if(_dos_write(filehand,buf,len,(unsigned int *)&b)!=0)
   b=0;
 }else
#endif
  b=write(filehand,buf,len);

#ifdef __DOS__
 pds_filehand_unlock_entrance();
#endif

 return b;
}

long pds_lseek(int filehand,long offset,int fromwhere)
{
 long newpos;
 if(filehand<1)
  return -1;
#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return -1;
 pds_filehand_lock_entrance();
#endif
 funcbit_enable(mpxplay_signal_events,MPXPLAY_SIGNALTYPE_DISKACCESS);
 newpos=lseek(filehand,offset,fromwhere);
#ifdef __DOS__
 pds_filehand_unlock_entrance();
#endif
 return newpos;
}

long pds_tell(int filehand)
{
 long filepos;
 if(filehand<1)
  return -1;
#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return -1;
 pds_filehand_lock_entrance();
#endif
 filepos=tell(filehand);
#ifdef __DOS__
 pds_filehand_unlock_entrance();
#endif
 return filepos;
}

int pds_eof(int filehand)
{
 int flag;
 if(filehand<1)
  return 1;
#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return 1;
 pds_filehand_lock_entrance();
#endif
 flag=eof(filehand);
#ifdef __DOS__
 pds_filehand_unlock_entrance();
#endif
 return flag;
}

long pds_filelength(int filehand)
{
 long filelen;
 if(filehand<1)
  return 0;
#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return 0;
 pds_filehand_lock_entrance();
#endif
 filelen=filelength(filehand);
#ifdef __DOS__
 pds_filehand_unlock_entrance();
#endif
 return filelen;
}

int pds_chsize(int filehand,long size)
{
 int success;
 if(filehand<1)
  return 0;
#ifdef __DOS__
 if(pds_filehand_check_entrance())
  return 0;
 pds_filehand_lock_entrance();
#endif
 funcbit_enable(mpxplay_signal_events,MPXPLAY_SIGNALTYPE_DISKACCESS);
 success=chsize(filehand,size);
 if(success<0)
  success=0;
 else
  success=1;
#ifdef __DOS__
 pds_filehand_unlock_entrance();
#endif
 return success;
}

// for non-audio files (playlists)
FILE *pds_fopen(char *filename,char *mode)
{
 FILE *fp=NULL;
#ifdef __DOS__
 char shortfname[300];
 if(pds_filehand_check_entrance())
  return fp;
 if(is_lfn_support && uselfn){
  pds_truename_dos(shortfname,filename);
  filename=&shortfname[0];
 }
 pds_filehand_lock_entrance();
#endif
 fp=fopen(filename,mode);
#ifdef __DOS__
 pds_filehand_unlock_entrance();
#endif
 return fp;
}
