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 or unformatted DVD-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 133 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().

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

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 178 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().

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

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 111 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().

00112 {
00113     int ret;
00114 
00115     if(drive_adr != NULL && drive_adr[0] != 0)
00116         ret = libburner_aquire_by_adr(drive_adr);
00117     else
00118         ret = libburner_aquire_by_driveno(driveno);
00119     if (ret <= 0 || *driveno <= 0)
00120         return ret;
00121     burn_disc_get_profile(drive_list[0].drive, &current_profile,
00122                  current_profile_name);
00123     if (current_profile_name[0])
00124         printf("Detected media type: %s\n", current_profile_name);
00125     return 1;
00126 }

int libburner_blank_disc ( struct burn_drive *  drive,
int  blank_fast 
)

Makes a previously used CD-RW or unformatted DVD-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 281 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().

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

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 341 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().

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

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 417 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().

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

int libburner_setup ( int  argc,
char **  argv 
)

Converts command line arguments into above setup parameters.

Definition at line 603 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().

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

int main ( int  argc,
char **  argv 
)

Note: driveno might change its value in this call

Definition at line 711 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.

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


Variable Documentation

int all_tracks_type = BURN_MODE1 [static]

Definition at line 598 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 88 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 89 of file libburner.c.

Referenced by libburner_aquire_drive(), and libburner_format().

int do_blank = 0 [static]

Definition at line 593 of file libburner.c.

Referenced by libburner_setup(), and main().

int do_multi = 0 [static]

Definition at line 596 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 591 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 81 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 85 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 77 of file libburner.c.

int driveno = 0 [static]

Definition at line 592 of file libburner.c.

Referenced by libburner_setup(), and main().

int simulate_burn = 0 [static]

Definition at line 597 of file libburner.c.

Referenced by libburner_setup(), and main().

char source_adr[99][4096] [static]

Definition at line 594 of file libburner.c.

Referenced by libburner_setup(), and main().

int source_adr_count = 0 [static]

Definition at line 595 of file libburner.c.

Referenced by libburner_setup(), and main().


Generated by  doxygen 1.6.2