libburn-0.2.6.3/test/libburner.c

Go to the documentation of this file.
00001 
00002 /* test/libburner.c , API illustration of burning data or audio tracks to CD */
00003 /* Copyright (C) 2005 - 2006 Thomas Schmitt <scdbackup@gmx.net> */
00004 /* Provided under GPL, see also "License and copyright aspects" at file end */
00005 
00006 
00007 /**                               Overview 
00008   
00009   libburner is a minimal demo application for the library libburn as provided
00010   on  http://libburn.pykix.org . It can list the available devices, can
00011   blank a CD-RW and can burn to CD-R or CD-RW.
00012   It's main purpose, nevertheless, is to show you how to use libburn and also
00013   to serve the libburn team as reference application. libburner.c does indeed
00014   define the standard way how above three gestures can be implemented and
00015   stay upward compatible for a good while.
00016   
00017   Before you can do anything, you have to initialize libburn by
00018      burn_initialize()
00019   and provide some signal and abort handling, e.g. by the builtin handler, by
00020      burn_set_signal_handling() 
00021   as it is done in main() at the end of this file. Then you aquire a
00022   drive in an appropriate way conforming to the API. The two main
00023   approaches are shown here in application functions:
00024      libburner_aquire_by_adr()     demonstrates usage as of cdrecord traditions
00025      libburner_aquire_by_driveno()      demonstrates a scan-and-choose approach
00026   With that aquired drive you can blank a CD-RW
00027      libburner_blank_disc()
00028   Between blanking and burning one eventually has to reload the drive status
00029      libburner_regrab()
00030   With the aquired drive you can burn to CD-R or blank CD-RW
00031      libburner_payload()
00032   When everything is done, main() releases the drive and shuts down libburn:
00033      burn_drive_release();
00034      burn_finish()
00035   
00036 */
00037 
00038 /** See this for the decisive API specs . libburn.h is The Original */
00039 /*  For using the installed header file :  #include <libburn/libburn.h> */
00040 /*  This program insists in the own headerfile. */
00041 #include "../libburn/libburn.h"
00042 
00043 /* libburn is intended for Linux systems with kernel 2.4 or 2.6 for now */
00044 #include <stdio.h>
00045 #include <ctype.h>
00046 #include <sys/types.h>
00047 #include <unistd.h>
00048 #include <string.h>
00049 #include <stdlib.h>
00050 #include <time.h>
00051 #include <errno.h>
00052 #include <sys/stat.h>
00053 #include <fcntl.h>
00054 
00055 
00056 /** For simplicity i use global variables to represent the drives.
00057     Drives are systemwide global, so we do not give away much of good style.
00058 */
00059 
00060 /** This list will hold the drives known to libburn. This might be all CD
00061     drives of the system and thus might impose severe impact on the system.
00062 */
00063 static struct burn_drive_info *drive_list;
00064 
00065 /** If you start a long lasting operation with drive_count > 1 then you are
00066     not friendly to the users of other drives on those systems. Beware. */
00067 static unsigned int drive_count;
00068 
00069 /** This variable indicates wether the drive is grabbed and must be
00070     finally released */
00071 static int drive_is_grabbed = 0;
00072 
00073 
00074 /* Some in-advance definitions to allow a more comprehensive ordering
00075    of the functions and their explanations in here */
00076 int libburner_aquire_by_adr(char *drive_adr);
00077 int libburner_aquire_by_driveno(int *drive_no);
00078 
00079 
00080 /* ------------------------------- API gestures ---------------------------- */
00081 
00082 /** You need to aquire a drive before burning. The API offers this as one
00083     compact call and alternatively as application controllable gestures of
00084     whitelisting, scanning for drives and finally grabbing one of them.
00085 
00086     If you have a persistent address of the drive, then the compact call is
00087     to prefer because it only touches one drive. On modern Linux kernels,
00088     there should be no fatal disturbance of ongoing burns of other libburn
00089     instances with any of our approaches. We use open(O_EXCL) by default.
00090     On /dev/hdX it should cooperate with growisofs and some cdrecord variants.
00091     On /dev/sgN versus /dev/scdM expect it not to respect other programs.
00092 */
00093 int libburner_aquire_drive(char *drive_adr, int *driveno)
00094 {
00095     int ret;
00096 
00097     if(drive_adr != NULL && drive_adr[0] != 0)
00098         ret = libburner_aquire_by_adr(drive_adr);
00099     else
00100         ret = libburner_aquire_by_driveno(driveno);
00101     return ret;
00102 }
00103 
00104 
00105 /** If the persistent drive address is known, then this approach is much
00106     more un-obtrusive to the systemwide livestock of drives. Only the
00107     given drive device will be opened during this procedure.
00108 */
00109 int libburner_aquire_by_adr(char *drive_adr)
00110 {
00111     int ret;
00112     
00113     printf("Aquiring drive '%s' ...\n",drive_adr);
00114     ret = burn_drive_scan_and_grab(&drive_list,drive_adr,1);
00115     if (ret <= 0) {
00116         fprintf(stderr,"FAILURE with persistent drive address  '%s'\n",
00117             drive_adr);
00118     } else {
00119         printf("Done\n");
00120         drive_is_grabbed = 1;
00121     }
00122     return ret;
00123 }
00124 
00125 
00126 /** This method demonstrates how to use libburn without knowing a persistent
00127     drive address in advance. It has to make sure that after assessing the list
00128     of available drives, all unwanted drives get closed again. As long as they
00129     are open, no other libburn instance can see them. This is an intended
00130     locking feature. The application is responsible for giving up the locks
00131     by either burn_drive_release() (only after burn_drive_grab() !),
00132     burn_drive_info_forget(), burn_drive_info_free(), or burn_finish().
00133     @param driveno the index number in libburn's drive list. This will get
00134                    set to 0 on success and will then be the drive index to
00135                    use in the further dourse of processing.
00136     @return 1 success , <= 0 failure
00137 */
00138 int libburner_aquire_by_driveno(int *driveno)
00139 {
00140     char adr[BURN_DRIVE_ADR_LEN];
00141     int ret, i;
00142 
00143     printf("Beginning to scan for devices ...\n");
00144     while (!burn_drive_scan(&drive_list, &drive_count))
00145         usleep(1002);
00146     if (drive_count <= 0 && *driveno >= 0) {
00147         printf("FAILED (no drives found)\n");
00148         return 0;
00149     }
00150     printf("Done\n");
00151 
00152     /*
00153     Interactive programs may choose the drive number at this moment.
00154 
00155     drive[0] to drive[drive_count-1] are struct burn_drive_info
00156     as defined in  libburn/libburn.h  . This structure is part of API
00157     and thus will strive for future compatibility on source level.
00158     Have a look at the info offered.
00159     Caution: do not take .location for drive address. Always use
00160         burn_drive_get_adr() or you might become incompatible
00161         in future.
00162     Note: bugs with struct burn_drive_info - if any - will not be
00163         easy to fix. Please report them but also strive for
00164         workarounds on application level.
00165     */
00166     printf("\nOverview of accessible drives (%d found) :\n",
00167         drive_count);
00168     printf("-----------------------------------------------------------------------------\n");
00169     for (i = 0; i < drive_count; i++) {
00170         if (burn_drive_get_adr(&(drive_list[i]), adr) <=0)
00171             strcpy(adr, "-get_adr_failed-");
00172         printf("%d  --drive '%s'  :  '%s'  '%s'\n",
00173             i,adr,drive_list[i].vendor,drive_list[i].product);
00174     }
00175     printf("-----------------------------------------------------------------------------\n\n");
00176 
00177     /*
00178     On multi-drive systems save yourself from sysadmins' revenge.
00179 
00180     Be aware that you hold reserved all available drives at this point.
00181     So either make your choice quick enough not to annoy other system
00182     users, or set free the drives for a while.
00183 
00184     The tested way of setting free all drives is to shutdown the library
00185     and to restart when the choice has been made. The list of selectable
00186     drives should also hold persistent drive addresses as obtained
00187     above by burn_drive_get_adr(). By such an address one may use
00188     burn_drive_scan_and_grab() to finally aquire exactly one drive.
00189 
00190     A not yet tested shortcut should be to call burn_drive_info_free()
00191     and to call either burn_drive_scan() or burn_drive_scan_and_grab()
00192     before accessing any drives again.
00193 
00194     In both cases you have to be aware that the desired drive might get
00195     aquired in the meantime by another user resp. libburn process.
00196     */
00197 
00198     /* We already made our choice via command line. (default is 0)
00199        So we just have to keep our desired drive and drop all others.
00200        No other libburn instance will have a chance to steal our drive.
00201      */
00202     if (*driveno < 0) {
00203         printf("Pseudo-drive \"-\" given : bus scanning done.\n");
00204         return 2; /* the program will end after this */
00205     }
00206     if (drive_count <= *driveno) {
00207         fprintf(stderr,
00208             "Found only %d drives. Number %d not available.\n",
00209             drive_count, *driveno);
00210         return 0; /* the program will end after this */
00211     }
00212 
00213     /* Drop all drives which we do not want to use */
00214     for (i = 0; i < drive_count; i++) {
00215         if (i == *driveno) /* the one drive we want to keep */
00216     continue;
00217         ret = burn_drive_info_forget(&(drive_list[i]),0);
00218         if (ret != 1)
00219             fprintf(stderr, "Cannot drop drive %d. Please report \"ret=%d\" to libburn-hackers@pykix.org\n",
00220                 i, ret);
00221         else
00222             printf("Dropped unwanted drive %d\n",i);
00223     }
00224     /* Make the one we want ready for blanking or burning */
00225     ret= burn_drive_grab(drive_list[*driveno].drive, 1);
00226     if (ret != 1)
00227         return 0;
00228     drive_is_grabbed = 1;
00229     return 1;
00230 }
00231 
00232 
00233 /** Makes a previously used CD-RW ready for thorough re-usal.
00234 
00235     To our knowledge it is hardly possible to abort an ongoing blank operation
00236     because after start it is entirely handled by the drive.
00237     So expect signal handling to wait the normal blanking timespan until it
00238     can allow the process to end. External kill -9 will not help the drive.
00239 */
00240 int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
00241 {
00242     enum burn_disc_status disc_state;
00243     struct burn_progress p;
00244     int percent = 1;
00245 
00246     while (burn_drive_get_status(drive, NULL) != BURN_DRIVE_IDLE)
00247         usleep(1001);
00248 
00249     while ((disc_state = burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
00250         usleep(1001);
00251     printf(
00252         "Drive media status:  %d  (see  libburn/libburn.h  BURN_DISC_*)\n",
00253         disc_state);
00254     if (disc_state == BURN_DISC_BLANK) {
00255         fprintf(stderr,
00256           "IDLE: Blank CD media detected. Will leave it untouched\n");
00257         return 2;
00258     } else if (disc_state == BURN_DISC_FULL ||
00259            disc_state == BURN_DISC_APPENDABLE) {
00260         ; /* this is what libburn is willing to blank */
00261     } else if (disc_state == BURN_DISC_EMPTY) {
00262         fprintf(stderr,"FATAL: No media detected in drive\n");
00263         return 0;
00264     } else {
00265         fprintf(stderr,
00266             "FATAL: Cannot recognize drive and media state\n");
00267         return 0;
00268     }
00269     if(!burn_disc_erasable(drive)) {
00270         fprintf(stderr,
00271             "FATAL : Media is not of erasable type\n");
00272         return 0;
00273     }
00274     printf(
00275           "Beginning to %s-blank CD media.\n", (blank_fast?"fast":"full"));
00276     burn_disc_erase(drive, blank_fast);
00277     sleep(1);
00278     while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
00279         if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
00280             percent = 1.0 + ((double) p.sector+1.0)
00281                      / ((double) p.sectors) * 98.0;
00282         printf("Blanking  ( %d%% done )\n", percent);
00283         sleep(1);
00284     }
00285     printf("Done\n");
00286     return 1;
00287 }
00288 
00289 
00290 /** This gesture is necessary to get the drive info after blanking.
00291     It opens a small gap for losing the drive to another libburn instance.
00292     We will work on closing this gap.
00293 */
00294 int libburner_regrab(struct burn_drive *drive) {
00295     int ret;
00296 
00297     printf("Releasing and regrabbing drive ...\n");
00298     if (drive_is_grabbed)
00299         burn_drive_release(drive, 0);
00300     drive_is_grabbed = 0;
00301     ret = burn_drive_grab(drive, 0);
00302     if (ret != 0) {
00303         drive_is_grabbed = 1;
00304         printf("Done\n");
00305     } else
00306         printf("FAILED\n");
00307     return !!ret;
00308 }
00309 
00310 
00311 /** Brings preformatted track images (ISO 9660, audio, ...) onto media.
00312     To make sure a data image is fully readable on any Linux machine, this
00313     function adds 300 kB of padding to the (usualy single) track.
00314     Audio tracks get padded to complete their last sector.
00315 
00316     In case of external signals expect abort handling of an ongoing burn to
00317     last up to a minute. Wait the normal burning timespan before any kill -9.
00318 */
00319 int libburner_payload(struct burn_drive *drive, 
00320               char source_adr[][4096], int source_adr_count,
00321               int multi, int simulate_burn, int all_tracks_type)
00322 {
00323     struct burn_source *data_src;
00324     struct burn_disc *target_disc;
00325     struct burn_session *session;
00326     struct burn_write_opts *burn_options;
00327     enum burn_disc_status disc_state;
00328     struct burn_track *track, *tracklist[99];
00329     struct burn_progress progress;
00330     time_t start_time;
00331     int last_sector = 0, padding = 0, trackno, write_mode_tao = 0, fd;
00332     off_t fixed_size;
00333     char *adr;
00334     struct stat stbuf;
00335 
00336     if (all_tracks_type != BURN_AUDIO) {
00337         all_tracks_type = BURN_MODE1;
00338         /* a padding of 300 kB helps to avoid the read-ahead bug */
00339         padding = 300*1024;
00340     }
00341 
00342     target_disc = burn_disc_create();
00343     session = burn_session_create();
00344     burn_disc_add_session(target_disc, session, BURN_POS_END);
00345 
00346     for (trackno = 0 ; trackno < source_adr_count; trackno++) {
00347       tracklist[trackno] = track = burn_track_create();
00348       burn_track_define_data(track, 0, padding, 1, all_tracks_type);
00349 
00350       adr = source_adr[trackno];
00351       fixed_size = 0;
00352       if (adr[0] == '-' && adr[1] == 0) {
00353         fd = 0;
00354       } else {
00355         fd = open(adr, O_RDONLY);
00356         if (fd>=0)
00357             if (fstat(fd,&stbuf)!=-1)
00358                 if((stbuf.st_mode&S_IFMT)==S_IFREG)
00359                     fixed_size = stbuf.st_size;
00360       }
00361       if (fixed_size==0)
00362         write_mode_tao = 1;
00363       data_src = NULL;
00364       if (fd>=0)
00365         data_src = burn_fd_source_new(fd, -1, fixed_size);
00366       if (data_src == NULL) {
00367         fprintf(stderr,
00368                "FATAL: Could not open data source '%s'.\n",adr);
00369         if(errno!=0)
00370             fprintf(stderr,"(Most recent system error: %s )\n",
00371                 strerror(errno));
00372         return 0;
00373       }
00374       if (burn_track_set_source(track, data_src) != BURN_SOURCE_OK) {
00375         printf("FATAL: Cannot attach source object to track object\n");
00376         return 0;
00377       }
00378 
00379       burn_session_add_track(session, track, BURN_POS_END);
00380       printf("Track %d : source is '%s'\n", trackno, adr);
00381       burn_source_free(data_src);
00382         } /* trackno loop end */
00383 
00384     while (burn_drive_get_status(drive, NULL) != BURN_DRIVE_IDLE)
00385         usleep(100001);
00386 
00387     /* Evaluate drive and media */
00388     while ((disc_state = burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
00389         usleep(100001);
00390     if (disc_state == BURN_DISC_APPENDABLE) {
00391         write_mode_tao = 1;
00392     } else if (disc_state != BURN_DISC_BLANK) {
00393         if (disc_state == BURN_DISC_FULL) {
00394             fprintf(stderr, "FATAL: Closed media with data detected. Need blank or appendable media.\n");
00395             if (burn_disc_erasable(drive))
00396                 fprintf(stderr, "HINT: Try --blank_fast\n\n");
00397         } else if (disc_state == BURN_DISC_EMPTY) 
00398             fprintf(stderr,"FATAL: No media detected in drive\n");
00399         else
00400             fprintf(stderr,
00401              "FATAL: Cannot recognize state of drive and media\n");
00402         return 0;
00403     }
00404 
00405     burn_options = burn_write_opts_new(drive);
00406     burn_write_opts_set_perform_opc(burn_options, 0);
00407     burn_write_opts_set_multi(burn_options, !!multi);
00408     if (write_mode_tao)
00409         burn_write_opts_set_write_type(burn_options,
00410                     BURN_WRITE_TAO, BURN_BLOCK_MODE1);
00411     else
00412         burn_write_opts_set_write_type(burn_options,
00413                     BURN_WRITE_SAO, BURN_BLOCK_SAO);
00414     if(simulate_burn)
00415         printf("\n*** Will TRY to SIMULATE burning ***\n\n");
00416     burn_write_opts_set_simulate(burn_options, simulate_burn);
00417     burn_structure_print_disc(target_disc);
00418     burn_drive_set_speed(drive, 0, 0);
00419     burn_write_opts_set_underrun_proof(burn_options, 1);
00420 
00421     printf("Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n");
00422     start_time = time(0);
00423     burn_disc_write(burn_options, target_disc);
00424 
00425     burn_write_opts_free(burn_options);
00426     while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING)
00427         usleep(1002);
00428     while (burn_drive_get_status(drive, &progress) != BURN_DRIVE_IDLE) {
00429         if( progress.sectors <= 0 || progress.sector == last_sector)
00430             printf(
00431                  "Thank you for being patient since %d seconds.\n",
00432                  (int) (time(0) - start_time));
00433         else if(write_mode_tao)
00434             printf("Track %d : sector %d\n", progress.track+1,
00435                 progress.sector);
00436         else
00437             printf("Track %d : sector %d of %d\n",progress.track+1,
00438                 progress.sector, progress.sectors);
00439         last_sector = progress.sector;
00440         sleep(1);
00441     }
00442     printf("\n");
00443 
00444     for (trackno = 0 ; trackno < source_adr_count; trackno++)
00445         burn_track_free(tracklist[trackno]);
00446     burn_session_free(session);
00447     burn_disc_free(target_disc);
00448     if (multi)
00449         printf("NOTE: Media left appendable.\n");
00450     if (simulate_burn)
00451         printf("\n*** Did TRY to SIMULATE burning ***\n\n");
00452     return 0;
00453 }
00454 
00455 
00456 /** The setup parameters of libburner */
00457 static char drive_adr[BURN_DRIVE_ADR_LEN] = {""};
00458 static int driveno = 0;
00459 static int do_blank = 0;
00460 static char source_adr[99][4096];
00461 static int source_adr_count = 0;
00462 static int do_multi = 0;
00463 static int simulate_burn = 0;
00464 static int all_tracks_type = BURN_MODE1;
00465 
00466 
00467 /** Converts command line arguments into above setup parameters.
00468     drive_adr[] must provide at least BURN_DRIVE_ADR_LEN bytes.
00469     source_adr[] must provide at least 4096 bytes.
00470 */
00471 int libburner_setup(int argc, char **argv)
00472 {
00473     int i, insuffient_parameters = 0, print_help = 0;
00474 
00475     for (i = 1; i < argc; ++i) {
00476         if (!strcmp(argv[i], "--audio")) {
00477             all_tracks_type = BURN_AUDIO;
00478 
00479         } else if (!strcmp(argv[i], "--blank_fast")) {
00480             do_blank = 1;
00481 
00482         } else if (!strcmp(argv[i], "--blank_full")) {
00483             do_blank = 2;
00484 
00485         } else if (!strcmp(argv[i], "--burn_for_real")) {
00486             simulate_burn = 0;
00487 
00488         } else if (!strcmp(argv[i], "--drive")) {
00489             ++i;
00490             if (i >= argc) {
00491                 fprintf(stderr,"--drive requires an argument\n");
00492                 return 1;
00493             } else if (strcmp(argv[i], "-") == 0) {
00494                 drive_adr[0] = 0;
00495                 driveno = -1;
00496             } else if (isdigit(argv[i][0])) {
00497                 drive_adr[0] = 0;
00498                 driveno = atoi(argv[i]);
00499             } else {
00500                 if(strlen(argv[i]) >= BURN_DRIVE_ADR_LEN) {
00501                     fprintf(stderr,"--drive address too long (max. %d)\n",
00502                             BURN_DRIVE_ADR_LEN-1);
00503                     return 2;
00504                 }
00505                 strcpy(drive_adr, argv[i]);
00506             }
00507         } else if (!strcmp(argv[i], "--multi")) {
00508         do_multi = 1;
00509 
00510     } else if (!strcmp(argv[i], "--stdin_size")) { /* obsoleted */
00511         i++;
00512 
00513         } else if (!strcmp(argv[i], "--try_to_simulate")) {
00514             simulate_burn = 1;
00515 
00516         } else if (!strcmp(argv[i], "--help")) {
00517             print_help = 1;
00518 
00519         } else if (!strncmp(argv[i], "--",2)) {
00520             fprintf(stderr, "Unidentified option: %s\n", argv[i]);
00521             return 7;
00522         } else {
00523             if(strlen(argv[i]) >= 4096) {
00524                 fprintf(stderr, "Source address too long (max. %d)\n", 4096-1);
00525                 return 5;
00526             }
00527             if(source_adr_count >= 99) {
00528                 fprintf(stderr, "Too many tracks (max. 99)\n");
00529                 return 6;
00530             }
00531             strcpy(source_adr[source_adr_count], argv[i]);
00532             source_adr_count++;
00533         }
00534     }
00535     insuffient_parameters = 1;
00536     if (driveno < 0)
00537         insuffient_parameters = 0;
00538     if (source_adr_count > 0)
00539         insuffient_parameters = 0; 
00540     if (do_blank)
00541         insuffient_parameters = 0;
00542     if (print_help || insuffient_parameters ) {
00543         printf("Usage: %s\n", argv[0]);
00544         printf("       [--drive <address>|<driveno>|\"-\"]  [--audio]\n");
00545         printf("       [--blank_fast|--blank_full]  [--try_to_simulate]\n");
00546         printf("       [--multi]  [<one or more imagefiles>|\"-\"]\n");
00547         printf("Examples\n");
00548         printf("A bus scan (needs rw-permissions to see a drive):\n");
00549         printf("  %s --drive -\n",argv[0]);
00550         printf("Burn a file to drive chosen by number, leave appendable:\n");
00551         printf("  %s --drive 0 --multi my_image_file\n", argv[0]);
00552         printf("Burn a file to drive chosen by persistent address, close:\n");
00553         printf("  %s --drive /dev/hdc my_image_file\n", argv[0]);
00554         printf("Blank a used CD-RW (is combinable with burning in one run):\n");
00555         printf("  %s --drive /dev/hdc --blank_fast\n",argv[0]);
00556         printf("Burn two audio tracks\n");
00557         printf("  lame --decode -t /path/to/track1.mp3 track1.cd\n");
00558         printf("  test/dewav /path/to/track2.wav -o track2.cd\n");
00559         printf("  %s --drive /dev/hdc --audio track1.cd track2.cd\n", argv[0]);
00560         printf("Burn a compressed afio archive on-the-fly:\n");
00561         printf("  ( cd my_directory ; find . -print | afio -oZ - ) | \\\n");
00562         printf("  %s --drive /dev/hdc -\n", argv[0]);
00563         printf("To be read from *not mounted* CD via: afio -tvZ /dev/hdc\n");
00564         printf("Program tar would need a clean EOF which our padded CD cannot deliver.\n");
00565         if (insuffient_parameters)
00566             return 6;
00567     }
00568     return 0;
00569 }
00570 
00571 
00572 int main(int argc, char **argv)
00573 {
00574     int ret;
00575 
00576     ret = libburner_setup(argc, argv);
00577     if (ret)
00578         exit(ret);
00579 
00580     printf("Initializing libburn.pykix.org ...\n");
00581     if (burn_initialize())
00582         printf("Done\n");
00583     else {
00584         printf("FAILED\n");
00585         fprintf(stderr,"\nFATAL: Failed to initialize.\n");
00586         exit(33);
00587     }
00588 
00589     /* Print messages of severity SORRY or more directly to stderr */
00590     burn_msgs_set_severities("NEVER", "SORRY", "libburner : ");
00591 
00592     /* Activate the default signal handler which eventually will try to
00593        properly shutdown drive and library on aborting events. */
00594     burn_set_signal_handling("libburner : ", NULL, 0);
00595 
00596     /** Note: driveno might change its value in this call */
00597     ret = libburner_aquire_drive(drive_adr, &driveno);
00598     if (ret<=0) {
00599         fprintf(stderr,"\nFATAL: Failed to aquire drive.\n");
00600         { ret = 34; goto finish_libburn; }
00601     }
00602     if (ret == 2)
00603         { ret = 0; goto release_drive; }
00604     if (do_blank) {
00605         ret = libburner_blank_disc(drive_list[driveno].drive,
00606                       do_blank == 1);
00607         if (ret<=0)
00608             { ret = 36; goto release_drive; }
00609         if (ret != 2 && source_adr_count > 0)
00610             ret = libburner_regrab(drive_list[driveno].drive);
00611         if (ret<=0) {
00612             fprintf(stderr,
00613             "FATAL: Cannot release and grab again drive after blanking\n");
00614             { ret = 37; goto finish_libburn; }
00615         }
00616     }
00617     if (source_adr_count > 0) {
00618         ret = libburner_payload(drive_list[driveno].drive,
00619                 source_adr, source_adr_count,
00620                 do_multi, simulate_burn, all_tracks_type);
00621         if (ret<=0)
00622             { ret = 38; goto release_drive; }
00623     }
00624     ret = 0;
00625 release_drive:;
00626     if (drive_is_grabbed)
00627         burn_drive_release(drive_list[driveno].drive, 0);
00628 
00629 finish_libburn:;
00630     /* This app does not bother to know about exact scan state. 
00631        Better to accept a memory leak here. We are done anyway. */
00632     /* burn_drive_info_free(drive_list); */
00633 
00634     burn_finish();
00635     exit(ret);
00636 }
00637 
00638 
00639 /*  License and copyright aspects:
00640 
00641 This all is provided under GPL.
00642 Read. Try. Think. Play. Write yourself some code. Be free of my copyright.
00643 
00644 Be also invited to study the code of cdrskin/cdrskin.c et al.
00645 
00646 
00647 Clarification in my name and in the name of Mario Danic, copyright holder
00648 on toplevel of libburn. To be fully in effect after the remaining other
00649 copyrighted code has been replaced by ours and by copyright-free contributions
00650 of our friends:
00651 
00652 We, the copyright holders, agree on the interpretation that
00653 dynamical linking of our libraries constitutes "use of" and
00654 not "derivation from" our work in the sense of GPL, provided
00655 those libraries are compiled from our unaltered code.
00656 
00657 Thus you may link our libraries dynamically with applications
00658 which are not under GPL. You may distribute our libraries and
00659 application tools in binary form, if you fulfill the usual
00660 condition of GPL to offer a copy of the source code -altered
00661 or unaltered- under GPL.
00662 
00663 We ask you politely to use our work in open source spirit
00664 and with the due reference to the entire open source community.
00665 
00666 If there should really arise the case where above clarification
00667 does not suffice to fulfill a clear and neat request in open source
00668 spirit that would otherwise be declined for mere formal reasons,
00669 only in that case we will duely consider to issue a special license
00670 covering only that special case.
00671 It is the open source idea of responsible freedom which will be
00672 decisive and you will have to prove that you exhausted all own
00673 means to qualify for GPL.
00674 
00675 For now we are firmly committed to maintain one single license: GPL.
00676 
00677 History:
00678 libburner is a compilation of my own contributions to test/burniso.c and
00679 fresh code which replaced the remaining parts under copyright of
00680 Derek Foreman.
00681 My respect and my thanks to Derek for providing me a start back in 2005.
00682 
00683 */
00684 

Generated on Mon Mar 26 11:39:36 2007 for libburn by  doxygen 1.5.1