#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 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_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 133 of file libburner.c.
References BURN_DRIVE_ADR_LEN, burn_drive_convert_fs_adr(), burn_drive_scan_and_grab(), and drive_is_grabbed.
Referenced by libburner_aquire_drive().
00134 { 00135 int ret; 00136 char libburn_drive_adr[BURN_DRIVE_ADR_LEN]; 00137 00138 /* Some not-so-harmless drive addresses get blocked in this demo */ 00139 if (strncmp(drive_adr, "stdio:/dev/fd/", 14) == 0 || 00140 strcmp(drive_adr, "stdio:-") == 0) { 00141 fprintf(stderr, "Will not work with pseudo-drive '%s'\n", 00142 drive_adr); 00143 return 0; 00144 } 00145 00146 /* This tries to resolve links or alternative device files */ 00147 ret = burn_drive_convert_fs_adr(drive_adr, libburn_drive_adr); 00148 if (ret<=0) { 00149 fprintf(stderr, "Address does not lead to a CD burner: '%s'\n", 00150 drive_adr); 00151 return 0; 00152 } 00153 fprintf(stderr,"Aquiring drive '%s' ...\n", libburn_drive_adr); 00154 ret = burn_drive_scan_and_grab(&drive_list, libburn_drive_adr, 1); 00155 if (ret <= 0) { 00156 fprintf(stderr,"FAILURE with persistent drive address '%s'\n", 00157 libburn_drive_adr); 00158 } else { 00159 fprintf(stderr,"Done\n"); 00160 drive_is_grabbed = 1; 00161 } 00162 return ret; 00163 }
int libburner_aquire_by_driveno | ( | int * | driveno | ) |
This method demonstrates how to use libburn without knowing a persistent drive address in advance.
It has to make sure that after assessing the list of available drives, all unwanted drives get closed again. As long as they are open, no other libburn instance can see them. This is an intended locking feature. The application is responsible for giving up the locks by either burn_drive_release() (only after burn_drive_grab() !), burn_drive_info_forget(), burn_drive_info_free(), or burn_finish().
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 178 of file libburner.c.
References BURN_DRIVE_ADR_LEN, burn_drive_get_adr(), burn_drive_grab(), burn_drive_info_forget(), burn_drive_scan(), burn_drive_info::drive, drive_count, drive_is_grabbed, burn_drive_info::product, and burn_drive_info::vendor.
Referenced by libburner_aquire_drive().
00179 { 00180 char adr[BURN_DRIVE_ADR_LEN]; 00181 int ret, i; 00182 00183 printf("Beginning to scan for devices ...\n"); 00184 while (!burn_drive_scan(&drive_list, &drive_count)) 00185 usleep(100002); 00186 if (drive_count <= 0 && *driveno >= 0) { 00187 printf("FAILED (no drives found)\n"); 00188 return 0; 00189 } 00190 printf("Done\n"); 00191 00192 /* 00193 Interactive programs may choose the drive number at this moment. 00194 00195 drive[0] to drive[drive_count-1] are struct burn_drive_info 00196 as defined in libburn/libburn.h . This structure is part of API 00197 and thus will strive for future compatibility on source level. 00198 Have a look at the info offered. 00199 Caution: do not take .location for drive address. Always use 00200 burn_drive_get_adr() or you might become incompatible 00201 in future. 00202 Note: bugs with struct burn_drive_info - if any - will not be 00203 easy to fix. Please report them but also strive for 00204 workarounds on application level. 00205 */ 00206 printf("\nOverview of accessible drives (%d found) :\n", 00207 drive_count); 00208 printf("-----------------------------------------------------------------------------\n"); 00209 for (i = 0; i < drive_count; i++) { 00210 if (burn_drive_get_adr(&(drive_list[i]), adr) <=0) 00211 strcpy(adr, "-get_adr_failed-"); 00212 printf("%d --drive '%s' : '%s' '%s'\n", 00213 i,adr,drive_list[i].vendor,drive_list[i].product); 00214 } 00215 printf("-----------------------------------------------------------------------------\n\n"); 00216 00217 /* 00218 On multi-drive systems save yourself from sysadmins' revenge. 00219 00220 Be aware that you hold reserved all available drives at this point. 00221 So either make your choice quick enough not to annoy other system 00222 users, or set free the drives for a while. 00223 00224 The tested way of setting free all drives is to shutdown the library 00225 and to restart when the choice has been made. The list of selectable 00226 drives should also hold persistent drive addresses as obtained 00227 above by burn_drive_get_adr(). By such an address one may use 00228 burn_drive_scan_and_grab() to finally aquire exactly one drive. 00229 00230 A not yet tested shortcut should be to call burn_drive_info_free() 00231 and to call either burn_drive_scan() or burn_drive_scan_and_grab() 00232 before accessing any drives again. 00233 00234 In both cases you have to be aware that the desired drive might get 00235 aquired in the meantime by another user resp. libburn process. 00236 */ 00237 00238 /* We already made our choice via command line. (default is 0) 00239 So we just have to keep our desired drive and drop all others. 00240 No other libburn instance will have a chance to steal our drive. 00241 */ 00242 if (*driveno < 0) { 00243 printf("Pseudo-drive \"-\" given : bus scanning done.\n"); 00244 return 2; /* the program will end after this */ 00245 } 00246 if (drive_count <= *driveno) { 00247 fprintf(stderr, 00248 "Found only %d drives. Number %d not available.\n", 00249 drive_count, *driveno); 00250 return 0; /* the program will end after this */ 00251 } 00252 00253 /* Drop all drives which we do not want to use */ 00254 for (i = 0; i < drive_count; i++) { 00255 if (i == *driveno) /* the one drive we want to keep */ 00256 continue; 00257 ret = burn_drive_info_forget(&(drive_list[i]),0); 00258 if (ret != 1) 00259 fprintf(stderr, "Cannot drop drive %d. Please report \"ret=%d\" to libburn-hackers@pykix.org\n", 00260 i, ret); 00261 else 00262 printf("Dropped unwanted drive %d\n",i); 00263 } 00264 /* Make the one we want ready for blanking or burning */ 00265 ret= burn_drive_grab(drive_list[*driveno].drive, 1); 00266 if (ret != 1) 00267 return 0; 00268 drive_is_grabbed = 1; 00269 return 1; 00270 }
int libburner_aquire_drive | ( | char * | drive_adr, | |
int * | driveno | |||
) |
You need to aquire a drive before burning.
The API offers this as one compact call and alternatively as application controllable gestures of whitelisting, scanning for drives and finally grabbing one of them.
If you have a persistent address of the drive, then the compact call is to prefer because it only touches one drive. On modern Linux kernels, there should be no fatal disturbance of ongoing burns of other libburn instances with any of our approaches. We use open(O_EXCL) by default. On /dev/hdX it should cooperate with growisofs and some cdrecord variants. On /dev/sgN versus /dev/scdM expect it not to respect other programs.
Definition at line 111 of file libburner.c.
References burn_disc_get_profile(), current_profile, current_profile_name, burn_drive_info::drive, libburner_aquire_by_adr(), and libburner_aquire_by_driveno().
Referenced by main().
00112 { 00113 int ret; 00114 00115 if(drive_adr != NULL && drive_adr[0] != 0) 00116 ret = libburner_aquire_by_adr(drive_adr); 00117 else 00118 ret = libburner_aquire_by_driveno(driveno); 00119 if (ret <= 0 || *driveno <= 0) 00120 return ret; 00121 burn_disc_get_profile(drive_list[0].drive, ¤t_profile, 00122 current_profile_name); 00123 if (current_profile_name[0]) 00124 printf("Detected media type: %s\n", current_profile_name); 00125 return 1; 00126 }
int libburner_blank_disc | ( | struct burn_drive * | drive, | |
int | blank_fast | |||
) |
Makes a previously used CD-RW or unformatted DVD-RW ready for thorough re-usal.
To our knowledge it is hardly possible to abort an ongoing blank operation because after start it is entirely handled by the drive. So expect signal handling to wait the normal blanking timespan until it can allow the process to end. External kill -9 will not help the drive.
Definition at line 281 of file libburner.c.
References BURN_DISC_APPENDABLE, BURN_DISC_BLANK, BURN_DISC_EMPTY, burn_disc_erasable(), burn_disc_erase(), BURN_DISC_FULL, burn_disc_get_status(), burn_drive_get_status(), BURN_DRIVE_IDLE, current_profile, burn_progress::sector, and burn_progress::sectors.
Referenced by main().
00282 { 00283 enum burn_disc_status disc_state; 00284 struct burn_progress p; 00285 double percent = 1.0; 00286 00287 disc_state = burn_disc_get_status(drive); 00288 printf( 00289 "Drive media status: %d (see libburn/libburn.h BURN_DISC_*)\n", 00290 disc_state); 00291 if (current_profile == 0x13) { 00292 ; /* formatted DVD-RW will get blanked to sequential state */ 00293 } else if (disc_state == BURN_DISC_BLANK) { 00294 fprintf(stderr, 00295 "IDLE: Blank media detected. Will leave it untouched\n"); 00296 return 2; 00297 } else if (disc_state == BURN_DISC_FULL || 00298 disc_state == BURN_DISC_APPENDABLE) { 00299 ; /* this is what libburner is willing to blank */ 00300 } else if (disc_state == BURN_DISC_EMPTY) { 00301 fprintf(stderr,"FATAL: No media detected in drive\n"); 00302 return 0; 00303 } else { 00304 fprintf(stderr, 00305 "FATAL: Unsuitable drive and media state\n"); 00306 return 0; 00307 } 00308 if(!burn_disc_erasable(drive)) { 00309 fprintf(stderr, 00310 "FATAL : Media is not of erasable type\n"); 00311 return 0; 00312 } 00313 printf( 00314 "Beginning to %s-blank media.\n", (blank_fast?"fast":"full")); 00315 burn_disc_erase(drive, blank_fast); 00316 sleep(1); 00317 while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) { 00318 if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */ 00319 percent = 1.0 + ((double) p.sector+1.0) 00320 / ((double) p.sectors) * 98.0; 00321 printf("Blanking ( %.1f%% done )\n", percent); 00322 sleep(1); 00323 } 00324 printf("Done\n"); 00325 return 1; 00326 }
int libburner_format | ( | struct burn_drive * | drive | ) |
Formats unformatted DVD-RW to profile 0013h "Restricted Overwrite" which needs no blanking for re-use but is not capable of multi-session.
Expect a behavior similar to blanking with unusual noises from the drive.
Formats unformatted BD-RE to default size. This will allocate some reserve space, test for bad blocks and make the media ready for writing. Expect a very long run time.
Formats unformatted blank BD-R to hold a default amount of spare blocks for eventual mishaps during writing. If BD-R get written without being formatted, then they get no such reserve and will burn at full speed.
Definition at line 341 of file libburner.c.
References BURN_DISC_BLANK, burn_disc_format(), burn_disc_get_formats(), burn_disc_get_profile(), burn_disc_get_status(), burn_drive_get_status(), BURN_DRIVE_IDLE, BURN_FORMAT_IS_UNFORMATTED, current_profile, current_profile_name, burn_progress::sector, and burn_progress::sectors.
Referenced by main().
00342 { 00343 struct burn_progress p; 00344 double percent = 1.0; 00345 int ret, status, num_formats, format_flag= 0; 00346 off_t size = 0; 00347 unsigned dummy; 00348 enum burn_disc_status disc_state; 00349 00350 if (current_profile == 0x13) { 00351 fprintf(stderr, "IDLE: DVD-RW media is already formatted\n"); 00352 return 2; 00353 } else if (current_profile == 0x41 || current_profile == 0x43) { 00354 disc_state = burn_disc_get_status(drive); 00355 if (disc_state != BURN_DISC_BLANK && current_profile == 0x41) { 00356 fprintf(stderr, 00357 "FATAL: BD-R is not blank. Cannot format.\n"); 00358 return 0; 00359 } 00360 ret = burn_disc_get_formats(drive, &status, &size, &dummy, 00361 &num_formats); 00362 if (ret > 0 && status != BURN_FORMAT_IS_UNFORMATTED) { 00363 fprintf(stderr, 00364 "IDLE: BD media is already formatted\n"); 00365 return 2; 00366 } 00367 size = 0; /* does not really matter */ 00368 format_flag = 3<<1; /* format to default size, no quick */ 00369 } else if (current_profile == 0x14) { /* sequential DVD-RW */ 00370 size = 128 * 1024 * 1024; 00371 format_flag = 1; /* write initial 128 MiB */ 00372 } else { 00373 fprintf(stderr, "FATAL: Can only format DVD-RW or BD\n"); 00374 return 0; 00375 } 00376 00377 printf("Beginning to format media.\n"); 00378 burn_disc_format(drive, size, format_flag); 00379 00380 sleep(1); 00381 while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) { 00382 if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */ 00383 percent = 1.0 + ((double) p.sector+1.0) 00384 / ((double) p.sectors) * 98.0; 00385 printf("Formatting ( %.1f%% done )\n", percent); 00386 sleep(1); 00387 } 00388 burn_disc_get_profile(drive_list[0].drive, ¤t_profile, 00389 current_profile_name); 00390 if (current_profile == 0x14 || current_profile == 0x13) 00391 printf("Media type now: %4.4xh \"%s\"\n", 00392 current_profile, current_profile_name); 00393 if (current_profile == 0x14) { 00394 fprintf(stderr, 00395 "FATAL: Failed to change media profile to desired value\n"); 00396 return 0; 00397 } 00398 return 1; 00399 }
int libburner_payload | ( | struct burn_drive * | drive, | |
char | source_adr[][4096], | |||
int | source_adr_count, | |||
int | multi, | |||
int | simulate_burn, | |||
int | all_tracks_type | |||
) |
Brings preformatted track images (ISO 9660, audio, .
..) onto media. To make sure a data image is fully readable on any Linux machine, this function adds 300 kiB of padding to the (usualy single) track. Audio tracks get padded to complete their last sector. A fifo of 4 MB is installed between each track and its data source. Each of the 4 MB buffers gets allocated automatically as soon as a track begins to be processed and it gets freed as soon as the track is done. The fifos do not wait for buffer fill but writing starts immediately.
In case of external signals expect abort handling of an ongoing burn to last up to a minute. Wait the normal burning timespan before any kill -9.
For simplicity, this function allows memory leaks in case of failure. In apps which do not abort immediately, one should clean up better.
Definition at line 417 of file libburner.c.
References BURN_AUDIO, burn_disc_add_session(), BURN_DISC_APPENDABLE, BURN_DISC_BLANK, burn_disc_create(), BURN_DISC_EMPTY, burn_disc_erasable(), burn_disc_free(), BURN_DISC_FULL, burn_disc_get_status(), burn_disc_write(), burn_drive_get_status(), BURN_DRIVE_IDLE, burn_drive_set_speed(), BURN_DRIVE_SPAWNING, burn_fd_source_new(), burn_fifo_inquire_status(), burn_fifo_source_new(), BURN_MODE1, BURN_POS_END, BURN_REASONS_LEN, burn_session_add_track(), burn_session_create(), burn_session_free(), burn_source_free(), BURN_SOURCE_OK, burn_track_create(), burn_track_define_data(), burn_track_free(), burn_track_set_source(), BURN_WRITE_NONE, burn_write_opts_auto_write_type(), burn_write_opts_free(), burn_write_opts_new(), burn_write_opts_set_multi(), burn_write_opts_set_perform_opc(), burn_write_opts_set_simulate(), burn_write_opts_set_underrun_proof(), current_profile, burn_progress::sector, burn_progress::sectors, and burn_progress::track.
Referenced by main().
00420 { 00421 struct burn_source *data_src, *fifo_src[99]; 00422 struct burn_disc *target_disc; 00423 struct burn_session *session; 00424 struct burn_write_opts *burn_options; 00425 enum burn_disc_status disc_state; 00426 struct burn_track *track, *tracklist[99]; 00427 struct burn_progress progress; 00428 time_t start_time; 00429 int last_sector = 0, padding = 0, trackno, unpredicted_size = 0, fd; 00430 int fifo_chunksize = 2352, fifo_chunks = 1783; /* ~ 4 MB fifo */ 00431 off_t fixed_size; 00432 char *adr, reasons[BURN_REASONS_LEN]; 00433 struct stat stbuf; 00434 00435 if (all_tracks_type != BURN_AUDIO) { 00436 all_tracks_type = BURN_MODE1; 00437 /* a padding of 300 kiB helps to avoid the read-ahead bug */ 00438 padding = 300*1024; 00439 fifo_chunksize = 2048; 00440 fifo_chunks = 2048; /* 4 MB fifo */ 00441 } 00442 00443 target_disc = burn_disc_create(); 00444 session = burn_session_create(); 00445 burn_disc_add_session(target_disc, session, BURN_POS_END); 00446 00447 for (trackno = 0 ; trackno < source_adr_count; trackno++) { 00448 tracklist[trackno] = track = burn_track_create(); 00449 burn_track_define_data(track, 0, padding, 1, all_tracks_type); 00450 00451 /* Open file descriptor to source of track data */ 00452 adr = source_adr[trackno]; 00453 fixed_size = 0; 00454 if (adr[0] == '-' && adr[1] == 0) { 00455 fd = 0; 00456 } else { 00457 fd = open(adr, O_RDONLY); 00458 if (fd>=0) 00459 if (fstat(fd,&stbuf)!=-1) 00460 if((stbuf.st_mode&S_IFMT)==S_IFREG) 00461 fixed_size = stbuf.st_size; 00462 } 00463 if (fixed_size==0) 00464 unpredicted_size = 1; 00465 00466 /* Convert this filedescriptor into a burn_source object */ 00467 data_src = NULL; 00468 if (fd>=0) 00469 data_src = burn_fd_source_new(fd, -1, fixed_size); 00470 if (data_src == NULL) { 00471 fprintf(stderr, 00472 "FATAL: Could not open data source '%s'.\n",adr); 00473 if(errno!=0) 00474 fprintf(stderr,"(Most recent system error: %s )\n", 00475 strerror(errno)); 00476 return 0; 00477 } 00478 /* Install a fifo object on top of that data source object */ 00479 fifo_src[trackno] = burn_fifo_source_new(data_src, 00480 fifo_chunksize, fifo_chunks, 0); 00481 if (fifo_src[trackno] == NULL) { 00482 fprintf(stderr, 00483 "FATAL: Could not create fifo object of 4 MB\n"); 00484 return 0; 00485 } 00486 00487 /* Use the fifo object as data source for the track */ 00488 if (burn_track_set_source(track, fifo_src[trackno]) 00489 != BURN_SOURCE_OK) { 00490 fprintf(stderr, 00491 "FATAL: Cannot attach source object to track object\n"); 00492 return 0; 00493 } 00494 00495 burn_session_add_track(session, track, BURN_POS_END); 00496 printf("Track %d : source is '%s'\n", trackno+1, adr); 00497 00498 /* Give up local reference to the data burn_source object */ 00499 burn_source_free(data_src); 00500 00501 } /* trackno loop end */ 00502 00503 /* Evaluate drive and media */ 00504 disc_state = burn_disc_get_status(drive); 00505 if (disc_state != BURN_DISC_BLANK && 00506 disc_state != BURN_DISC_APPENDABLE) { 00507 if (disc_state == BURN_DISC_FULL) { 00508 fprintf(stderr, "FATAL: Closed media with data detected. Need blank or appendable media.\n"); 00509 if (burn_disc_erasable(drive)) 00510 fprintf(stderr, "HINT: Try --blank_fast\n\n"); 00511 } else if (disc_state == BURN_DISC_EMPTY) 00512 fprintf(stderr,"FATAL: No media detected in drive\n"); 00513 else 00514 fprintf(stderr, 00515 "FATAL: Cannot recognize state of drive and media\n"); 00516 return 0; 00517 } 00518 00519 burn_options = burn_write_opts_new(drive); 00520 burn_write_opts_set_perform_opc(burn_options, 0); 00521 burn_write_opts_set_multi(burn_options, !!multi); 00522 if(simulate_burn) 00523 printf("\n*** Will TRY to SIMULATE burning ***\n\n"); 00524 burn_write_opts_set_simulate(burn_options, simulate_burn); 00525 burn_drive_set_speed(drive, 0, 0); 00526 burn_write_opts_set_underrun_proof(burn_options, 1); 00527 if (burn_write_opts_auto_write_type(burn_options, target_disc, 00528 reasons, 0) == BURN_WRITE_NONE) { 00529 fprintf(stderr, "FATAL: Failed to find a suitable write mode with this media.\n"); 00530 fprintf(stderr, "Reasons given:\n%s\n", reasons); 00531 return 0; 00532 } 00533 00534 printf("Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n"); 00535 start_time = time(0); 00536 burn_disc_write(burn_options, target_disc); 00537 00538 burn_write_opts_free(burn_options); 00539 while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING) 00540 usleep(100002); 00541 while (burn_drive_get_status(drive, &progress) != BURN_DRIVE_IDLE) { 00542 if (progress.sectors <= 0 || 00543 (progress.sector >= progress.sectors - 1 && 00544 !unpredicted_size) || 00545 (unpredicted_size && progress.sector == last_sector)) 00546 printf( 00547 "Thank you for being patient since %d seconds.", 00548 (int) (time(0) - start_time)); 00549 else if(unpredicted_size) 00550 printf("Track %d : sector %d", progress.track+1, 00551 progress.sector); 00552 else 00553 printf("Track %d : sector %d of %d",progress.track+1, 00554 progress.sector, progress.sectors); 00555 last_sector = progress.sector; 00556 if (progress.track >= 0 && progress.track < source_adr_count) { 00557 int size, free_bytes, ret; 00558 char *status_text; 00559 00560 ret = burn_fifo_inquire_status( 00561 fifo_src[progress.track], &size, &free_bytes, 00562 &status_text); 00563 if (ret >= 0 ) 00564 printf(" [fifo %s, %2d%% fill]", status_text, 00565 (int) (100.0 - 100.0 * 00566 ((double) free_bytes) / 00567 (double) size)); 00568 } 00569 printf("\n"); 00570 sleep(1); 00571 } 00572 printf("\n"); 00573 00574 for (trackno = 0 ; trackno < source_adr_count; trackno++) { 00575 burn_source_free(fifo_src[trackno]); 00576 burn_track_free(tracklist[trackno]); 00577 } 00578 burn_session_free(session); 00579 burn_disc_free(target_disc); 00580 if (multi && current_profile != 0x1a && current_profile != 0x13 && 00581 current_profile != 0x12 && current_profile != 0x43) 00582 /* not with DVD+RW, formatted DVD-RW, DVD-RAM, BD-RE */ 00583 printf("NOTE: Media left appendable.\n"); 00584 if (simulate_burn) 00585 printf("\n*** Did TRY to SIMULATE burning ***\n\n"); 00586 return 1; 00587 }
int libburner_setup | ( | int | argc, | |
char ** | argv | |||
) |
Converts command line arguments into above setup parameters.
Definition at line 603 of file libburner.c.
References all_tracks_type, BURN_AUDIO, BURN_DRIVE_ADR_LEN, do_blank, do_multi, drive_adr, driveno, simulate_burn, source_adr, and source_adr_count.
Referenced by main().
00604 { 00605 int i, insuffient_parameters = 0, print_help = 0; 00606 00607 for (i = 1; i < argc; ++i) { 00608 if (!strcmp(argv[i], "--audio")) { 00609 all_tracks_type = BURN_AUDIO; 00610 00611 } else if (!strcmp(argv[i], "--blank_fast")) { 00612 do_blank = 1; 00613 00614 } else if (!strcmp(argv[i], "--blank_full")) { 00615 do_blank = 2; 00616 00617 } else if (!strcmp(argv[i], "--burn_for_real")) { 00618 simulate_burn = 0; 00619 00620 } else if (!strcmp(argv[i], "--drive")) { 00621 ++i; 00622 if (i >= argc) { 00623 fprintf(stderr,"--drive requires an argument\n"); 00624 return 1; 00625 } else if (strcmp(argv[i], "-") == 0) { 00626 drive_adr[0] = 0; 00627 driveno = -1; 00628 } else if (isdigit(argv[i][0])) { 00629 drive_adr[0] = 0; 00630 driveno = atoi(argv[i]); 00631 } else { 00632 if(strlen(argv[i]) >= BURN_DRIVE_ADR_LEN) { 00633 fprintf(stderr,"--drive address too long (max. %d)\n", 00634 BURN_DRIVE_ADR_LEN-1); 00635 return 2; 00636 } 00637 strcpy(drive_adr, argv[i]); 00638 } 00639 } else if ((!strcmp(argv[i], "--format_overwrite")) || 00640 (!strcmp(argv[i], "--format"))) { 00641 do_blank = 101; 00642 00643 } else if (!strcmp(argv[i], "--multi")) { 00644 do_multi = 1; 00645 00646 } else if (!strcmp(argv[i], "--stdin_size")) { /* obsoleted */ 00647 i++; 00648 00649 } else if (!strcmp(argv[i], "--try_to_simulate")) { 00650 simulate_burn = 1; 00651 00652 } else if (!strcmp(argv[i], "--help")) { 00653 print_help = 1; 00654 00655 } else if (!strncmp(argv[i], "--",2)) { 00656 fprintf(stderr, "Unidentified option: %s\n", argv[i]); 00657 return 7; 00658 } else { 00659 if(strlen(argv[i]) >= 4096) { 00660 fprintf(stderr, "Source address too long (max. %d)\n", 4096-1); 00661 return 5; 00662 } 00663 if(source_adr_count >= 99) { 00664 fprintf(stderr, "Too many tracks (max. 99)\n"); 00665 return 6; 00666 } 00667 strcpy(source_adr[source_adr_count], argv[i]); 00668 source_adr_count++; 00669 } 00670 } 00671 insuffient_parameters = 1; 00672 if (driveno < 0) 00673 insuffient_parameters = 0; 00674 if (source_adr_count > 0) 00675 insuffient_parameters = 0; 00676 if (do_blank) 00677 insuffient_parameters = 0; 00678 if (print_help || insuffient_parameters ) { 00679 printf("Usage: %s\n", argv[0]); 00680 printf(" [--drive <address>|<driveno>|\"-\"] [--audio]\n"); 00681 printf(" [--blank_fast|--blank_full|--format] [--try_to_simulate]\n"); 00682 printf(" [--multi] [<one or more imagefiles>|\"-\"]\n"); 00683 printf("Examples\n"); 00684 printf("A bus scan (needs rw-permissions to see a drive):\n"); 00685 printf(" %s --drive -\n",argv[0]); 00686 printf("Burn a file to drive chosen by number, leave appendable:\n"); 00687 printf(" %s --drive 0 --multi my_image_file\n", argv[0]); 00688 printf("Burn a file to drive chosen by persistent address, close:\n"); 00689 printf(" %s --drive /dev/hdc my_image_file\n", argv[0]); 00690 printf("Blank a used CD-RW (is combinable with burning in one run):\n"); 00691 printf(" %s --drive /dev/hdc --blank_fast\n",argv[0]); 00692 printf("Blank a used DVD-RW (is combinable with burning in one run):\n"); 00693 printf(" %s --drive /dev/hdc --blank_full\n",argv[0]); 00694 printf("Format a DVD-RW, BD-RE or BD-R:\n"); 00695 printf(" %s --drive /dev/hdc --format\n", argv[0]); 00696 printf("Burn two audio tracks (to CD only):\n"); 00697 printf(" lame --decode -t /path/to/track1.mp3 track1.cd\n"); 00698 printf(" test/dewav /path/to/track2.wav -o track2.cd\n"); 00699 printf(" %s --drive /dev/hdc --audio track1.cd track2.cd\n", argv[0]); 00700 printf("Burn a compressed afio archive on-the-fly:\n"); 00701 printf(" ( cd my_directory ; find . -print | afio -oZ - ) | \\\n"); 00702 printf(" %s --drive /dev/hdc -\n", argv[0]); 00703 printf("To be read from *not mounted* media via: afio -tvZ /dev/hdc\n"); 00704 if (insuffient_parameters) 00705 return 6; 00706 } 00707 return 0; 00708 }
int main | ( | int | argc, | |
char ** | argv | |||
) |
Note: driveno might change its value in this call
Definition at line 711 of file libburner.c.
References all_tracks_type, burn_drive_release(), burn_finish(), burn_initialize(), burn_msgs_set_severities(), burn_set_signal_handling(), do_blank, do_multi, drive_adr, drive_is_grabbed, driveno, libburner_aquire_drive(), libburner_blank_disc(), libburner_format(), libburner_payload(), libburner_setup(), simulate_burn, source_adr, and source_adr_count.
00712 { 00713 int ret; 00714 00715 ret = libburner_setup(argc, argv); 00716 if (ret) 00717 exit(ret); 00718 00719 printf("Initializing libburnia-project.org ...\n"); 00720 if (burn_initialize()) 00721 printf("Done\n"); 00722 else { 00723 printf("FAILED\n"); 00724 fprintf(stderr,"\nFATAL: Failed to initialize.\n"); 00725 exit(33); 00726 } 00727 00728 /* Print messages of severity SORRY or more directly to stderr */ 00729 burn_msgs_set_severities("NEVER", "SORRY", "libburner : "); 00730 00731 /* Activate the default signal handler which eventually will try to 00732 properly shutdown drive and library on aborting events. */ 00733 burn_set_signal_handling("libburner : ", NULL, 0); 00734 00735 /** Note: driveno might change its value in this call */ 00736 ret = libburner_aquire_drive(drive_adr, &driveno); 00737 if (ret<=0) { 00738 fprintf(stderr,"\nFATAL: Failed to aquire drive.\n"); 00739 { ret = 34; goto finish_libburn; } 00740 } 00741 if (ret == 2) 00742 { ret = 0; goto release_drive; } 00743 if (do_blank) { 00744 if (do_blank > 100) 00745 ret = libburner_format(drive_list[driveno].drive); 00746 else 00747 ret = libburner_blank_disc(drive_list[driveno].drive, 00748 do_blank == 1); 00749 if (ret<=0) 00750 { ret = 36; goto release_drive; } 00751 } 00752 if (source_adr_count > 0) { 00753 ret = libburner_payload(drive_list[driveno].drive, 00754 source_adr, source_adr_count, 00755 do_multi, simulate_burn, all_tracks_type); 00756 if (ret<=0) 00757 { ret = 38; goto release_drive; } 00758 } 00759 ret = 0; 00760 release_drive:; 00761 if (drive_is_grabbed) 00762 burn_drive_release(drive_list[driveno].drive, 0); 00763 00764 finish_libburn:; 00765 /* This app does not bother to know about exact scan state. 00766 Better to accept a memory leak here. We are done anyway. */ 00767 /* burn_drive_info_free(drive_list); */ 00768 00769 burn_finish(); 00770 exit(ret); 00771 }
int all_tracks_type = BURN_MODE1 [static] |
Definition at line 598 of file libburner.c.
Referenced by libburner_setup(), and main().
int current_profile = -1 [static] |
A number and a text describing the type of media in aquired drive.
Definition at line 88 of file libburner.c.
Referenced by libburner_aquire_drive(), libburner_blank_disc(), libburner_format(), and libburner_payload().
char current_profile_name[80] = {""} [static] |
Definition at line 89 of file libburner.c.
Referenced by libburner_aquire_drive(), and libburner_format().
int do_blank = 0 [static] |
Definition at line 593 of file libburner.c.
Referenced by libburner_setup(), and main().
int do_multi = 0 [static] |
Definition at line 596 of file libburner.c.
Referenced by libburner_setup(), and main().
char drive_adr[BURN_DRIVE_ADR_LEN] = {""} [static] |
The setup parameters of libburner.
Definition at line 591 of file libburner.c.
Referenced by libburner_setup(), and main().
unsigned int drive_count [static] |
If you start a long lasting operation with drive_count > 1 then you are not friendly to the users of other drives on those systems.
Beware.
Definition at line 81 of file libburner.c.
Referenced by libburner_aquire_by_driveno().
int drive_is_grabbed = 0 [static] |
This variable indicates wether the drive is grabbed and must be finally released.
Definition at line 85 of file libburner.c.
Referenced by libburner_aquire_by_adr(), libburner_aquire_by_driveno(), and main().
struct burn_drive_info* drive_list [static] |
Overview.
libburner is a minimal demo application for the library libburn as provided on http://libburnia-project.org . It can list the available devices, can blank a CD-RW or DVD-RW, can format DVD-RW and BD, can burn to CD-R, CD-RW, DVD-R, DVD+R, DVD+R/DL, DVD+RW, DVD-RW, DVD-RAM, BD-R, BD-RE. Not supported yet: DVD-R/DL.
It's main purpose, nevertheless, is to show you how to use libburn and also to serve the libburnia team as reference application. libburner.c does indeed define the standard way how above three gestures can be implemented and stay upward compatible for a good while.
Before you can do anything, you have to initialize libburn by burn_initialize() and provide some signal and abort handling, e.g. by the builtin handler, by burn_set_signal_handling() as it is done in main() at the end of this file. Then you aquire a drive in an appropriate way conforming to the API. The two main approaches are shown here in application functions: libburner_aquire_by_adr() demonstrates usage as of cdrecord traditions libburner_aquire_by_driveno() demonstrates a scan-and-choose approach With that aquired drive you can blank a CD-RW libburner_blank_disc() or you can format a DVD-RW to profile "Restricted Overwrite" (needed once) or an unused BD to default size with spare blocks libburner_format() With the aquired drive you can burn to CD, DVD, BD libburner_payload() When everything is done, main() releases the drive and shuts down libburn: burn_drive_release(); burn_finish() See this for the decisive API specs . libburn.h is The Original For simplicity i use global variables to represent the drives. Drives are systemwide global, so we do not give away much of good style. This list will hold the drives known to libburn. This might be all CD drives of the system and thus might impose severe impact on the system.
Definition at line 77 of file libburner.c.
int driveno = 0 [static] |
Definition at line 592 of file libburner.c.
Referenced by libburner_setup(), and main().
int simulate_burn = 0 [static] |
Definition at line 597 of file libburner.c.
Referenced by libburner_setup(), and main().
char source_adr[99][4096] [static] |
Definition at line 594 of file libburner.c.
Referenced by libburner_setup(), and main().
int source_adr_count = 0 [static] |
Definition at line 595 of file libburner.c.
Referenced by libburner_setup(), and main().