main.c
上传用户:bjsgzm
上传日期:2007-01-08
资源大小:256k
文件大小:35k
源码类别:

mpeg/mp3

开发平台:

Visual C++

  1. /*
  2. (c) Copyright 1998, 1999 - Tord Jansson
  3. =======================================
  4. This file is part of the BladeEnc MP3 Encoder, based on
  5. ISO's reference code for MPEG Layer 3 compression.
  6. This file doesn't contain any of the ISO reference code and
  7. is copyright Tord Jansson (tord.jansson@swipnet.se).
  8. BladeEnc is free software; you can redistribute this file
  9. and/or modify it under the terms of the GNU Lesser General Public
  10. License as published by the Free Software Foundation; either
  11. version 2.1 of the License, or (at your option) any later version.
  12. */
  13. #include <stdio.h>
  14. #include    <stdlib.h>
  15. #include    <string.h>
  16. #include    <time.h>
  17. #include    "system.h"
  18. #include "codec.h"
  19. #include    "samplein.h"
  20. #include "arglink.h"
  21. #include "bladesys.h"
  22. #ifdef OS2
  23. # define INCL_DOSFILEMGR
  24. # define INCL_DOSERRORS
  25. # define INCL_DOSPROCESS
  26. # include <os2.h>
  27. # include "os2key.h"
  28. #endif
  29. #if SYSTEM == MAC_OS
  30. # include <SIOUX.h>
  31. # include <Events.h>
  32. void DoEvent(EventRecord *i);
  33. extern int gFriendliness;
  34. #endif
  35. extern char *mystrupr(char * strng);
  36. enum
  37. {
  38. PROG_OFF,
  39. PROG_BOTH_PERC_ETA,
  40. PROG_FILE_GRAPH,
  41. PROG_BATCH_GRAPH,
  42. PROG_BOTH_GRAPH,
  43. PROG_BOTH_SAMPLES,
  44. PROG_BOTH_ETA,
  45. PROG_FILE_RLEN,
  46. PROG_FILE_NORETURN,
  47. };
  48. /*____ Structure Definitions __________________________________________________*/
  49. typedef struct  JobDef  Job;
  50. struct JobDef
  51. {
  52. CodecInitIn sCodec;
  53. SplIn         sInput;
  54. Job         * psNext;
  55. int           fDeleteSource;
  56. char          outputFilename[MAX_NAMELEN];
  57. char          sourceFilename[MAX_NAMELEN];
  58. };
  59. /*____ Function Prototypes ____________________________________________________*/
  60. int printUsage( void );
  61. int validateJobs( Job * psJob );
  62. argLink * readGlobalSwitches( argLink * pArgLink );
  63. argLink * readLocalSwitches( argLink * pArgLink, Job * psJob );
  64. int addCommandlineJob( argLink ** pArgLink );
  65. int addFileToBatch( char * pFilename, char * pOutputFilename );
  66. int clearJobQueue( void );
  67. int removeJobQueueEntry( Job * psJob );
  68. int readL3EncCommandline( int argc, char * argv[] );
  69. void updateProgressIndicator( time_t startBatch, double batchLen, double batchDone,
  70.                      time_t startFile, double fileLen, double fileDone, 
  71.  int progType, Job * psJob );
  72. void quit( int returnValue );
  73. void timerCalibrate( void );
  74. time_t timerStart( void );
  75. float timerStop( time_t startTime );
  76. /*____ Static Data ____________________________________________________________*/
  77. /* Parameters set through the commandline. */
  78. int wantedBitrate = -1;             /* -1 = Unspecified. */
  79. int wantedCRC = FALSE;
  80. int wantedPrivate = FALSE;
  81. int wantedCopyright = FALSE;
  82. int wantedOriginal = TRUE;
  83. SampleType wantedInputType = STEREO;
  84. int wantedProgressBarRate = 2;
  85. int wantedChannelSwap = FALSE;
  86. int wantedDeleteSource = FALSE;
  87. #ifdef WAIT_KEY
  88. int     wantedQuit = FALSE;
  89. int defWantedQuit = FALSE;
  90. #else
  91. int wantedQuit = TRUE;
  92. int defWantedQuit = TRUE;
  93. #endif
  94. int wantedQuiet = FALSE;
  95. int wantedSTDOUT = FALSE;
  96. int fPreparedSTDIN = FALSE;
  97. char prioString[256];
  98. char * pPrioString = NULL;
  99. Job * psJobQueue = NULL;
  100. char outputDir[MAX_NAMELEN];
  101. FILE * textout;
  102. int timerCalibrationValue; /* Only used if PRECISE_TIMER is defined. */
  103. int progType = PROG_BOTH_PERC_ETA; /* Style of the progress bar */
  104. int rawFrequency = 44100;
  105. int rawChannels = 2;
  106. int rawBits = 16;
  107. int rawSigned = TRUE;
  108. int rawByteorder = BYTEORDER;
  109. /*____ main() _________________________________________________________________*/
  110. #if SYSTEM == MAC_OS
  111. int main_( int argc, char* argv[] ) /* Because the real main is somewhere else */
  112. #else
  113. int main( int argc, char* argv[] )
  114. #endif
  115. {
  116. int           samplesPerFrame;
  117. int           nSamples;
  118. short         readBuffer[2304];
  119. int           x;
  120. char          input;
  121. Job         * psTemp;
  122. time_t        startTimeBatch, startTimeFile;
  123. float   seconds;
  124. double        batchSamplesTotal = 0.0, batchSamplesRead = 0.0;
  125. double   fileSamplesRead;
  126. int   showProgressCnt = 0;
  127. CodecInitOut *pCodecInfo;
  128. char        * pBuffer;
  129. uint          encodedChunkSize;
  130. FILE        * fp;
  131. char   temp[256];
  132. argLink * pArgLink, * pNextArg;
  133. #if SYSTEM == MAC_OS
  134. long macTickStart = TickCount();
  135. #endif
  136. /* Setting default parameters. Might seem useless since most of them
  137.    allready are predefined, but the MAC OS port uses main() as a subroutine
  138.    which can be called multiple times. */
  139. wantedBitrate = -1;             /* -1 = Unspecified. */
  140. wantedCRC = FALSE;
  141. wantedPrivate = FALSE;
  142. wantedCopyright = FALSE;
  143. wantedOriginal = TRUE;
  144. wantedInputType = STEREO;
  145. wantedProgressBarRate = 2;
  146. wantedChannelSwap = FALSE;
  147. wantedDeleteSource = FALSE;
  148. wantedQuit = defWantedQuit;
  149. wantedQuiet = FALSE;
  150. wantedSTDOUT = FALSE;
  151. fPreparedSTDIN = FALSE;
  152. pPrioString = NULL;
  153. psJobQueue = NULL;
  154. progType = PROG_BOTH_PERC_ETA; /* Style of the progress bar */
  155. rawFrequency = 44100;
  156. rawChannels = 2;
  157. rawBits = 16;
  158. rawSigned = TRUE;
  159. rawByteorder = BYTEORDER;
  160. textout = stdout;
  161. outputDir[0] = 0;
  162. /* Fix ArgLink */
  163. pArgLink = argv2ArgLink( argc-1, argv+1 );
  164. if( findStrInArgLink( pArgLink, "-NOCFG" ) == NULL )
  165. if( findConfigFile( argv[0], temp ) == TRUE )
  166. addFileContentToArgLink( &pArgLink, temp );
  167. #ifdef WILDCARDS
  168. expandWildcards( &pArgLink );
  169. #endif
  170. pNextArg = readGlobalSwitches( pArgLink );
  171. /* Check for STDOUT */
  172. if( findStrInArgLink( pArgLink, "stdout" ) != NULL )
  173. {
  174. prepStdout();
  175. textout = stderr;
  176. }
  177. /* Print Text */
  178. if( !wantedQuiet )
  179. {
  180. fprintf( textout, "n" );
  181. fprintf( textout, "BladeEnc 0.90    (c) Tord Jansson          Homepage: http://bladeenc.mp3.non" );
  182. fprintf( textout, "===============================================================================n" );
  183. fprintf( textout, "BladeEnc is free software, distributed under the Lesser General Public License.n" );
  184. fprintf( textout, "See the file COPYING, BladeEnc's homepage or www.fsf.org for more details.n" );
  185. fprintf( textout, "n" );
  186. }
  187. /* Initialise batch */
  188. while( pNextArg != NULL )
  189. {
  190. x = addCommandlineJob( &pNextArg );
  191. if( x == FALSE )
  192. {
  193. deleteArgLink( pArgLink );
  194. quit( -1 );
  195. }
  196. }
  197. deleteArgLink( pArgLink );
  198. /* Validate job settings */
  199. x = validateJobs( psJobQueue );
  200. if( x == FALSE )
  201. quit( -2 );
  202. /* Make sure we don't have certain progress indicators if RAW file in batch */
  203. x = 0;
  204. for( psTemp = psJobQueue ; psTemp != NULL ; psTemp = psTemp->psNext )
  205. {
  206. if( psTemp->sInput.filetype == RAW )
  207. x++;
  208. }
  209. if( x != 0 && progType != PROG_OFF && progType != PROG_FILE_RLEN )
  210. progType = PROG_FILE_RLEN;
  211. /* Set priority */
  212. if( setPriority( pPrioString ) == FALSE )
  213. {
  214. fprintf( textout, "Error: '%s' is not a valid priority setting!n", pPrioString );
  215. quit( -1 );
  216. };
  217. /* Procedure if no files found */
  218. if( psJobQueue == NULL )
  219. {
  220. printUsage();                                                           /* No files on the commandline */
  221. quit( -1 );
  222. }
  223. /* Print files to encode */
  224. for( x = 0, psTemp = psJobQueue ; psTemp != NULL ; x++, psTemp = psTemp->psNext );
  225. if( !wantedQuiet )
  226. fprintf( textout, "Files to encode: %dnn", x );
  227. /* Encode */
  228. #ifdef PRECISE_TIMER
  229. timerCalibrate();
  230. #endif
  231. startTimeBatch = timerStart();
  232. for( psTemp = psJobQueue ; psTemp != NULL ; psTemp = psTemp->psNext )
  233. if( psTemp->sInput.length == 0xFFFFFFFF )
  234. {
  235. batchSamplesTotal = 0xFFFFFFFF;
  236. break;
  237. }
  238. else
  239. batchSamplesTotal += psTemp->sInput.length;
  240. while( psJobQueue != NULL )
  241. {
  242. /* Print information */
  243. if( !wantedQuiet )
  244. {
  245. fprintf( textout, "Encoding:  %sn", psJobQueue->sourceFilename );
  246. fprintf( textout, "Input:     %.1f kHz, %d bit, ", psJobQueue->sInput.freq/1000.f, psJobQueue->sInput.bits );
  247. if( psJobQueue->sInput.fReadStereo == TRUE )
  248. fprintf( textout, "stereo.n" );
  249. else
  250. fprintf( textout, "mono.n" );
  251. fprintf( textout, "Output:    %d kBit, ", psJobQueue->sCodec.bitrate );
  252. if( psJobQueue->sCodec.mode == 0 )
  253. fprintf( textout, "stereo.nn" );
  254. else
  255. fprintf( textout, "mono.nn" );
  256. }
  257. /* Init a new job */
  258. startTimeFile = timerStart();
  259. fileSamplesRead = 0;
  260. pCodecInfo = codecInit( &psJobQueue->sCodec );
  261. samplesPerFrame = pCodecInfo->nSamples;
  262. pBuffer = (char *) malloc( pCodecInfo->bufferSize );
  263. if( strcmp( psJobQueue->outputFilename, "STDOUT" ) == 0 )
  264. fp = stdout;
  265. else
  266. {
  267. fp = fopen( psJobQueue->outputFilename, "wb" );
  268. if( fp == NULL )
  269. {
  270. /*  codecExit(); */
  271. closeInput( &psJobQueue->sInput );
  272. fprintf( textout, "ERROR: Couldn't create '%s'!n", psJobQueue->outputFilename );
  273. quit( -1 );
  274. }
  275. }
  276. /* Encoding loop */
  277. while ( (nSamples = readSamples( &psJobQueue->sInput, samplesPerFrame, readBuffer)) > 0 )
  278. {
  279. #if SYSTEM == MAC_OS /* Stuff needed for Petteri Kamppuri's Mac OS port */
  280.   if(macTickStart + gFriendliness < TickCount())
  281. {
  282.          macTickStart = TickCount();
  283.         Boolean       gotEvent;
  284.           EventRecord event;
  285.           gotEvent = GetNextEvent(everyEvent, &event);
  286.           if(gotEvent)
  287. {
  288.              SIOUXHandleOneEvent(&event);
  289.             DoEvent(&event);
  290.           }
  291. }
  292. #endif
  293. encodedChunkSize = codecEncodeChunk( nSamples, readBuffer, pBuffer );
  294. if( fwrite( pBuffer, 1, encodedChunkSize, fp ) != encodedChunkSize )
  295. {
  296. fprintf( textout, "ERROR: Couldn't write '%s'! Disc probably full.n", psJobQueue->outputFilename );
  297. quit( -1 );
  298. }
  299. batchSamplesRead += nSamples;
  300. fileSamplesRead += nSamples;
  301. if( !wantedQuiet )
  302. {
  303. showProgressCnt = (showProgressCnt+1) % wantedProgressBarRate;
  304. if( showProgressCnt == 0 )
  305. updateProgressIndicator( startTimeBatch, batchSamplesTotal, batchSamplesRead,
  306.                          startTimeFile, psJobQueue->sInput.length, fileSamplesRead, 
  307.  progType, psJobQueue );
  308. }
  309. if( be_kbhit() != 0 )
  310. {
  311. input = be_getch();
  312. if( input == 27 )
  313. {
  314. fprintf( textout, "r                                                                             r" );
  315. fprintf( textout, "Quit, are you sure? (y/n)" );
  316. fflush( textout );
  317. input = be_getch();
  318. if( input == 'y' || input == 'Y' )
  319. {
  320. encodedChunkSize = codecExit( pBuffer );
  321. if( encodedChunkSize != 0 )
  322. if( fwrite( pBuffer, encodedChunkSize, 1, fp ) != 1 )
  323. {
  324. fprintf( textout, "ERROR: Couldn't write '%s'! Disc probably full.n", psJobQueue->outputFilename );
  325. quit( -1 );
  326. }
  327. free( pBuffer );
  328. closeInput( &psJobQueue->sInput );
  329. if( fp != stdout )
  330. fclose( fp );
  331. return  0;
  332. }
  333. else
  334. fprintf( textout, "r                                                                             r" );
  335. }
  336. }
  337. }
  338. /* File done */
  339. encodedChunkSize = codecExit( pBuffer );
  340. if( encodedChunkSize != 0 )
  341. if( fwrite( pBuffer, encodedChunkSize, 1, fp ) != 1 )
  342. {
  343. fprintf( textout, "ERROR: Couldn't write '%s'! Disc probably full.n", psJobQueue->outputFilename );
  344. quit( -1 );
  345. }
  346. if( fp != stdout )
  347. fclose( fp );
  348. free( pBuffer );
  349. if( psJobQueue->fDeleteSource == TRUE )
  350. remove( psJobQueue->sourceFilename );
  351. seconds = timerStop( startTimeFile );
  352. x = (int) seconds;
  353. if( !wantedQuiet )
  354. {
  355. fprintf( textout, "r                                                                             r" );
  356. fprintf( textout, "Completed. Encoding time: %02d:%02d:%02d (%.2fX)nn",
  357.          x/3600, (x/60)%60, x%60, ((float)fileSamplesRead) /
  358.          ((psJobQueue->sInput.fReadStereo+1)*psJobQueue->sInput.freq*seconds) );
  359. }
  360. removeJobQueueEntry( psJobQueue );
  361. }
  362. /* Batch done */
  363. if( !wantedQuiet )
  364. {
  365. seconds = timerStop( startTimeBatch );
  366. fprintf( textout, "All operations completed. Total encoding time: %02d:%02d:%02dn",
  367.          (int) seconds/3600, (int)(seconds/60)%60, (int) seconds%60 );
  368. if( !wantedQuit )
  369. {
  370. fprintf( textout, "Press ENTER to exit..." );
  371. be_getch();
  372. fprintf( textout, "n" );
  373. }
  374. }
  375. return 0;
  376. }
  377. /*____ quit() _________________________________________________________________*/
  378. void    quit( int returnValue )
  379. {
  380. if( !wantedQuit )
  381. {
  382. fprintf( textout, "Press ENTER to exit..." );
  383. be_getch();
  384. fprintf( textout, "n" );
  385. }
  386. #if SYSTEM == MAC_OS
  387. throw returnValue;
  388. #else
  389. exit( returnValue );
  390. #endif
  391. }
  392. /*____ timerCalibrate() _______________________________________________________*/
  393. void timerCalibrate( void )
  394. {
  395. time_t x, y;
  396. int i;
  397. x = y = time( NULL );
  398. while( y == x )
  399. y = time( NULL );
  400. for( i = 0 ; y == time( NULL ) ; i++ );
  401. timerCalibrationValue = i;
  402. printf( "Timer Calibration Value: %dn", timerCalibrationValue );
  403. }
  404. /*____ timerStart() ___________________________________________________________*/
  405. time_t timerStart( void )
  406. {
  407. time_t x, y;
  408. x = y = time( NULL );
  409. #ifdef PRECISE_TIMER
  410. while( y == x )
  411. y = time( NULL );
  412. #endif
  413. return y;
  414. }
  415. /*____ timerStop() ____________________________________________________________*/
  416. float timerStop( time_t startTime )
  417. {
  418. float seconds;
  419. time_t stopTime = time( NULL );
  420. #ifdef PRECISE_TIMER
  421. int i;
  422. for( i = 0 ; stopTime == time( NULL ) ; i++ );
  423. #endif
  424. seconds = (float) (stopTime - startTime);
  425. #ifdef PRECISE_TIMER
  426. seconds += ((float)(timerCalibrationValue - i))/timerCalibrationValue;
  427. printf( "Exact seconds: %.5fn", seconds );
  428. #endif
  429. return seconds;
  430. }
  431. /*____ updateProgressIndicator() ______________________________________________*/
  432. void    updateProgressIndicator( time_t startBatch, double batchLen, double batchDone,
  433.                                  time_t startFile, double fileLen, double fileDone, 
  434.  int progType, Job * psJob )
  435. {
  436. time_t  currTime;
  437. float   percentageFile, percentageBatch;
  438. int     fileEta, batchEta;
  439. char temp[82];
  440. int x, i;
  441. static char wheel[4] = { '|' , '/' , '-' , '\' };
  442. static int wheelindex = 0;
  443. static int prevFileDone = -1;
  444. currTime = time( NULL );
  445. switch( progType )
  446. {
  447. case PROG_BOTH_PERC_ETA:
  448. percentageFile = (float) (fileDone / fileLen * 100);
  449. if( percentageFile >= 100.f )
  450. percentageFile = (float) 99.9;
  451. fileEta = (int) (((float)(currTime - startFile)) / fileDone * (fileLen - fileDone) );
  452. percentageBatch = (float)(batchDone / batchLen * 100);
  453. batchEta = (int) (((float)(currTime - startBatch)) / batchDone * (batchLen - batchDone));
  454. fprintf( textout, "Status:   %4.1f%% done, ETA %02d:%02d:%02d          BATCH: %4.1f%% done, ETA %02d:%02d:%02dr",
  455.  percentageFile, fileEta/3600, (fileEta/60)%60, fileEta%60,
  456.  percentageBatch, batchEta/3600, (batchEta/60)%60, batchEta%60 );
  457. fflush( textout );
  458. break;
  459. case PROG_FILE_GRAPH:
  460. strcpy( temp, "File progress: [..................................................]r" );
  461. x = (int) (fileDone*50/fileLen);
  462. memset( temp + 16, '*', x );
  463. if( x < 50 )
  464. {
  465. temp[16+x] = wheel[wheelindex];
  466. wheelindex = (wheelindex + 1) % 4;
  467. }
  468. fprintf( textout, temp );
  469. break;
  470. case PROG_BATCH_GRAPH:
  471. strcpy( temp, "Batch progress: [..................................................]r" );
  472. x = (int) (batchDone*50/batchLen);
  473. memset( temp + 16, '*', x );
  474. if( x < 50 )
  475. {
  476. temp[16+x] = wheel[wheelindex];
  477. wheelindex = (wheelindex + 1) % 4;
  478. }
  479. fprintf( textout, temp );
  480. break;
  481. case PROG_BOTH_GRAPH:
  482. strcpy( temp, "File: [.........................]   Batch: [.........................]r" );
  483. x = (int) (fileDone*25/fileLen);
  484. memset( temp + 7, '*', x );
  485. x = (int) (batchDone*25/batchLen);
  486. memset( temp + 44, '*', x );
  487. if( x < 25 )
  488. {
  489. temp[7+x] = temp[44+x] = wheel[wheelindex];
  490. wheelindex = (wheelindex + 1) % 4;
  491. }
  492. fprintf( textout, temp );
  493. break;
  494. case PROG_BOTH_SAMPLES:
  495. fprintf( textout, "Samples encoded:%10d / %d      BATCH:%10d / %dr", 
  496.  (int) fileDone, (int) fileLen, (int) batchDone, (int) batchLen );
  497. break;
  498. case PROG_BOTH_ETA:
  499. fileEta = (int) (((float)(currTime - startFile)) / fileDone * (fileLen - fileDone) );
  500. batchEta = (int) (((float)(currTime - startBatch)) / batchDone * (batchLen - batchDone));
  501. fprintf( textout, "                >>> %02d:%02d:%02d <<<                >>> %02d:%02d:%02d <<<r",
  502.  fileEta/3600, (fileEta/60)%60, fileEta%60,
  503.  batchEta/3600, (batchEta/60)%60, batchEta%60 );
  504. fflush( textout );
  505. break;
  506. case PROG_FILE_RLEN:
  507. x = (int) (fileDone / psJob->sCodec.frequency);
  508. if( psJob->sCodec.mode != 3 )
  509. x /= 2;
  510. fprintf( textout, "Encoded runlength (current file): %02d:%02d:%02dr", 
  511.          x/3600, (x/60)%60, x%60 );
  512. break;
  513. case PROG_FILE_NORETURN:
  514. x = (int) (fileDone*70/fileLen);
  515. if( prevFileDone > x || prevFileDone == -1 )
  516. {
  517. prevFileDone = 0;
  518. fprintf( textout, " |----------------------------------------------------------------------|n |" );
  519. fflush( textout );
  520. }
  521. for( i = prevFileDone ; i < x ; i++ )
  522. {
  523. fprintf( textout, "#" );
  524. fflush( textout );
  525. }
  526. if( x == 70 )
  527. fprintf( textout, "|nn" );
  528. prevFileDone = x;
  529. break;
  530. }
  531. }
  532. /*____ setOutputDir() _______________________________________________________*/
  533. void setOutputDir( char * pPath )
  534. {
  535. int i;
  536. strcpy( outputDir, pPath );
  537. i = strlen( outputDir ) -1;
  538. if( outputDir[i] != DIRECTORY_SEPARATOR )
  539. {
  540. outputDir[i+1] = DIRECTORY_SEPARATOR;
  541. outputDir[i+2] = 0;
  542. }
  543. }
  544. /*____ readGlobalSwitches() ___________________________________________________*/
  545. argLink * readGlobalSwitches( argLink * pArgLink )
  546. {
  547. char arg[256];
  548. int x, y;
  549. for( ; pArgLink != NULL ; pArgLink = pArgLink->psNext )
  550. {
  551. strcpy( arg, pArgLink->pString );
  552. mystrupr( arg );
  553. if( arg[0] != '-' )
  554. return pArgLink;
  555. if( !strcmp( arg+1, "MONO" ) || !strcmp( arg+1, "DM" ) )
  556. wantedInputType = DOWNMIX_MONO;
  557. else if( !strcmp( arg+1, "CRC" ) )
  558. wantedCRC = TRUE;
  559. else if( !strcmp( arg+1, "PRIVATE" ) || !strcmp( arg+1, "P" ) )
  560. wantedPrivate = TRUE;
  561. else if( !strcmp( arg+1, "COPYRIGHT" ) || !strcmp( arg+1, "C" ) )
  562. wantedCopyright = TRUE;
  563. else if( !strcmp( arg+1, "ORIGINAL" ) )
  564. wantedOriginal = TRUE;
  565. else if( !strcmp( arg+1, "COPY" ) )
  566. wantedOriginal = FALSE;
  567. else if( !strcmp( arg+1, "DELETE" ) || !strcmp( arg+1, "DEL" ) )
  568. wantedDeleteSource = TRUE;
  569. else if( !strcmp( arg+1, "QUIT" ) || !strcmp( arg+1, "Q" ))
  570. wantedQuit = TRUE;
  571. else if( !strcmp( arg+1, "SWAP" ) )
  572. wantedInputType = INVERSE_STEREO;
  573. else if( !strcmp( arg+1, "LEFTMONO" ) || !strcmp( arg+1, "LM" ))
  574. wantedInputType = LEFT_CHANNEL_MONO;
  575. else if( !strcmp( arg+1, "RIGHTMONO" ) || !strcmp( arg+1, "RM" ))
  576. wantedInputType = RIGHT_CHANNEL_MONO;
  577. else if( !strcmp( arg+1, "QUIET" ) )
  578. wantedQuiet = TRUE;
  579. else if( !strcmp( arg+1, "NOCFG" ) )
  580. ; /* simply do nothing... */
  581. else if( strstr( arg+1, "PROGRESS=" ) == arg+1 )
  582. progType = atoi( arg+10 );
  583. else if( strstr( arg+1, "OUTDIR=" ) == arg+1 )
  584. setOutputDir( pArgLink->pString + 8 );
  585. else if( strstr( arg+1, "REFRESH=" ) == arg+1 )
  586. {
  587. wantedProgressBarRate = atoi( arg+9 );
  588. if( wantedProgressBarRate < 1 )
  589. wantedProgressBarRate = 1;
  590. }
  591. #ifdef  PRIO
  592. else if( strstr( arg+1, "PRIO=" ) == arg+1 )
  593. {
  594. strcpy( prioString, arg+6 );
  595. pPrioString = prioString;
  596. }
  597. #endif
  598. else if( !strcmp( arg+1, "RAWMONO" ) )
  599. rawChannels = 1;
  600. else if( !strcmp( arg+1, "RAWSTEREO" ) )
  601. rawChannels = 2;
  602. else if( !strcmp( arg+1, "RAWSIGNED" ) )
  603. rawSigned = TRUE;
  604. else if( !strcmp( arg+1, "RAWUNSIGNED" ) )
  605. rawSigned = FALSE;
  606. else if( strstr( arg+1, "RAWBITS=" ) == arg+1 )
  607. {
  608. rawBits = atoi( arg+9 );
  609. if( rawBits != 8 && rawBits != 16 )
  610. rawBits = 16;
  611. }
  612. else if( strstr( arg+1, "RAWFREQ=" ) == arg+1 )
  613. {
  614. rawFrequency = atoi( arg+9 );
  615. }
  616. else if( strstr( arg+1, "RAWBYTEORDER=" ) == arg+1 )
  617. {
  618. if( strstr( arg+14, "LITTLE" ) == arg+14 )
  619. rawByteorder = LITTLE_ENDIAN;
  620. if( strstr( arg+14, "BIG" ) == arg+14 )
  621. rawByteorder = BIG_ENDIAN;
  622. if( strstr( arg+14, "DEFAULT" ) == arg+14 )
  623. rawByteorder = BYTEORDER;
  624. }
  625. else if( strstr( arg+1, "RAWCHANNELS=" ) == arg+1 )
  626. {
  627. rawChannels = atoi( arg+13 );
  628. if( rawChannels != 1 && rawChannels != 2 )
  629. rawChannels = 2;
  630. }
  631. else if( !strcmp( arg+1, "BR" ) )
  632. {
  633. pArgLink = pArgLink->psNext;
  634. if( pArgLink == NULL )
  635. return NULL;
  636. wantedBitrate = atoi( pArgLink->pString );
  637. if( wantedBitrate > 1000 )
  638. wantedBitrate /= 1000;
  639. }
  640. else
  641. {
  642. y = 0;
  643. for( x = 1 ; arg[x] >= '0' && arg[x] <= '9' ; x++ )
  644. y = y * 10 + (arg[x] - '0');
  645. if( arg[x] == 0 )
  646. {
  647. wantedBitrate = y;
  648. if( wantedBitrate > 1000 )
  649. wantedBitrate /= 1000;
  650. }
  651. else
  652. return pArgLink;
  653. }
  654. }
  655. return  pArgLink;
  656. }
  657. /*____ readLocalSwitches() ___________________________________________________*/
  658. argLink * readLocalSwitches( argLink * pArgLink, Job * psJob )
  659. {
  660. char arg[256];
  661. int x, y;
  662. for( ; pArgLink != NULL ; pArgLink = pArgLink->psNext )
  663. {
  664. strcpy( arg, pArgLink->pString );
  665. mystrupr( arg );
  666. if( arg[0] != '-' )
  667. return pArgLink;
  668. if( !strcmp( arg+1, "MONO" ) || !strcmp( arg+1, "DM" ) )
  669. {
  670. psJob->sInput.outputType = DOWNMIX_MONO;
  671. psJob->sCodec.mode = 3;
  672. }
  673. else if( !strcmp( arg+1, "CRC" ) )
  674. psJob->sCodec.fCRC = TRUE;
  675. else if( !strcmp( arg+1, "PRIVATE" ) || !strcmp( arg+1, "P" ) )
  676. psJob->sCodec.fPrivate = TRUE;
  677. else if( !strcmp( arg+1, "COPYRIGHT" ) || !strcmp( arg+1, "C" ) )
  678. psJob->sCodec.fCopyright = TRUE;
  679. else if( !strcmp( arg+1, "ORIGINAL" ) )
  680. psJob->sCodec.fOriginal = TRUE;
  681. else if( !strcmp( arg+1, "COPY" ) )
  682. psJob->sCodec.fOriginal = FALSE;
  683. else if( !strcmp( arg+1, "DELETE" ) || !strcmp( arg+1, "DEL" ) )
  684. psJob->fDeleteSource = TRUE;
  685. else if( !strcmp( arg+1, "SWAP" ) )
  686. {
  687. if( psJob->sInput.fReadStereo == TRUE )
  688. {
  689. psJob->sInput.outputType = INVERSE_STEREO;
  690. psJob->sCodec.mode = 3;
  691. }
  692. }
  693. else if( !strcmp( arg+1, "LEFTMONO" ) || !strcmp( arg+1, "LM" ))
  694. {
  695. if( psJob->sInput.fReadStereo == TRUE )
  696. {
  697. psJob->sInput.outputType = LEFT_CHANNEL_MONO;
  698. psJob->sCodec.mode = 3;
  699. }
  700. }
  701. else if( !strcmp( arg+1, "RIGHTMONO" ) || !strcmp( arg+1, "RM" ))
  702. {
  703. if( psJob->sInput.fReadStereo == TRUE )
  704. {
  705. psJob->sInput.outputType = RIGHT_CHANNEL_MONO;
  706. psJob->sCodec.mode = 3;
  707. }
  708. }
  709. else if( !strcmp( arg+1, "RAWMONO" ) )
  710. {
  711. if( psJob->sInput.filetype == RAW )
  712. psJob->sInput.fReadStereo = FALSE;
  713. }
  714. else if( !strcmp( arg+1, "RAWSTEREO" ) )
  715. {
  716. if( psJob->sInput.filetype == RAW )
  717. psJob->sInput.fReadStereo = TRUE;
  718. }
  719. else if( !strcmp( arg+1, "RAWSIGNED" ) )
  720. {
  721. if( psJob->sInput.filetype == RAW )
  722. psJob->sInput.fSign = TRUE;
  723. }
  724. else if( !strcmp( arg+1, "RAWUNSIGNED" ) )
  725. {
  726. if( psJob->sInput.filetype == RAW )
  727. psJob->sInput.fSign = FALSE;
  728. }
  729. else if( strstr( arg+1, "RAWBITS=" ) == arg+1 )
  730. {
  731. if( psJob->sInput.filetype == RAW )
  732. {
  733. psJob->sInput.bits = atoi( arg+9 );
  734. if( psJob->sInput.bits != 8 && psJob->sInput.bits != 16 )
  735. psJob->sInput.bits = 16;
  736. }
  737. }
  738. else if( strstr( arg+1, "RAWFREQ=" ) == arg+1 )
  739. {
  740. if( psJob->sInput.filetype == RAW )
  741. psJob->sInput.freq = atoi( arg+9 );
  742. }
  743. else if( strstr( arg+1, "RAWBYTEORDER=" ) == arg+1 )
  744. {
  745. if( psJob->sInput.filetype == RAW )
  746. {
  747. if( strstr( arg+14, "LITTLE" ) == arg+14 )
  748. psJob->sInput.byteorder = LITTLE_ENDIAN;
  749. if( strstr( arg+14, "BIG" ) == arg+14 )
  750. psJob->sInput.byteorder = BIG_ENDIAN;
  751. if( strstr( arg+14, "DEFAULT" ) == arg+14 )
  752. psJob->sInput.byteorder = BYTEORDER;
  753. }
  754. }
  755. else if( strstr( arg+1, "RAWCHANNELS=" ) == arg+1 )
  756. {
  757. if( psJob->sInput.filetype == RAW )
  758. {
  759. psJob->sInput.fReadStereo = atoi( arg+13 )-1;
  760. if( psJob->sInput.fReadStereo != FALSE && psJob->sInput.fReadStereo != TRUE )
  761. psJob->sInput.fReadStereo = TRUE;
  762. }
  763. }
  764. else if( !strcmp( arg+1, "BR" ) )
  765. {
  766. pArgLink = pArgLink->psNext;
  767. if( pArgLink == NULL )
  768. return pArgLink;
  769. psJob->sCodec.bitrate = atoi( pArgLink->pString );
  770. if( psJob->sCodec.bitrate > 1000 )
  771. {
  772. psJob->sCodec.bitrate /= 1000;
  773. wantedQuit = TRUE;
  774. }
  775. }
  776. else if( !strcmp( arg+1, "HQ" ) )
  777. {
  778. wantedQuit = TRUE; /* Dummy for l3enc support */
  779. }
  780. else
  781. {
  782. y = 0;
  783. for( x = 1 ; arg[x] >= '0' && arg[x] <= '9' ; x++ )
  784. y = y * 10 + (arg[x] - '0');
  785. if( arg[x] == 0 )
  786. {
  787. psJob->sCodec.bitrate = y;
  788. if( psJob->sCodec.bitrate > 1000 )
  789. psJob->sCodec.bitrate /= 1000;
  790. }
  791. else
  792. return pArgLink;
  793. }
  794. }
  795. return  pArgLink;
  796. }
  797. /*____ validateJobs() _________________________________________________________*/
  798. int validateJobs( Job * psJob )
  799. {
  800. static  int     aValidBitrates[14] = { 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 };
  801. int i;
  802. int fOk = TRUE;
  803. while( psJob != NULL && fOk )
  804. {
  805. fOk = FALSE;
  806. for( i = 0 ; i < 14 ; i++ )
  807. if( wantedBitrate == aValidBitrates[i] )
  808. fOk = TRUE;
  809. psJob = psJob->psNext;
  810. }
  811. if( fOk )
  812. return TRUE;
  813. fprintf( textout, "ERROR: %d is not a valid bitrate!nn", wantedBitrate );
  814. fprintf( textout, "Valid bitrates are:nn" );
  815. for( i = 0 ; i < 13 ; i++ )
  816. fprintf( textout, "%d, ", aValidBitrates[i] );
  817. fprintf( textout, "and %d kBit.n", aValidBitrates[13] );
  818. return  FALSE;
  819. }
  820. /*____ printUsage() ___________________________________________________________*/
  821. int     printUsage( void )
  822. {
  823. fprintf( textout, "Usage: bladeenc [global switches] input1 [output1 [switches]] input2 ...n" );
  824. fprintf( textout, "n" );
  825. fprintf( textout, "General switches:n" );
  826. fprintf( textout, "  -[kbit], -br [kbit]  Set MP3 bitrate. Default is 128 (64 for mono output).n" );
  827. fprintf( textout, "  -crc                 Include checksum data in MP3 file.n" );
  828. fprintf( textout, "  -delete, -del        Delete sample after successful encoding.n" );
  829. fprintf( textout, "  -private, -p         Set the private-flag in the output file.n" );
  830. fprintf( textout, "  -copyright, -c       Set the copyright-flag in the output file.n" );
  831. fprintf( textout, "  -copy                Clears the original-flag in the output file.n" );
  832. fprintf( textout, "  -mono, -dm           Produce mono MP3 files by combining stereo channels.n" );
  833. fprintf( textout, "  -leftmono, -lm       Produce mono MP3 files from left stereo channel only.n" );
  834. fprintf( textout, "  -rightmono, -rm      Produce mono MP3 files from right stereo channel only.n" );
  835. fprintf( textout, "  -swap                Swap left and right stereo channels.n" );
  836. fprintf( textout, "  -rawfreq=[freq]      Specify frequency for RAW samples. Default is 44100.n" );
  837. fprintf( textout, "  -rawbits=[bits]      Specify bits per channel for RAW samples. Default is 16.n" );
  838. fprintf( textout, "  -rawmono             Specifies that RAW samples are in mono, not stereo.n" );
  839.     fprintf( textout, "  -rawstereo           Specifies that RAW samples are in stereo (default).n" );
  840. fprintf( textout, "  -rawsigned           Specifies that RAW samples are signed (default).n" );
  841. fprintf( textout, "  -rawunsigned         Specifies that RAW samples are unsigned.n" );
  842. #ifdef PAUSE_25_LINES
  843. fprintf( textout, "Press ENTER to continue..." );
  844. fflush( textout );
  845. be_getch();
  846. fprintf( textout, "n" );
  847. #endif
  848. fprintf( textout, "  -rawbyteorder=[order]Specifies byteorder for RAW samples, LITTLE or BIG.n" );
  849. fprintf( textout, "  -rawchannels=[1/2]   Specifies number of channels for RAW samples. Doesn" );
  850. fprintf( textout, "                       the same as -rawmono and -rawstereo respectively.n" );
  851. fprintf( textout, "n" );
  852. fprintf( textout, "Global only switches:n" );
  853. fprintf( textout, "  -quit, -q            Quit without waiting for keypress when finished.n" );
  854. fprintf( textout, "  -outdir=[dir]        Save MP3 files in specified directory.n" );
  855. fprintf( textout, "  -quiet               Disable screen output.n" );
  856. fprintf( textout, "  -nocfg               Don't take settings from the config-file.n" );
  857. #ifdef  PRIO
  858. fprintf( textout, "  -prio=[prio]         Sets the task priority for BladeEnc. Valid settings aren" );
  859. fprintf( textout, "                       HIGHEST, HIGHER, NORMAL, LOWER, LOWEST(default) and IDLEn" );
  860. #endif
  861. fprintf( textout, "  -refresh=[rate]      Refresh rate for progress indicator. 1=fastest, 2=def.n" );
  862. fprintf( textout, "  -progress=[0-8]      Which progress indicator to use. 0=Off, 1=Default.n" );
  863. fprintf( textout, "n" );
  864. fprintf( textout, "Input/output files can be replaced with STDIN and STDOUT respectively.n" );
  865. #ifdef  DRAG_DROP
  866. fprintf( textout, "To make a normal 128kBit MP3, just drag-n-drop your WAV onto the BladeEnc icon.n" );
  867. #endif
  868. fprintf( textout, "n" );
  869. return  TRUE;
  870. }
  871. /*____ addCommandlineJob() ____________________________________________________*/
  872. int addCommandlineJob( argLink ** ppArgLink )
  873. {
  874. char temp[256];
  875. Job * psOp, * psTemp;
  876. int x;
  877. argLink * pArgLink;
  878. pArgLink = * ppArgLink;
  879. psOp = (Job *) malloc( sizeof( Job ) );
  880. psOp->psNext = NULL;
  881. /* Open Input File              */
  882. strcpy( temp, pArgLink->pString );
  883. mystrupr( temp );
  884. if( strcmp( temp, "STDIN" ) == 0 )
  885. {
  886. if( !fPreparedSTDIN )
  887. {
  888. prepStdin();
  889. fPreparedSTDIN = TRUE;
  890. }
  891. strcpy( psOp->sourceFilename, "Standard input stream" );
  892. x = openInput( &psOp->sInput, NULL );
  893. }
  894. else
  895. {
  896. strcpy( psOp->sourceFilename, pArgLink->pString );
  897. x = openInput( &psOp->sInput, pArgLink->pString );
  898. }
  899. if( x != TRUE )
  900. {
  901. switch( psOp->sInput.errcode )
  902. {
  903. case -1:
  904. fprintf( textout, "ERROR: '%s' is not a WAV or AIFF file!n", psOp->sourceFilename );
  905. break;
  906. case -2:
  907. fprintf( textout, "ERROR: Couldn't open '%s'!n", psOp->sourceFilename );
  908. break;
  909. case -3:
  910. fprintf( textout, "ERROR: Unexpected end of file '%s'!n", psOp->sourceFilename );
  911. break;
  912. case -5:
  913. fprintf( textout, "ERROR: Necessary chunk missing in '%s'!n", psOp->sourceFilename );
  914. break;
  915. case -6:
  916. fprintf( textout, "ERROR: Sample '%s' is of an unknown subtype!n", psOp->sourceFilename );
  917. break;
  918. default:
  919. fprintf( textout, "ERROR: Unknown error while opening '%s'!n", psOp->sourceFilename );
  920. }
  921. free( psOp );
  922. return  FALSE;
  923. }
  924. /* If RAW, set default values */
  925. if( psOp->sInput.filetype == RAW )
  926. {
  927. psOp->sInput.freq = rawFrequency;
  928. psOp->sInput.outputFreq = rawFrequency;
  929. psOp->sInput.fReadStereo = rawChannels-1;
  930. psOp->sInput.bits = rawBits;
  931. psOp->sInput.fSign = rawSigned;
  932. psOp->sInput.byteorder = rawByteorder;
  933. }
  934. /* */
  935. if( !psOp->sInput.fReadStereo && (wantedInputType == STEREO || wantedInputType == INVERSE_STEREO) )
  936. psOp->sInput.outputType = DOWNMIX_MONO;
  937. else
  938. psOp->sInput.outputType = wantedInputType;
  939. /* Set sCodec.mode (MONO or STEREO) */
  940. if( psOp->sInput.outputType == DOWNMIX_MONO || psOp->sInput.outputType == LEFT_CHANNEL_MONO
  941.         || psOp->sInput.outputType == RIGHT_CHANNEL_MONO )
  942. psOp->sCodec.mode = 3;                                                   /* Force to mono... */
  943. else
  944. {
  945. psOp->sCodec.mode = 0;
  946. }
  947. /* Set frequency */
  948. if( psOp->sInput.freq != 44100 && psOp->sInput.freq != 48000
  949.         && psOp->sInput.freq != 32000 )
  950. {
  951. fprintf( textout, "ERROR: Sample '%s' is not in 32, 44.1 or 48 kHz!n", psOp->sourceFilename );
  952. closeInput( &(psOp->sInput) );
  953. free( psOp );
  954. return  FALSE;
  955. }
  956. psOp->sCodec.frequency = psOp->sInput.freq;
  957. /* Set bitrate */
  958. if( wantedBitrate == -1 )
  959. {
  960. if( psOp->sCodec.mode == 3 )
  961. wantedBitrate = 64;
  962. else
  963. wantedBitrate = 128;
  964. }
  965. else
  966. psOp->sCodec.bitrate = wantedBitrate;
  967. /* Set other parameters */
  968. psOp->sCodec.bitrate = wantedBitrate;
  969. psOp->sCodec.fPrivate = wantedPrivate;
  970. psOp->sCodec.fCRC = wantedCRC;
  971. psOp->sCodec.fCopyright = wantedCopyright;
  972. psOp->sCodec.fOriginal = wantedOriginal;
  973. psOp->fDeleteSource = wantedDeleteSource;
  974. /* Set unsupported parameters */
  975. psOp->sCodec.emphasis = 0;
  976. pArgLink = pArgLink->psNext;
  977. /* Check for output specification and set output name */
  978. psOp->outputFilename[0] = 0;
  979. if( pArgLink != NULL )
  980. {
  981. strcpy( temp, pArgLink->pString );
  982. mystrupr( temp );
  983. if( !strcmp( temp, "STDOUT" ) )
  984. {
  985. wantedSTDOUT = TRUE;
  986. strcpy( psOp->outputFilename, "STDOUT" );
  987. pArgLink = pArgLink->psNext;
  988. }
  989. else if( strlen( temp ) >= 4 && !strcmp( temp+strlen(temp)-4, ".MP3" ) )
  990. {
  991. strcpy( psOp->outputFilename, pArgLink->pString );
  992. pArgLink = pArgLink->psNext;
  993. }
  994. }
  995. /* Generate output name if not allready set */
  996. if( psOp->outputFilename[0] == 0 )
  997. {
  998. if( outputDir[0] != 0 )
  999. {
  1000. strcpy( psOp->outputFilename, outputDir );
  1001. strcpy( temp, psOp->sourceFilename );
  1002. x = strlen( temp );
  1003. while( temp[x] != '.' && x >=0 && temp[x] != DIRECTORY_SEPARATOR )
  1004. x--;
  1005. if( temp[x] == DIRECTORY_SEPARATOR )
  1006. x = strlen(temp);
  1007. if( x >= 0 )
  1008. strcpy( temp + x, ".mp3" );
  1009. else
  1010. {
  1011. x = strlen( temp );
  1012. strcat( temp, ".mp3" );
  1013. }
  1014. while( x >= 0 && temp[x] != '\' && temp[x] != '/' && temp[x] != ':' )
  1015. x--;
  1016. x++;
  1017. strcat( psOp->outputFilename, temp + x );
  1018. }
  1019. else
  1020. {
  1021. strcpy( temp, psOp->sourceFilename );
  1022. x = strlen( temp );
  1023. while( temp[x] != '.' && x >=0 && temp[x] != DIRECTORY_SEPARATOR )
  1024. x--;
  1025. if( temp[x] == DIRECTORY_SEPARATOR )
  1026. x = strlen(temp);
  1027. if( x >= 0 )
  1028. strcpy( temp + x, ".mp3" );
  1029. else
  1030. strcat( temp, ".mp3" );
  1031. strcpy( psOp->outputFilename, temp );
  1032. }
  1033. }
  1034. /* Read local switches */
  1035. pArgLink = readLocalSwitches( pArgLink, psOp );
  1036. /* Put this Job in the batch */
  1037. if( psJobQueue == NULL )
  1038. psJobQueue = psOp;
  1039. else
  1040. {
  1041. psTemp = psJobQueue;
  1042. while( psTemp->psNext != NULL )
  1043. psTemp = psTemp->psNext;
  1044. psTemp->psNext = psOp;
  1045. }
  1046. * ppArgLink = pArgLink;
  1047. return  TRUE;
  1048. }
  1049. /*____ clearJobQueue() ________________________________________________________*/
  1050. int     clearJobQueue( void )
  1051. {
  1052. while( psJobQueue != NULL )
  1053. removeJobQueueEntry( psJobQueue );
  1054. return  TRUE;
  1055. }
  1056. /*____ removeQueueEntry() _____________________________________________________*/
  1057. int removeJobQueueEntry( Job * psJob )
  1058. {
  1059. Job     * psPrev;
  1060. /* Unlink specified entry */
  1061. if( psJob == psJobQueue )
  1062. psJobQueue = psJob->psNext;
  1063. else
  1064. {
  1065. psPrev = psJobQueue;
  1066. while( psPrev->psNext != psJobQueue && psPrev->psNext != NULL )
  1067. psPrev = psPrev->psNext;
  1068. if( psPrev->psNext == NULL )
  1069. return  FALSE;
  1070. psPrev->psNext = psJob->psNext;
  1071. }
  1072. /* Close open file, free the entry and return. */
  1073. closeInput( &psJob->sInput );
  1074. free( psJob );
  1075. return  TRUE;
  1076. }