NeroAPITest.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281
  1. /******************************************************************************
  2. |* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  3. |* ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  4. |* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  5. |* PARTICULAR PURPOSE.
  6. |*
  7. |* Copyright 1995-2005 Nero AG. All Rights Reserved.
  8. |*-----------------------------------------------------------------------------
  9. |* NeroSDK / Samples
  10. |*
  11. |* PROGRAM: NeroAPITest.cpp
  12. |*
  13. |* PURPOSE: This command line program demonstrates many things that Nero API can do:
  14. |* - read information about a CD
  15. |* - burn audio CD
  16. |* - burn ISO CD
  17. |* - burn mixed mode CD
  18. |* - burn Video and Super Video CD
  19. |* - burn Nero CD image
  20. |* - extract CDA tracks
  21. ******************************************************************************/
  22. #include "NeroAPIGlue.h"
  23. #include <winbase.h>
  24. #include <stdlib.h>
  25. #include <sys/stat.h>
  26. #include <io.h>
  27. #include <stdio.h>
  28. #include <signal.h>
  29. #include "NeroISODemo.h"
  30. // import the implementation of NeroWaitCDTexts()
  31. #define NERO_WAITCD_TEXTS
  32. #include "NeroUserDialog.h"
  33. #undef NERO_WAITCD_TEXTS
  34. /*
  35. ** function declarations
  36. */
  37. static void NeroError (char *action); /* display Nero error and exit */
  38. /* for the settings */
  39. static BOOL NERO_CALLBACK_ATTR IdleCallback (void *pUserData);
  40. static NeroUserDlgInOut NERO_CALLBACK_ATTR UserDialog (void *pUserData, NeroUserDlgInOut type, void *data);
  41. /* for the progress display */
  42. static BOOL NERO_CALLBACK_ATTR ProgressCallback (void *pUserData, DWORD dwProgressInPercent);
  43. static BOOL NERO_CALLBACK_ATTR AbortedCallback (void *pUserData);
  44. static void NERO_CALLBACK_ATTR AddLogLine (void *pUserData, NERO_TEXT_TYPE type, const char *text);
  45. static void NERO_CALLBACK_ATTR SetPhaseCallback (void *pUserData, const char *text);
  46. static void NERO_CALLBACK_ATTR DisableAbortCallback (void *pUserData,BOOL abortEnabled);
  47. static void NERO_CALLBACK_ATTR SetMajorPhaseCallback(void *pUserData,NERO_MAJOR_PHASE phase,void *reserved);
  48. /* IO callbacks - both take a FILE * as user data */
  49. static DWORD NERO_CALLBACK_ATTR WriteIOCallback (void *pUserData, BYTE *pBuffer, DWORD dwLen);
  50. static DWORD NERO_CALLBACK_ATTR ReadIOCallback (void *pUserData, BYTE *pBuffer, DWORD dwLen);
  51. static BOOL NERO_CALLBACK_ATTR EOFCallback (void *pUserData);
  52. static BOOL NERO_CALLBACK_ATTR ErrorCallback (void *pUserData);
  53. /* parameter parsing */
  54. typedef enum {
  55. WAV,
  56. MP3,
  57. WMA,
  58. PCM,
  59. MPEG,
  60. JPEG,
  61. AVI,
  62. IMAGE,
  63. UNKNOWN
  64. } FileType_t;
  65. /*
  66. ** global resources
  67. */
  68. NERO_DEVICEHANDLE NeroDeviceHandle;
  69. NERO_SCSI_DEVICE_INFOS *NeroDeviceInfos;
  70. NERO_CD_INFO *NeroCDInfo;
  71. #define DUMMY_USER_DATA &NeroSettings /* &NeroSettings as user data is only used as illustration */
  72. NERO_SETTINGS NeroSettings =
  73. {
  74. "NeroFiles", /* look for DLLs in sub directory */
  75. NULL,NULL,
  76. "Nero.txt",
  77. { IdleCallback, DUMMY_USER_DATA },
  78. { UserDialog, DUMMY_USER_DATA }
  79. };
  80. NERO_PROGRESS NeroProgress =
  81. {
  82. ProgressCallback,
  83. AbortedCallback,
  84. AddLogLine,
  85. SetPhaseCallback,
  86. DUMMY_USER_DATA,
  87. DisableAbortCallback,
  88. SetMajorPhaseCallback
  89. };
  90. /*
  91. ** CTRL-C handling => remember and return TRUE in IdleCallback to make API abort
  92. */
  93. BOOL Aborted = FALSE;
  94. static void __cdecl SigCtrlC (int sig)
  95. {
  96. Aborted = TRUE;
  97. }
  98. /* free resources and exit */
  99. static void Exit (int ret)
  100. {
  101. /* all of these functions may be called even if NeroAPIGlueInit() failed. */
  102. NeroCloseDevice (NeroDeviceHandle);
  103. NeroFreeMem (NeroDeviceInfos);
  104. NeroFreeMem (NeroCDInfo);
  105. NeroClearErrors ();
  106. NeroDone ();
  107. NeroAPIGlueDone();
  108. puts ("\npress RETURN to exit");
  109. getchar ();
  110. exit (ret);
  111. }
  112. static void Usage (char *descr, void *descr_param)
  113. {
  114. if (descr) {
  115. printf (descr, descr_param);
  116. puts ("");
  117. }
  118. puts ("Usage: --listdrives\n"
  119. " --cdinfo --drivename 'xxx'\n"
  120. " --write --drivename 'xxx' [--real] [--TAO] [--bup] [--artist 'artist'] [--title 'title'] [--speed x] [--pause x] [--audioinindex0] 'audio file1' 'audio file2' ... [--cdextra] [--iso 'volume name'] [--iso-no-joliet] [--iso-mode2] 'file/dir1' 'file/dir2' ...\n"
  121. " --write --drivename 'xxx' --videocd [--real] [--TAO] [--bup] [--speed x] 'mpeg/jpeg file1' ...\n"
  122. " --write --drivename 'xxx' --svideocd [--real] [--TAO] [--bup] [--speed x] 'mpeg/jpeg file1' ...\n"
  123. " --write --drivename 'xxx' --image [--real] [--TAO] [--bup] [--speed x] 'nrg file'\n"
  124. " --read --drivename 'xxx' --'xy' 'file1' --'xy' 'file2' ...\n"
  125. " --erase [--entire] --drivename 'xxx'\n"
  126. " --eject --drivename 'xxx'\n"
  127. " --load --drivename 'xxx'\n"
  128. "\n"
  129. "'xy' = track number\n"
  130. "'file' = file name including suffix; only .wav and .pcm are supported for audio\n"
  131. "'dir/file' = after --iso: file or or directory tree to be added in the root directory\n"
  132. );
  133. Exit (10);
  134. }
  135. int __cdecl main(int argc, char* argv[])
  136. {
  137. /* parse args */
  138. BOOL listdrives = FALSE,
  139. cdinfo = FALSE,
  140. write = FALSE,
  141. read = FALSE,
  142. real = FALSE,
  143. CDExtra = FALSE,
  144. TAO = FALSE,
  145. data = FALSE,
  146. videocd = FALSE,
  147. svideocd = FALSE,
  148. image = FALSE,
  149. speedtest = FALSE,
  150. eject = FALSE,
  151. no_eject = FALSE,
  152. load = FALSE,
  153. erase = FALSE,
  154. entire = FALSE,
  155. bup = FALSE,
  156. dvd = FALSE,
  157. verify = FALSE,
  158. listspeed = FALSE,
  159. bAudioInIndex0 = FALSE;
  160. int writebuffersize=0,iPauseLength=-1;
  161. float speed = 0; /* maximum */
  162. char *drivename = NULL;
  163. char *artist = NULL, *title = NULL, *pPauseLenStr = NULL;
  164. char *files[99]; /* maximum number of tracks per CD */
  165. char *tempdir=NULL;
  166. unsigned int tracks[99];
  167. FileType_t type[99];
  168. unsigned int num_files = 0;
  169. unsigned int i;
  170. CDemoIsoTrack IsoTrack;
  171. /* skip program name */
  172. argc--;
  173. argv++;
  174. while (argc > 0) {
  175. BOOL had_parameter = FALSE; /* this argument had a parameter */
  176. if (!strncmp(*argv, "--", 2)) {
  177. /* option */
  178. if (!stricmp(*argv, "--listdrives")) {
  179. listdrives = TRUE;
  180. } else if (!stricmp(*argv, "--cdinfo")) {
  181. cdinfo = TRUE;
  182. } else if (!stricmp(*argv, "--drivename")) {
  183. if (argc <= 1) {
  184. Usage ("no drive name specified", 0);
  185. }
  186. drivename = argv[1];
  187. had_parameter = TRUE;
  188. } else if (!stricmp(*argv, "--write")) {
  189. write = TRUE;
  190. } else if (!stricmp(*argv, "--real")) {
  191. real = TRUE;
  192. } else if (!stricmp(*argv, "--speedtest"))
  193. {
  194. speedtest = TRUE;
  195. } else if (!stricmp(*argv, "--TAO")) {
  196. TAO = TRUE;
  197. } else if (!stricmp(*argv, "--bup"))
  198. {
  199. bup = TRUE;
  200. } else if (!stricmp(*argv, "--read"))
  201. {
  202. read = TRUE;
  203. } else if (!stricmp(*argv, "--speed")) {
  204. if (argc <= 1) {
  205. Usage ("missing argument for --speed", 0);
  206. }
  207. speed = atof (argv[1]);
  208. had_parameter = TRUE;
  209. } else if (!stricmp(*argv, "--artist"))
  210. {
  211. if (argc<=1)
  212. Usage("Missing argument for --artist", 0);
  213. artist=argv[1];
  214. had_parameter=TRUE;
  215. } else if (!stricmp(*argv, "--title"))
  216. {
  217. if (argc<=1)
  218. Usage("Missing argument for --title", 0);
  219. title=argv[1];
  220. had_parameter=TRUE;
  221. } else if (!stricmp(*argv, "--audioinindex0"))
  222. {
  223. bAudioInIndex0 = TRUE;
  224. } else if (!stricmp(*argv, "--pause"))
  225. {
  226. if(argc<=1)
  227. Usage("Missing argument for --pause", 0);
  228. pPauseLenStr=argv[1];
  229. had_parameter=TRUE;
  230. }
  231. else if (!stricmp(*argv, "--iso") || !stricmp(*argv, "--udf") || !stricmp(*argv, "--isoudf"))
  232. {
  233. data = TRUE;
  234. if (argc > 1) {
  235. IsoTrack.SetVolumeName (argv[1]);
  236. had_parameter = TRUE;
  237. }
  238. IsoTrack.SetISO(!stricmp(*argv, "--iso") || !stricmp(*argv, "--isoudf"));
  239. IsoTrack.SetUDF(!stricmp(*argv, "--udf") || !stricmp(*argv, "--isoudf"));
  240. }
  241. else if (!stricmp(*argv, "--dvd"))
  242. {
  243. dvd=TRUE;
  244. }
  245. else if (!stricmp(*argv, "--dvdvideo"))
  246. {
  247. dvd=TRUE;
  248. IsoTrack.SetReallocDVDVideoFiles(TRUE);
  249. }
  250. else if (!stricmp (*argv, "--iso-no-joliet")) {
  251. IsoTrack.SetJoliet (FALSE);
  252. } else if (!stricmp (*argv, "--iso-mode2")) {
  253. IsoTrack.SetMode2 (TRUE);
  254. } else if (!stricmp (*argv, "--cdextra")) {
  255. CDExtra = TRUE;
  256. } else if (!stricmp (*argv, "--videocd"))
  257. {
  258. videocd = TRUE;
  259. } else if (!stricmp (*argv, "--svideocd"))
  260. {
  261. svideocd = TRUE;
  262. } else if (!stricmp (*argv, "--image"))
  263. {
  264. image = TRUE;
  265. } else if (!stricmp (*argv, "--eject"))
  266. {
  267. eject = TRUE;
  268. } else if (!stricmp (*argv, "--no_eject"))
  269. {
  270. no_eject = TRUE;
  271. } else if (!stricmp (*argv, "--load"))
  272. {
  273. load = TRUE;
  274. } else if (!stricmp (*argv, "--erase"))
  275. {
  276. erase = TRUE;
  277. } else if (!stricmp (*argv, "--entire"))
  278. {
  279. entire = TRUE;
  280. } else if (!stricmp( *argv, "--writebuffersize"))
  281. {
  282. if (argc<=1)
  283. Usage("Missing buffer size",0);
  284. else
  285. {
  286. writebuffersize=atoi(argv[1])*1024;
  287. had_parameter = TRUE;
  288. }
  289. } else if (!stricmp( *argv, "--tempdir"))
  290. {
  291. if (argc<=1)
  292. Usage("Missing temp directory",0);
  293. else
  294. {
  295. tempdir=argv[1];
  296. had_parameter = TRUE;
  297. }
  298. } else if (!stricmp( *argv, "--verify"))
  299. {
  300. verify = TRUE;
  301. } else if (!stricmp( *argv, "--listspeed"))
  302. {
  303. listspeed = TRUE;
  304. }
  305. else if (atoi(&argv[0][2])) {
  306. /* file with track number */
  307. int track_number = atoi(&argv[0][2]);
  308. if (argc <= 1) {
  309. Usage ("no file specified after track number %ld", (void *)track_number);
  310. }
  311. if (num_files < sizeof(files) / sizeof(files[0])) {
  312. tracks[num_files] = track_number;
  313. files[num_files++] = argv[1];
  314. } else {
  315. Usage ("Number of files limited to 99.", 0);
  316. }
  317. had_parameter = TRUE;
  318. } else {
  319. Usage ("Unknown parameter %s", argv[0]);
  320. }
  321. } else {
  322. /* file - either ISO or audio */
  323. if (data) {
  324. IsoTrack.AddEntry (*argv);
  325. }
  326. else if (write)
  327. {
  328. if (num_files < sizeof(files) / sizeof(files[0])) {
  329. tracks[num_files] = 0;
  330. files[num_files++] = argv[0];
  331. } else {
  332. Usage ("Number of files limited to 99.", 0);
  333. }
  334. } else
  335. {
  336. Usage("",0);
  337. Exit(0);
  338. }
  339. }
  340. argc--;
  341. argv++;
  342. if (had_parameter) {
  343. argc--;
  344. argv++;
  345. }
  346. }
  347. /* verify args */
  348. if(TAO && bAudioInIndex0)
  349. Usage ("--TAO and --audioinindex0 are mutually exclusive", 0);
  350. if(pPauseLenStr != NULL)
  351. {
  352. iPauseLength = atoi(pPauseLenStr);
  353. if((iPauseLength<0) || (iPauseLength>7500))
  354. Usage ("invalid pause length specified (valid: 0-7500)", 0);
  355. }
  356. if(iPauseLength < 0) /* Pause length unspecified -> set it to the default pause length of 2 seconds */
  357. iPauseLength = 2 * 75;
  358. if(TAO && (iPauseLength!=2*75)) /* In TAO only default pause length is supported */
  359. {
  360. Usage ("a pause length other than 150 blocks is not supported in TAO mode", 0);
  361. }
  362. if (read && write) {
  363. Usage ("--read and --write are mutually exclusive", 0);
  364. }
  365. if (read || write) {
  366. if (!drivename) {
  367. Usage ("required drive name not specified", 0);
  368. }
  369. if (!num_files && !data) {
  370. Usage ("no files specified", 0);
  371. }
  372. unsigned int i;
  373. for (i = 0; i < num_files; i++) {
  374. char *ext = strrchr (files[i], '.');
  375. if (ext && !stricmp (ext, ".wav") && !videocd && !svideocd)
  376. {
  377. type[i] = WAV;
  378. } else if (ext && !stricmp (ext, ".mp3") && !videocd && !svideocd)
  379. {
  380. type[i] = MP3;
  381. } else if (ext && !stricmp (ext, ".wma") && !videocd && !svideocd)
  382. {
  383. type[i] = WMA;
  384. } else if (ext && !stricmp (ext, ".pcm") && !videocd && !svideocd)
  385. {
  386. type[i] = PCM;
  387. } else if (ext && (!stricmp (ext, ".mpg") || !stricmp (ext, ".mpeg")) && (videocd || svideocd))
  388. {
  389. type[i] = MPEG;
  390. } else if (ext && !stricmp (ext, ".avi") && (videocd || svideocd))
  391. {
  392. type[i] = AVI;
  393. } else if (ext && (!stricmp (ext, ".jpg") || !stricmp (ext, ".jpeg")) && (videocd || svideocd))
  394. {
  395. type[i] = JPEG;
  396. } else if (ext && (!stricmp (ext, ".nrg") || !stricmp (ext, ".iso") || !stricmp (ext, ".cue")) && image)
  397. {
  398. type[i] = IMAGE;
  399. }
  400. else {
  401. type[i] = UNKNOWN;
  402. Usage ("unknown file type %s", files[i]);
  403. }
  404. /* read needs track number */
  405. if (read && !tracks[i]) {
  406. Usage ("no track number specified for file %s", files[i]);
  407. }
  408. }
  409. }
  410. /* initialize */
  411. signal (SIGINT, SigCtrlC);
  412. if (!NeroAPIGlueConnect(NULL))
  413. {
  414. puts ("Cannot connect to NeroAPI");
  415. Exit (10);
  416. }
  417. WORD ver1, ver2, ver3, ver4;
  418. if (!NeroGetAPIVersionEx(&ver1,&ver2,&ver3,&ver4,NULL))
  419. {
  420. puts("Could not get NeroAPI version number");
  421. Exit(10);
  422. }
  423. printf ("Nero API version %d.%d.%d.%d\n\n",ver1,ver2,ver3,ver4);
  424. NEROAPI_INIT_ERROR initErr=NeroInit (&NeroSettings,NULL);
  425. switch (initErr)
  426. {
  427. case NEROAPI_INIT_OK:
  428. break;
  429. case NEROAPI_INIT_INVALID_ARGS:
  430. NeroError ("NeroInit() : invalid args");
  431. break;
  432. case NEROAPI_INIT_INVALID_SERIAL_NUM:
  433. NeroError ("NeroInit() : invalid serial number");
  434. break;
  435. case NEROAPI_INIT_DEMOVERSION_EXPIRED:
  436. NeroError ("NeroInit() : demo version has expired");
  437. break;
  438. case NEROAPI_INIT_CANNOT_LOCK:
  439. NeroError ("NeroInit() : cannot lock");
  440. break;
  441. default:
  442. case NEROAPI_INIT_UNSPECIFIED_ERROR:
  443. NeroError ("NeroInit() : unspecified error");
  444. }
  445. if (writebuffersize!=0)
  446. {
  447. NeroSetOption(NEROAPI_OPTION_WRITE_BUFFER_SIZE,&writebuffersize);
  448. }
  449. NeroDeviceInfos = NeroGetAvailableDrivesEx (dvd ? MEDIA_DVD_ANY : MEDIA_CD,NULL);
  450. if (!NeroDeviceInfos) {
  451. NeroError ("NeroGetAvailableDrives()");
  452. }
  453. NERO_SCSI_DEVICE_INFO *pSelectedDeviceInfo;
  454. if (drivename) {
  455. for (i = 0; i < NeroDeviceInfos->nsdisNumDevInfos; i++)
  456. {
  457. char driveLetter=NeroDeviceInfos->nsdisDevInfos[i].nsdiDriveLetter ? NeroDeviceInfos->nsdisDevInfos[i].nsdiDriveLetter : '?';
  458. if (!stricmp(drivename, NeroDeviceInfos->nsdisDevInfos[i].nsdiDeviceName)
  459. || (strlen(drivename)==1 && toupper(drivename[0])==toupper(driveLetter)))
  460. {
  461. NeroDeviceHandle = NeroOpenDevice (&NeroDeviceInfos->nsdisDevInfos[i]);
  462. pSelectedDeviceInfo=&NeroDeviceInfos->nsdisDevInfos[i];
  463. if (!NeroDeviceHandle)
  464. {
  465. NeroError (drivename);
  466. }
  467. break;
  468. }
  469. }
  470. if (!NeroDeviceHandle) {
  471. printf ("Drive %s not found, available are:\n", drivename);
  472. listdrives = TRUE;
  473. }
  474. }
  475. if (listdrives)
  476. {
  477. printf ("Drive: adapter # (type), ID\n"
  478. "-------------------------\n");
  479. for (i = 0; i < NeroDeviceInfos->nsdisNumDevInfos; i++)
  480. {
  481. char bufUnderrunProtName[128]="";
  482. char *str;
  483. if (NeroDeviceInfos->nsdisDevInfos[i].nsdiCapabilities&NSDI_BUF_UNDERRUN_PROT)
  484. {
  485. sprintf(bufUnderrunProtName," (%s)",NeroDeviceInfos->nsdisDevInfos[i].nsdiBufUnderrunProtName);
  486. if (NeroDeviceInfos->nsdisDevInfos[i].nsdiMandatoryBUPSpeed)
  487. sprintf(bufUnderrunProtName+strlen(bufUnderrunProtName)," (recommanded when burning at %dX or faster)",NeroDeviceInfos->nsdisDevInfos[i].nsdiMandatoryBUPSpeed);
  488. }
  489. printf ("%c. %s: %d (%s), %d, %s%s (%s) (%d KB buffer)\n",
  490. NeroDeviceInfos->nsdisDevInfos[i].nsdiDriveLetter ? NeroDeviceInfos->nsdisDevInfos[i].nsdiDriveLetter : '?',
  491. NeroDeviceInfos->nsdisDevInfos[i].nsdiDeviceName,
  492. NeroDeviceInfos->nsdisDevInfos[i].nsdiHostAdapterNo,
  493. NeroDeviceInfos->nsdisDevInfos[i].nsdiHostAdapterName,
  494. NeroDeviceInfos->nsdisDevInfos[i].nsdiDeviceID,
  495. NeroDeviceInfos->nsdisDevInfos[i].nsdiCapabilities&NSDI_ALLOWED ? "" : "(Not allowed) ",
  496. bufUnderrunProtName,
  497. str=NeroGetTypeNameOfMedia(NeroDeviceInfos->nsdisDevInfos[i].nsdiMediaSupport,","),
  498. NeroDeviceInfos->nsdisDevInfos[i].nsdiDriveBufferSize);
  499. NeroFreeMem(str);
  500. }
  501. puts ("");
  502. Exit(0);
  503. }
  504. if (!NeroDeviceHandle)
  505. {
  506. Usage ("drive name required", 0);
  507. Exit (0);
  508. }
  509. if (listspeed)
  510. {
  511. printf("List of possible speed:\n");
  512. for(int i=0;i<(int)pSelectedDeviceInfo->nsdiWriteSpeeds.nsiNumSupportedSpeeds;i++)
  513. printf("%.1fX (%d KB/s)\n",(float)pSelectedDeviceInfo->nsdiWriteSpeeds.nsiSupportedSpeedsKBs[i]/pSelectedDeviceInfo->nsdiWriteSpeeds.nsiBaseSpeedKBs
  514. ,pSelectedDeviceInfo->nsdiWriteSpeeds.nsiSupportedSpeedsKBs[i]);
  515. }
  516. if (load)
  517. {
  518. NeroEjectLoadCD(NeroDeviceHandle,FALSE);
  519. }
  520. if (erase)
  521. { // Erase CDRW
  522. NEROAPI_CDRW_ERASE_MODE mode=NEROAPI_ERASE_QUICK; // Default is quickly
  523. int time;
  524. if (entire) mode=NEROAPI_ERASE_ENTIRE;
  525. time=NeroGetCDRWErasingTime(NeroDeviceHandle,mode);
  526. if (time==-1)
  527. NeroError("No CD inserted");
  528. else if (time==-2)
  529. NeroError("This CD recorder doesn't support CDRW");
  530. else if (time==-3)
  531. NeroError("This media is not rewritable");
  532. printf("Erasing CDRW. This will take %d seconds.\n",time);
  533. int err=NeroEraseCDRW(NeroDeviceHandle,mode);
  534. if (err)
  535. NeroError("Error erasing the CDRW");
  536. }
  537. if (eject)
  538. {
  539. NeroEjectLoadCD(NeroDeviceHandle,TRUE);
  540. }
  541. if (cdinfo || read) {
  542. NeroCDInfo = NeroGetCDInfo (NeroDeviceHandle, NGCDI_READ_CD_TEXT|NGCDI_READ_ISRC);
  543. if (!NeroCDInfo) {
  544. NeroError ("NeroGetCDInfo()");
  545. }
  546. if (cdinfo) {
  547. switch (NeroCDInfo->ncdiMediumType) {
  548. case NMT_CD_ROM:
  549. printf ("Read-only media, ");
  550. break;
  551. case NMT_CD_RECORDABLE:
  552. printf ("Recordable media, ");
  553. break;
  554. case NMT_CD_REWRITEABLE:
  555. printf ("Rewriteable media, ");
  556. break;
  557. default:
  558. printf ("unknown media, ");
  559. break;
  560. }
  561. char *mediatypename=NeroGetTypeNameOfMedia(NeroCDInfo->ncdiMediaType,NULL);
  562. printf("%s ",mediatypename);
  563. NeroFreeMem(mediatypename);
  564. printf ("%s, %d blocks free\n",
  565. NeroCDInfo->ncdiIsWriteable ? "writeable" : "not writable",
  566. NeroCDInfo->ncdiFreeCapacityInBlocks);
  567. printf ("Artist %s, Title %s\n",
  568. NeroCDInfo->ncdiArtist[0] ? NeroCDInfo->ncdiArtist : "unknown",
  569. NeroCDInfo->ncdiTitle[0] ? NeroCDInfo->ncdiTitle : "unknown");
  570. for (i = 0; i < NeroCDInfo->ncdiNumTracks; i++) {
  571. NERO_TRACK_INFO *pTrackInfo = &NeroCDInfo->ncdiTrackInfos[i];
  572. printf ("%02d. %6s %6d - %6d = %6d blocks, session %d",
  573. pTrackInfo->ntiTrackNumber,
  574. pTrackInfo->ntiTrackType == NTT_AUDIO ? "audio" :
  575. pTrackInfo->ntiTrackType == NTT_DATA ? "data" :
  576. "unknown",
  577. pTrackInfo->ntiTrackStartBlk,
  578. pTrackInfo->ntiTrackStartBlk + pTrackInfo->ntiTrackLengthInBlks,
  579. pTrackInfo->ntiTrackLengthInBlks,
  580. pTrackInfo->ntiSessionNumber);
  581. if (pTrackInfo->ntiArtist[0] || pTrackInfo->ntiTitle[0])
  582. printf (" (%s %s)\n", pTrackInfo->ntiArtist, pTrackInfo->ntiTitle);
  583. else
  584. puts("");
  585. if (pTrackInfo->ntiISRC[0])
  586. printf("\tISRC: %s\n",pTrackInfo->ntiISRC);
  587. }
  588. }
  589. if (read) {
  590. for (i = 0; (int)i < num_files; i++) {
  591. NERO_TRACK_INFO *pTrackInfo = NULL;
  592. unsigned int e;
  593. NERO_CALLBACK callback;
  594. NERO_DATA_EXCHANGE exchange;
  595. /* tracks may start with a number higher than 1, so search for track */
  596. for (e = 0; e < NeroCDInfo->ncdiNumTracks; e++) {
  597. if (NeroCDInfo->ncdiTrackInfos[e].ntiTrackNumber == tracks[i]) {
  598. pTrackInfo = &NeroCDInfo->ncdiTrackInfos[e];
  599. break;
  600. }
  601. }
  602. if (!pTrackInfo) {
  603. printf ("track %d for file '%s' not found on CD\n", tracks[i], files[i]);
  604. Exit (10);
  605. }
  606. /* extract audio */
  607. callback.ncCallbackFunction = ProgressCallback;
  608. callback.ncUserData = DUMMY_USER_DATA;
  609. switch (type[i]) {
  610. case WAV:
  611. exchange.ndeType = NERO_ET_FILE;
  612. strncpy(exchange.ndeData.ndeFileName, files[i], sizeof(exchange.ndeData.ndeFileName));
  613. exchange.ndeData.ndeFileName[sizeof(exchange.ndeData.ndeFileName) - 1] = 0;
  614. break;
  615. case PCM:
  616. exchange.ndeType = NERO_ET_IO_CALLBACK;
  617. exchange.ndeData.ndeIO.nioIOCallback = WriteIOCallback;
  618. exchange.ndeData.ndeIO.nioEOFCallback = EOFCallback;
  619. exchange.ndeData.ndeIO.nioErrorCallback = ErrorCallback;
  620. exchange.ndeData.ndeIO.nioUserData = fopen (files[i], "wb");
  621. if (!exchange.ndeData.ndeIO.nioUserData) {
  622. printf ("Cannot open target file %s\n", files[i]);
  623. Exit (10);
  624. /* We are lazy - closing the file will be done by resource tracking. */
  625. }
  626. break;
  627. default:
  628. /* unknown */
  629. printf ("unknown file type for writing of %s\n", files[i]);
  630. Exit (10);
  631. break;
  632. }
  633. printf ("%02d. '%s':\n", tracks[i], files[i]);
  634. if (NeroDAE (NeroDeviceHandle, pTrackInfo->ntiTrackStartBlk, pTrackInfo->ntiTrackLengthInBlks,
  635. &exchange, 0, &callback)) {
  636. NeroError ("NeroDAE()");
  637. }
  638. puts ("");
  639. }
  640. }
  641. }
  642. if (write)
  643. {
  644. int res=0;
  645. if (!videocd && !svideocd && !image)
  646. {
  647. // Burn ISO/Audio CD
  648. int size = sizeof (NERO_WRITE_CD) + (num_files - 1) * sizeof (NERO_AUDIO_TRACK);
  649. NERO_WRITE_CD *pWriteCD = (NERO_WRITE_CD *)malloc (size);
  650. if (!pWriteCD) {
  651. puts ("no mem");
  652. Exit (10);
  653. }
  654. memset (pWriteCD, 0, size);
  655. pWriteCD->nwcdMediaType = dvd ? MEDIA_DVD_ANY : MEDIA_CD;
  656. pWriteCD->nwcdNumTracks = num_files;
  657. pWriteCD->nwcdArtist = artist;
  658. pWriteCD->nwcdTitle = title;
  659. if (data)
  660. {
  661. pWriteCD->nwcdIsoTrack = &IsoTrack;
  662. pWriteCD->nwcdCDExtra = CDExtra;
  663. }
  664. for (i = 0; i < num_files; i++)
  665. {
  666. pWriteCD->nwcdTracks [i].natPauseInBlksBeforeThisTrack = ((i==0) ? 2*75 : iPauseLength); /* Write continously; first track requires minimal pause of 2 seconds (2*75) */
  667. pWriteCD->nwcdTracks [i].natIndex0ContainsData = ((i==0) ? FALSE : bAudioInIndex0); /* The first track may never contain data in index 0 */
  668. /* no indices, artist or title: these values are already NULL */
  669. switch (type [i]) {
  670. case WAV:
  671. pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeType = NERO_ET_FILE;
  672. strncpy (pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeFileName, files[i], sizeof(pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeFileName));
  673. pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeFileName[sizeof(pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeFileName) - 1] = 0;
  674. break;
  675. case MP3:
  676. pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeType = NERO_ET_FILE_MP3;
  677. strncpy (pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeFileName, files[i], sizeof(pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeFileName));
  678. pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeFileName[sizeof(pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeFileName) - 1] = 0;
  679. break;
  680. case WMA:
  681. pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeType = NERO_ET_FILE_WMA;
  682. strncpy (pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeFileName, files[i], sizeof(pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeFileName));
  683. pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeFileName[sizeof(pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeFileName) - 1] = 0;
  684. break;
  685. case PCM: {
  686. struct _stat buf;
  687. pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeType = NERO_ET_IO_CALLBACK;
  688. pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeIO.nioIOCallback = ReadIOCallback;
  689. pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeIO.nioEOFCallback = EOFCallback;
  690. pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeIO.nioErrorCallback = ErrorCallback;
  691. if (_stat (files[i], &buf)) {
  692. printf ("Cannot determine length of file %s\n", files[i]);
  693. Exit (10);
  694. }
  695. pWriteCD->nwcdTracks [i].natLengthInBlocks = buf.st_size / 2352;
  696. pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeIO.nioUserData = fopen (files[i], "rb");
  697. if (!pWriteCD->nwcdTracks [i].natSourceDataExchg.ndeData.ndeIO.nioUserData) {
  698. printf ("Cannot open source file %s\n", files[i]);
  699. Exit (10);
  700. }
  701. /* We are lazy - closing the file will be done by resource tracking. */
  702. break;
  703. }
  704. default:
  705. /* unknown */
  706. printf ("unknown file type for writing of %s\n", files[i]);
  707. Exit (10);
  708. break;
  709. }
  710. }
  711. /* burn, baby, burn... */
  712. res = NeroBurn (NeroDeviceHandle,NERO_ISO_AUDIO_CD ,pWriteCD,
  713. (real ? NBF_WRITE : NBF_SIMULATE) // Write and simulate are not mutually exclusive, we just use either one or the other here.
  714. | (TAO ? 0 : NBF_DAO) | NBF_DISABLE_ABORT | NBF_DETECT_NON_EMPTY_CDRW | NBF_SPEED_IN_KBS
  715. | (speedtest ? NBF_SPEED_TEST : 0)
  716. | NBF_CLOSE_SESSION
  717. | (!dvd ? NBF_CD_TEXT : 0)
  718. | (bup ? NBF_BUF_UNDERRUN_PROT : 0)
  719. | (verify ? NBF_VERIFY : 0)
  720. | (no_eject ? NBF_DISABLE_EJECT : 0),
  721. speed*pSelectedDeviceInfo->nsdiWriteSpeeds.nsiBaseSpeedKBs
  722. , &NeroProgress);
  723. free (pWriteCD);
  724. pWriteCD = NULL;
  725. } else if (videocd || svideocd)
  726. {
  727. // Burn Video CD or Super Video CD
  728. int size = sizeof (NERO_WRITE_VIDEO_CD) + (num_files - 1) * sizeof (NERO_VIDEO_ITEM);
  729. NERO_WRITE_VIDEO_CD *pWriteCD = (NERO_WRITE_VIDEO_CD *)malloc (size);
  730. if (!pWriteCD) {
  731. puts ("no mem");
  732. Exit (10);
  733. }
  734. memset (pWriteCD, 0, size);
  735. pWriteCD->nwvcdSVCD=svideocd;
  736. pWriteCD->nwvcdNumItems=num_files;
  737. pWriteCD->nwvcdIsoTrack=&IsoTrack;
  738. if (tempdir)
  739. {
  740. strncpy(pWriteCD->nwvcdTempPath,tempdir,sizeof(pWriteCD->nwvcdTempPath));
  741. pWriteCD->nwvcdTempPath[sizeof(pWriteCD->nwvcdTempPath)-1]=0;
  742. }
  743. for (i=0;i<num_files;i++)
  744. {
  745. NERO_VIDEO_ITEM *item=&pWriteCD->nwvcdItems[i];
  746. strncpy (item->nviSourceFileName, files[i], sizeof(pWriteCD->nwvcdItems[i].nviSourceFileName));
  747. pWriteCD->nwvcdItems[i].nviSourceFileName[sizeof(pWriteCD->nwvcdItems[i].nviSourceFileName)-1]=0;
  748. if (type[i]==JPEG)
  749. {
  750. item->nviItemType=NERO_JPEG_ITEM;
  751. item->nviPauseAfterItem=-1;
  752. } else
  753. if (type[i]==AVI)
  754. {
  755. item->nviItemType=NERO_NONENCODED_VIDEO_ITEM;
  756. item->nviPauseAfterItem=0;
  757. } else
  758. {
  759. item->nviItemType=NERO_MPEG_ITEM;
  760. item->nviPauseAfterItem=0;
  761. }
  762. }
  763. /* burn, baby, burn... */
  764. res = NeroBurn (NeroDeviceHandle,NERO_VIDEO_CD ,pWriteCD,
  765. (real ? NBF_WRITE : NBF_SIMULATE)
  766. | (TAO ? 0 : NBF_DAO)
  767. | NBF_DETECT_NON_EMPTY_CDRW
  768. | NBF_DISABLE_ABORT
  769. | (speedtest ? NBF_SPEED_TEST : 0)/*| NBF_CLOSE_SESSION*/ /* Write and simulate are not mutually exclusive, we just use either one or the other here. */
  770. | (no_eject ? NBF_DISABLE_EJECT : 0),
  771. speed, &NeroProgress);
  772. free (pWriteCD);
  773. } else if (image)
  774. {
  775. // Burn image
  776. NERO_WRITE_IMAGE pWriteCD;
  777. if (num_files<1)
  778. {
  779. puts("Image file not specified");
  780. Exit(10);
  781. }
  782. strncpy(pWriteCD.nwiImageFileName,files[0],sizeof(pWriteCD.nwiImageFileName));
  783. pWriteCD.nwiImageFileName[sizeof(pWriteCD.nwiImageFileName)-1]=0;
  784. /* burn, baby, burn... */
  785. res = NeroBurn (NeroDeviceHandle,NERO_BURN_IMAGE_CD ,&pWriteCD,
  786. (real ? NBF_WRITE : NBF_SIMULATE)
  787. | (TAO ? 0 : NBF_DAO)
  788. | NBF_DISABLE_ABORT
  789. | (speedtest ? NBF_SPEED_TEST : 0)/*| NBF_CLOSE_SESSION*/ /* Write and simulate are not mutually exclusive, we just use either one or the other here. */
  790. | (no_eject ? NBF_DISABLE_EJECT : 0),
  791. speed, &NeroProgress);
  792. }
  793. /* automatically save a log file */
  794. FILE *fp = fopen ("neroerr.txt", "w");
  795. if (fp) {
  796. char *log = NeroGetErrorLog ();
  797. fputs (log, fp);
  798. fclose (fp);
  799. NeroFreeMem (log);
  800. }
  801. switch(res)
  802. {
  803. case NEROAPI_BURN_OK:
  804. break;
  805. case NEROAPI_BURN_UNKNOWN_CD_FORMAT:
  806. NeroError ("BurnCD() : unknown CD format");
  807. break;
  808. case NEROAPI_BURN_INVALID_DRIVE:
  809. NeroError ("BurnCD() : invalid drive");
  810. break;
  811. case NEROAPI_BURN_FAILED:
  812. NeroError ("BurnCD() : burn failed");
  813. break;
  814. case NEROAPI_BURN_FUNCTION_NOT_ALLOWED:
  815. NeroError ("BurnCD() : function not allowed");
  816. break;
  817. case NEROAPI_BURN_DRIVE_NOT_ALLOWED:
  818. NeroError ("BurnCD() : drive not allowed");
  819. break;
  820. case NEROAPI_BURN_USER_ABORT:
  821. NeroError ("BurnCD() : aborted by the user");
  822. break;
  823. default:
  824. NeroError ("BurnCD() : unknown error");
  825. }
  826. }
  827. /* done */
  828. Exit (0);
  829. return 0;
  830. }
  831. /*
  832. ** functions using/implementing the API
  833. */
  834. static BOOL NERO_CALLBACK_ATTR IdleCallback (void *pUserData)
  835. {
  836. assert (pUserData == DUMMY_USER_DATA);
  837. /*
  838. ** Nothing to be done in a Shell application.
  839. ** A GUI might react to messages here:
  840. static MSG msg;
  841. while ("not canceled" && ::PeekMessage(&msg,NULL,NULL,NULL,PM_NOREMOVE))
  842. if (!AfxGetThread()->PumpMessage())
  843. break; // All messages "pumped"
  844. */
  845. return Aborted;
  846. }
  847. typedef struct {
  848. char input;
  849. NeroUserDlgInOut result;
  850. } Input2DlgOut;
  851. static NeroUserDlgInOut CharIO (const Input2DlgOut *CharMapping, const char *prompt) /* array is terminated with input == 0 */
  852. {
  853. NeroUserDlgInOut res = DLG_RETURN_EXIT;
  854. BOOL cont = TRUE;
  855. char buffer[80];
  856. do {
  857. puts (prompt);
  858. fgets (buffer, sizeof(buffer), stdin);
  859. for (int i = 0; CharMapping[i].input != 0; i++) {
  860. if (toupper(CharMapping[i].input) == toupper(buffer[0])) {
  861. res = CharMapping[i].result;
  862. cont = FALSE;
  863. break;
  864. }
  865. }
  866. } while (!Aborted && cont);
  867. return res;
  868. }
  869. static NeroUserDlgInOut NERO_CALLBACK_ATTR UserDialog (void *pUserData, NeroUserDlgInOut type, void *data)
  870. {
  871. static const Input2DlgOut okay_mapping[] =
  872. {
  873. 'O', DLG_RETURN_EXIT,
  874. 0
  875. };
  876. static const Input2DlgOut yes_no_mapping[] =
  877. {
  878. 'Y', DLG_RETURN_TRUE,
  879. 'N', DLG_RETURN_FALSE,
  880. 0
  881. };
  882. assert (pUserData == DUMMY_USER_DATA);
  883. switch (type) {
  884. case DLG_AUTO_INSERT:
  885. {
  886. static const Input2DlgOut mapping[] =
  887. {
  888. 'I', DLG_RETURN_INSTALL_DRIVER,
  889. 'T', DLG_RETURN_OFF_RESTART,
  890. 'E', DLG_RETURN_EXIT,
  891. 'C', DLG_RETURN_CONTINUE,
  892. 0
  893. };
  894. puts ("Auto Insert Notification is turned on in the system configuration.\n"
  895. "This may cause serious problems while burning: your CD might be damaged,\n"
  896. "or the system might hang up.\n\n"
  897. "Nero is able to burn CDs with Auto Insert Notification turned on if all\n"
  898. "necessary drivers are installed.\n");
  899. return CharIO (mapping,
  900. "[I]nstall drivers and restart Windows\n"
  901. "[T]urn off Auto Insert Notification and restart Windows\n"
  902. "[E]xit Nero\n"
  903. "[C]ontinue at your own risk\n");
  904. break;
  905. }
  906. case DLG_DISCONNECT_RESTART:
  907. case DLG_DISCONNECT:
  908. {
  909. puts ("Disconnect is turned off in the system configuration.\n"
  910. "This may cause serious problems while burning: your CD\n"
  911. "might be damaged, or the system might hang up.\n");
  912. if (DLG_DISCONNECT_RESTART == type) {
  913. static const Input2DlgOut mapping[] =
  914. {
  915. 'T', DLG_RETURN_ON_RESTART,
  916. 'D', DLG_RETURN_RESTART,
  917. 0
  918. };
  919. return CharIO (mapping,
  920. "[T]urn on Disconnect and restart\n"
  921. "[D]on't change Disconnect option and restart\n");
  922. } else {
  923. static const Input2DlgOut mapping[] =
  924. {
  925. 'T', DLG_RETURN_ON_RESTART,
  926. 'D', DLG_RETURN_RESTART,
  927. 'C', DLG_RETURN_CONTINUE,
  928. 0
  929. };
  930. return CharIO (mapping,
  931. "[T]urn on Disconnect and restart\n"
  932. "[D]on't change Disconnect option and restart\n"
  933. "[C]ontinue at your own risk\n");
  934. }
  935. break;
  936. }
  937. case DLG_AUTO_INSERT_RESTART:
  938. puts ("Auto Insert Notification is now OFF. You should restart Windows.\n");
  939. return CharIO (okay_mapping, "[O]kay\n");
  940. break;
  941. case DLG_RESTART:
  942. puts ("Please restart Windows now.\n");
  943. return CharIO (okay_mapping, "[O]kay\n");
  944. break;
  945. case DLG_SETTINGS_RESTART: {
  946. static const Input2DlgOut mapping[] =
  947. {
  948. 'R', DLG_RETURN_RESTART,
  949. 'C', DLG_RETURN_CONTINUE,
  950. 0
  951. };
  952. puts ("Nero detected some modifications of your PC system configuration\n"
  953. "and needs to modify some settings. Please restart your PC to make\n"
  954. "the changes become effective.\n");
  955. return CharIO (mapping,
  956. "[R]estart\n"
  957. "[C]ontinue at your own risk\n");
  958. break;
  959. }
  960. case DLG_OVERBURN:
  961. puts ("Sorry, this compilation contains too much data to fit on the CD\n"
  962. "with respect to the normal CD capacity. Do you want to try\n"
  963. "overburn writing at your own risk (this might cause read\n"
  964. "errors at the end of the CD or might even damage your recorder)?\n\n"
  965. "Note: It is also possible, that SCSI/Atapi errors occur at the end\n"
  966. "of the simulation or burning. Even in this case there is a certain\n"
  967. "chance, that the CD is readable.\n");
  968. return CharIO (yes_no_mapping, "[Y]es\n[N]o\n");
  969. break;
  970. case DLG_COPY_QUALITY_LOSS:
  971. puts( "Disc must be written as 'track at once' ('disc at once' not\n"
  972. "supported or not able to write such a disc). This means\n"
  973. "there might be some minor quality loss (e.g. lost audio index\n"
  974. "or different pause between audio tracks). Do you want to\n"
  975. "proceed anyway?\n");
  976. return CharIO (yes_no_mapping, "[Y]es\n[N]o\n");
  977. break;
  978. case DLG_COPY_FULLRISK:
  979. puts( "Disc must be written as 'track at once' ('disc at once' not\n"
  980. "supported or not able to write such a disc). Unfortunately\n"
  981. "your image has a special format which can most likely only\n"
  982. "be written correctly with 'disc at once'. But you may\n"
  983. "PROCEED AT YOUR OWN RISK. Do you want to continue\n"
  984. "burning?\n");
  985. return CharIO (yes_no_mapping, "[Y]es\n[N]o\n");
  986. break;
  987. case DLG_AUDIO_PROBLEMS:
  988. if ((INT_PTR)data & AUP_NOTRACK_FOUND) {
  989. puts ("No tracks given.");
  990. return DLG_RETURN_EXIT;
  991. }
  992. if ((INT_PTR)data == AUP_MEGA_FATAL) {
  993. puts ("fatal internal problem");
  994. return DLG_RETURN_EXIT;
  995. }
  996. puts ("Nero has detected that the following audio properties are not\n"
  997. "supported by your recorder in the current write mode and need\n"
  998. "to be modified:");
  999. if ((INT_PTR)data & AUP_FIRST_TR_PAUSE) puts ("- CD specification allows only 2-3 Seconds pause for the first track");
  1000. if ((INT_PTR)data & AUP_PAUSE_SETTINGS) puts ("- Pause length between the tracks not supported");
  1001. if ((INT_PTR)data & AUP_INDEX_SETTINGS) puts ("- Additional index positions not supported");
  1002. if ((INT_PTR)data & AUP_ISRC_SETTINGS) puts ("- ISRC codes not supported");
  1003. if ((INT_PTR)data & AUP_COPYPROT_SETTINGS) puts ("- Copy protection bit not supported");
  1004. puts ("Nero can change the audio track settings for you to fit the\n"
  1005. "capabilities of your recorder. This might cause some audio\n"
  1006. "properties to be lost. Do you want Nero to change the track\n"
  1007. "settings for you?\n");
  1008. return CharIO (yes_no_mapping, "[Y]es\n[N]o\n");
  1009. break;
  1010. case DLG_WAITCD:
  1011. {
  1012. char *msg=NeroGetLocalizedWaitCDTexts ((NERO_WAITCD_TYPE) (int)data);
  1013. printf("\n%s\n", msg);
  1014. NeroFreeMem(msg);
  1015. }
  1016. break;
  1017. case DLG_WAITCD_REMINDER:
  1018. printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\b");
  1019. break;
  1020. case DLG_WAITCD_DONE:
  1021. // nothing to be done in the text interface,
  1022. // should close dialog box in a GUI
  1023. break;
  1024. case DLG_FILESEL_IMAGE:
  1025. printf("\nSave image file : ");
  1026. fgets((char *)data,255,stdin);
  1027. // Remove the carriage return
  1028. ((char *)data)[strlen((char *)data)-1]=0;
  1029. return DLG_RETURN_TRUE;
  1030. break;
  1031. case DLG_BURNIMAGE_CANCEL:
  1032. printf("There is not enough space available to burn the image.\n");
  1033. break;
  1034. case DLG_NON_EMPTY_CDRW:
  1035. {
  1036. puts("This CDRW is not empty.");
  1037. static const Input2DlgOut mapping[] =
  1038. {
  1039. 'C', DLG_RETURN_EXIT,
  1040. 'E', DLG_RETURN_CONTINUE,
  1041. 'O', DLG_RETURN_RESTART,
  1042. 0
  1043. };
  1044. NeroUserDlgInOut res=CharIO(mapping,"[E]rase CD\n[O]pen tray\n[C]ancel");
  1045. if (res==DLG_RETURN_CONTINUE)
  1046. {
  1047. // Erase the CDRW
  1048. NEROAPI_CDRW_ERASE_MODE mode=NEROAPI_ERASE_QUICK;
  1049. int time=NeroGetCDRWErasingTime(NeroDeviceHandle,mode);
  1050. if (time==-1)
  1051. NeroError("No CD inserted");
  1052. else if (time==-2)
  1053. NeroError("This CD recorder doesn't support CDRW");
  1054. printf("Erasing CDRW. This will take %d seconds.\n",time);
  1055. int err=NeroEraseCDRW(NeroDeviceHandle,mode);
  1056. if (err)
  1057. NeroError("Error erasing the CDRW");
  1058. }
  1059. return res;
  1060. }
  1061. case DLG_WAITCD_MEDIA_INFO:
  1062. {
  1063. NERO_DLG_WAITCD_MEDIA_INFO *pInfos=(NERO_DLG_WAITCD_MEDIA_INFO *)data;
  1064. printf("Requested media: %s\n",pInfos->ndwmiRequestedMediaName);
  1065. printf("Last detected media: %s\n",pInfos->ndwmiLastDetectedMediaName);
  1066. }
  1067. break;
  1068. default:
  1069. assert (FALSE); // we don't know this type of requester!
  1070. break;
  1071. }
  1072. return DLG_RETURN_EXIT;
  1073. }
  1074. static BOOL NERO_CALLBACK_ATTR ProgressCallback (void *pUserData, DWORD dwProgressInPercent)
  1075. {
  1076. printf ("%03d%%\r", dwProgressInPercent);
  1077. return IdleCallback (pUserData);
  1078. }
  1079. static BOOL NERO_CALLBACK_ATTR AbortedCallback (void *pUserData)
  1080. {
  1081. // printf("Abort ?\n");
  1082. return Aborted;
  1083. }
  1084. static void NERO_CALLBACK_ATTR AddLogLine (void *pUserData, NERO_TEXT_TYPE type, const char *text)
  1085. {
  1086. char *header = " ";
  1087. const char *start;
  1088. switch (type) {
  1089. case NERO_TEXT_INFO: /* informative text */
  1090. header = "i ";
  1091. break;
  1092. case NERO_TEXT_STOP: /* some operation stopped prematurely */
  1093. header = "# ";
  1094. break;
  1095. case NERO_TEXT_EXCLAMATION: /* important information */
  1096. header = "! ";
  1097. break;
  1098. case NERO_TEXT_QUESTION: /* a question which requires an answer */
  1099. header = "? ";
  1100. break;
  1101. case NERO_TEXT_DRIVE: /* a message concerning a CD-ROM drive or recorder */
  1102. header = "- ";
  1103. break;
  1104. default:
  1105. break;
  1106. }
  1107. start = text;
  1108. while (start) {
  1109. const char *end = strchr (start, '\n');
  1110. int len = end ? (int)(end - start) : strlen (start);
  1111. fputs (header, stdout);
  1112. fwrite (start, 1, len, stdout);
  1113. // clear rest of line
  1114. len = 79 - strlen (header) - len;
  1115. while (--len >= 0) {
  1116. putchar (' ');
  1117. }
  1118. puts ("");
  1119. start = end ? end + 1 : NULL;
  1120. }
  1121. }
  1122. static void NERO_CALLBACK_ATTR SetPhaseCallback (void *pUserData, const char *text)
  1123. {
  1124. int len;
  1125. printf (" %s", text);
  1126. // clear rest of line
  1127. len = 79 - strlen (text) - 5;
  1128. while (--len >= 0) {
  1129. putchar (' ');
  1130. }
  1131. putchar ('\r');
  1132. }
  1133. static void NERO_CALLBACK_ATTR DisableAbortCallback (void *pUserData, BOOL enableAbort)
  1134. {
  1135. if (!enableAbort)
  1136. puts("The current process cannot be interrupted");
  1137. else puts("The process can be interrupted again");
  1138. }
  1139. static void NERO_CALLBACK_ATTR SetMajorPhaseCallback(void *pUserData,NERO_MAJOR_PHASE phase,void *reserved)
  1140. {
  1141. }
  1142. static DWORD NERO_CALLBACK_ATTR WriteIOCallback (void *pUserData, BYTE *pBuffer, DWORD dwLen)
  1143. {
  1144. return fwrite (pBuffer, 1, dwLen, (FILE *)pUserData);
  1145. }
  1146. static BOOL NERO_CALLBACK_ATTR EOFCallback (void *pUserData)
  1147. {
  1148. return feof ((FILE *)pUserData);
  1149. }
  1150. static BOOL NERO_CALLBACK_ATTR ErrorCallback (void *pUserData)
  1151. {
  1152. return ferror ((FILE *)pUserData);
  1153. }
  1154. static DWORD NERO_CALLBACK_ATTR ReadIOCallback (void *pUserData, BYTE *pBuffer, DWORD dwLen)
  1155. {
  1156. return fread (pBuffer, 1, dwLen, (FILE *)pUserData);
  1157. }
  1158. static void NeroError (char *action) /* display Nero error and exit */
  1159. {
  1160. char *error = NeroGetLastError ();
  1161. puts (action);
  1162. puts (error ? error : "failed");
  1163. NeroFreeMem (error);
  1164. Exit (10);
  1165. }