#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>
Go to the source code of this file.
Functions | |
int | libburner_aquire_by_adr (char *drive_adr) |
If the persistent drive address is known, then this approach is much more un-obtrusive to the systemwide livestock of drives. | |
int | libburner_aquire_by_driveno (int *driveno) |
This method demonstrates how to use libburn without knowing a persistent drive address in advance. | |
int | libburner_aquire_drive (char *drive_adr, int *driveno) |
You need to aquire a drive before burning. | |
int | libburner_blank_disc (struct burn_drive *drive, int blank_fast) |
Makes a previously used CD-RW ready for thorough re-usal. | |
int | libburner_format_row (struct burn_drive *drive) |
Persistently changes DVD-RW profile 0014h "Sequential Recording" 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_info * | drive_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 |
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 121 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().
00122 { 00123 int ret; 00124 char libburn_drive_adr[BURN_DRIVE_ADR_LEN]; 00125 00126 /* Some not-so-harmless drive addresses get blocked in this demo */ 00127 if (strncmp(drive_adr, "stdio:/dev/fd/", 14) == 0 || 00128 strcmp(drive_adr, "stdio:-") == 0) { 00129 fprintf(stderr, "Will not work with pseudo-drive '%s'\n", 00130 drive_adr); 00131 return 0; 00132 } 00133 00134 /* This tries to resolve links or alternative device files */ 00135 ret = burn_drive_convert_fs_adr(drive_adr, libburn_drive_adr); 00136 if (ret<=0) { 00137 fprintf(stderr, "Address does not lead to a CD burner: '%s'\n", 00138 drive_adr); 00139 return 0; 00140 } 00141 fprintf(stderr,"Aquiring drive '%s' ...\n", libburn_drive_adr); 00142 ret = burn_drive_scan_and_grab(&drive_list, libburn_drive_adr, 1); 00143 if (ret <= 0) { 00144 fprintf(stderr,"FAILURE with persistent drive address '%s'\n", 00145 libburn_drive_adr); 00146 } else { 00147 fprintf(stderr,"Done\n"); 00148 drive_is_grabbed = 1; 00149 } 00150 return ret; 00151 }
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().
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. |
Definition at line 166 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().
00167 { 00168 char adr[BURN_DRIVE_ADR_LEN]; 00169 int ret, i; 00170 00171 printf("Beginning to scan for devices ...\n"); 00172 while (!burn_drive_scan(&drive_list, &drive_count)) 00173 usleep(100002); 00174 if (drive_count <= 0 && *driveno >= 0) { 00175 printf("FAILED (no drives found)\n"); 00176 return 0; 00177 } 00178 printf("Done\n"); 00179 00180 /* 00181 Interactive programs may choose the drive number at this moment. 00182 00183 drive[0] to drive[drive_count-1] are struct burn_drive_info 00184 as defined in libburn/libburn.h . This structure is part of API 00185 and thus will strive for future compatibility on source level. 00186 Have a look at the info offered. 00187 Caution: do not take .location for drive address. Always use 00188 burn_drive_get_adr() or you might become incompatible 00189 in future. 00190 Note: bugs with struct burn_drive_info - if any - will not be 00191 easy to fix. Please report them but also strive for 00192 workarounds on application level. 00193 */ 00194 printf("\nOverview of accessible drives (%d found) :\n", 00195 drive_count); 00196 printf("-----------------------------------------------------------------------------\n"); 00197 for (i = 0; i < drive_count; i++) { 00198 if (burn_drive_get_adr(&(drive_list[i]), adr) <=0) 00199 strcpy(adr, "-get_adr_failed-"); 00200 printf("%d --drive '%s' : '%s' '%s'\n", 00201 i,adr,drive_list[i].vendor,drive_list[i].product); 00202 } 00203 printf("-----------------------------------------------------------------------------\n\n"); 00204 00205 /* 00206 On multi-drive systems save yourself from sysadmins' revenge. 00207 00208 Be aware that you hold reserved all available drives at this point. 00209 So either make your choice quick enough not to annoy other system 00210 users, or set free the drives for a while. 00211 00212 The tested way of setting free all drives is to shutdown the library 00213 and to restart when the choice has been made. The list of selectable 00214 drives should also hold persistent drive addresses as obtained 00215 above by burn_drive_get_adr(). By such an address one may use 00216 burn_drive_scan_and_grab() to finally aquire exactly one drive. 00217 00218 A not yet tested shortcut should be to call burn_drive_info_free() 00219 and to call either burn_drive_scan() or burn_drive_scan_and_grab() 00220 before accessing any drives again. 00221 00222 In both cases you have to be aware that the desired drive might get 00223 aquired in the meantime by another user resp. libburn process. 00224 */ 00225 00226 /* We already made our choice via command line. (default is 0) 00227 So we just have to keep our desired drive and drop all others. 00228 No other libburn instance will have a chance to steal our drive. 00229 */ 00230 if (*driveno < 0) { 00231 printf("Pseudo-drive \"-\" given : bus scanning done.\n"); 00232 return 2; /* the program will end after this */ 00233 } 00234 if (drive_count <= *driveno) { 00235 fprintf(stderr, 00236 "Found only %d drives. Number %d not available.\n", 00237 drive_count, *driveno); 00238 return 0; /* the program will end after this */ 00239 } 00240 00241 /* Drop all drives which we do not want to use */ 00242 for (i = 0; i < drive_count; i++) { 00243 if (i == *driveno) /* the one drive we want to keep */ 00244 continue; 00245 ret = burn_drive_info_forget(&(drive_list[i]),0); 00246 if (ret != 1) 00247 fprintf(stderr, "Cannot drop drive %d. Please report \"ret=%d\" to libburn-hackers@pykix.org\n", 00248 i, ret); 00249 else 00250 printf("Dropped unwanted drive %d\n",i); 00251 } 00252 /* Make the one we want ready for blanking or burning */ 00253 ret= burn_drive_grab(drive_list[*driveno].drive, 1); 00254 if (ret != 1) 00255 return 0; 00256 drive_is_grabbed = 1; 00257 return 1; 00258 }
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 99 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().
00100 { 00101 int ret; 00102 00103 if(drive_adr != NULL && drive_adr[0] != 0) 00104 ret = libburner_aquire_by_adr(drive_adr); 00105 else 00106 ret = libburner_aquire_by_driveno(driveno); 00107 if (ret <= 0) 00108 return ret; 00109 burn_disc_get_profile(drive_list[0].drive, ¤t_profile, 00110 current_profile_name); 00111 if (current_profile_name[0]) 00112 printf("Detected media type: %s\n", current_profile_name); 00113 return 1; 00114 }
int libburner_blank_disc | ( | struct burn_drive * | drive, | |
int | blank_fast | |||
) |
Makes a previously used CD-RW ready for thorough re-usal.
To our knowledge it is hardly possible to abort an ongoing blank operation because after start it is entirely handled by the drive. So expect signal handling to wait the normal blanking timespan until it can allow the process to end. External kill -9 will not help the drive.
Definition at line 268 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().
00269 { 00270 enum burn_disc_status disc_state; 00271 struct burn_progress p; 00272 double percent = 1.0; 00273 00274 disc_state = burn_disc_get_status(drive); 00275 printf( 00276 "Drive media status: %d (see libburn/libburn.h BURN_DISC_*)\n", 00277 disc_state); 00278 if (current_profile == 0x13) { 00279 ; /* formatted DVD-RW will get blanked to sequential state */ 00280 } else if (disc_state == BURN_DISC_BLANK) { 00281 fprintf(stderr, 00282 "IDLE: Blank media detected. Will leave it untouched\n"); 00283 return 2; 00284 } else if (disc_state == BURN_DISC_FULL || 00285 disc_state == BURN_DISC_APPENDABLE) { 00286 ; /* this is what libburner is willing to blank */ 00287 } else if (disc_state == BURN_DISC_EMPTY) { 00288 fprintf(stderr,"FATAL: No media detected in drive\n"); 00289 return 0; 00290 } else { 00291 fprintf(stderr, 00292 "FATAL: Unsuitable drive and media state\n"); 00293 return 0; 00294 } 00295 if(!burn_disc_erasable(drive)) { 00296 fprintf(stderr, 00297 "FATAL : Media is not of erasable type\n"); 00298 return 0; 00299 } 00300 printf( 00301 "Beginning to %s-blank media.\n", (blank_fast?"fast":"full")); 00302 burn_disc_erase(drive, blank_fast); 00303 sleep(1); 00304 while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) { 00305 if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */ 00306 percent = 1.0 + ((double) p.sector+1.0) 00307 / ((double) p.sectors) * 98.0; 00308 printf("Blanking ( %.1f%% done )\n", percent); 00309 sleep(1); 00310 } 00311 printf("Done\n"); 00312 return 1; 00313 }
int libburner_format_row | ( | struct burn_drive * | drive | ) |
Persistently changes DVD-RW profile 0014h "Sequential Recording" 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.
Definition at line 322 of file libburner.c.
References burn_disc_format(), burn_disc_get_profile(), burn_drive_get_status(), BURN_DRIVE_IDLE, current_profile, current_profile_name, burn_progress::sector, and burn_progress::sectors.
Referenced by main().
00323 { 00324 struct burn_progress p; 00325 double percent = 1.0; 00326 00327 if (current_profile == 0x13) { 00328 fprintf(stderr, "IDLE: DVD-RW media is already formatted\n"); 00329 return 2; 00330 } else if (current_profile != 0x14) { 00331 fprintf(stderr, "FATAL: Can only format DVD-RW\n"); 00332 return 0; 00333 } 00334 printf("Beginning to format media.\n"); 00335 burn_disc_format(drive, (off_t) 0, 0); 00336 00337 sleep(1); 00338 while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) { 00339 if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */ 00340 percent = 1.0 + ((double) p.sector+1.0) 00341 / ((double) p.sectors) * 98.0; 00342 printf("Formatting ( %.1f%% done )\n", percent); 00343 sleep(1); 00344 } 00345 burn_disc_get_profile(drive_list[0].drive, ¤t_profile, 00346 current_profile_name); 00347 printf("Media type now: %4.4xh \"%s\"\n", 00348 current_profile, current_profile_name); 00349 if (current_profile != 0x13) { 00350 fprintf(stderr, 00351 "FATAL: Failed to change media profile to desired value\n"); 00352 return 0; 00353 } 00354 return 1; 00355 }
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 373 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().
00376 { 00377 struct burn_source *data_src, *fifo_src[99]; 00378 struct burn_disc *target_disc; 00379 struct burn_session *session; 00380 struct burn_write_opts *burn_options; 00381 enum burn_disc_status disc_state; 00382 struct burn_track *track, *tracklist[99]; 00383 struct burn_progress progress; 00384 time_t start_time; 00385 int last_sector = 0, padding = 0, trackno, unpredicted_size = 0, fd; 00386 int fifo_chunksize = 2352, fifo_chunks = 1783; /* ~ 4 MB fifo */ 00387 off_t fixed_size; 00388 char *adr, reasons[BURN_REASONS_LEN]; 00389 struct stat stbuf; 00390 00391 if (all_tracks_type != BURN_AUDIO) { 00392 all_tracks_type = BURN_MODE1; 00393 /* a padding of 300 kiB helps to avoid the read-ahead bug */ 00394 padding = 300*1024; 00395 fifo_chunksize = 2048; 00396 fifo_chunks = 2048; /* 4 MB fifo */ 00397 } 00398 00399 target_disc = burn_disc_create(); 00400 session = burn_session_create(); 00401 burn_disc_add_session(target_disc, session, BURN_POS_END); 00402 00403 for (trackno = 0 ; trackno < source_adr_count; trackno++) { 00404 tracklist[trackno] = track = burn_track_create(); 00405 burn_track_define_data(track, 0, padding, 1, all_tracks_type); 00406 00407 /* Open file descriptor to source of track data */ 00408 adr = source_adr[trackno]; 00409 fixed_size = 0; 00410 if (adr[0] == '-' && adr[1] == 0) { 00411 fd = 0; 00412 } else { 00413 fd = open(adr, O_RDONLY); 00414 if (fd>=0) 00415 if (fstat(fd,&stbuf)!=-1) 00416 if((stbuf.st_mode&S_IFMT)==S_IFREG) 00417 fixed_size = stbuf.st_size; 00418 } 00419 if (fixed_size==0) 00420 unpredicted_size = 1; 00421 00422 /* Convert this filedescriptor into a burn_source object */ 00423 data_src = NULL; 00424 if (fd>=0) 00425 data_src = burn_fd_source_new(fd, -1, fixed_size); 00426 if (data_src == NULL) { 00427 fprintf(stderr, 00428 "FATAL: Could not open data source '%s'.\n",adr); 00429 if(errno!=0) 00430 fprintf(stderr,"(Most recent system error: %s )\n", 00431 strerror(errno)); 00432 return 0; 00433 } 00434 /* Install a fifo object on top of that data source object */ 00435 fifo_src[trackno] = burn_fifo_source_new(data_src, 00436 fifo_chunksize, fifo_chunks, 0); 00437 if (fifo_src[trackno] == NULL) { 00438 fprintf(stderr, 00439 "FATAL: Could not create fifo object of 4 MB\n"); 00440 return 0; 00441 } 00442 00443 /* Use the fifo object as data source for the track */ 00444 if (burn_track_set_source(track, fifo_src[trackno]) 00445 != BURN_SOURCE_OK) { 00446 fprintf(stderr, 00447 "FATAL: Cannot attach source object to track object\n"); 00448 return 0; 00449 } 00450 00451 burn_session_add_track(session, track, BURN_POS_END); 00452 printf("Track %d : source is '%s'\n", trackno+1, adr); 00453 00454 /* Give up local reference to the data burn_source object */ 00455 burn_source_free(data_src); 00456 00457 } /* trackno loop end */ 00458 00459 /* Evaluate drive and media */ 00460 disc_state = burn_disc_get_status(drive); 00461 if (disc_state != BURN_DISC_BLANK && 00462 disc_state != BURN_DISC_APPENDABLE) { 00463 if (disc_state == BURN_DISC_FULL) { 00464 fprintf(stderr, "FATAL: Closed media with data detected. Need blank or appendable media.\n"); 00465 if (burn_disc_erasable(drive)) 00466 fprintf(stderr, "HINT: Try --blank_fast\n\n"); 00467 } else if (disc_state == BURN_DISC_EMPTY) 00468 fprintf(stderr,"FATAL: No media detected in drive\n"); 00469 else 00470 fprintf(stderr, 00471 "FATAL: Cannot recognize state of drive and media\n"); 00472 return 0; 00473 } 00474 00475 burn_options = burn_write_opts_new(drive); 00476 burn_write_opts_set_perform_opc(burn_options, 0); 00477 burn_write_opts_set_multi(burn_options, !!multi); 00478 if(simulate_burn) 00479 printf("\n*** Will TRY to SIMULATE burning ***\n\n"); 00480 burn_write_opts_set_simulate(burn_options, simulate_burn); 00481 burn_drive_set_speed(drive, 0, 0); 00482 burn_write_opts_set_underrun_proof(burn_options, 1); 00483 if (burn_write_opts_auto_write_type(burn_options, target_disc, 00484 reasons, 0) == BURN_WRITE_NONE) { 00485 fprintf(stderr, "FATAL: Failed to find a suitable write mode with this media.\n"); 00486 fprintf(stderr, "Reasons given:\n%s\n", reasons); 00487 return 0; 00488 } 00489 00490 printf("Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n"); 00491 start_time = time(0); 00492 burn_disc_write(burn_options, target_disc); 00493 00494 burn_write_opts_free(burn_options); 00495 while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING) 00496 usleep(100002); 00497 while (burn_drive_get_status(drive, &progress) != BURN_DRIVE_IDLE) { 00498 if (progress.sectors <= 0 || 00499 (progress.sector >= progress.sectors - 1 && 00500 !unpredicted_size) || 00501 (unpredicted_size && progress.sector == last_sector)) 00502 printf( 00503 "Thank you for being patient since %d seconds.", 00504 (int) (time(0) - start_time)); 00505 else if(unpredicted_size) 00506 printf("Track %d : sector %d", progress.track+1, 00507 progress.sector); 00508 else 00509 printf("Track %d : sector %d of %d",progress.track+1, 00510 progress.sector, progress.sectors); 00511 last_sector = progress.sector; 00512 if (progress.track >= 0 && progress.track < source_adr_count) { 00513 int size, free_bytes, ret; 00514 char *status_text; 00515 00516 ret = burn_fifo_inquire_status( 00517 fifo_src[progress.track], &size, &free_bytes, 00518 &status_text); 00519 if (ret >= 0 ) 00520 printf(" [fifo %s, %2d%% fill]", status_text, 00521 (int) (100.0 - 100.0 * 00522 ((double) free_bytes) / 00523 (double) size)); 00524 } 00525 printf("\n"); 00526 sleep(1); 00527 } 00528 printf("\n"); 00529 00530 for (trackno = 0 ; trackno < source_adr_count; trackno++) { 00531 burn_source_free(fifo_src[trackno]); 00532 burn_track_free(tracklist[trackno]); 00533 } 00534 burn_session_free(session); 00535 burn_disc_free(target_disc); 00536 if (multi && current_profile != 0x1a && current_profile != 0x13 && 00537 current_profile != 0x12) /* not with DVD+RW, DVD-RW, DVD-RAM */ 00538 printf("NOTE: Media left appendable.\n"); 00539 if (simulate_burn) 00540 printf("\n*** Did TRY to SIMULATE burning ***\n\n"); 00541 return 1; 00542 }
int libburner_setup | ( | int | argc, | |
char ** | argv | |||
) |
Converts command line arguments into above setup parameters.
Definition at line 558 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().
00559 { 00560 int i, insuffient_parameters = 0, print_help = 0; 00561 00562 for (i = 1; i < argc; ++i) { 00563 if (!strcmp(argv[i], "--audio")) { 00564 all_tracks_type = BURN_AUDIO; 00565 00566 } else if (!strcmp(argv[i], "--blank_fast")) { 00567 do_blank = 1; 00568 00569 } else if (!strcmp(argv[i], "--blank_full")) { 00570 do_blank = 2; 00571 00572 } else if (!strcmp(argv[i], "--burn_for_real")) { 00573 simulate_burn = 0; 00574 00575 } else if (!strcmp(argv[i], "--drive")) { 00576 ++i; 00577 if (i >= argc) { 00578 fprintf(stderr,"--drive requires an argument\n"); 00579 return 1; 00580 } else if (strcmp(argv[i], "-") == 0) { 00581 drive_adr[0] = 0; 00582 driveno = -1; 00583 } else if (isdigit(argv[i][0])) { 00584 drive_adr[0] = 0; 00585 driveno = atoi(argv[i]); 00586 } else { 00587 if(strlen(argv[i]) >= BURN_DRIVE_ADR_LEN) { 00588 fprintf(stderr,"--drive address too long (max. %d)\n", 00589 BURN_DRIVE_ADR_LEN-1); 00590 return 2; 00591 } 00592 strcpy(drive_adr, argv[i]); 00593 } 00594 } else if (!strcmp(argv[i], "--format_overwrite")) { 00595 do_blank = 101; 00596 00597 } else if (!strcmp(argv[i], "--multi")) { 00598 do_multi = 1; 00599 00600 } else if (!strcmp(argv[i], "--stdin_size")) { /* obsoleted */ 00601 i++; 00602 00603 } else if (!strcmp(argv[i], "--try_to_simulate")) { 00604 simulate_burn = 1; 00605 00606 } else if (!strcmp(argv[i], "--help")) { 00607 print_help = 1; 00608 00609 } else if (!strncmp(argv[i], "--",2)) { 00610 fprintf(stderr, "Unidentified option: %s\n", argv[i]); 00611 return 7; 00612 } else { 00613 if(strlen(argv[i]) >= 4096) { 00614 fprintf(stderr, "Source address too long (max. %d)\n", 4096-1); 00615 return 5; 00616 } 00617 if(source_adr_count >= 99) { 00618 fprintf(stderr, "Too many tracks (max. 99)\n"); 00619 return 6; 00620 } 00621 strcpy(source_adr[source_adr_count], argv[i]); 00622 source_adr_count++; 00623 } 00624 } 00625 insuffient_parameters = 1; 00626 if (driveno < 0) 00627 insuffient_parameters = 0; 00628 if (source_adr_count > 0) 00629 insuffient_parameters = 0; 00630 if (do_blank) 00631 insuffient_parameters = 0; 00632 if (print_help || insuffient_parameters ) { 00633 printf("Usage: %s\n", argv[0]); 00634 printf(" [--drive <address>|<driveno>|\"-\"] [--audio]\n"); 00635 printf(" [--blank_fast|--blank_full|--format_overwrite]\n"); 00636 printf(" [--try_to_simulate]\n"); 00637 printf(" [--multi] [<one or more imagefiles>|\"-\"]\n"); 00638 printf("Examples\n"); 00639 printf("A bus scan (needs rw-permissions to see a drive):\n"); 00640 printf(" %s --drive -\n",argv[0]); 00641 printf("Burn a file to drive chosen by number, leave appendable:\n"); 00642 printf(" %s --drive 0 --multi my_image_file\n", argv[0]); 00643 printf("Burn a file to drive chosen by persistent address, close:\n"); 00644 printf(" %s --drive /dev/hdc my_image_file\n", argv[0]); 00645 printf("Blank a used CD-RW (is combinable with burning in one run):\n"); 00646 printf(" %s --drive /dev/hdc --blank_fast\n",argv[0]); 00647 printf("Blank a used DVD-RW (is combinable with burning in one run):\n"); 00648 printf(" %s --drive /dev/hdc --blank_full\n",argv[0]); 00649 printf("Format a DVD-RW to avoid need for blanking before re-use:\n"); 00650 printf(" %s --drive /dev/hdc --format_overwrite\n", argv[0]); 00651 printf("Burn two audio tracks (to CD only):\n"); 00652 printf(" lame --decode -t /path/to/track1.mp3 track1.cd\n"); 00653 printf(" test/dewav /path/to/track2.wav -o track2.cd\n"); 00654 printf(" %s --drive /dev/hdc --audio track1.cd track2.cd\n", argv[0]); 00655 printf("Burn a compressed afio archive on-the-fly:\n"); 00656 printf(" ( cd my_directory ; find . -print | afio -oZ - ) | \\\n"); 00657 printf(" %s --drive /dev/hdc -\n", argv[0]); 00658 printf("To be read from *not mounted* media via: afio -tvZ /dev/hdc\n"); 00659 if (insuffient_parameters) 00660 return 6; 00661 } 00662 return 0; 00663 }
int main | ( | int | argc, | |
char ** | argv | |||
) |
Note: driveno might change its value in this call
Definition at line 666 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_row(), libburner_payload(), libburner_setup(), simulate_burn, source_adr, and source_adr_count.
00667 { 00668 int ret; 00669 00670 ret = libburner_setup(argc, argv); 00671 if (ret) 00672 exit(ret); 00673 00674 printf("Initializing libburnia-project.org ...\n"); 00675 if (burn_initialize()) 00676 printf("Done\n"); 00677 else { 00678 printf("FAILED\n"); 00679 fprintf(stderr,"\nFATAL: Failed to initialize.\n"); 00680 exit(33); 00681 } 00682 00683 /* Print messages of severity SORRY or more directly to stderr */ 00684 burn_msgs_set_severities("NEVER", "SORRY", "libburner : "); 00685 00686 /* Activate the default signal handler which eventually will try to 00687 properly shutdown drive and library on aborting events. */ 00688 burn_set_signal_handling("libburner : ", NULL, 0); 00689 00690 /** Note: driveno might change its value in this call */ 00691 ret = libburner_aquire_drive(drive_adr, &driveno); 00692 if (ret<=0) { 00693 fprintf(stderr,"\nFATAL: Failed to aquire drive.\n"); 00694 { ret = 34; goto finish_libburn; } 00695 } 00696 if (ret == 2) 00697 { ret = 0; goto release_drive; } 00698 if (do_blank) { 00699 if (do_blank > 100) 00700 ret = libburner_format_row(drive_list[driveno].drive); 00701 else 00702 ret = libburner_blank_disc(drive_list[driveno].drive, 00703 do_blank == 1); 00704 if (ret<=0) 00705 { ret = 36; goto release_drive; } 00706 } 00707 if (source_adr_count > 0) { 00708 ret = libburner_payload(drive_list[driveno].drive, 00709 source_adr, source_adr_count, 00710 do_multi, simulate_burn, all_tracks_type); 00711 if (ret<=0) 00712 { ret = 38; goto release_drive; } 00713 } 00714 ret = 0; 00715 release_drive:; 00716 if (drive_is_grabbed) 00717 burn_drive_release(drive_list[driveno].drive, 0); 00718 00719 finish_libburn:; 00720 /* This app does not bother to know about exact scan state. 00721 Better to accept a memory leak here. We are done anyway. */ 00722 /* burn_drive_info_free(drive_list); */ 00723 00724 burn_finish(); 00725 exit(ret); 00726 }
int all_tracks_type = BURN_MODE1 [static] |
int current_profile = -1 [static] |
A number and a text describing the type of media in aquired drive.
Definition at line 76 of file libburner.c.
Referenced by libburner_aquire_drive(), libburner_blank_disc(), libburner_format_row(), and libburner_payload().
char current_profile_name[80] = {""} [static] |
Definition at line 77 of file libburner.c.
Referenced by libburner_aquire_drive(), and libburner_format_row().
int do_blank = 0 [static] |
int do_multi = 0 [static] |
char drive_adr[BURN_DRIVE_ADR_LEN] = {""} [static] |
The setup parameters of libburner.
Definition at line 546 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 69 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 73 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 a DVD-RW, can burn to CD-R, CD-RW, DVD-R, DVD+R, DVD+R/DL, DVD+RW, DVD-RAM or DVD-RW. Not supported yet: DVD-R/DL, BD.
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) libburner_format_row() With the aquired drive you can burn to CD or DVD 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 65 of file libburner.c.
int driveno = 0 [static] |
int simulate_burn = 0 [static] |
char source_adr[99][4096] [static] |
int source_adr_count = 0 [static] |