main.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495
  1. /*
  2. * Command line frontend program
  3. *
  4. * Copyright (c) 1999 Mark Taylor
  5. * 2000 Takehiro TOMINAGA
  6. * 2010-2012 Robert Hegemann
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Library General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Library General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Library General Public
  19. * License along with this library; if not, write to the
  20. * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  21. * Boston, MA 02111-1307, USA.
  22. */
  23. /* $Id$ */
  24. #ifdef HAVE_CONFIG_H
  25. # include <config.h>
  26. #endif
  27. #include <assert.h>
  28. #include <stdio.h>
  29. #ifdef STDC_HEADERS
  30. # include <stdlib.h>
  31. # include <string.h>
  32. #else
  33. # ifndef HAVE_STRCHR
  34. # define strchr index
  35. # define strrchr rindex
  36. # endif
  37. char *strchr(), *strrchr();
  38. # ifndef HAVE_MEMCPY
  39. # define memcpy(d, s, n) bcopy ((s), (d), (n))
  40. # define memmove(d, s, n) bcopy ((s), (d), (n))
  41. # endif
  42. #endif
  43. #ifdef HAVE_FCNTL_H
  44. # include <fcntl.h>
  45. #endif
  46. #ifdef __sun__
  47. /* woraround for SunOS 4.x, it has SEEK_* defined here */
  48. #include <unistd.h>
  49. #endif
  50. #ifdef __OS2__
  51. #include <os2.h>
  52. #define PRTYC_IDLE 1
  53. #define PRTYC_REGULAR 2
  54. #define PRTYD_MINIMUM -31
  55. #define PRTYD_MAXIMUM 31
  56. #endif
  57. #if defined(_WIN32)
  58. # include <windows.h>
  59. #endif
  60. /*
  61. main.c is example code for how to use libmp3lame.a. To use this library,
  62. you only need the library and lame.h. All other .h files are private
  63. to the library.
  64. */
  65. #include "lame.h"
  66. #include "console.h"
  67. #include "main.h"
  68. /* PLL 14/04/2000 */
  69. #if macintosh
  70. #include <console.h>
  71. #endif
  72. #ifdef WITH_DMALLOC
  73. #include <dmalloc.h>
  74. #endif
  75. static int c_main(int argc, char *argv[]);
  76. extern int lame_main(lame_t gf, int argc, char *argv[]);
  77. /************************************************************************
  78. *
  79. * main
  80. *
  81. * PURPOSE: MPEG-1,2 Layer III encoder with GPSYCHO
  82. * psychoacoustic model.
  83. *
  84. ************************************************************************/
  85. #if defined( _WIN32 ) && !defined(__MINGW32__)
  86. static void
  87. set_process_affinity()
  88. {
  89. #if 0
  90. /* rh 061207
  91. the following fix seems to be a workaround for a problem in the
  92. parent process calling LAME. It would be better to fix the broken
  93. application => code disabled.
  94. */
  95. #if defined(_WIN32)
  96. /* set affinity back to all CPUs. Fix for EAC/lame on SMP systems from
  97. "Todd Richmond" <todd.richmond@openwave.com> */
  98. typedef BOOL(WINAPI * SPAMFunc) (HANDLE, DWORD_PTR);
  99. SPAMFunc func;
  100. SYSTEM_INFO si;
  101. if ((func = (SPAMFunc) GetProcAddress(GetModuleHandleW(L"KERNEL32.DLL"),
  102. "SetProcessAffinityMask")) != NULL) {
  103. GetSystemInfo(&si);
  104. func(GetCurrentProcess(), si.dwActiveProcessorMask);
  105. }
  106. #endif
  107. #endif
  108. }
  109. #endif
  110. #if defined(WIN32)
  111. /**
  112. * Long Filename support for the WIN32 platform
  113. *
  114. */
  115. void
  116. dosToLongFileName(char *fn)
  117. {
  118. const size_t MSIZE = PATH_MAX + 1 - 4; /* we wanna add ".mp3" later */
  119. WIN32_FIND_DATAA lpFindFileData;
  120. HANDLE h = FindFirstFileA(fn, &lpFindFileData);
  121. if (h != INVALID_HANDLE_VALUE) {
  122. size_t a;
  123. char *q, *p;
  124. FindClose(h);
  125. for (a = 0; a < MSIZE; a++) {
  126. if ('\0' == lpFindFileData.cFileName[a])
  127. break;
  128. }
  129. if (a >= MSIZE || a == 0)
  130. return;
  131. q = strrchr(fn, '\\');
  132. p = strrchr(fn, '/');
  133. if (p - q > 0)
  134. q = p;
  135. if (q == NULL)
  136. q = strrchr(fn, ':');
  137. if (q == NULL)
  138. strncpy(fn, lpFindFileData.cFileName, a);
  139. else {
  140. a += q - fn + 1;
  141. if (a >= MSIZE)
  142. return;
  143. strncpy(++q, lpFindFileData.cFileName, MSIZE - a);
  144. }
  145. }
  146. }
  147. BOOL
  148. SetPriorityClassMacro(DWORD p)
  149. {
  150. HANDLE op = GetCurrentProcess();
  151. return SetPriorityClass(op, p);
  152. }
  153. void
  154. setProcessPriority(int Priority)
  155. {
  156. switch (Priority) {
  157. case 0:
  158. case 1:
  159. SetPriorityClassMacro(IDLE_PRIORITY_CLASS);
  160. console_printf("==> Priority set to Low.\n");
  161. break;
  162. default:
  163. case 2:
  164. SetPriorityClassMacro(NORMAL_PRIORITY_CLASS);
  165. console_printf("==> Priority set to Normal.\n");
  166. break;
  167. case 3:
  168. case 4:
  169. SetPriorityClassMacro(HIGH_PRIORITY_CLASS);
  170. console_printf("==> Priority set to High.\n");
  171. break;
  172. }
  173. }
  174. #endif
  175. #if defined(__OS2__)
  176. /* OS/2 priority functions */
  177. static void
  178. setProcessPriority(int Priority)
  179. {
  180. int rc;
  181. switch (Priority) {
  182. case 0:
  183. rc = DosSetPriority(0, /* Scope: only one process */
  184. PRTYC_IDLE, /* select priority class (idle, regular, etc) */
  185. 0, /* set delta */
  186. 0); /* Assume current process */
  187. console_printf("==> Priority set to 0 (Low priority).\n");
  188. break;
  189. case 1:
  190. rc = DosSetPriority(0, /* Scope: only one process */
  191. PRTYC_IDLE, /* select priority class (idle, regular, etc) */
  192. PRTYD_MAXIMUM, /* set delta */
  193. 0); /* Assume current process */
  194. console_printf("==> Priority set to 1 (Medium priority).\n");
  195. break;
  196. case 2:
  197. rc = DosSetPriority(0, /* Scope: only one process */
  198. PRTYC_REGULAR, /* select priority class (idle, regular, etc) */
  199. PRTYD_MINIMUM, /* set delta */
  200. 0); /* Assume current process */
  201. console_printf("==> Priority set to 2 (Regular priority).\n");
  202. break;
  203. case 3:
  204. rc = DosSetPriority(0, /* Scope: only one process */
  205. PRTYC_REGULAR, /* select priority class (idle, regular, etc) */
  206. 0, /* set delta */
  207. 0); /* Assume current process */
  208. console_printf("==> Priority set to 3 (High priority).\n");
  209. break;
  210. case 4:
  211. rc = DosSetPriority(0, /* Scope: only one process */
  212. PRTYC_REGULAR, /* select priority class (idle, regular, etc) */
  213. PRTYD_MAXIMUM, /* set delta */
  214. 0); /* Assume current process */
  215. console_printf("==> Priority set to 4 (Maximum priority). I hope you enjoy it :)\n");
  216. break;
  217. default:
  218. console_printf("==> Invalid priority specified! Assuming idle priority.\n");
  219. }
  220. }
  221. #endif
  222. /***********************************************************************
  223. *
  224. * Message Output
  225. *
  226. ***********************************************************************/
  227. #if defined( _WIN32 ) && !defined(__MINGW32__)
  228. /* Idea for unicode support in LAME, work in progress
  229. * - map UTF-16 to UTF-8
  230. * - advantage, the rest can be kept unchanged (mostly)
  231. * - make sure, fprintf on console is in correct code page
  232. * + normal text in source code is in ASCII anyway
  233. * + ID3 tags and filenames coming from command line need attention
  234. * - call wfopen with UTF-16 names where needed
  235. *
  236. * why not wchar_t all the way?
  237. * well, that seems to be a big mess and not portable at all
  238. */
  239. #ifndef NDEBUG
  240. #define _CRTDBG_MAP_ALLOC
  241. #include <stdlib.h>
  242. #include <crtdbg.h>
  243. #endif
  244. #include <wchar.h>
  245. #include <mbstring.h>
  246. static wchar_t *mbsToUnicode(const char *mbstr, int code_page)
  247. {
  248. int n = MultiByteToWideChar(code_page, 0, mbstr, -1, NULL, 0);
  249. wchar_t* wstr = malloc( n*sizeof(wstr[0]) );
  250. if ( wstr !=0 ) {
  251. n = MultiByteToWideChar(code_page, 0, mbstr, -1, wstr, n);
  252. if ( n==0 ) {
  253. free( wstr );
  254. wstr = 0;
  255. }
  256. }
  257. return wstr;
  258. }
  259. static char *unicodeToMbs(const wchar_t *wstr, int code_page)
  260. {
  261. int n = 1+WideCharToMultiByte(code_page, 0, wstr, -1, 0, 0, 0, 0);
  262. char* mbstr = malloc( n*sizeof(mbstr[0]) );
  263. if ( mbstr !=0 ) {
  264. n = WideCharToMultiByte(code_page, 0, wstr, -1, mbstr, n, 0, 0);
  265. if( n == 0 ){
  266. free( mbstr );
  267. mbstr = 0;
  268. }
  269. }
  270. return mbstr;
  271. }
  272. char* mbsToMbs(const char* str, int cp_from, int cp_to)
  273. {
  274. wchar_t* wstr = mbsToUnicode(str, cp_from);
  275. if ( wstr != 0 ) {
  276. char* local8bit = unicodeToMbs(wstr, cp_to);
  277. free( wstr );
  278. return local8bit;
  279. }
  280. return 0;
  281. }
  282. enum { cp_utf8, cp_console, cp_actual };
  283. wchar_t *utf8ToUnicode(const char *mbstr)
  284. {
  285. return mbsToUnicode(mbstr, CP_UTF8);
  286. }
  287. char *unicodeToUtf8(const wchar_t *wstr)
  288. {
  289. return unicodeToMbs(wstr, CP_UTF8);
  290. }
  291. char* utf8ToLocal8Bit(const char* str)
  292. {
  293. return mbsToMbs(str, CP_UTF8, CP_ACP);
  294. }
  295. char* utf8ToConsole8Bit(const char* str)
  296. {
  297. return mbsToMbs(str, CP_UTF8, GetConsoleOutputCP());
  298. }
  299. char* local8BitToUtf8(const char* str)
  300. {
  301. return mbsToMbs(str, CP_ACP, CP_UTF8);
  302. }
  303. char* console8BitToUtf8(const char* str)
  304. {
  305. return mbsToMbs(str, GetConsoleOutputCP(), CP_UTF8);
  306. }
  307. char* utf8ToLatin1(char const* str)
  308. {
  309. return mbsToMbs(str, CP_UTF8, 28591); /* Latin-1 is code page 28591 */
  310. }
  311. unsigned short* utf8ToUtf16(char const* mbstr) /* additional Byte-Order-Marker */
  312. {
  313. int n = MultiByteToWideChar(CP_UTF8, 0, mbstr, -1, NULL, 0);
  314. wchar_t* wstr = malloc( (n+1)*sizeof(wstr[0]) );
  315. if ( wstr !=0 ) {
  316. wstr[0] = 0xfeff; /* BOM */
  317. n = MultiByteToWideChar(CP_UTF8, 0, mbstr, -1, wstr+1, n);
  318. if ( n==0 ) {
  319. free( wstr );
  320. wstr = 0;
  321. }
  322. }
  323. return wstr;
  324. }
  325. static
  326. void setDebugMode()
  327. {
  328. #ifndef NDEBUG
  329. if ( IsDebuggerPresent() ) {
  330. // Get current flag
  331. int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );
  332. //tmpFlag |= _CRTDBG_DELAY_FREE_MEM_DF;
  333. tmpFlag |= _CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF;
  334. // Set flag to the new value.
  335. _CrtSetDbgFlag( tmpFlag );
  336. _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
  337. _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
  338. }
  339. #endif
  340. }
  341. int wmain(int argc, wchar_t* argv[])
  342. {
  343. char **utf8_argv;
  344. int i, ret;
  345. setDebugMode();
  346. utf8_argv = calloc(argc, sizeof(char*));
  347. for (i = 0; i < argc; ++i) {
  348. utf8_argv[i] = unicodeToUtf8(argv[i]);
  349. }
  350. ret = c_main(argc, utf8_argv);
  351. for (i = 0; i < argc; ++i) {
  352. free( utf8_argv[i] );
  353. }
  354. free( utf8_argv );
  355. return ret;
  356. }
  357. FILE* lame_fopen(char const* file, char const* mode)
  358. {
  359. FILE* fh = 0;
  360. wchar_t* wfile = utf8ToUnicode(file);
  361. wchar_t* wmode = utf8ToUnicode(mode);
  362. if (wfile != 0 && wmode != 0) {
  363. fh = _wfopen(wfile, wmode);
  364. }
  365. else {
  366. fh = fopen(file, mode);
  367. }
  368. free(wfile);
  369. free(wmode);
  370. return fh;
  371. }
  372. char* lame_getenv(char const* var)
  373. {
  374. char* str = 0;
  375. wchar_t* wvar = utf8ToUnicode(var);
  376. if (wvar != 0) {
  377. wchar_t* wstr = _wgetenv(wvar);
  378. if (wstr != 0) {
  379. str = unicodeToUtf8(wstr);
  380. }
  381. }
  382. free(wvar);
  383. return str;
  384. }
  385. #else
  386. FILE* lame_fopen(char const* file, char const* mode)
  387. {
  388. return fopen(file, mode);
  389. }
  390. char* lame_getenv(char const* var)
  391. {
  392. char* str = getenv(var);
  393. if (str) {
  394. return strdup(str);
  395. }
  396. return 0;
  397. }
  398. int main(int argc, char *argv[])
  399. {
  400. return c_main(argc, argv);
  401. }
  402. #endif
  403. static int
  404. c_main(int argc, char *argv[])
  405. {
  406. lame_t gf;
  407. int ret;
  408. #if macintosh
  409. argc = ccommand(&argv);
  410. #endif
  411. #ifdef __EMX__
  412. /* This gives wildcard expansion on Non-POSIX shells with OS/2 */
  413. _wildcard(&argc, &argv);
  414. #endif
  415. #if defined( _WIN32 ) && !defined(__MINGW32__)
  416. set_process_affinity();
  417. #endif
  418. frontend_open_console();
  419. gf = lame_init(); /* initialize libmp3lame */
  420. if (NULL == gf) {
  421. error_printf("fatal error during initialization\n");
  422. ret = 1;
  423. }
  424. else {
  425. ret = lame_main(gf, argc, argv);
  426. lame_close(gf);
  427. }
  428. frontend_close_console();
  429. return ret;
  430. }