TXPBurn

What is it?

The TXPBurn component allows your Delphi or C# programs to burn files to CDR/W discs on a Window XP® or Windows 2003 Server system.  This component does not work for systems which have a different OS installed; though it will detect that case and give a reasonable error message.

How is this different than TCDBurner?

Our other component, TCDBurner, allows CDs to be burned by invoking the Windows XP® burner wizard, which is usually adequate; however, sometimes it's nice to be able to put your own UI on top of burning CDs.  Think about snazzy progress bars, professional looking dialogs and consistency with the rest of your program. 

Download

Delphi 6,7 - TXPBurn_v2.zip

Need the .NET equivalent? See xpburn.msi and The GotDotNet Project workspace

Installation is easy, just copy the .pas files and the .dcr file to a convenient directory, perhaps delphi6\lib\thirdparty\.  Choose the Install | Component menu option from the Delphi IDE, then browse to that directory.  Change the filter on the browse dialog to .pas files, select the XPBurn.pas file included with the component, and then build!  If successful, you should see the following dialog:

License

The component is freely redistributable in compiled form to any party and it may be used and packaged along with any software.  The component may not be redistributed in source form, nor may it be distributed under any other license (e.g. GPL).  If you're providing a source distribution of your application, please offer the user a link to this page.

Why Free?

I figured I'd sell it (and buy my partner something nice for putting up with my late hours ;-) but she said that I should just give it away. 

Thanks and Greets!

Bayden Systems gratefully acknowledges the assistance of Roger Harris in developing this component.  Roger tracked down a number of pesky bugs in the component and provided source-level fixes.  He also contributed the working sample program.

Known issues

Please post feedback or bug reports here.


Developer's guide

Type TXPBurn = class(TComponent)

Methods

constructor Create(AOwner: TComponent); Pass a TForm in as the owner.  If you need a non-visual version, register, and we'll talk.
procedure AddFile(filename, nameOnCD: string); This procedure will 'add files' onto a queue. The first parameter is the name of that file on some media, the second parameter indicates whether the file will be named differently on disc.  Notice that the nameOnCD parameter may include drive information, or may not, but either way it must include a filename.  For example, nameOnCD may be 'c:\temp\foo.pas' or 'temp\foo.pas', but cannot be 'c:\temp\'.

Precondition: File specified by filename must exist on disc
Postcondition: File table is updated with information (note that this information isn't fully resolved until RecordDisc is called).  Therefore, if filename is deleted after this procedure but prior to RecordDisc being called, RecordDisc will fail.

procedure AddFolder(folderName, folderNameOnCD: string); This procedure is not yet implemented.  It can be easily mimicked by recursively calling AddFile on a directory.
procedure Eject; This procedure causes the active disc recorder to eject its media.  The recorder must not currently be burning, and it must be able to be opened for exclusive access.  That is, it must not be recording from any program.

Precondition: Burner is not currently burning. The discRecorder has been set up.

procedure Erase(eraseType: TEraseKind); This procedure will erase the media in the active recorder.  The selected disc recorder must be a CDRW recorder, and the current media must be a CDRW.

Precondition: disc recorder must be CDRW, current media must be CDRW.

procedure RecordDisc(simulate, ejectAfterBurn: boolean); This procedure actually starts off a series of events.  First, it stages the current list of files built up through the AddFile and RemoveFile procedures.  This is the one bit of work for which there is no progress reported, though it tends to be fairly speedy.  Next all of the data is burned to the CD through several stages: adding data, preparing burn, writing data, and closing the disc.  Notice that this is all done on a separate thread such that the RecordDisc procedure returns immediately after spawning that thread.  The only possible interaction after this procedure has been initiated is to cancel the burn.  This is done through the Cancel property.  If this occurs, an exception will be thrown.  The progress of the burn may be tracked through the events defined below.  The simulate parameter indicates that all of the actions required to write the CD be performed, except for the actual burn.  This can be useful to see if everything is set up correctly.  The ejectAfterBurn parameter indicates whether the CD should be ejected from the recorder when it has finished burning.

Precondition: Every file in the current file list exists on disc.  An active recorder has been specified.  The media to be written has been inserted into the CD drive.  The media is blank.

procedure RemoveFile(filename, nameOnCD: string); This procedure removes files from the list to be added to the CD. The filename and nameOnCD parameters passed in should be identical to the filename and nameOnCD parameters that were passed to the AddFile method. This method will fail if filename is nil, or if the file isn't located in the list.

Precondition: Filename must not be nil, and must exist in the file table
Postcondition: File is removed from the file table

 

Properties

property ActiveFormat: TRecordType; Reads or writes the active format for recording.  This is largely useless in the current implementation as the only valid recording type is afData (afMusic is currently unsupported).
property AudioGapSize: byte; Reads the current recorder setting for the number of blank audio blocks to put in between tracks when writing a music CD.  The default value is 150.
property BurnerDrive: string; Reads or writes the current burner drive.  Depending on the computer that the component is running on the string returned may either be a drive letter, or a fully qualified device name (/dev/CDRom1).  In order to write to this value, use one of the strings returned by RecorderDrives.

This property affects several of the other properties, including AudioGapSize, DiscSpace, FreeDiscSpace, MaxWriteSpeed, MediaInfo, ProductID, RecorderType, Revision, Vendor, VolumeName, and WriteSpeed.  It also affects the target of the methods Eject, Erase, and RecordDisc.

property Cancel: boolean; Reads or writes the current cancel state of the component.  If this value is set to true, then RecordDisc will stop executing and throw an exception indicating that the user cancelled the burn.
property DiscSpace: integer; Reads the amount of space on the disc currently inserted in the recorder.
property FilesToBurn: TStringList; Reads a copy of the list of files that are currently set to be burned to CD.  Notice that strings member of the TStringList contains the filenames, where the Objects member contains the name on CD. 

Changing this list will not affect the list stored internally by the component.  In order to change that list, use the AddFile and RemoveFile procedures.

property FreeDiscSpace: integer; Reads the amount of free disc space on a given CD.  Notice that this number doesn't change based on the files which are currently in the file table (but not burned to CD). 
property IsBurning: boolean; Reads whether the currently selected BurnerDrive is burning a CD.  Notice that this value is only set by this component, so if another program is writing to a CD on the currently selected drive this value will be set to false.  This property is read-only; however, you can use the Cancel property to cancel an active burn (so long as it was initiated by this component).
property LastError: string; In the event that an exception occurs, this property can be queried to get a human-readable message which can be shown to the user.
property MediaInfo: TMedia; Reads information about the media inserted in the currently selected recorder.  This information includes whether the CD is blank, writable, erasable (RW), or usable.
property MaxWriteSpeed: cardinal; Reads the maximum write speed for the currently selected recorder.  This number will be 4, 8, 10, etc. representing a 4x, 8x, or 10x CD recorder drive.
property NumberOfDrives: integer; Reads the current number of drives on the system.  It's possible that this number will change throughout the course of the existence of the component if a USB device (for example), is added or removed.  One of the events below (RecorderChange) is meant to indicate that this may have happened.
property ProductID: string; Reads the product ID of the currently selected recorder.  This string is set by the manufacturer of the recorder.
property RecorderDrives: TStringList; Reads a copy of the recorder drives available on the system.  This may change in the same way that the NumberOfDrives property may change.  Use the strings returned in this TStringList to set the BurnerDrive property.
property RecorderType: TRecorderType; Reads the currently selected burner's type.  This may be rtCDR or rtCDRW.  If it's rtCDRW then the recorder supports erasing media, if it's rtCDR then it doesn't.
property Revision: string; Reads the revision of the currently selected recorder.  This string is set by the manufacturer of the recorder (through the driver).
property Vendor: string; Reads the vendor of the currently selected recorder.  This string is set by the manufacturer of the recorder.
property VolumeName: string; Reads the volume name of the CD in the currently selected recorder.  This property will be read/write in the future.
property WriteSpeed: cardinal; Reads the currently selected recorder's write speed.  This is usually equal to the MaxWriteSpeed, however, it is occasionally lower if the CD recorder is unreliable at it's max speed.  This property will be read/write in the future.

 

Events

property OnRecorderChange: TNotifyPnPActivity; This event occurs when some sort of plug and play activity has been detected.  It may change both the number of CD recorders, the number of recorder drives, and possibly, it may indicate the removal of the recorder on which the component is currently acting.
property OnAddProgress: TNotifyCDProgress; This event occurs as the first step of the burn process, while data which has been added through AddFile is being staged.
property OnBlockProgress: TNotifyCDProgress; This event is the third step in the burn process (for data CDs), and is the main burning phase.  While this phase executes, the staged area will be written to the CD.
property OnTrackProgress: TNotifyCDProgress; This event is the third step in the burn process (for music CDs).  Currently it will never be invoked.
property OnPreparingBurn: TNotifyEstimatedTime; This event is the second step in the burn process, it is called once with an estimated time it will take before the recorder starts writing data to the CD.
property OnClosingDisc: TNotifyEstimatedTime; This event occurs as the fourth and final step of the burn process.  It is called once with an estimated time it will take before the burn is completely finished (it is during this step that the recorder is writing the table of contents of the CD).
property OnBurnComplete: TNotifyCompletionStatus; This event occurs after all four stages of the burn process have completed.  After this event occurs the burner may burn again.
property OnEraseComplete: TNotifyCompletionStatus; This event occurs after a full erase has completed.  It is not called for a quick erase.

 

Type MessageQueue = class(TForm)

Ignore this type, it is used only internally for synchronization purposes between the burn thread and the thread which created the component.

Type TSupportedRecordTypes = (sfNone = 0, sfData = 1, sfMusic = 2, sfBoth = 3);

Ignore this type for the moment, in the future it will be returned by a property which will indicate which types of recording operations are permitted by the active recorder.

Type TRecordType = (afMusic, afData);

This type is returned by the ActiveFormat property and indicates whether the component is set to write data or music to the CD.

Type TEraseKind = (ekQuick, ekFull);

This type is passed as a parameter to the Erase procedure.  If set to ekQuick, on the table of contents is erased, all of the data still exists on the CD though it is inaccessible by normal means (and may be overwritten with a subsequent write).  If set to ekFull all data is erased from each track of the CD.

TRecorderType = (rtCDR, rtCDRW);

This type is returned by the RecorderType property and indicates whether the active recorder can both write and erase CDs (rtCDRW) or only write them (rtCDR).

TMedia = RECORD
  isBlank: boolean;
  isRW: boolean;
  isWritable: boolean;
  isUsable: boolean;
end;

This type is returned by the MediaInfo property and contains information about the media (CD) which is currently inserted into the recorder. 

Error Handling

Currently, all exceptions thrown are of the form (LastError will contain a string representation of the last error prior to the exception):

EBurnException = class(Exception);

Note that for stringent error handling, this component shouldn't be created through the designer.  That is, exceptions can be thrown from the constructor (I may change this in future versions).  For example, if no recorder drive is present on the system, and exception will be thrown when the component is created.