/*
			(c) Copyright 1998-2000 - Tord Jansson
			======================================

		This file is part of the BladeEnc MP3 Encoder, based on
		ISO's reference code for MPEG Layer 3 compression.

		This file doesn't contain any of the ISO reference code and
		is copyright Tord Jansson (tord.jansson@swipnet.se).

	BladeEnc is free software; you can redistribute this file
	and/or modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, or (at your option) any later version.



	------------    Changes    ------------

	2000-12-15  Andre Piotrowski

	-	reformatted, slightly optimized
*/

/******************************************************************************
							>>> BLADESYS <<<

The intention of this file is to keep all system specific things away from the
rest of the code.

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



#include		<stdio.h>
#include		<stdlib.h>
#include		<string.h>
#include		<time.h>
#include		<fcntl.h>

#include		"system.h"

#ifdef  MSWIN
#	include		<windows.h>
#	include		<conio.h>
#	include		<io.h>
#endif


#ifdef OS2
#	define		INCL_DOSFILEMGR
#	define		INCL_DOSERRORS
#	define		INCL_DOSPROCESS
#	define		INCL_KBD
#	include		<os2.h>
#	include		<conio.h>
#endif

#ifdef UNIX_SYSTEM
#	include		<pwd.h>
#	include		<sys/time.h>
#	include		<sys/resource.h>
#	include		<unistd.h>
#	include		<sys/types.h>

#	ifndef PRIO_MAX
#		define		PRIO_MAX	 20
#		define		PRIO_MIN	-20
#	endif
#endif

#if	SYSTEM == MAC_OS
#	include		"EventHandling.h"
#endif

#ifdef RISC_OS
#	include		<pwd.h>
#	include		<sys/time.h>
#	include		<sys/resource.h>
#	include		<unistd.h>
#	include		<sys/types.h>
#endif

#include	"codec.h"
#include	"samplein.h"
#include	"arglink.h"
#include	"bladesys.h"




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

				>>> SYSTEM FOR PRIORITY HANDLING <<<


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






#ifdef OS2

typedef		struct
			{
				ULONG					ulClass;
				LONG					loDelta;
			}						OS2PRIORITIES;

OS2PRIORITIES			OS2PrioTab[] =
			{
			    {PRTYC_IDLETIME    ,   0},
			    {PRTYC_IDLETIME    ,  31},
			    {PRTYC_REGULAR     , -31},
			    {PRTYC_REGULAR     ,   0},
			    {PRTYC_REGULAR     ,  31},
			    {PRTYC_TIMECRITICAL,   0}
			};

#endif





int						setPriority
(
	char					*pPrioString
)
{

#ifdef  MSWIN
	HANDLE					hThread;

	hThread = GetCurrentThread();

	     if (        pPrioString == NULL         )  SetThreadPriority (hThread, THREAD_PRIORITY_LOWEST);   /* Set default priority if NULL! */
	else if (strcmp (pPrioString, "HIGHEST") == 0)  SetThreadPriority (hThread, THREAD_PRIORITY_HIGHEST);
	else if (strcmp (pPrioString, "HIGHER" ) == 0)  SetThreadPriority (hThread, THREAD_PRIORITY_ABOVE_NORMAL);
	else if (strcmp (pPrioString, "NORMAL" ) == 0)  SetThreadPriority (hThread, THREAD_PRIORITY_NORMAL);
	else if (strcmp (pPrioString, "LOWER"  ) == 0)  SetThreadPriority (hThread, THREAD_PRIORITY_BELOW_NORMAL);
	else if (strcmp (pPrioString, "LOWEST" ) == 0)  SetThreadPriority (hThread, THREAD_PRIORITY_LOWEST);
	else if (strcmp (pPrioString, "IDLE"   ) == 0)  SetThreadPriority (hThread, THREAD_PRIORITY_IDLE);
	else return FALSE;
#endif


#ifdef OS2
	APIRET					rc;
	int						prio;

	     if (        pPrioString == NULL         )  prio = 1;   /* Set default priority if NULL! */
	else if (strcmp (pPrioString, "HIGHEST") == 0)  prio = 5;
	else if (strcmp (pPrioString, "HIGHER" ) == 0)  prio = 4;
	else if (strcmp (pPrioString, "NORMAL" ) == 0)  prio = 3;
	else if (strcmp (pPrioString, "LOWER"  ) == 0)  prio = 2;
	else if (strcmp (pPrioString, "LOWEST" ) == 0)  prio = 1;
	else if (strcmp (pPrioString, "IDLE"   ) == 0)  prio = 0;
	else return FALSE;

	if ((rc = DosSetPriority (PRTYS_PROCESS, OS2PrioTab[prio].ulClass, OS2PrioTab[prio].loDelta, 0L)) != NO_ERROR)
	{
		printf (" DosSetPriority error : rc = %lu\n", rc);
		exit (1);
	}
#endif


#ifdef	UNIX_SYSTEM
	pid_t					my_pid;
	int						prio;

	     if (        pPrioString == NULL         )  prio = (    PRIO_MIN +     PRIO_MAX) / 2;   /* Set default priority if NULL! */
	else if (strcmp (pPrioString, "HIGHEST") == 0)  prio =      PRIO_MIN;
	else if (strcmp (pPrioString, "HIGHER" ) == 0)  prio = (2 * PRIO_MIN +     PRIO_MAX) / 3;
	else if (strcmp (pPrioString, "NORMAL" ) == 0)  prio = (    PRIO_MIN +     PRIO_MAX) / 2;
	else if (strcmp (pPrioString, "LOWER"  ) == 0)  prio = (    PRIO_MIN + 2 * PRIO_MAX) / 3;
	else if (strcmp (pPrioString, "LOWEST" ) == 0)  prio = (    PRIO_MIN + 3 * PRIO_MAX) / 4;
	else if (strcmp (pPrioString, "IDLE"   ) == 0)  prio =                     PRIO_MAX;
	else
	{
		prio = atoi (pPrioString);
		if (prio < PRIO_MIN)  prio = PRIO_MIN;
		if (prio > PRIO_MAX)  prio = PRIO_MAX;
	}
	my_pid = getpid();
	setpriority (PRIO_PROCESS, my_pid, prio);
#endif


	/* Include Prioritysettings for other systems here... */

	return TRUE;
}





/* Some systems are by default using text-input/output instead of binary.:- (*/


void prepStdin( void )
{
#ifdef MSWIN
#	ifdef __BORLANDC__
		setmode(_fileno(stdin), _O_BINARY );
#	else
		_setmode(_fileno(stdin), _O_BINARY );
#	endif
#endif
}
void prepStdout( void )
{
#ifdef MSWIN
#	ifdef __BORLANDC__
		setmode(_fileno(stdin), _O_BINARY );
#	else
		_setmode(_fileno(stdout), _O_BINARY );
#	endif
#endif
}




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

											>>> ROUTINES FOR KEYHANDLING <<<

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



int						be_kbhit (void)
{

#ifdef MSWIN
	return kbhit();
#endif

#ifdef OS2
	KBDKEYINFOk;

	return KbdPeek(&k, NULLHANDLE) == 0  &&  (k.fbStatus & KBDTRF_FINAL_CHAR_IN);
#endif

	return 0;
}



int						be_getch (void)
{

#if defined(MSWIN) || defined(OS2)
	return getch();
#else
	return 0;
#endif

}





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

		>>> EXPAND WILDCARDS FOR SYSTEMS THAT DON'T DO IT AUTOMATICALLY <<<

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

#ifdef WILDCARDS



static	int				findFirstMatch (char *pFileName, char *wpName);
static	int				findNextMatch (char *pFileName, char *wpName);




/*____ expandWildcards() ____________________________________________________*/

int						expandWildcards (argLink **ppArgLink)
{
	argLink					*pFirstNewLink = NULL;
	argLink					**wppPrev = &pFirstNewLink;

	argLink					*pArgLink = *ppArgLink;
	argLink					*pTmp;

	int						nNew = 0;
	int						x;
	char					temp[MAX_NAMELEN];

	while (pArgLink != NULL)
	{
#ifdef	MSWIN
		if (strchr (pArgLink->pString, '*') != NULL || strchr (pArgLink->pString, '?') != NULL || strchr (pArgLink->pString, '~') != NULL)
#else
		if (strchr (pArgLink->pString, '*') != NULL || strchr (pArgLink->pString, '?') != NULL)
#endif
		{
			x = findFirstMatch (pArgLink->pString, temp);
			while (x)
			{
				pTmp = insertStringInArgLink (wppPrev, temp);
				wppPrev = &pTmp->psNext;
				nNew++;

				x = findNextMatch (pArgLink->pString, temp);
			}
			pTmp = pArgLink;
			pArgLink = pArgLink->psNext;
			free (pTmp);
		}
		else
		{
			*wppPrev = pArgLink;
			wppPrev = &pArgLink->psNext;
			pArgLink = pArgLink->psNext;
		}
	}

	*wppPrev = NULL;
	*ppArgLink = pFirstNewLink;

	return nNew;
}



#ifdef MSWIN

static	struct			_finddata_t sFind;
static	long			hFind;


/*____ findFirstMatch() - MSWIN version ______________________________________*/

static	int				findFirstMatch (char *pFileName, char *wpName)
{
	int						x;

	hFind = _findfirst (pFileName, &sFind);
	if (hFind == -1)
		return FALSE;

	if ((sFind.attrib & _A_SUBDIR) != 0)
		return findNextMatch (pFileName, wpName);


	strcpy (wpName, pFileName);
	for (x = strlen(wpName)-1;  wpName[x] != '\\' && wpName[x] !='/' && wpName[x] != ':' && x > 0;  x--)
	{}   /* avoid compiler warning */

	if (x != 0)
		x++;
	strcpy (wpName + x, sFind.name);

	return TRUE;
}


/*____ findNextMatch() - MSWIN version _______________________________________*/

static	int				findNextMatch (char *pFileName, char *wpName)
{
	int						x;

	while (1)
	{
		if (_findnext (hFind, &sFind) != 0)
			return FALSE;

		if ((sFind.attrib & _A_SUBDIR) == 0)
		{
			strcpy (wpName, pFileName);
			for (x = strlen(wpName)-1;  wpName[x] != '\\' && wpName[x] !='/' && wpName[x] != ':' && x > 0;  x--)
			{}   /* avoid compiler warning */

			if (x != 0)
				x++;
			strcpy (wpName + x, sFind.name);

			return TRUE;
		}
	}
}

#endif  /* MSWIN */



#ifdef OS2

static	HDIR			hdirFindHandle = HDIR_SYSTEM;
static	FILEFINDBUF3	FindBuffer     = {0};
static	ULONG			ulResultBufLen = sizeof(FILEFINDBUF3);
static	ULONG			ulFindCount    = 1;


/*____ findFirstMatch() - OS/2 version _______________________________________*/

static	int				findFirstMatch (char *pFileName, char *wpName)
{
	int						x;
	APIRET					rc = NO_ERROR;

	ulFindCount = 1;
	rc = DosFindFirst (pFileName, &hdirFindHandle, FILE_NORMAL, &FindBuffer, ulResultBufLen, &ulFindCount, FIL_STANDARD);

	if (rc != NO_ERROR)
		return FALSE;

	if ((FindBuffer.attrFile & FILE_DIRECTORY) != 0)
		return findNextMatch (pFileName, wpName);


	strcpy (wpName, pFileName);
	for (x = strlen(wpName)-1;  wpName[x] != '\\' && wpName[x] !='/' && wpName[x] != ':' && x > 0;  x--)
	{}   /* avoid compiler warning */

	if (x != 0)
		x++;
	strcpy (wpName + x, FindBuffer.achName);

	return TRUE;
}


/*____ findNextMatch() - OS/2 version ________________________________________*/

static	int				findNextMatch (char *pFileName, char *wpName)
{
	int						x;
	APIRET					rc = NO_ERROR;

	while (1)
	{
		ulFindCount = 1;

		if ((rc = DosFindNext(hdirFindHandle, &FindBuffer, ulResultBufLen, &ulFindCount)) != NO_ERROR)
		{
			if ((rc = DosFindClose(hdirFindHandle)) != NO_ERROR)
				printf ("DosFindClose error: return code = %lu\n", rc);

			return FALSE;
		}

		if ((FindBuffer.attrFile & FILE_DIRECTORY) == 0)
		{
			strcpy (wpName, pFileName);
			for (x = strlen(wpName)-1;  wpName[x] != '\\' && wpName[x] !='/' && wpName[x] != ':' && x > 0;  x--)
			{}   /* avoid compiler warning */

			if (x != 0)
				x++;
			strcpy (wpName + x, FindBuffer.achName);

			return TRUE;
		}
	}
}

#endif /* OS/2 */


#endif /* WILDCARDS */





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

				>>> Routine for finding config file <<<

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

/*____ findConfigFile() _____________________________________________________*/

int						findConfigFile (char *pExepath, char *wpPath)
{
	char					*pTmp;
	FILE					*fp;


#if			defined(MSWIN) || defined(OS2) || (SYSTEM == BEOS_X86) || (SYSTEM == BEOS_PPC) || (SYSTEM == MAC_OS)

#if			defined(MSWIN) || defined(OS2)
#	define		CONFIG_FILE		"bladeenc.cfg"
#elif		(SYSTEM == BEOS_X86) || (SYSTEM == BEOS_PPC)
#	define		CONFIG_FILE		"bladeenc.cfg"
#elif		(SYSTEM == MAC_OS)
#	define		CONFIG_FILE		MAC_BLADEENC_PREFSFILE
#endif

	strcpy (wpPath, pExepath);
	pTmp = wpPath + strlen (wpPath) - 1;

	while (pTmp >= wpPath  &&  *pTmp != DIRECTORY_SEPARATOR)
		pTmp--;

	/* now we have  pTmp == wpPath-1  or  *pTmp == DIRECTORY_SEPARATOR !!! */
	strcpy (pTmp+1, CONFIG_FILE);

	fp = fopen (wpPath, "r");
	if (fp != NULL)
	{
		fclose (fp);
		return TRUE;
	}
#endif


#ifdef	UNIX_SYSTEM
	pTmp = getenv ("HOME");
	if (pTmp != NULL)
	{
		strcpy (wpPath, pTmp);
		if (wpPath[strlen(wpPath)-1] != '/')
			strcat (wpPath, "/");

		strcat (wpPath, ".bladeencrc");

		fp = fopen (wpPath, "r");
		if (fp != NULL)
		{
			fclose (fp);
			return	TRUE;
		}
	}
#endif


	return FALSE;
}



