libburner.c File Reference

#include "../libburn/libburn.h"
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>

Include dependency graph for libburner.c:

Go to the source code of this file.

Functions

int libburner_aquire_by_adr (char *drive_adr)
 If the persistent drive address is known, then this approach is much more un-obtrusive to the systemwide livestock of drives.
int libburner_aquire_by_driveno (int *driveno)
 This method demonstrates how to use libburn without knowing a persistent drive address in advance.
int libburner_aquire_drive (char *drive_adr, int *driveno)
 You need to aquire a drive before burning.
int libburner_blank_disc (struct burn_drive *drive, int blank_fast)
 Makes a previously used CD-RW ready for thorough re-usal.
int libburner_format (struct burn_drive *drive)
 Formats unformatted DVD-RW to profile 0013h "Restricted Overwrite" which needs no blanking for re-use but is not capable of multi-session.
int libburner_payload (struct burn_drive *drive, char source_adr[][4096], int source_adr_count, int multi, int simulate_burn, int all_tracks_type)
 Brings preformatted track images (ISO 9660, audio, .
int libburner_setup (int argc, char **argv)
 Converts command line arguments into above setup parameters.
int main (int argc, char **argv)

Variables

static struct burn_drive_infodrive_list
 Overview.
static unsigned int drive_count
 If you start a long lasting operation with drive_count > 1 then you are not friendly to the users of other drives on those systems.
static int drive_is_grabbed = 0
 This variable indicates wether the drive is grabbed and must be finally released.
static int current_profile = -1
 A number and a text describing the type of media in aquired drive.
static char current_profile_name [80] = {""}
static char drive_adr [BURN_DRIVE_ADR_LEN] = {""}
 The setup parameters of libburner.
static int driveno = 0
static int do_blank = 0
static char source_adr [99][4096]
static int source_adr_count = 0
static int do_multi = 0
static int simulate_burn = 0
static int all_tracks_type = BURN_MODE1


Function Documentation

int libburner_aquire_by_adr ( char *  drive_adr  ) 

If the persistent drive address is known, then this approach is much more un-obtrusive to the systemwide livestock of drives.

Only the given drive device will be opened during this procedure.

Definition at line 123 of file libburner.c.

References BURN_DRIVE_ADR_LEN, burn_drive_convert_fs_adr(), burn_drive_scan_and_grab(), and drive_is_grabbed.

Referenced by libburner_aquire_drive().

00124 {
00125     int ret;
00126     char libburn_drive_adr[BURN_DRIVE_ADR_LEN];
00127 
00128     /* Some not-so-harmless drive addresses get blocked in this demo */
00129     if (strncmp(drive_adr, "stdio:/dev/fd/", 14) == 0 ||
00130         strcmp(drive_adr, "stdio:-") == 0) {
00131         fprintf(stderr, "Will not work with pseudo-drive '%s'\n",
00132             drive_adr);
00133         return 0;
00134     }
00135 
00136     /* This tries to resolve links or alternative device files */
00137     ret = burn_drive_convert_fs_adr(drive_adr, libburn_drive_adr);  
00138     if (ret<=0) {
00139         fprintf(stderr, "Address does not lead to a CD burner: '%s'\n",
00140                  drive_adr);
00141         return 0;
00142     }
00143     fprintf(stderr,"Aquiring drive '%s' ...\n", libburn_drive_adr);
00144     ret = burn_drive_scan_and_grab(&drive_list, libburn_drive_adr, 1);
00145     if (ret <= 0) {
00146         fprintf(stderr,"FAILURE with persistent drive address  '%s'\n",
00147             libburn_drive_adr);
00148     } else {
00149         fprintf(stderr,"Done\n");
00150         drive_is_grabbed = 1;
00151     }
00152     return ret;
00153 }

int libburner_aquire_by_driveno ( int *  driveno  ) 

This method demonstrates how to use libburn without knowing a persistent drive address in advance.

It has to make sure that after assessing the list of available drives, all unwanted drives get closed again. As long as they are open, no other libburn instance can see them. This is an intended locking feature. The application is responsible for giving up the locks by either burn_drive_release() (only after burn_drive_grab() !), burn_drive_info_forget(), burn_drive_info_free(), or burn_finish().

Parameters:
driveno the index number in libburn's drive list. This will get set to 0 on success and will then be the drive index to use in the further dourse of processing.
Returns:
1 success , <= 0 failure

Definition at line 168 of file libburner.c.

References BURN_DRIVE_ADR_LEN, burn_drive_get_adr(), burn_drive_grab(), burn_drive_info_forget(), burn_drive_scan(), burn_drive_info::drive, drive_count, drive_is_grabbed, burn_drive_info::product, and burn_drive_info::vendor.

Referenced by libburner_aquire_drive().

00169 {
00170     char adr[BURN_DRIVE_ADR_LEN];
00171     int ret, i;
00172 
00173     printf("Beginning to scan for devices ...\n");
00174     while (!burn_drive_scan(&drive_list, &drive_count))
00175         usleep(100002);
00176     if (drive_count <= 0 && *driveno >= 0) {
00177         printf("FAILED (no drives found)\n");
00178         return 0;
00179     }
00180     printf("Done\n");
00181 
00182     /*
00183     Interactive programs may choose the drive number at this moment.
00184 
00185     drive[0] to drive[drive_count-1] are struct burn_drive_info
00186     as defined in  libburn/libburn.h  . This structure is part of API
00187     and thus will strive for future compatibility on source level.
00188     Have a look at the info offered.
00189     Caution: do not take .location for drive address. Always use
00190         burn_drive_get_adr() or you might become incompatible
00191         in future.
00192     Note: bugs with struct burn_drive_info - if any - will not be
00193         easy to fix. Please report them but also strive for
00194         workarounds on application level.
00195     */
00196     printf("\nOverview of accessible drives (%d found) :\n",
00197         drive_count);
00198     printf("-----------------------------------------------------------------------------\n");
00199     for (i = 0; i < drive_count; i++) {
00200         if (burn_drive_get_adr(&(drive_list[i]), adr) <=0)
00201             strcpy(adr, "-get_adr_failed-");
00202         printf("%d  --drive '%s'  :  '%s'  '%s'\n",
00203             i,adr,drive_list[i].vendor,drive_list[i].product);
00204     }
00205     printf("-----------------------------------------------------------------------------\n\n");
00206 
00207     /*
00208     On multi-drive systems save yourself from sysadmins' revenge.
00209 
00210     Be aware that you hold reserved all available drives at this point.
00211     So either make your choice quick enough not to annoy other system
00212     users, or set free the drives for a while.
00213 
00214     The tested way of setting free all drives is to shutdown the library
00215     and to restart when the choice has been made. The list of selectable
00216     drives should also hold persistent drive addresses as obtained
00217     above by burn_drive_get_adr(). By such an address one may use
00218     burn_drive_scan_and_grab() to finally aquire exactly one drive.
00219 
00220     A not yet tested shortcut should be to call burn_drive_info_free()
00221     and to call either burn_drive_scan() or burn_drive_scan_and_grab()
00222     before accessing any drives again.
00223 
00224     In both cases you have to be aware that the desired drive might get
00225     aquired in the meantime by another user resp. libburn process.
00226     */
00227 
00228     /* We already made our choice via command line. (default is 0)
00229        So we just have to keep our desired drive and drop all others.
00230        No other libburn instance will have a chance to steal our drive.
00231      */
00232     if (*driveno < 0) {
00233         printf("Pseudo-drive \"-\" given : bus scanning done.\n");
00234         return 2; /* the program will end after this */
00235     }
00236     if (drive_count <= *driveno) {
00237         fprintf(stderr,
00238             "Found only %d drives. Number %d not available.\n",
00239             drive_count, *driveno);
00240         return 0; /* the program will end after this */
00241     }
00242 
00243     /* Drop all drives which we do not want to use */
00244     for (i = 0; i < drive_count; i++) {
00245         if (i == *driveno) /* the one drive we want to keep */
00246     continue;
00247         ret = burn_drive_info_forget(&(drive_list[i]),0);
00248         if (ret != 1)
00249             fprintf(stderr, "Cannot drop drive %d. Please report \"ret=%d\" to libburn-hackers@pykix.org\n",
00250                 i, ret);
00251         else
00252             printf("Dropped unwanted drive %d\n",i);
00253     }
00254     /* Make the one we want ready for blanking or burning */
00255     ret= burn_drive_grab(drive_list[*driveno].drive, 1);
00256     if (ret != 1)
00257         return 0;
00258     drive_is_grabbed = 1;
00259     return 1;
00260 }

int libburner_aquire_drive ( char *  drive_adr,
int *  driveno 
)

You need to aquire a drive before burning.

The API offers this as one compact call and alternatively as application controllable gestures of whitelisting, scanning for drives and finally grabbing one of them.

If you have a persistent address of the drive, then the compact call is to prefer because it only touches one drive. On modern Linux kernels, there should be no fatal disturbance of ongoing burns of other libburn instances with any of our approaches. We use open(O_EXCL) by default. On /dev/hdX it should cooperate with growisofs and some cdrecord variants. On /dev/sgN versus /dev/scdM expect it not to respect other programs.

Definition at line 101 of file libburner.c.

References burn_disc_get_profile(), current_profile, current_profile_name, burn_drive_info::drive, libburner_aquire_by_adr(), and libburner_aquire_by_driveno().

Referenced by main().

00102 {
00103     int ret;
00104 
00105     if(drive_adr != NULL && drive_adr[0] != 0)
00106         ret = libburner_aquire_by_adr(drive_adr);
00107     else
00108         ret = libburner_aquire_by_driveno(driveno);
00109     if (ret <= 0)
00110         return ret;
00111     burn_disc_get_profile(drive_list[0].drive, &current_profile,
00112                  current_profile_name);
00113     if (current_profile_name[0])
00114         printf("Detected media type: %s\n", current_profile_name);
00115     return 1;
00116 }

int libburner_blank_disc ( struct burn_drive *  drive,
int  blank_fast 
)

Makes a previously used CD-RW ready for thorough re-usal.

To our knowledge it is hardly possible to abort an ongoing blank operation because after start it is entirely handled by the drive. So expect signal handling to wait the normal blanking timespan until it can allow the process to end. External kill -9 will not help the drive.

Definition at line 270 of file libburner.c.

References BURN_DISC_APPENDABLE, BURN_DISC_BLANK, BURN_DISC_EMPTY, burn_disc_erasable(), burn_disc_erase(), BURN_DISC_FULL, burn_disc_get_status(), burn_drive_get_status(), BURN_DRIVE_IDLE, current_profile, burn_progress::sector, and burn_progress::sectors.

Referenced by main().

00271 {
00272     enum burn_disc_status disc_state;
00273     struct burn_progress p;
00274     double percent = 1.0;
00275 
00276     disc_state = burn_disc_get_status(drive);
00277     printf(
00278         "Drive media status:  %d  (see  libburn/libburn.h  BURN_DISC_*)\n",
00279         disc_state);
00280     if (current_profile == 0x13) {
00281         ; /* formatted DVD-RW will get blanked to sequential state */
00282     } else if (disc_state == BURN_DISC_BLANK) {
00283         fprintf(stderr,
00284           "IDLE: Blank media detected. Will leave it untouched\n");
00285         return 2;
00286     } else if (disc_state == BURN_DISC_FULL ||
00287            disc_state == BURN_DISC_APPENDABLE) {
00288         ; /* this is what libburner is willing to blank */
00289     } else if (disc_state == BURN_DISC_EMPTY) {
00290         fprintf(stderr,"FATAL: No media detected in drive\n");
00291         return 0;
00292     } else {
00293         fprintf(stderr,
00294             "FATAL: Unsuitable drive and media state\n");
00295         return 0;
00296     }
00297     if(!burn_disc_erasable(drive)) {
00298         fprintf(stderr,
00299             "FATAL : Media is not of erasable type\n");
00300         return 0;
00301     }
00302     printf(
00303           "Beginning to %s-blank media.\n", (blank_fast?"fast":"full"));
00304     burn_disc_erase(drive, blank_fast);
00305     sleep(1);
00306     while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
00307         if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
00308             percent = 1.0 + ((double) p.sector+1.0)
00309                      / ((double) p.sectors) * 98.0;
00310         printf("Blanking  ( %.1f%% done )\n", percent);
00311         sleep(1);
00312     }
00313     printf("Done\n");
00314     return 1;
00315 }

int libburner_format ( struct burn_drive *  drive  ) 

Formats unformatted DVD-RW to profile 0013h "Restricted Overwrite" which needs no blanking for re-use but is not capable of multi-session.

Expect a behavior similar to blanking with unusual noises from the drive.

Formats unformatted BD-RE to default size. This will allocate some reserve space, test for bad blocks and make the media ready for writing. Expect a very long run time.

Formats unformatted blank BD-R to hold a default amount of spare blocks for eventual mishaps during writing. If BD-R get written without being formatted, then they get no such reserve and will burn at full speed.

Definition at line 330 of file libburner.c.

References BURN_DISC_BLANK, burn_disc_format(), burn_disc_get_formats(), burn_disc_get_profile(), burn_disc_get_status(), burn_drive_get_status(), BURN_DRIVE_IDLE, BURN_FORMAT_IS_UNFORMATTED, current_profile, current_profile_name, burn_progress::sector, and burn_progress::sectors.

Referenced by main().

00331 {
00332     struct burn_progress p;
00333     double percent = 1.0;
00334     int ret, status, num_formats, format_flag= 0;
00335     off_t size = 0;
00336     unsigned dummy;
00337     enum burn_disc_status disc_state;
00338 
00339     if (current_profile == 0x13) {
00340         fprintf(stderr, "IDLE: DVD-RW media is already formatted\n");
00341         return 2;
00342     } else if (current_profile == 0x41 || current_profile == 0x43) {
00343         disc_state = burn_disc_get_status(drive);
00344         if (disc_state != BURN_DISC_BLANK && current_profile == 0x41) {
00345             fprintf(stderr,
00346                 "FATAL: BD-R is not blank. Cannot format.\n");
00347             return 0;
00348         }
00349         ret = burn_disc_get_formats(drive, &status, &size, &dummy,
00350                                 &num_formats);
00351         if (ret > 0 && status != BURN_FORMAT_IS_UNFORMATTED) {
00352             fprintf(stderr,
00353                 "IDLE: BD media is already formatted\n");
00354             return 2;
00355         }
00356         size = 0;           /* does not really matter */
00357         format_flag = 3<<1; /* format to default size, no quick */
00358     } else if (current_profile == 0x14) { /* sequential DVD-RW */
00359         size = 128 * 1024 * 1024;
00360         format_flag = 1; /* write initial 128 MiB */
00361     } else {
00362         fprintf(stderr, "FATAL: Can only format DVD-RW or BD\n");
00363         return 0;
00364     }
00365 
00366     printf("Beginning to format media.\n");
00367     burn_disc_format(drive, size, format_flag);
00368 
00369     sleep(1);
00370     while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
00371         if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
00372             percent = 1.0 + ((double) p.sector+1.0)
00373                      / ((double) p.sectors) * 98.0;
00374         printf("Formatting  ( %.1f%% done )\n", percent);
00375         sleep(1);
00376     }
00377     burn_disc_get_profile(drive_list[0].drive, &current_profile,
00378                  current_profile_name);
00379     if (current_profile == 0x14 || current_profile == 0x13)
00380         printf("Media type now: %4.4xh  \"%s\"\n",
00381                  current_profile, current_profile_name);
00382     if (current_profile == 0x14) {
00383         fprintf(stderr,
00384           "FATAL: Failed to change media profile to desired value\n");
00385         return 0;
00386     }
00387     return 1;
00388 }

int libburner_payload ( struct burn_drive *  drive,
char  source_adr[][4096],
int  source_adr_count,
int  multi,
int  simulate_burn,
int  all_tracks_type 
)

Brings preformatted track images (ISO 9660, audio, .

..) onto media. To make sure a data image is fully readable on any Linux machine, this function adds 300 kiB of padding to the (usualy single) track. Audio tracks get padded to complete their last sector. A fifo of 4 MB is installed between each track and its data source. Each of the 4 MB buffers gets allocated automatically as soon as a track begins to be processed and it gets freed as soon as the track is done. The fifos do not wait for buffer fill but writing starts immediately.

In case of external signals expect abort handling of an ongoing burn to last up to a minute. Wait the normal burning timespan before any kill -9.

For simplicity, this function allows memory leaks in case of failure. In apps which do not abort immediately, one should clean up better.

Definition at line 406 of file libburner.c.

References BURN_AUDIO, burn_disc_add_session(), BURN_DISC_APPENDABLE, BURN_DISC_BLANK, burn_disc_create(), BURN_DISC_EMPTY, burn_disc_erasable(), burn_disc_free(), BURN_DISC_FULL, burn_disc_get_status(), burn_disc_write(), burn_drive_get_status(), BURN_DRIVE_IDLE, burn_drive_set_speed(), BURN_DRIVE_SPAWNING, burn_fd_source_new(), burn_fifo_inquire_status(), burn_fifo_source_new(), BURN_MODE1, BURN_POS_END, BURN_REASONS_LEN, burn_session_add_track(), burn_session_create(), burn_session_free(), burn_source_free(), BURN_SOURCE_OK, burn_track_create(), burn_track_define_data(), burn_track_free(), burn_track_set_source(), BURN_WRITE_NONE, burn_write_opts_auto_write_type(), burn_write_opts_free(), burn_write_opts_new(), burn_write_opts_set_multi(), burn_write_opts_set_perform_opc(), burn_write_opts_set_simulate(), burn_write_opts_set_underrun_proof(), current_profile, burn_progress::sector, burn_progress::sectors, and burn_progress::track.

Referenced by main().

00409 {
00410     struct burn_source *data_src, *fifo_src[99];
00411     struct burn_disc *target_disc;
00412     struct burn_session *session;
00413     struct burn_write_opts *burn_options;
00414     enum burn_disc_status disc_state;
00415     struct burn_track *track, *tracklist[99];
00416     struct burn_progress progress;
00417     time_t start_time;
00418     int last_sector = 0, padding = 0, trackno, unpredicted_size = 0, fd;
00419     int fifo_chunksize = 2352, fifo_chunks = 1783; /* ~ 4 MB fifo */
00420     off_t fixed_size;
00421     char *adr, reasons[BURN_REASONS_LEN];
00422     struct stat stbuf;
00423 
00424     if (all_tracks_type != BURN_AUDIO) {
00425         all_tracks_type = BURN_MODE1;
00426         /* a padding of 300 kiB helps to avoid the read-ahead bug */
00427         padding = 300*1024;
00428         fifo_chunksize = 2048;
00429         fifo_chunks = 2048; /* 4 MB fifo */
00430     }
00431 
00432     target_disc = burn_disc_create();
00433     session = burn_session_create();
00434     burn_disc_add_session(target_disc, session, BURN_POS_END);
00435 
00436     for (trackno = 0 ; trackno < source_adr_count; trackno++) {
00437       tracklist[trackno] = track = burn_track_create();
00438       burn_track_define_data(track, 0, padding, 1, all_tracks_type);
00439 
00440       /* Open file descriptor to source of track data */
00441       adr = source_adr[trackno];
00442       fixed_size = 0;
00443       if (adr[0] == '-' && adr[1] == 0) {
00444         fd = 0;
00445       } else {
00446         fd = open(adr, O_RDONLY);
00447         if (fd>=0)
00448             if (fstat(fd,&stbuf)!=-1)
00449                 if((stbuf.st_mode&S_IFMT)==S_IFREG)
00450                     fixed_size = stbuf.st_size;
00451       }
00452       if (fixed_size==0)
00453         unpredicted_size = 1;
00454 
00455       /* Convert this filedescriptor into a burn_source object */
00456       data_src = NULL;
00457       if (fd>=0)
00458         data_src = burn_fd_source_new(fd, -1, fixed_size);
00459       if (data_src == NULL) {
00460         fprintf(stderr,
00461                "FATAL: Could not open data source '%s'.\n",adr);
00462         if(errno!=0)
00463             fprintf(stderr,"(Most recent system error: %s )\n",
00464                 strerror(errno));
00465         return 0;
00466       }
00467       /* Install a fifo object on top of that data source object */
00468       fifo_src[trackno] = burn_fifo_source_new(data_src,
00469                     fifo_chunksize, fifo_chunks, 0);
00470       if (fifo_src[trackno] == NULL) {
00471         fprintf(stderr,
00472             "FATAL: Could not create fifo object of 4 MB\n");
00473         return 0;
00474       }
00475 
00476       /* Use the fifo object as data source for the track */
00477       if (burn_track_set_source(track, fifo_src[trackno])
00478                              != BURN_SOURCE_OK) {
00479         fprintf(stderr,
00480                "FATAL: Cannot attach source object to track object\n");
00481         return 0;
00482       }
00483 
00484       burn_session_add_track(session, track, BURN_POS_END);
00485       printf("Track %d : source is '%s'\n", trackno+1, adr);
00486 
00487       /* Give up local reference to the data burn_source object */
00488       burn_source_free(data_src);
00489       
00490         } /* trackno loop end */
00491 
00492     /* Evaluate drive and media */
00493     disc_state = burn_disc_get_status(drive);
00494     if (disc_state != BURN_DISC_BLANK &&
00495         disc_state != BURN_DISC_APPENDABLE) {
00496         if (disc_state == BURN_DISC_FULL) {
00497             fprintf(stderr, "FATAL: Closed media with data detected. Need blank or appendable media.\n");
00498             if (burn_disc_erasable(drive))
00499                 fprintf(stderr, "HINT: Try --blank_fast\n\n");
00500         } else if (disc_state == BURN_DISC_EMPTY) 
00501             fprintf(stderr,"FATAL: No media detected in drive\n");
00502         else
00503             fprintf(stderr,
00504              "FATAL: Cannot recognize state of drive and media\n");
00505         return 0;
00506     }
00507 
00508     burn_options = burn_write_opts_new(drive);
00509     burn_write_opts_set_perform_opc(burn_options, 0);
00510     burn_write_opts_set_multi(burn_options, !!multi);
00511     if(simulate_burn)
00512         printf("\n*** Will TRY to SIMULATE burning ***\n\n");
00513     burn_write_opts_set_simulate(burn_options, simulate_burn);
00514     burn_drive_set_speed(drive, 0, 0);
00515     burn_write_opts_set_underrun_proof(burn_options, 1);
00516     if (burn_write_opts_auto_write_type(burn_options, target_disc,
00517                     reasons, 0) == BURN_WRITE_NONE) {
00518         fprintf(stderr, "FATAL: Failed to find a suitable write mode with this media.\n");
00519         fprintf(stderr, "Reasons given:\n%s\n", reasons);
00520         return 0;
00521     }
00522 
00523     printf("Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n");
00524     start_time = time(0);
00525     burn_disc_write(burn_options, target_disc);
00526 
00527     burn_write_opts_free(burn_options);
00528     while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING)
00529         usleep(100002);
00530     while (burn_drive_get_status(drive, &progress) != BURN_DRIVE_IDLE) {
00531         if (progress.sectors <= 0 ||
00532             (progress.sector >= progress.sectors - 1 &&
00533                  !unpredicted_size) ||
00534             (unpredicted_size && progress.sector == last_sector))
00535             printf(
00536                  "Thank you for being patient since %d seconds.",
00537                  (int) (time(0) - start_time));
00538         else if(unpredicted_size)
00539             printf("Track %d : sector %d", progress.track+1,
00540                 progress.sector);
00541         else
00542             printf("Track %d : sector %d of %d",progress.track+1,
00543                 progress.sector, progress.sectors);
00544         last_sector = progress.sector;
00545         if (progress.track >= 0 && progress.track < source_adr_count) {
00546             int size, free_bytes, ret;
00547             char *status_text;
00548     
00549             ret = burn_fifo_inquire_status(
00550                 fifo_src[progress.track], &size, &free_bytes,
00551                 &status_text);
00552             if (ret >= 0 ) 
00553                 printf("  [fifo %s, %2d%% fill]", status_text,
00554                     (int) (100.0 - 100.0 *
00555                         ((double) free_bytes) /
00556                         (double) size));
00557         } 
00558         printf("\n");
00559         sleep(1);
00560     }
00561     printf("\n");
00562 
00563     for (trackno = 0 ; trackno < source_adr_count; trackno++) {
00564         burn_source_free(fifo_src[trackno]);
00565         burn_track_free(tracklist[trackno]);
00566     }
00567     burn_session_free(session);
00568     burn_disc_free(target_disc);
00569     if (multi && current_profile != 0x1a && current_profile != 0x13 &&
00570         current_profile != 0x12 && current_profile != 0x43) 
00571             /* not with DVD+RW, formatted DVD-RW, DVD-RAM, BD-RE */
00572         printf("NOTE: Media left appendable.\n");
00573     if (simulate_burn)
00574         printf("\n*** Did TRY to SIMULATE burning ***\n\n");
00575     return 1;
00576 }

int libburner_setup ( int  argc,
char **  argv 
)

Converts command line arguments into above setup parameters.

Definition at line 592 of file libburner.c.

References all_tracks_type, BURN_AUDIO, BURN_DRIVE_ADR_LEN, do_blank, do_multi, drive_adr, driveno, simulate_burn, source_adr, and source_adr_count.

Referenced by main().

00593 {
00594     int i, insuffient_parameters = 0, print_help = 0;
00595 
00596     for (i = 1; i < argc; ++i) {
00597         if (!strcmp(argv[i], "--audio")) {
00598             all_tracks_type = BURN_AUDIO;
00599 
00600         } else if (!strcmp(argv[i], "--blank_fast")) {
00601             do_blank = 1;
00602 
00603         } else if (!strcmp(argv[i], "--blank_full")) {
00604             do_blank = 2;
00605 
00606         } else if (!strcmp(argv[i], "--burn_for_real")) {
00607             simulate_burn = 0;
00608 
00609         } else if (!strcmp(argv[i], "--drive")) {
00610             ++i;
00611             if (i >= argc) {
00612                 fprintf(stderr,"--drive requires an argument\n");
00613                 return 1;
00614             } else if (strcmp(argv[i], "-") == 0) {
00615                 drive_adr[0] = 0;
00616                 driveno = -1;
00617             } else if (isdigit(argv[i][0])) {
00618                 drive_adr[0] = 0;
00619                 driveno = atoi(argv[i]);
00620             } else {
00621                 if(strlen(argv[i]) >= BURN_DRIVE_ADR_LEN) {
00622                     fprintf(stderr,"--drive address too long (max. %d)\n",
00623                             BURN_DRIVE_ADR_LEN-1);
00624                     return 2;
00625                 }
00626                 strcpy(drive_adr, argv[i]);
00627             }
00628         } else if ((!strcmp(argv[i], "--format_overwrite")) ||
00629            (!strcmp(argv[i], "--format"))) {
00630             do_blank = 101;
00631 
00632         } else if (!strcmp(argv[i], "--multi")) {
00633         do_multi = 1;
00634 
00635     } else if (!strcmp(argv[i], "--stdin_size")) { /* obsoleted */
00636         i++;
00637 
00638         } else if (!strcmp(argv[i], "--try_to_simulate")) {
00639             simulate_burn = 1;
00640 
00641         } else if (!strcmp(argv[i], "--help")) {
00642             print_help = 1;
00643 
00644         } else if (!strncmp(argv[i], "--",2)) {
00645             fprintf(stderr, "Unidentified option: %s\n", argv[i]);
00646             return 7;
00647         } else {
00648             if(strlen(argv[i]) >= 4096) {
00649                 fprintf(stderr, "Source address too long (max. %d)\n", 4096-1);
00650                 return 5;
00651             }
00652             if(source_adr_count >= 99) {
00653                 fprintf(stderr, "Too many tracks (max. 99)\n");
00654                 return 6;
00655             }
00656             strcpy(source_adr[source_adr_count], argv[i]);
00657             source_adr_count++;
00658         }
00659     }
00660     insuffient_parameters = 1;
00661     if (driveno < 0)
00662         insuffient_parameters = 0;
00663     if (source_adr_count > 0)
00664         insuffient_parameters = 0; 
00665     if (do_blank)
00666         insuffient_parameters = 0;
00667     if (print_help || insuffient_parameters ) {
00668         printf("Usage: %s\n", argv[0]);
00669         printf("       [--drive <address>|<driveno>|\"-\"]  [--audio]\n");
00670         printf("       [--blank_fast|--blank_full|--format]  [--try_to_simulate]\n");
00671         printf("       [--multi]  [<one or more imagefiles>|\"-\"]\n");
00672         printf("Examples\n");
00673         printf("A bus scan (needs rw-permissions to see a drive):\n");
00674         printf("  %s --drive -\n",argv[0]);
00675         printf("Burn a file to drive chosen by number, leave appendable:\n");
00676         printf("  %s --drive 0 --multi my_image_file\n", argv[0]);
00677         printf("Burn a file to drive chosen by persistent address, close:\n");
00678         printf("  %s --drive /dev/hdc my_image_file\n", argv[0]);
00679         printf("Blank a used CD-RW (is combinable with burning in one run):\n");
00680         printf("  %s --drive /dev/hdc --blank_fast\n",argv[0]);
00681         printf("Blank a used DVD-RW (is combinable with burning in one run):\n");
00682         printf("  %s --drive /dev/hdc --blank_full\n",argv[0]);
00683         printf("Format a DVD-RW, BD-RE or BD-R:\n");
00684         printf("  %s --drive /dev/hdc --format\n", argv[0]);
00685         printf("Burn two audio tracks (to CD only):\n");
00686         printf("  lame --decode -t /path/to/track1.mp3 track1.cd\n");
00687         printf("  test/dewav /path/to/track2.wav -o track2.cd\n");
00688         printf("  %s --drive /dev/hdc --audio track1.cd track2.cd\n", argv[0]);
00689         printf("Burn a compressed afio archive on-the-fly:\n");
00690         printf("  ( cd my_directory ; find . -print | afio -oZ - ) | \\\n");
00691         printf("  %s --drive /dev/hdc -\n", argv[0]);
00692         printf("To be read from *not mounted* media via: afio -tvZ /dev/hdc\n");
00693         if (insuffient_parameters)
00694             return 6;
00695     }
00696     return 0;
00697 }

int main ( int  argc,
char **  argv 
)

Note: driveno might change its value in this call

Definition at line 700 of file libburner.c.

References all_tracks_type, burn_drive_release(), burn_finish(), burn_initialize(), burn_msgs_set_severities(), burn_set_signal_handling(), do_blank, do_multi, drive_adr, drive_is_grabbed, driveno, libburner_aquire_drive(), libburner_blank_disc(), libburner_format(), libburner_payload(), libburner_setup(), simulate_burn, source_adr, and source_adr_count.

00701 {
00702     int ret;
00703 
00704     ret = libburner_setup(argc, argv);
00705     if (ret)
00706         exit(ret);
00707 
00708     printf("Initializing libburnia-project.org ...\n");
00709     if (burn_initialize())
00710         printf("Done\n");
00711     else {
00712         printf("FAILED\n");
00713         fprintf(stderr,"\nFATAL: Failed to initialize.\n");
00714         exit(33);
00715     }
00716 
00717     /* Print messages of severity SORRY or more directly to stderr */
00718     burn_msgs_set_severities("NEVER", "SORRY", "libburner : ");
00719 
00720     /* Activate the default signal handler which eventually will try to
00721        properly shutdown drive and library on aborting events. */
00722     burn_set_signal_handling("libburner : ", NULL, 0);
00723 
00724     /** Note: driveno might change its value in this call */
00725     ret = libburner_aquire_drive(drive_adr, &driveno);
00726     if (ret<=0) {
00727         fprintf(stderr,"\nFATAL: Failed to aquire drive.\n");
00728         { ret = 34; goto finish_libburn; }
00729     }
00730     if (ret == 2)
00731         { ret = 0; goto release_drive; }
00732     if (do_blank) {
00733         if (do_blank > 100)
00734             ret = libburner_format(drive_list[driveno].drive);
00735         else
00736             ret = libburner_blank_disc(drive_list[driveno].drive,
00737                             do_blank == 1);
00738         if (ret<=0)
00739             { ret = 36; goto release_drive; }
00740     }
00741     if (source_adr_count > 0) {
00742         ret = libburner_payload(drive_list[driveno].drive,
00743                 source_adr, source_adr_count,
00744                 do_multi, simulate_burn, all_tracks_type);
00745         if (ret<=0)
00746             { ret = 38; goto release_drive; }
00747     }
00748     ret = 0;
00749 release_drive:;
00750     if (drive_is_grabbed)
00751         burn_drive_release(drive_list[driveno].drive, 0);
00752 
00753 finish_libburn:;
00754     /* This app does not bother to know about exact scan state. 
00755        Better to accept a memory leak here. We are done anyway. */
00756     /* burn_drive_info_free(drive_list); */
00757 
00758     burn_finish();
00759     exit(ret);
00760 }


Variable Documentation

int all_tracks_type = BURN_MODE1 [static]

Definition at line 587 of file libburner.c.

Referenced by libburner_setup(), and main().

int current_profile = -1 [static]

A number and a text describing the type of media in aquired drive.

Definition at line 78 of file libburner.c.

Referenced by libburner_aquire_drive(), libburner_blank_disc(), libburner_format(), and libburner_payload().

char current_profile_name[80] = {""} [static]

Definition at line 79 of file libburner.c.

Referenced by libburner_aquire_drive(), and libburner_format().

int do_blank = 0 [static]

Definition at line 582 of file libburner.c.

Referenced by libburner_setup(), and main().

int do_multi = 0 [static]

Definition at line 585 of file libburner.c.

Referenced by libburner_setup(), and main().

char drive_adr[BURN_DRIVE_ADR_LEN] = {""} [static]

The setup parameters of libburner.

Definition at line 580 of file libburner.c.

Referenced by libburner_setup(), and main().

unsigned int drive_count [static]

If you start a long lasting operation with drive_count > 1 then you are not friendly to the users of other drives on those systems.

Beware.

Definition at line 71 of file libburner.c.

Referenced by libburner_aquire_by_driveno().

int drive_is_grabbed = 0 [static]

This variable indicates wether the drive is grabbed and must be finally released.

Definition at line 75 of file libburner.c.

Referenced by libburner_aquire_by_adr(), libburner_aquire_by_driveno(), and main().

struct burn_drive_info* drive_list [static]

Overview.

libburner is a minimal demo application for the library libburn as provided on http://libburnia-project.org . It can list the available devices, can blank a CD-RW or DVD-RW, can format DVD-RW and BD, can burn to CD-R, CD-RW, DVD-R, DVD+R, DVD+R/DL, DVD+RW, DVD-RW, DVD-RAM, BD-R, BD-RE. Not supported yet: DVD-R/DL.

It's main purpose, nevertheless, is to show you how to use libburn and also to serve the libburnia team as reference application. libburner.c does indeed define the standard way how above three gestures can be implemented and stay upward compatible for a good while.

Before you can do anything, you have to initialize libburn by burn_initialize() and provide some signal and abort handling, e.g. by the builtin handler, by burn_set_signal_handling() as it is done in main() at the end of this file. Then you aquire a drive in an appropriate way conforming to the API. The two main approaches are shown here in application functions: libburner_aquire_by_adr() demonstrates usage as of cdrecord traditions libburner_aquire_by_driveno() demonstrates a scan-and-choose approach With that aquired drive you can blank a CD-RW libburner_blank_disc() or you can format a DVD-RW to profile "Restricted Overwrite" (needed once) or an unused BD to default size with spare blocks libburner_format() With the aquired drive you can burn to CD, DVD, BD libburner_payload() When everything is done, main() releases the drive and shuts down libburn: burn_drive_release(); burn_finish() See this for the decisive API specs . libburn.h is The Original For simplicity i use global variables to represent the drives. Drives are systemwide global, so we do not give away much of good style. This list will hold the drives known to libburn. This might be all CD drives of the system and thus might impose severe impact on the system.

Definition at line 67 of file libburner.c.

int driveno = 0 [static]

Definition at line 581 of file libburner.c.

Referenced by libburner_setup(), and main().

int simulate_burn = 0 [static]

Definition at line 586 of file libburner.c.

Referenced by libburner_setup(), and main().

char source_adr[99][4096] [static]

Definition at line 583 of file libburner.c.

Referenced by libburner_setup(), and main().

int source_adr_count = 0 [static]

Definition at line 584 of file libburner.c.

Referenced by libburner_setup(), and main().


Generated on Tue Dec 16 11:15:59 2008 for libburn by  doxygen 1.5.6