MainForm.cs 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175
  1. using System;
  2. using System.ComponentModel;
  3. using System.Drawing;
  4. using System.IO;
  5. using System.Runtime.InteropServices;
  6. using System.Runtime.InteropServices.ComTypes;
  7. using System.Text;
  8. using System.Windows.Forms;
  9. using IMAPI2.Interop;
  10. using IMAPI2.MediaItem;
  11. namespace BurnMedia
  12. {
  13. public partial class MainForm : Form
  14. {
  15. private const string ClientName = "BurnMedia";
  16. Int64 _totalDiscSize;
  17. private bool _isBurning;
  18. private bool _isFormatting;
  19. private IMAPI_BURN_VERIFICATION_LEVEL _verificationLevel =
  20. IMAPI_BURN_VERIFICATION_LEVEL.IMAPI_BURN_VERIFICATION_NONE;
  21. private bool _closeMedia;
  22. private bool _ejectMedia;
  23. private BurnData _burnData = new BurnData();
  24. public MainForm()
  25. {
  26. InitializeComponent();
  27. }
  28. /// <summary>
  29. /// Initialize the form
  30. /// </summary>
  31. /// <param name="sender"></param>
  32. /// <param name="e"></param>
  33. private void MainForm_Load(object sender, EventArgs e)
  34. {
  35. //
  36. // Determine the current recording devices
  37. //
  38. MsftDiscMaster2 discMaster = null;
  39. try
  40. {
  41. discMaster = new MsftDiscMaster2();
  42. if (!discMaster.IsSupportedEnvironment)
  43. return;
  44. foreach (string uniqueRecorderId in discMaster)
  45. {
  46. var discRecorder2 = new MsftDiscRecorder2();
  47. discRecorder2.InitializeDiscRecorder(uniqueRecorderId);
  48. devicesComboBox.Items.Add(discRecorder2);
  49. }
  50. if (devicesComboBox.Items.Count > 0)
  51. {
  52. devicesComboBox.SelectedIndex = 0;
  53. }
  54. }
  55. catch (COMException ex)
  56. {
  57. MessageBox.Show(ex.Message,
  58. string.Format("Error:{0} - Please install IMAPI2", ex.ErrorCode),
  59. MessageBoxButtons.OK, MessageBoxIcon.Stop);
  60. return;
  61. }
  62. finally
  63. {
  64. if (discMaster != null)
  65. {
  66. Marshal.ReleaseComObject(discMaster);
  67. }
  68. }
  69. //
  70. // Create the volume label based on the current date
  71. //
  72. DateTime now = DateTime.Now;
  73. textBoxLabel.Text = now.Year + "_" + now.Month + "_" + now.Day;
  74. labelStatusText.Text = string.Empty;
  75. labelFormatStatusText.Text = string.Empty;
  76. //
  77. // Select no verification, by default
  78. //
  79. comboBoxVerification.SelectedIndex = 0;
  80. UpdateCapacity();
  81. }
  82. private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
  83. {
  84. //
  85. // Release the disc recorder items
  86. //
  87. foreach (MsftDiscRecorder2 discRecorder2 in devicesComboBox.Items)
  88. {
  89. if (discRecorder2 != null)
  90. {
  91. Marshal.ReleaseComObject(discRecorder2);
  92. }
  93. }
  94. }
  95. #region Device ComboBox
  96. /// <summary>
  97. /// Selected a new device
  98. /// </summary>
  99. /// <param name="sender"></param>
  100. /// <param name="e"></param>
  101. private void devicesComboBox_SelectedIndexChanged(object sender, EventArgs e)
  102. {
  103. if (devicesComboBox.SelectedIndex == -1)
  104. {
  105. return;
  106. }
  107. var discRecorder =
  108. (IDiscRecorder2)devicesComboBox.Items[devicesComboBox.SelectedIndex];
  109. supportedMediaLabel.Text = string.Empty;
  110. //
  111. // Verify recorder is supported
  112. //
  113. IDiscFormat2Data discFormatData = null;
  114. try
  115. {
  116. discFormatData = new MsftDiscFormat2Data();
  117. if (!discFormatData.IsRecorderSupported(discRecorder))
  118. {
  119. MessageBox.Show("Recorder not supported", ClientName,
  120. MessageBoxButtons.OK, MessageBoxIcon.Error);
  121. return;
  122. }
  123. StringBuilder supportedMediaTypes = new StringBuilder();
  124. foreach (IMAPI_PROFILE_TYPE profileType in discRecorder.SupportedProfiles)
  125. {
  126. string profileName = GetProfileTypeString(profileType);
  127. if (string.IsNullOrEmpty(profileName))
  128. continue;
  129. if (supportedMediaTypes.Length > 0)
  130. supportedMediaTypes.Append(", ");
  131. supportedMediaTypes.Append(profileName);
  132. }
  133. supportedMediaLabel.Text = supportedMediaTypes.ToString();
  134. }
  135. catch (COMException)
  136. {
  137. supportedMediaLabel.Text = "Error getting supported types";
  138. }
  139. finally
  140. {
  141. if (discFormatData != null)
  142. {
  143. Marshal.ReleaseComObject(discFormatData);
  144. }
  145. }
  146. }
  147. /// <summary>
  148. /// converts an IMAPI_MEDIA_PHYSICAL_TYPE to it's string
  149. /// </summary>
  150. /// <param name="mediaType"></param>
  151. /// <returns></returns>
  152. private static string GetMediaTypeString(IMAPI_MEDIA_PHYSICAL_TYPE mediaType)
  153. {
  154. switch (mediaType)
  155. {
  156. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_UNKNOWN:
  157. default:
  158. return "Unknown Media Type";
  159. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_CDROM:
  160. return "CD-ROM";
  161. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_CDR:
  162. return "CD-R";
  163. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_CDRW:
  164. return "CD-RW";
  165. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDROM:
  166. return "DVD ROM";
  167. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDRAM:
  168. return "DVD-RAM";
  169. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSR:
  170. return "DVD+R";
  171. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSRW:
  172. return "DVD+RW";
  173. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSR_DUALLAYER:
  174. return "DVD+R Dual Layer";
  175. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDDASHR:
  176. return "DVD-R";
  177. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDDASHRW:
  178. return "DVD-RW";
  179. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDDASHR_DUALLAYER:
  180. return "DVD-R Dual Layer";
  181. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DISK:
  182. return "random-access writes";
  183. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_DVDPLUSRW_DUALLAYER:
  184. return "DVD+RW DL";
  185. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_HDDVDROM:
  186. return "HD DVD-ROM";
  187. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_HDDVDR:
  188. return "HD DVD-R";
  189. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_HDDVDRAM:
  190. return "HD DVD-RAM";
  191. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_BDROM:
  192. return "Blu-ray DVD (BD-ROM)";
  193. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_BDR:
  194. return "Blu-ray media";
  195. case IMAPI_MEDIA_PHYSICAL_TYPE.IMAPI_MEDIA_TYPE_BDRE:
  196. return "Blu-ray Rewritable media";
  197. }
  198. }
  199. /// <summary>
  200. /// converts an IMAPI_PROFILE_TYPE to it's string
  201. /// </summary>
  202. /// <param name="profileType"></param>
  203. /// <returns></returns>
  204. static string GetProfileTypeString(IMAPI_PROFILE_TYPE profileType)
  205. {
  206. switch (profileType)
  207. {
  208. default:
  209. return string.Empty;
  210. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_CD_RECORDABLE:
  211. return "CD-R";
  212. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_CD_REWRITABLE:
  213. return "CD-RW";
  214. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_DVDROM:
  215. return "DVD ROM";
  216. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_DVD_DASH_RECORDABLE:
  217. return "DVD-R";
  218. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_DVD_RAM:
  219. return "DVD-RAM";
  220. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_DVD_PLUS_R:
  221. return "DVD+R";
  222. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_DVD_PLUS_RW:
  223. return "DVD+RW";
  224. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_DVD_PLUS_R_DUAL:
  225. return "DVD+R Dual Layer";
  226. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_DVD_DASH_REWRITABLE:
  227. return "DVD-RW";
  228. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_DVD_DASH_RW_SEQUENTIAL:
  229. return "DVD-RW Sequential";
  230. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_DVD_DASH_R_DUAL_SEQUENTIAL:
  231. return "DVD-R DL Sequential";
  232. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_DVD_DASH_R_DUAL_LAYER_JUMP:
  233. return "DVD-R Dual Layer";
  234. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_DVD_PLUS_RW_DUAL:
  235. return "DVD+RW DL";
  236. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_HD_DVD_ROM:
  237. return "HD DVD-ROM";
  238. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_HD_DVD_RECORDABLE:
  239. return "HD DVD-R";
  240. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_HD_DVD_RAM:
  241. return "HD DVD-RAM";
  242. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_BD_ROM:
  243. return "Blu-ray DVD (BD-ROM)";
  244. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_BD_R_SEQUENTIAL:
  245. return "Blu-ray media Sequential";
  246. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_BD_R_RANDOM_RECORDING:
  247. return "Blu-ray media";
  248. case IMAPI_PROFILE_TYPE.IMAPI_PROFILE_TYPE_BD_REWRITABLE:
  249. return "Blu-ray Rewritable media";
  250. }
  251. }
  252. /// <summary>
  253. /// Provides the display string for an IDiscRecorder2 object in the combobox
  254. /// </summary>
  255. /// <param name="sender"></param>
  256. /// <param name="e"></param>
  257. private void devicesComboBox_Format(object sender, ListControlConvertEventArgs e)
  258. {
  259. IDiscRecorder2 discRecorder2 = (IDiscRecorder2)e.ListItem;
  260. string devicePaths = string.Empty;
  261. string volumePath = (string)discRecorder2.VolumePathNames.GetValue(0);
  262. foreach (string volPath in discRecorder2.VolumePathNames)
  263. {
  264. if (!string.IsNullOrEmpty(devicePaths))
  265. {
  266. devicePaths += ",";
  267. }
  268. devicePaths += volumePath;
  269. }
  270. e.Value = string.Format("{0} [{1}]", devicePaths, discRecorder2.ProductId);
  271. }
  272. #endregion
  273. #region Media Size
  274. private void buttonDetectMedia_Click(object sender, EventArgs e)
  275. {
  276. if (devicesComboBox.SelectedIndex == -1)
  277. {
  278. return;
  279. }
  280. var discRecorder =
  281. (IDiscRecorder2)devicesComboBox.Items[devicesComboBox.SelectedIndex];
  282. MsftFileSystemImage fileSystemImage = null;
  283. MsftDiscFormat2Data discFormatData = null;
  284. try
  285. {
  286. //
  287. // Create and initialize the IDiscFormat2Data
  288. //
  289. discFormatData = new MsftDiscFormat2Data();
  290. if (!discFormatData.IsCurrentMediaSupported(discRecorder))
  291. {
  292. labelMediaType.Text = "Media not supported!";
  293. _totalDiscSize = 0;
  294. return;
  295. }
  296. else
  297. {
  298. //
  299. // Get the media type in the recorder
  300. //
  301. discFormatData.Recorder = discRecorder;
  302. IMAPI_MEDIA_PHYSICAL_TYPE mediaType = discFormatData.CurrentPhysicalMediaType;
  303. labelMediaType.Text = GetMediaTypeString(mediaType);
  304. //
  305. // Create a file system and select the media type
  306. //
  307. fileSystemImage = new MsftFileSystemImage();
  308. fileSystemImage.ChooseImageDefaultsForMediaType(mediaType);
  309. //
  310. // See if there are other recorded sessions on the disc
  311. //
  312. if (!discFormatData.MediaHeuristicallyBlank)
  313. {
  314. fileSystemImage.MultisessionInterfaces = discFormatData.MultisessionInterfaces;
  315. fileSystemImage.ImportFileSystem();
  316. }
  317. Int64 freeMediaBlocks = fileSystemImage.FreeMediaBlocks;
  318. _totalDiscSize = 2048 * freeMediaBlocks;
  319. }
  320. }
  321. catch (COMException exception)
  322. {
  323. MessageBox.Show(this, exception.Message, "Detect Media Error",
  324. MessageBoxButtons.OK, MessageBoxIcon.Error);
  325. }
  326. finally
  327. {
  328. if (discFormatData != null)
  329. {
  330. Marshal.ReleaseComObject(discFormatData);
  331. }
  332. if (fileSystemImage != null)
  333. {
  334. Marshal.ReleaseComObject(fileSystemImage);
  335. }
  336. }
  337. UpdateCapacity();
  338. }
  339. /// <summary>
  340. /// Updates the capacity progressbar
  341. /// </summary>
  342. private void UpdateCapacity()
  343. {
  344. //
  345. // Get the text for the Max Size
  346. //
  347. if (_totalDiscSize == 0)
  348. {
  349. labelTotalSize.Text = "0MB";
  350. return;
  351. }
  352. labelTotalSize.Text = _totalDiscSize < 1000000000 ?
  353. string.Format("{0}MB", _totalDiscSize / 1000000) :
  354. string.Format("{0:F2}GB", (float)_totalDiscSize / 1000000000.0);
  355. //
  356. // Calculate the size of the files
  357. //
  358. Int64 totalMediaSize = 0;
  359. foreach (IMediaItem mediaItem in listBoxFiles.Items)
  360. {
  361. totalMediaSize += mediaItem.SizeOnDisc;
  362. }
  363. if (totalMediaSize == 0)
  364. {
  365. progressBarCapacity.Value = 0;
  366. progressBarCapacity.ForeColor = SystemColors.Highlight;
  367. }
  368. else
  369. {
  370. var percent = (int)((totalMediaSize * 100) / _totalDiscSize);
  371. if (percent > 100)
  372. {
  373. progressBarCapacity.Value = 100;
  374. progressBarCapacity.ForeColor = Color.Red;
  375. }
  376. else
  377. {
  378. progressBarCapacity.Value = percent;
  379. progressBarCapacity.ForeColor = SystemColors.Highlight;
  380. }
  381. }
  382. }
  383. #endregion
  384. #region Burn Media Process
  385. /// <summary>
  386. /// User clicked the "Burn" button
  387. /// </summary>
  388. /// <param name="sender"></param>
  389. /// <param name="e"></param>
  390. private void buttonBurn_Click(object sender, EventArgs e)
  391. {
  392. if (devicesComboBox.SelectedIndex == -1)
  393. {
  394. return;
  395. }
  396. if (_isBurning)
  397. {
  398. buttonBurn.Enabled = false;
  399. backgroundBurnWorker.CancelAsync();
  400. }
  401. else
  402. {
  403. _isBurning = true;
  404. _closeMedia = checkBoxCloseMedia.Checked;
  405. _ejectMedia = checkBoxEject.Checked;
  406. EnableBurnUI(false);
  407. var discRecorder =
  408. (IDiscRecorder2)devicesComboBox.Items[devicesComboBox.SelectedIndex];
  409. _burnData.uniqueRecorderId = discRecorder.ActiveDiscRecorder;
  410. backgroundBurnWorker.RunWorkerAsync(_burnData);
  411. }
  412. }
  413. /// <summary>
  414. /// The thread that does the burning of the media
  415. /// </summary>
  416. /// <param name="sender"></param>
  417. /// <param name="e"></param>
  418. private void backgroundBurnWorker_DoWork(object sender, DoWorkEventArgs e)
  419. {
  420. MsftDiscRecorder2 discRecorder = null;
  421. MsftDiscFormat2Data discFormatData = null;
  422. try
  423. {
  424. //
  425. // Create and initialize the IDiscRecorder2 object
  426. //
  427. discRecorder = new MsftDiscRecorder2();
  428. var burnData = (BurnData)e.Argument;
  429. discRecorder.InitializeDiscRecorder(burnData.uniqueRecorderId);
  430. //
  431. // Create and initialize the IDiscFormat2Data
  432. //
  433. discFormatData = new MsftDiscFormat2Data
  434. {
  435. Recorder = discRecorder,
  436. ClientName = ClientName,
  437. ForceMediaToBeClosed = _closeMedia
  438. };
  439. //
  440. // Set the verification level
  441. //
  442. var burnVerification = (IBurnVerification)discFormatData;
  443. burnVerification.BurnVerificationLevel = _verificationLevel;
  444. //
  445. // Check if media is blank, (for RW media)
  446. //
  447. object[] multisessionInterfaces = null;
  448. if (!discFormatData.MediaHeuristicallyBlank)
  449. {
  450. multisessionInterfaces = discFormatData.MultisessionInterfaces;
  451. }
  452. //
  453. // Create the file system
  454. //
  455. IStream fileSystem;
  456. if (!CreateMediaFileSystem(discRecorder, multisessionInterfaces, out fileSystem))
  457. {
  458. e.Result = -1;
  459. return;
  460. }
  461. //
  462. // add the Update event handler
  463. //
  464. discFormatData.Update += discFormatData_Update;
  465. //
  466. // Write the data here
  467. //
  468. try
  469. {
  470. discFormatData.Write(fileSystem);
  471. e.Result = 0;
  472. }
  473. catch (COMException ex)
  474. {
  475. e.Result = ex.ErrorCode;
  476. MessageBox.Show(ex.Message, "IDiscFormat2Data.Write failed",
  477. MessageBoxButtons.OK, MessageBoxIcon.Stop);
  478. }
  479. finally
  480. {
  481. if (fileSystem != null)
  482. {
  483. Marshal.FinalReleaseComObject(fileSystem);
  484. }
  485. }
  486. //
  487. // remove the Update event handler
  488. //
  489. discFormatData.Update -= discFormatData_Update;
  490. if (_ejectMedia)
  491. {
  492. discRecorder.EjectMedia();
  493. }
  494. }
  495. catch (COMException exception)
  496. {
  497. //
  498. // If anything happens during the format, show the message
  499. //
  500. MessageBox.Show(exception.Message);
  501. e.Result = exception.ErrorCode;
  502. }
  503. finally
  504. {
  505. if (discRecorder != null)
  506. {
  507. Marshal.ReleaseComObject(discRecorder);
  508. }
  509. if (discFormatData != null)
  510. {
  511. Marshal.ReleaseComObject(discFormatData);
  512. }
  513. }
  514. }
  515. /// <summary>
  516. ///
  517. /// </summary>
  518. /// <param name="sender"></param>
  519. /// <param name="progress"></param>
  520. void discFormatData_Update([In, MarshalAs(UnmanagedType.IDispatch)] object sender, [In, MarshalAs(UnmanagedType.IDispatch)] object progress)
  521. {
  522. //
  523. // Check if we've cancelled
  524. //
  525. if (backgroundBurnWorker.CancellationPending)
  526. {
  527. var format2Data = (IDiscFormat2Data)sender;
  528. format2Data.CancelWrite();
  529. return;
  530. }
  531. var eventArgs = (IDiscFormat2DataEventArgs)progress;
  532. _burnData.task = BURN_MEDIA_TASK.BURN_MEDIA_TASK_WRITING;
  533. // IDiscFormat2DataEventArgs Interface
  534. _burnData.elapsedTime = eventArgs.ElapsedTime;
  535. _burnData.remainingTime = eventArgs.RemainingTime;
  536. _burnData.totalTime = eventArgs.TotalTime;
  537. // IWriteEngine2EventArgs Interface
  538. _burnData.currentAction = eventArgs.CurrentAction;
  539. _burnData.startLba = eventArgs.StartLba;
  540. _burnData.sectorCount = eventArgs.SectorCount;
  541. _burnData.lastReadLba = eventArgs.LastReadLba;
  542. _burnData.lastWrittenLba = eventArgs.LastWrittenLba;
  543. _burnData.totalSystemBuffer = eventArgs.TotalSystemBuffer;
  544. _burnData.usedSystemBuffer = eventArgs.UsedSystemBuffer;
  545. _burnData.freeSystemBuffer = eventArgs.FreeSystemBuffer;
  546. //
  547. // Report back to the UI
  548. //
  549. backgroundBurnWorker.ReportProgress(0, _burnData);
  550. }
  551. /// <summary>
  552. /// Completed the "Burn" thread
  553. /// </summary>
  554. /// <param name="sender"></param>
  555. /// <param name="e"></param>
  556. private void backgroundBurnWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  557. {
  558. labelStatusText.Text = (int)e.Result == 0 ? "Finished Burning Disc!" : "Error Burning Disc!";
  559. statusProgressBar.Value = 0;
  560. _isBurning = false;
  561. EnableBurnUI(true);
  562. buttonBurn.Enabled = true;
  563. }
  564. /// <summary>
  565. /// Enables/Disables the "Burn" User Interface
  566. /// </summary>
  567. /// <param name="enable"></param>
  568. void EnableBurnUI(bool enable)
  569. {
  570. buttonBurn.Text = enable ? "&Burn" : "&Cancel";
  571. buttonDetectMedia.Enabled = enable;
  572. devicesComboBox.Enabled = enable;
  573. listBoxFiles.Enabled = enable;
  574. buttonAddFiles.Enabled = enable;
  575. buttonAddFolders.Enabled = enable;
  576. buttonRemoveFiles.Enabled = enable;
  577. checkBoxEject.Enabled = enable;
  578. checkBoxCloseMedia.Enabled = enable;
  579. textBoxLabel.Enabled = enable;
  580. comboBoxVerification.Enabled = enable;
  581. }
  582. /// <summary>
  583. /// Event receives notification from the Burn thread of an event
  584. /// </summary>
  585. /// <param name="sender"></param>
  586. /// <param name="e"></param>
  587. private void backgroundBurnWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
  588. {
  589. //int percent = e.ProgressPercentage;
  590. var burnData = (BurnData)e.UserState;
  591. if (burnData.task == BURN_MEDIA_TASK.BURN_MEDIA_TASK_FILE_SYSTEM)
  592. {
  593. labelStatusText.Text = burnData.statusMessage;
  594. }
  595. else if (burnData.task == BURN_MEDIA_TASK.BURN_MEDIA_TASK_WRITING)
  596. {
  597. switch (burnData.currentAction)
  598. {
  599. case IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_VALIDATING_MEDIA:
  600. labelStatusText.Text = "Validating current media...";
  601. break;
  602. case IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_FORMATTING_MEDIA:
  603. labelStatusText.Text = "Formatting media...";
  604. break;
  605. case IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_INITIALIZING_HARDWARE:
  606. labelStatusText.Text = "Initializing hardware...";
  607. break;
  608. case IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_CALIBRATING_POWER:
  609. labelStatusText.Text = "Optimizing laser intensity...";
  610. break;
  611. case IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_WRITING_DATA:
  612. long writtenSectors = burnData.lastWrittenLba - burnData.startLba;
  613. if (writtenSectors > 0 && burnData.sectorCount > 0)
  614. {
  615. var percent = (int)((100 * writtenSectors) / burnData.sectorCount);
  616. labelStatusText.Text = string.Format("Progress: {0}%", percent);
  617. statusProgressBar.Value = percent;
  618. }
  619. else
  620. {
  621. labelStatusText.Text = "Progress 0%";
  622. statusProgressBar.Value = 0;
  623. }
  624. break;
  625. case IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_FINALIZATION:
  626. labelStatusText.Text = "Finalizing writing...";
  627. break;
  628. case IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_COMPLETED:
  629. labelStatusText.Text = "Completed!";
  630. break;
  631. case IMAPI_FORMAT2_DATA_WRITE_ACTION.IMAPI_FORMAT2_DATA_WRITE_ACTION_VERIFYING:
  632. labelStatusText.Text = "Verifying";
  633. break;
  634. }
  635. }
  636. }
  637. /// <summary>
  638. /// Enable the Burn Button if items in the file listbox
  639. /// </summary>
  640. private void EnableBurnButton()
  641. {
  642. buttonBurn.Enabled = (listBoxFiles.Items.Count > 0);
  643. }
  644. #endregion
  645. #region File System Process
  646. private bool CreateMediaFileSystem(IDiscRecorder2 discRecorder, object[] multisessionInterfaces, out IStream dataStream)
  647. {
  648. MsftFileSystemImage fileSystemImage = null;
  649. try
  650. {
  651. fileSystemImage = new MsftFileSystemImage();
  652. fileSystemImage.ChooseImageDefaults(discRecorder);
  653. fileSystemImage.FileSystemsToCreate =
  654. FsiFileSystems.FsiFileSystemJoliet | FsiFileSystems.FsiFileSystemISO9660;
  655. fileSystemImage.VolumeName = textBoxLabel.Text;
  656. fileSystemImage.Update += fileSystemImage_Update;
  657. //
  658. // If multisessions, then import previous sessions
  659. //
  660. if (multisessionInterfaces != null)
  661. {
  662. fileSystemImage.MultisessionInterfaces = multisessionInterfaces;
  663. fileSystemImage.ImportFileSystem();
  664. }
  665. //
  666. // Get the image root
  667. //
  668. IFsiDirectoryItem rootItem = fileSystemImage.Root;
  669. //
  670. // Add Files and Directories to File System Image
  671. //
  672. foreach (IMediaItem mediaItem in listBoxFiles.Items)
  673. {
  674. //
  675. // Check if we've cancelled
  676. //
  677. if (backgroundBurnWorker.CancellationPending)
  678. {
  679. break;
  680. }
  681. //
  682. // Add to File System
  683. //
  684. mediaItem.AddToFileSystem(rootItem);
  685. }
  686. fileSystemImage.Update -= fileSystemImage_Update;
  687. //
  688. // did we cancel?
  689. //
  690. if (backgroundBurnWorker.CancellationPending)
  691. {
  692. dataStream = null;
  693. return false;
  694. }
  695. dataStream = fileSystemImage.CreateResultImage().ImageStream;
  696. }
  697. catch (COMException exception)
  698. {
  699. MessageBox.Show(this, exception.Message, "Create File System Error",
  700. MessageBoxButtons.OK, MessageBoxIcon.Error);
  701. dataStream = null;
  702. return false;
  703. }
  704. finally
  705. {
  706. if (fileSystemImage != null)
  707. {
  708. Marshal.ReleaseComObject(fileSystemImage);
  709. }
  710. }
  711. return true;
  712. }
  713. /// <summary>
  714. /// Event Handler for File System Progress Updates
  715. /// </summary>
  716. /// <param name="sender"></param>
  717. /// <param name="currentFile"></param>
  718. /// <param name="copiedSectors"></param>
  719. /// <param name="totalSectors"></param>
  720. void fileSystemImage_Update([In, MarshalAs(UnmanagedType.IDispatch)] object sender,
  721. [In, MarshalAs(UnmanagedType.BStr)]string currentFile, [In] int copiedSectors, [In] int totalSectors)
  722. {
  723. var percentProgress = 0;
  724. if (copiedSectors > 0 && totalSectors > 0)
  725. {
  726. percentProgress = (copiedSectors * 100) / totalSectors;
  727. }
  728. if (!string.IsNullOrEmpty(currentFile))
  729. {
  730. var fileInfo = new FileInfo(currentFile);
  731. _burnData.statusMessage = "Adding \"" + fileInfo.Name + "\" to image...";
  732. //
  733. // report back to the ui
  734. //
  735. _burnData.task = BURN_MEDIA_TASK.BURN_MEDIA_TASK_FILE_SYSTEM;
  736. backgroundBurnWorker.ReportProgress(percentProgress, _burnData);
  737. }
  738. }
  739. #endregion
  740. #region Add/Remove File(s)/Folder(s)
  741. /// <summary>
  742. /// Adds a file to the burn list
  743. /// </summary>
  744. /// <param name="sender"></param>
  745. /// <param name="e"></param>
  746. private void buttonAddFiles_Click(object sender, EventArgs e)
  747. {
  748. if (openFileDialog.ShowDialog(this) == DialogResult.OK)
  749. {
  750. var fileItem = new FileItem(openFileDialog.FileName);
  751. listBoxFiles.Items.Add(fileItem);
  752. UpdateCapacity();
  753. EnableBurnButton();
  754. }
  755. }
  756. /// <summary>
  757. /// Adds a folder to the burn list
  758. /// </summary>
  759. /// <param name="sender"></param>
  760. /// <param name="e"></param>
  761. private void buttonAddFolders_Click(object sender, EventArgs e)
  762. {
  763. if (folderBrowserDialog.ShowDialog(this) == DialogResult.OK)
  764. {
  765. var directoryItem = new DirectoryItem(folderBrowserDialog.SelectedPath);
  766. listBoxFiles.Items.Add(directoryItem);
  767. UpdateCapacity();
  768. EnableBurnButton();
  769. }
  770. }
  771. /// <summary>
  772. /// User wants to remove a file or folder
  773. /// </summary>
  774. /// <param name="sender"></param>
  775. /// <param name="e"></param>
  776. private void buttonRemoveFiles_Click(object sender, EventArgs e)
  777. {
  778. var mediaItem = (IMediaItem)listBoxFiles.SelectedItem;
  779. if (mediaItem == null)
  780. return;
  781. if (MessageBox.Show("Are you sure you want to remove \"" + mediaItem + "\"?",
  782. "Remove item", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
  783. {
  784. listBoxFiles.Items.Remove(mediaItem);
  785. EnableBurnButton();
  786. UpdateCapacity();
  787. }
  788. }
  789. #endregion
  790. #region File ListBox Events
  791. /// <summary>
  792. /// The user has selected a file or folder
  793. /// </summary>
  794. /// <param name="sender"></param>
  795. /// <param name="e"></param>
  796. private void listBoxFiles_SelectedIndexChanged(object sender, EventArgs e)
  797. {
  798. buttonRemoveFiles.Enabled = (listBoxFiles.SelectedIndex != -1);
  799. }
  800. /// <summary>
  801. ///
  802. /// </summary>
  803. /// <param name="sender"></param>
  804. /// <param name="e"></param>
  805. private void listBoxFiles_DrawItem(object sender, DrawItemEventArgs e)
  806. {
  807. var mediaItem = (IMediaItem)listBoxFiles.Items[e.Index];
  808. if (mediaItem == null)
  809. {
  810. return;
  811. }
  812. e.DrawBackground();
  813. if ((e.State & DrawItemState.Focus) != 0)
  814. {
  815. e.DrawFocusRectangle();
  816. }
  817. if (mediaItem.FileIconImage != null)
  818. {
  819. e.Graphics.DrawImage(mediaItem.FileIconImage, new Rectangle(4, e.Bounds.Y + 4, 16, 16));
  820. }
  821. var rectF = new RectangleF(e.Bounds.X + 24, e.Bounds.Y,
  822. e.Bounds.Width - 24, e.Bounds.Height);
  823. var font = new Font(FontFamily.GenericSansSerif, 11);
  824. var stringFormat = new StringFormat
  825. {
  826. LineAlignment = StringAlignment.Center,
  827. Alignment = StringAlignment.Near,
  828. Trimming = StringTrimming.EllipsisCharacter
  829. };
  830. e.Graphics.DrawString(mediaItem.ToString(), font, new SolidBrush(e.ForeColor),
  831. rectF, stringFormat);
  832. }
  833. #endregion
  834. #region Format/Erase the Disc
  835. /// <summary>
  836. /// The user has clicked the "Format" button
  837. /// </summary>
  838. /// <param name="sender"></param>
  839. /// <param name="e"></param>
  840. private void buttonFormat_Click(object sender, EventArgs e)
  841. {
  842. if (devicesComboBox.SelectedIndex == -1)
  843. {
  844. return;
  845. }
  846. _isFormatting = true;
  847. EnableFormatUI(false);
  848. var discRecorder =
  849. (IDiscRecorder2)devicesComboBox.Items[devicesComboBox.SelectedIndex];
  850. backgroundFormatWorker.RunWorkerAsync(discRecorder.ActiveDiscRecorder);
  851. }
  852. /// <summary>
  853. /// Enables/Disables the "Burn" User Interface
  854. /// </summary>
  855. /// <param name="enable"></param>
  856. void EnableFormatUI(bool enable)
  857. {
  858. buttonFormat.Enabled = enable;
  859. checkBoxEjectFormat.Enabled = enable;
  860. checkBoxQuickFormat.Enabled = enable;
  861. }
  862. /// <summary>
  863. /// Worker thread that Formats the Disc
  864. /// </summary>
  865. /// <param name="sender"></param>
  866. /// <param name="e"></param>
  867. private void backgroundFormatWorker_DoWork(object sender, DoWorkEventArgs e)
  868. {
  869. MsftDiscRecorder2 discRecorder = null;
  870. MsftDiscFormat2Erase discFormatErase = null;
  871. try
  872. {
  873. //
  874. // Create and initialize the IDiscRecorder2
  875. //
  876. discRecorder = new MsftDiscRecorder2();
  877. var activeDiscRecorder = (string)e.Argument;
  878. discRecorder.InitializeDiscRecorder(activeDiscRecorder);
  879. //
  880. // Create the IDiscFormat2Erase and set properties
  881. //
  882. discFormatErase = new MsftDiscFormat2Erase
  883. {
  884. Recorder = discRecorder,
  885. ClientName = ClientName,
  886. FullErase = !checkBoxQuickFormat.Checked
  887. };
  888. //
  889. // Setup the Update progress event handler
  890. //
  891. discFormatErase.Update += discFormatErase_Update;
  892. //
  893. // Erase the media here
  894. //
  895. try
  896. {
  897. discFormatErase.EraseMedia();
  898. e.Result = 0;
  899. }
  900. catch (COMException ex)
  901. {
  902. e.Result = ex.ErrorCode;
  903. MessageBox.Show(ex.Message, "IDiscFormat2.EraseMedia failed",
  904. MessageBoxButtons.OK, MessageBoxIcon.Stop);
  905. }
  906. //
  907. // Remove the Update progress event handler
  908. //
  909. discFormatErase.Update -= discFormatErase_Update;
  910. //
  911. // Eject the media
  912. //
  913. if (checkBoxEjectFormat.Checked)
  914. {
  915. discRecorder.EjectMedia();
  916. }
  917. }
  918. catch (COMException exception)
  919. {
  920. //
  921. // If anything happens during the format, show the message
  922. //
  923. MessageBox.Show(exception.Message);
  924. }
  925. finally
  926. {
  927. if (discRecorder != null)
  928. {
  929. Marshal.ReleaseComObject(discRecorder);
  930. }
  931. if (discFormatErase != null)
  932. {
  933. Marshal.ReleaseComObject(discFormatErase);
  934. }
  935. }
  936. }
  937. /// <summary>
  938. /// Event Handler for the Erase Progress Updates
  939. /// </summary>
  940. /// <param name="sender"></param>
  941. /// <param name="elapsedSeconds"></param>
  942. /// <param name="estimatedTotalSeconds"></param>
  943. void discFormatErase_Update([In, MarshalAs(UnmanagedType.IDispatch)] object sender, int elapsedSeconds, int estimatedTotalSeconds)
  944. {
  945. var percent = elapsedSeconds * 100 / estimatedTotalSeconds;
  946. //
  947. // Report back to the UI
  948. //
  949. backgroundFormatWorker.ReportProgress(percent);
  950. }
  951. private void backgroundFormatWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
  952. {
  953. labelFormatStatusText.Text = string.Format("Formatting {0}%...", e.ProgressPercentage);
  954. formatProgressBar.Value = e.ProgressPercentage;
  955. }
  956. private void backgroundFormatWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
  957. {
  958. labelFormatStatusText.Text = (int)e.Result == 0 ?
  959. "Finished Formatting Disc!" : "Error Formatting Disc!";
  960. formatProgressBar.Value = 0;
  961. _isFormatting = false;
  962. EnableFormatUI(true);
  963. }
  964. #endregion
  965. /// <summary>
  966. /// Called when user selects a new tab
  967. /// </summary>
  968. /// <param name="sender"></param>
  969. /// <param name="e"></param>
  970. private void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
  971. {
  972. //
  973. // Prevent page from changing if we're burning or formatting.
  974. //
  975. if (_isBurning || _isFormatting)
  976. {
  977. e.Cancel = true;
  978. }
  979. }
  980. /// <summary>
  981. /// Get the burn verification level when the user changes the selection
  982. /// </summary>
  983. /// <param name="sender"></param>
  984. /// <param name="e"></param>
  985. private void comboBoxVerification_SelectedIndexChanged(object sender, EventArgs e)
  986. {
  987. _verificationLevel = (IMAPI_BURN_VERIFICATION_LEVEL)comboBoxVerification.SelectedIndex;
  988. }
  989. }
  990. }