Blame frontend/main.c

Packit 47f805
/*
Packit 47f805
 *      Command line frontend program
Packit 47f805
 *
Packit 47f805
 *      Copyright (c) 1999 Mark Taylor
Packit 47f805
 *                    2000 Takehiro TOMINAGA
Packit 47f805
 *                    2010-2012 Robert Hegemann
Packit 47f805
 *
Packit 47f805
 * This library is free software; you can redistribute it and/or
Packit 47f805
 * modify it under the terms of the GNU Library General Public
Packit 47f805
 * License as published by the Free Software Foundation; either
Packit 47f805
 * version 2 of the License, or (at your option) any later version.
Packit 47f805
 *
Packit 47f805
 * This library is distributed in the hope that it will be useful,
Packit 47f805
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 47f805
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 47f805
 * Library General Public License for more details.
Packit 47f805
 *
Packit 47f805
 * You should have received a copy of the GNU Library General Public
Packit 47f805
 * License along with this library; if not, write to the
Packit 47f805
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit 47f805
 * Boston, MA 02111-1307, USA.
Packit 47f805
 */
Packit 47f805
Packit 47f805
/* $Id: main.c,v 1.131 2017/08/12 18:56:15 robert Exp $ */
Packit 47f805
Packit 47f805
#ifdef HAVE_CONFIG_H
Packit 47f805
# include <config.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#include <assert.h>
Packit 47f805
#include <stdio.h>
Packit 47f805
Packit 47f805
#ifdef STDC_HEADERS
Packit 47f805
# include <stdlib.h>
Packit 47f805
# include <string.h>
Packit 47f805
#else
Packit 47f805
# ifndef HAVE_STRCHR
Packit 47f805
#  define strchr index
Packit 47f805
#  define strrchr rindex
Packit 47f805
# endif
Packit 47f805
char   *strchr(), *strrchr();
Packit 47f805
# ifndef HAVE_MEMCPY
Packit 47f805
#  define memcpy(d, s, n) bcopy ((s), (d), (n))
Packit 47f805
#  define memmove(d, s, n) bcopy ((s), (d), (n))
Packit 47f805
# endif
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#ifdef HAVE_FCNTL_H
Packit 47f805
# include <fcntl.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#ifdef __sun__
Packit 47f805
/* woraround for SunOS 4.x, it has SEEK_* defined here */
Packit 47f805
#include <unistd.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#ifdef __OS2__
Packit 47f805
#include <os2.h>
Packit 47f805
#define PRTYC_IDLE 1
Packit 47f805
#define PRTYC_REGULAR 2
Packit 47f805
#define PRTYD_MINIMUM -31
Packit 47f805
#define PRTYD_MAXIMUM 31
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#if defined(_WIN32)
Packit 47f805
# include <windows.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
Packit 47f805
/*
Packit 47f805
 main.c is example code for how to use libmp3lame.a.  To use this library,
Packit 47f805
 you only need the library and lame.h.  All other .h files are private
Packit 47f805
 to the library.
Packit 47f805
*/
Packit 47f805
#include "lame.h"
Packit 47f805
Packit 47f805
#include "console.h"
Packit 47f805
#include "main.h"
Packit 47f805
Packit 47f805
/* PLL 14/04/2000 */
Packit 47f805
#if macintosh
Packit 47f805
#include <console.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#ifdef WITH_DMALLOC
Packit 47f805
#include <dmalloc.h>
Packit 47f805
#endif
Packit 47f805
Packit 47f805
Packit 47f805
static int c_main(int argc, char *argv[]);
Packit 47f805
extern int lame_main(lame_t gf, int argc, char *argv[]);
Packit 47f805
Packit 47f805
Packit 47f805
/************************************************************************
Packit 47f805
*
Packit 47f805
* main
Packit 47f805
*
Packit 47f805
* PURPOSE:  MPEG-1,2 Layer III encoder with GPSYCHO
Packit 47f805
* psychoacoustic model.
Packit 47f805
*
Packit 47f805
************************************************************************/
Packit 47f805
Packit 47f805
Packit 47f805
#if defined( _WIN32 ) && !defined(__MINGW32__)
Packit 47f805
static void
Packit 47f805
set_process_affinity()
Packit 47f805
{
Packit 47f805
#if 0
Packit 47f805
    /* rh 061207
Packit 47f805
       the following fix seems to be a workaround for a problem in the
Packit 47f805
       parent process calling LAME. It would be better to fix the broken
Packit 47f805
       application => code disabled.
Packit 47f805
     */
Packit 47f805
#if defined(_WIN32)
Packit 47f805
    /* set affinity back to all CPUs.  Fix for EAC/lame on SMP systems from
Packit 47f805
       "Todd Richmond" <todd.richmond@openwave.com> */
Packit 47f805
    typedef BOOL(WINAPI * SPAMFunc) (HANDLE, DWORD_PTR);
Packit 47f805
    SPAMFunc func;
Packit 47f805
    SYSTEM_INFO si;
Packit 47f805
Packit 47f805
    if ((func = (SPAMFunc) GetProcAddress(GetModuleHandleW(L"KERNEL32.DLL"),
Packit 47f805
                                          "SetProcessAffinityMask")) != NULL) {
Packit 47f805
        GetSystemInfo(&si);
Packit 47f805
        func(GetCurrentProcess(), si.dwActiveProcessorMask);
Packit 47f805
    }
Packit 47f805
#endif
Packit 47f805
#endif
Packit 47f805
}
Packit 47f805
#endif
Packit 47f805
Packit 47f805
#if defined(WIN32)
Packit 47f805
Packit 47f805
/**
Packit 47f805
 *  Long Filename support for the WIN32 platform
Packit 47f805
 *
Packit 47f805
 */
Packit 47f805
Packit 47f805
void
Packit 47f805
dosToLongFileName(char *fn)
Packit 47f805
{
Packit 47f805
    const size_t MSIZE = PATH_MAX + 1 - 4; /*  we wanna add ".mp3" later */
Packit 47f805
    WIN32_FIND_DATAA lpFindFileData;
Packit 47f805
    HANDLE  h = FindFirstFileA(fn, &lpFindFileData);
Packit 47f805
    if (h != INVALID_HANDLE_VALUE) {
Packit 47f805
        size_t  a;
Packit 47f805
        char   *q, *p;
Packit 47f805
        FindClose(h);
Packit 47f805
        for (a = 0; a < MSIZE; a++) {
Packit 47f805
            if ('\0' == lpFindFileData.cFileName[a])
Packit 47f805
                break;
Packit 47f805
        }
Packit 47f805
        if (a >= MSIZE || a == 0)
Packit 47f805
            return;
Packit 47f805
        q = strrchr(fn, '\\');
Packit 47f805
        p = strrchr(fn, '/');
Packit 47f805
        if (p - q > 0)
Packit 47f805
            q = p;
Packit 47f805
        if (q == NULL)
Packit 47f805
            q = strrchr(fn, ':');
Packit 47f805
        if (q == NULL)
Packit 47f805
            strncpy(fn, lpFindFileData.cFileName, a);
Packit 47f805
        else {
Packit 47f805
            a += q - fn + 1;
Packit 47f805
            if (a >= MSIZE)
Packit 47f805
                return;
Packit 47f805
            strncpy(++q, lpFindFileData.cFileName, MSIZE - a);
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
Packit 47f805
BOOL
Packit 47f805
SetPriorityClassMacro(DWORD p)
Packit 47f805
{
Packit 47f805
    HANDLE  op = GetCurrentProcess();
Packit 47f805
    return SetPriorityClass(op, p);
Packit 47f805
}
Packit 47f805
Packit 47f805
void
Packit 47f805
setProcessPriority(int Priority)
Packit 47f805
{
Packit 47f805
    switch (Priority) {
Packit 47f805
    case 0:
Packit 47f805
    case 1:
Packit 47f805
        SetPriorityClassMacro(IDLE_PRIORITY_CLASS);
Packit 47f805
        console_printf("==> Priority set to Low.\n");
Packit 47f805
        break;
Packit 47f805
    default:
Packit 47f805
    case 2:
Packit 47f805
        SetPriorityClassMacro(NORMAL_PRIORITY_CLASS);
Packit 47f805
        console_printf("==> Priority set to Normal.\n");
Packit 47f805
        break;
Packit 47f805
    case 3:
Packit 47f805
    case 4:
Packit 47f805
        SetPriorityClassMacro(HIGH_PRIORITY_CLASS);
Packit 47f805
        console_printf("==> Priority set to High.\n");
Packit 47f805
        break;
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
#endif
Packit 47f805
Packit 47f805
Packit 47f805
#if defined(__OS2__)
Packit 47f805
/* OS/2 priority functions */
Packit 47f805
static void
Packit 47f805
setProcessPriority(int Priority)
Packit 47f805
{
Packit 47f805
    int     rc;
Packit 47f805
Packit 47f805
    switch (Priority) {
Packit 47f805
Packit 47f805
    case 0:
Packit 47f805
        rc = DosSetPriority(0, /* Scope: only one process */
Packit 47f805
                            PRTYC_IDLE, /* select priority class (idle, regular, etc) */
Packit 47f805
                            0, /* set delta */
Packit 47f805
                            0); /* Assume current process */
Packit 47f805
        console_printf("==> Priority set to 0 (Low priority).\n");
Packit 47f805
        break;
Packit 47f805
Packit 47f805
    case 1:
Packit 47f805
        rc = DosSetPriority(0, /* Scope: only one process */
Packit 47f805
                            PRTYC_IDLE, /* select priority class (idle, regular, etc) */
Packit 47f805
                            PRTYD_MAXIMUM, /* set delta */
Packit 47f805
                            0); /* Assume current process */
Packit 47f805
        console_printf("==> Priority set to 1 (Medium priority).\n");
Packit 47f805
        break;
Packit 47f805
Packit 47f805
    case 2:
Packit 47f805
        rc = DosSetPriority(0, /* Scope: only one process */
Packit 47f805
                            PRTYC_REGULAR, /* select priority class (idle, regular, etc) */
Packit 47f805
                            PRTYD_MINIMUM, /* set delta */
Packit 47f805
                            0); /* Assume current process */
Packit 47f805
        console_printf("==> Priority set to 2 (Regular priority).\n");
Packit 47f805
        break;
Packit 47f805
Packit 47f805
    case 3:
Packit 47f805
        rc = DosSetPriority(0, /* Scope: only one process */
Packit 47f805
                            PRTYC_REGULAR, /* select priority class (idle, regular, etc) */
Packit 47f805
                            0, /* set delta */
Packit 47f805
                            0); /* Assume current process */
Packit 47f805
        console_printf("==> Priority set to 3 (High priority).\n");
Packit 47f805
        break;
Packit 47f805
Packit 47f805
    case 4:
Packit 47f805
        rc = DosSetPriority(0, /* Scope: only one process */
Packit 47f805
                            PRTYC_REGULAR, /* select priority class (idle, regular, etc) */
Packit 47f805
                            PRTYD_MAXIMUM, /* set delta */
Packit 47f805
                            0); /* Assume current process */
Packit 47f805
        console_printf("==> Priority set to 4 (Maximum priority). I hope you enjoy it :)\n");
Packit 47f805
        break;
Packit 47f805
Packit 47f805
    default:
Packit 47f805
        console_printf("==> Invalid priority specified! Assuming idle priority.\n");
Packit 47f805
    }
Packit 47f805
}
Packit 47f805
#endif
Packit 47f805
Packit 47f805
Packit 47f805
/***********************************************************************
Packit 47f805
*
Packit 47f805
*  Message Output
Packit 47f805
*
Packit 47f805
***********************************************************************/
Packit 47f805
Packit 47f805
Packit 47f805
#if defined( _WIN32 ) && !defined(__MINGW32__)
Packit 47f805
/* Idea for unicode support in LAME, work in progress
Packit 47f805
 * - map UTF-16 to UTF-8
Packit 47f805
 * - advantage, the rest can be kept unchanged (mostly)
Packit 47f805
 * - make sure, fprintf on console is in correct code page
Packit 47f805
 *   + normal text in source code is in ASCII anyway
Packit 47f805
 *   + ID3 tags and filenames coming from command line need attention
Packit 47f805
 * - call wfopen with UTF-16 names where needed
Packit 47f805
 *
Packit 47f805
 * why not wchar_t all the way?
Packit 47f805
 * well, that seems to be a big mess and not portable at all
Packit 47f805
 */
Packit 47f805
#ifndef NDEBUG
Packit 47f805
#define _CRTDBG_MAP_ALLOC
Packit 47f805
#include <stdlib.h>  
Packit 47f805
#include <crtdbg.h>
Packit 47f805
#endif
Packit 47f805
#include <wchar.h>
Packit 47f805
#include <mbstring.h>
Packit 47f805
Packit 47f805
static wchar_t *mbsToUnicode(const char *mbstr, int code_page)
Packit 47f805
{
Packit 47f805
  int n = MultiByteToWideChar(code_page, 0, mbstr, -1, NULL, 0);
Packit 47f805
  wchar_t* wstr = malloc( n*sizeof(wstr[0]) );
Packit 47f805
  if ( wstr !=0 ) {
Packit 47f805
    n = MultiByteToWideChar(code_page, 0, mbstr, -1, wstr, n);
Packit 47f805
    if ( n==0 ) {
Packit 47f805
      free( wstr );
Packit 47f805
      wstr = 0;
Packit 47f805
    }
Packit 47f805
  }
Packit 47f805
  return wstr;
Packit 47f805
}
Packit 47f805
Packit 47f805
static char *unicodeToMbs(const wchar_t *wstr, int code_page)
Packit 47f805
{
Packit 47f805
  int n = 1+WideCharToMultiByte(code_page, 0, wstr, -1, 0, 0, 0, 0);
Packit 47f805
  char* mbstr = malloc( n*sizeof(mbstr[0]) );
Packit 47f805
  if ( mbstr !=0 ) {
Packit 47f805
    n = WideCharToMultiByte(code_page, 0, wstr, -1, mbstr, n, 0, 0);
Packit 47f805
    if( n == 0 ){
Packit 47f805
      free( mbstr );
Packit 47f805
      mbstr = 0;
Packit 47f805
    }
Packit 47f805
  }
Packit 47f805
  return mbstr;
Packit 47f805
}
Packit 47f805
Packit 47f805
char* mbsToMbs(const char* str, int cp_from, int cp_to)
Packit 47f805
{
Packit 47f805
  wchar_t* wstr = mbsToUnicode(str, cp_from);
Packit 47f805
  if ( wstr != 0 ) {
Packit 47f805
    char* local8bit = unicodeToMbs(wstr, cp_to);
Packit 47f805
    free( wstr );
Packit 47f805
    return local8bit;
Packit 47f805
  }
Packit 47f805
  return 0;
Packit 47f805
}
Packit 47f805
Packit 47f805
enum { cp_utf8, cp_console, cp_actual };
Packit 47f805
Packit 47f805
wchar_t *utf8ToUnicode(const char *mbstr)
Packit 47f805
{
Packit 47f805
  return mbsToUnicode(mbstr, CP_UTF8);
Packit 47f805
}
Packit 47f805
Packit 47f805
char *unicodeToUtf8(const wchar_t *wstr)
Packit 47f805
{
Packit 47f805
  return unicodeToMbs(wstr, CP_UTF8);
Packit 47f805
}
Packit 47f805
Packit 47f805
char* utf8ToLocal8Bit(const char* str)
Packit 47f805
{
Packit 47f805
  return mbsToMbs(str, CP_UTF8, CP_ACP);
Packit 47f805
}
Packit 47f805
Packit 47f805
char* utf8ToConsole8Bit(const char* str)
Packit 47f805
{
Packit 47f805
  return mbsToMbs(str, CP_UTF8, GetConsoleOutputCP());
Packit 47f805
}
Packit 47f805
Packit 47f805
char* local8BitToUtf8(const char* str)
Packit 47f805
{
Packit 47f805
  return mbsToMbs(str, CP_ACP, CP_UTF8);
Packit 47f805
}
Packit 47f805
Packit 47f805
char* console8BitToUtf8(const char* str)
Packit 47f805
{
Packit 47f805
  return mbsToMbs(str, GetConsoleOutputCP(), CP_UTF8);
Packit 47f805
}
Packit 47f805
 
Packit 47f805
char* utf8ToLatin1(char const* str)
Packit 47f805
{
Packit 47f805
  return mbsToMbs(str, CP_UTF8, 28591); /* Latin-1 is code page 28591 */
Packit 47f805
}
Packit 47f805
Packit 47f805
unsigned short* utf8ToUtf16(char const* mbstr) /* additional Byte-Order-Marker */
Packit 47f805
{
Packit 47f805
  int n = MultiByteToWideChar(CP_UTF8, 0, mbstr, -1, NULL, 0);
Packit 47f805
  wchar_t* wstr = malloc( (n+1)*sizeof(wstr[0]) );
Packit 47f805
  if ( wstr !=0 ) {
Packit 47f805
    wstr[0] = 0xfeff; /* BOM */
Packit 47f805
    n = MultiByteToWideChar(CP_UTF8, 0, mbstr, -1, wstr+1, n);
Packit 47f805
    if ( n==0 ) {
Packit 47f805
      free( wstr );
Packit 47f805
      wstr = 0;
Packit 47f805
    }
Packit 47f805
  }
Packit 47f805
  return wstr;
Packit 47f805
}
Packit 47f805
Packit 47f805
static
Packit 47f805
void setDebugMode()
Packit 47f805
{
Packit 47f805
#ifndef NDEBUG
Packit 47f805
    if ( IsDebuggerPresent() ) {
Packit 47f805
        // Get current flag  
Packit 47f805
        int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
Packit 47f805
        //tmpFlag |= _CRTDBG_DELAY_FREE_MEM_DF;  
Packit 47f805
        tmpFlag |= _CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF;
Packit 47f805
        // Set flag to the new value.  
Packit 47f805
        _CrtSetDbgFlag( tmpFlag );
Packit 47f805
        _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
Packit 47f805
        _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
Packit 47f805
    }
Packit 47f805
#endif
Packit 47f805
}
Packit 47f805
Packit 47f805
int wmain(int argc, wchar_t* argv[])
Packit 47f805
{
Packit 47f805
  char **utf8_argv;
Packit 47f805
  int i, ret;
Packit 47f805
  setDebugMode();
Packit 47f805
  utf8_argv = calloc(argc, sizeof(char*));
Packit 47f805
  for (i = 0; i < argc; ++i) {
Packit 47f805
    utf8_argv[i] = unicodeToUtf8(argv[i]);
Packit 47f805
  }
Packit 47f805
  ret = c_main(argc, utf8_argv);
Packit 47f805
  for (i = 0; i < argc; ++i) {
Packit 47f805
    free( utf8_argv[i] );
Packit 47f805
  }
Packit 47f805
  free( utf8_argv );
Packit 47f805
  return ret;
Packit 47f805
}
Packit 47f805
Packit 47f805
FILE* lame_fopen(char const* file, char const* mode)
Packit 47f805
{
Packit 47f805
    FILE* fh = 0;
Packit 47f805
    wchar_t* wfile = utf8ToUnicode(file);
Packit 47f805
    wchar_t* wmode = utf8ToUnicode(mode);
Packit 47f805
    if (wfile != 0 && wmode != 0) {
Packit 47f805
        fh = _wfopen(wfile, wmode);
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        fh = fopen(file, mode);
Packit 47f805
    }
Packit 47f805
    free(wfile);
Packit 47f805
    free(wmode);
Packit 47f805
    return fh;
Packit 47f805
}
Packit 47f805
Packit 47f805
char* lame_getenv(char const* var)
Packit 47f805
{
Packit 47f805
    char* str = 0;
Packit 47f805
    wchar_t* wvar = utf8ToUnicode(var);
Packit 47f805
    if (wvar != 0) {
Packit 47f805
        wchar_t* wstr = _wgetenv(wvar);
Packit 47f805
        if (wstr != 0) {
Packit 47f805
            str = unicodeToUtf8(wstr);
Packit 47f805
        }
Packit 47f805
    }
Packit 47f805
    free(wvar);
Packit 47f805
    return str;
Packit 47f805
}
Packit 47f805
Packit 47f805
#else
Packit 47f805
Packit 47f805
FILE* lame_fopen(char const* file, char const* mode)
Packit 47f805
{
Packit 47f805
    return fopen(file, mode);
Packit 47f805
}
Packit 47f805
Packit 47f805
char* lame_getenv(char const* var)
Packit 47f805
{
Packit 47f805
    char* str = getenv(var);
Packit 47f805
    if (str) {
Packit 47f805
        return strdup(str);
Packit 47f805
    }
Packit 47f805
    return 0;
Packit 47f805
}
Packit 47f805
Packit 47f805
int main(int argc, char *argv[])
Packit 47f805
{
Packit 47f805
    return c_main(argc, argv);
Packit 47f805
}
Packit 47f805
Packit 47f805
#endif
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
Packit 47f805
static int
Packit 47f805
c_main(int argc, char *argv[])
Packit 47f805
{
Packit 47f805
    lame_t  gf;
Packit 47f805
    int     ret;
Packit 47f805
Packit 47f805
#if macintosh
Packit 47f805
    argc = ccommand(&argv);
Packit 47f805
#endif
Packit 47f805
#ifdef __EMX__
Packit 47f805
    /* This gives wildcard expansion on Non-POSIX shells with OS/2 */
Packit 47f805
    _wildcard(&argc, &argv);
Packit 47f805
#endif
Packit 47f805
#if defined( _WIN32 ) && !defined(__MINGW32__)
Packit 47f805
    set_process_affinity();
Packit 47f805
#endif
Packit 47f805
Packit 47f805
    frontend_open_console();    
Packit 47f805
    gf = lame_init(); /* initialize libmp3lame */
Packit 47f805
    if (NULL == gf) {
Packit 47f805
        error_printf("fatal error during initialization\n");
Packit 47f805
        ret = 1;
Packit 47f805
    }
Packit 47f805
    else {
Packit 47f805
        ret = lame_main(gf, argc, argv);
Packit 47f805
        lame_close(gf);
Packit 47f805
    }
Packit 47f805
    frontend_close_console();
Packit 47f805
    return ret;
Packit 47f805
}