libburner.c File Reference

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

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

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

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

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

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

00124 {
00125     int ret;
00126 
00127     if(drive_adr != NULL && drive_adr[0] != 0)
00128         ret = libburner_aquire_by_adr(drive_adr);
00129     else
00130         ret = libburner_aquire_by_driveno(driveno);
00131     if (ret <= 0 || *driveno <= 0)
00132         return ret;
00133     burn_disc_get_profile(drive_list[0].drive, &current_profile,
00134                  current_profile_name);
00135     if (current_profile_name[0])
00136         printf("Detected media type: %s\n", current_profile_name);
00137     return 1;
00138 }

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 293 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, burn_is_aborting(), burn_set_signal_handling(), current_profile, burn_progress::sector, and burn_progress::sectors.

Referenced by main().

00294 {
00295     enum burn_disc_status disc_state;
00296     struct burn_progress p;
00297     double percent = 1.0;
00298 
00299     disc_state = burn_disc_get_status(drive);
00300     printf(
00301         "Drive media status:  %d  (see  libburn/libburn.h  BURN_DISC_*)\n",
00302         disc_state);
00303     if (current_profile == 0x13) {
00304         ; /* formatted DVD-RW will get blanked to sequential state */
00305     } else if (disc_state == BURN_DISC_BLANK) {
00306         fprintf(stderr,
00307           "IDLE: Blank media detected. Will leave it untouched\n");
00308         return 2;
00309     } else if (disc_state == BURN_DISC_FULL ||
00310            disc_state == BURN_DISC_APPENDABLE) {
00311         ; /* this is what libburner is willing to blank */
00312     } else if (disc_state == BURN_DISC_EMPTY) {
00313         fprintf(stderr,"FATAL: No media detected in drive\n");
00314         return 0;
00315     } else {
00316         fprintf(stderr,
00317             "FATAL: Unsuitable drive and media state\n");
00318         return 0;
00319     }
00320     if(!burn_disc_erasable(drive)) {
00321         fprintf(stderr,
00322             "FATAL : Media is not of erasable type\n");
00323         return 0;
00324     }
00325     /* Switch to asynchronous signal handling for the time of waiting */
00326     burn_set_signal_handling("libburner : ", NULL, 0x30);
00327 
00328     printf("Beginning to %s-blank media.\n", (blank_fast?"fast":"full"));
00329     burn_disc_erase(drive, blank_fast);
00330 
00331     sleep(1);
00332     while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
00333         if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
00334             percent = 1.0 + ((double) p.sector+1.0)
00335                      / ((double) p.sectors) * 98.0;
00336         printf("Blanking  ( %.1f%% done )\n", percent);
00337         sleep(1);
00338     }
00339     if (burn_is_aborting(0) > 0)
00340         return -1;
00341     /* Back to synchronous handling */
00342     burn_set_signal_handling("libburner : ", NULL, 0x0);
00343     printf("Done\n");
00344     return 1;
00345 }

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 360 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, burn_is_aborting(), burn_set_signal_handling(), current_profile, current_profile_name, burn_progress::sector, and burn_progress::sectors.

Referenced by main().

00361 {
00362     struct burn_progress p;
00363     double percent = 1.0;
00364     int ret, status, num_formats, format_flag= 0;
00365     off_t size = 0;
00366     unsigned dummy;
00367     enum burn_disc_status disc_state;
00368 
00369     if (current_profile == 0x13) {
00370         fprintf(stderr, "IDLE: DVD-RW media is already formatted\n");
00371         return 2;
00372     } else if (current_profile == 0x41 || current_profile == 0x43) {
00373         disc_state = burn_disc_get_status(drive);
00374         if (disc_state != BURN_DISC_BLANK && current_profile == 0x41) {
00375             fprintf(stderr,
00376                 "FATAL: BD-R is not blank. Cannot format.\n");
00377             return 0;
00378         }
00379         ret = burn_disc_get_formats(drive, &status, &size, &dummy,
00380                                 &num_formats);
00381         if (ret > 0 && status != BURN_FORMAT_IS_UNFORMATTED) {
00382             fprintf(stderr,
00383                 "IDLE: BD media is already formatted\n");
00384             return 2;
00385         }
00386         size = 0;           /* does not really matter */
00387         format_flag = 3<<1; /* format to default size, no quick */
00388     } else if (current_profile == 0x14) { /* sequential DVD-RW */
00389         size = 128 * 1024 * 1024;
00390         format_flag = 1; /* write initial 128 MiB */
00391     } else {
00392         fprintf(stderr, "FATAL: Can only format DVD-RW or BD\n");
00393         return 0;
00394     }
00395     burn_set_signal_handling("libburner : ", NULL, 0x30);
00396 
00397     printf("Beginning to format media.\n");
00398     burn_disc_format(drive, size, format_flag);
00399 
00400     sleep(1);
00401     while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
00402         if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
00403             percent = 1.0 + ((double) p.sector+1.0)
00404                      / ((double) p.sectors) * 98.0;
00405         printf("Formatting  ( %.1f%% done )\n", percent);
00406         sleep(1);
00407     }
00408     if (burn_is_aborting(0) > 0)
00409         return -1;
00410     burn_set_signal_handling("libburner : ", NULL, 0x0);
00411     burn_disc_get_profile(drive_list[0].drive, &current_profile,
00412                  current_profile_name);
00413     if (current_profile == 0x14 || current_profile == 0x13)
00414         printf("Media type now: %4.4xh  \"%s\"\n",
00415                  current_profile, current_profile_name);
00416     if (current_profile == 0x14) {
00417         fprintf(stderr,
00418           "FATAL: Failed to change media profile to desired value\n");
00419         return 0;
00420     }
00421     return 1;
00422 }

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 440 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_is_aborting(), BURN_MODE1, BURN_POS_END, BURN_REASONS_LEN, burn_session_add_track(), burn_session_create(), burn_session_free(), burn_set_signal_handling(), 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().

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

int libburner_setup ( int  argc,
char **  argv 
)

Converts command line arguments into above setup parameters.

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

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

int main ( int  argc,
char **  argv 
)

Note: driveno might change its value in this call

Definition at line 737 of file libburner.c.

References all_tracks_type, burn_abort(), burn_abort_pacifier(), burn_drive_release(), burn_finish(), burn_initialize(), burn_is_aborting(), 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.

00738 {
00739     int ret;
00740 
00741     /* A warning to programmers who start their own projekt from here. */
00742     if (sizeof(off_t) != 8) {
00743          fprintf(stderr,
00744        "\nFATAL: Compile time misconfiguration. off_t is not 64 bit.\n\n");
00745          exit(39);
00746     }
00747 
00748     ret = libburner_setup(argc, argv);
00749     if (ret)
00750         exit(ret);
00751 
00752     printf("Initializing libburnia-project.org ...\n");
00753     if (burn_initialize())
00754         printf("Done\n");
00755     else {
00756         printf("FAILED\n");
00757         fprintf(stderr,"\nFATAL: Failed to initialize.\n");
00758         exit(33);
00759     }
00760 
00761     /* Print messages of severity SORRY or more directly to stderr */
00762     burn_msgs_set_severities("NEVER", "SORRY", "libburner : ");
00763 
00764     /* Activate the synchronous signal handler which eventually will try to
00765        properly shutdown drive and library on aborting events. */
00766     burn_set_signal_handling("libburner : ", NULL, 0x0);
00767 
00768     /** Note: driveno might change its value in this call */
00769     ret = libburner_aquire_drive(drive_adr, &driveno);
00770     if (ret<=0) {
00771         fprintf(stderr,"\nFATAL: Failed to aquire drive.\n");
00772         { ret = 34; goto finish_libburn; }
00773     }
00774     if (ret == 2)
00775         { ret = 0; goto release_drive; }
00776     if (do_blank) {
00777         if (do_blank > 100)
00778             ret = libburner_format(drive_list[driveno].drive);
00779         else
00780             ret = libburner_blank_disc(drive_list[driveno].drive,
00781                             do_blank == 1);
00782         if (ret<=0)
00783             { ret = 36; goto release_drive; }
00784     }
00785     if (source_adr_count > 0) {
00786         ret = libburner_payload(drive_list[driveno].drive,
00787                 source_adr, source_adr_count,
00788                 do_multi, simulate_burn, all_tracks_type);
00789         if (ret<=0)
00790             { ret = 38; goto release_drive; }
00791     }
00792     ret = 0;
00793 release_drive:;
00794     if (drive_is_grabbed)
00795         burn_drive_release(drive_list[driveno].drive, 0);
00796 
00797 finish_libburn:;
00798     if (burn_is_aborting(0) > 0) {
00799         burn_abort(4400, burn_abort_pacifier, "libburner : ");
00800         fprintf(stderr,"\nlibburner run aborted\n");
00801         exit(1);
00802     } 
00803     /* This app does not bother to know about exact scan state. 
00804        Better to accept a memory leak here. We are done anyway. */
00805     /* burn_drive_info_free(drive_list); */
00806     burn_finish();
00807     exit(ret);
00808 }


Variable Documentation

int all_tracks_type = BURN_MODE1 [static]

Definition at line 624 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 100 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 101 of file libburner.c.

Referenced by libburner_aquire_drive(), and libburner_format().

int do_blank = 0 [static]

Definition at line 619 of file libburner.c.

Referenced by libburner_setup(), and main().

int do_multi = 0 [static]

Definition at line 622 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 617 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 93 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 97 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("libburner : ", NULL, 0x0) 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 twoi 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 or DVD-RW as shown in 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. See libburner_payload()

These three functions switch temporarily to a non-fatal signal handler while they are waiting for the drive to become idle again: burn_set_signal_handling("libburner : ", NULL, 0x30) After the waiting loop ended, they check for eventual abort events by burn_is_aborting(0) The 0x30 handler will eventually execute burn_abort() but not wait for the drive to become idle and not call exit(). This is needed because the worker threads might block as long as the signal handler has not returned. The 0x0 handler would wait for them to finish. Take this into respect when implementing own signal handlers.

When everything is done, main() releases the drive and shuts down libburn: burn_drive_release(); burn_finish()

Applications must use 64 bit off_t. E.g. by defining define _LARGEFILE_SOURCE define _FILE_OFFSET_BITS 64 or take special precautions to interface with the library by 64 bit integers where libburn/libburn.h prescribes off_t. This program gets fed with appropriate settings externally by libburn's autotools generated build system. 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 89 of file libburner.c.

int driveno = 0 [static]

Definition at line 618 of file libburner.c.

Referenced by libburner_setup(), and main().

int simulate_burn = 0 [static]

Definition at line 623 of file libburner.c.

Referenced by libburner_setup(), and main().

char source_adr[99][4096] [static]

Definition at line 620 of file libburner.c.

Referenced by libburner_setup(), and main().

int source_adr_count = 0 [static]

Definition at line 621 of file libburner.c.

Referenced by libburner_setup(), and main().

Generated on 12 Dec 2013 for libburn by  doxygen 1.6.3