static gboolean prepare_params (ThreadBurnIsoParams *params, struct burn_drive *drive, gchar **failure_msg) { struct burn_write_opts * burn_options; burn_options = burn_write_opts_new (drive); burn_write_opts_set_perform_opc (burn_options, 0); burn_write_opts_set_multi (burn_options, 0); burn_write_opts_set_simulate(burn_options, params->dummy ? 1 : 0); burn_write_opts_set_underrun_proof (burn_options, params->burnfree ? 1 : 0); /* * 32 is the number of blocks to skip. This will increase reliability with BD disks that * are used for multisessions. xfburn doesn't support this, but other programs may be using * the disc that way, so we respect that here. */ burn_write_opts_set_stream_recording (burn_options, params->stream_recording ? 32 : 0); if (!xfburn_set_write_mode (burn_options, params->write_mode, params->disc, WRITE_MODE_TAO)) { burn_write_opts_free (burn_options); *failure_msg = _("Burn mode is not currently implemented."); return FALSE; } params->burn_options = burn_options; params->disc = burn_disc_create (); params->session = burn_session_create (); params->track = burn_track_create (); if (!create_disc (params, failure_msg)) { return FALSE; } return TRUE; }
int telltoc_msinfo(struct burn_drive *drive, int msinfo_explicit, int msinfo_alone) { int ret, lba, nwa = -123456789, aux_lba; enum burn_disc_status s; struct burn_write_opts *o= NULL; s = burn_disc_get_status(drive); if (s!=BURN_DISC_APPENDABLE) { if (!msinfo_explicit) return 2; fprintf(stderr, "SORRY: --msinfo can only operate on appendable media.\n"); return 0; } /* man mkisofs , option -C : The first number is the sector number of the first sector in the last session of the disk that should be appended to. */ ret = burn_disc_get_msc1(drive, &lba); if (ret <= 0) { fprintf(stderr, "SORRY: Cannot obtain start address of last session\n"); { ret = 0; goto ex; } } /* man mkisofs , option -C : The second number is the starting sector number of the new session. */ /* Set some roughly suitable write opts to be sent to drive. */ o= burn_write_opts_new(drive); if(o!=NULL) { burn_write_opts_set_perform_opc(o, 0); burn_write_opts_set_write_type(o, BURN_WRITE_TAO, BURN_BLOCK_MODE1); } /* Now try to inquire nwa from drive */ ret= burn_disc_track_lba_nwa(drive,o,0,&aux_lba,&nwa); telltoc_regrab(drive); /* necessary to calm down my NEC drive */ if(ret<=0) { fprintf(stderr, "SORRY: Cannot obtain next writeable address\n"); { ret = 0; goto ex; } } if (!msinfo_alone) printf("Media msinfo : mkisofs ... -C "); printf("%d,%d\n",lba,nwa); ret = 1; ex:; if (o != NULL) burn_write_opts_free(o); return ret; }
static void free_params (ThreadBurnIsoParams *params) { if (params->fifo_src) burn_source_free (params->fifo_src); if (params->burn_options) burn_write_opts_free (params->burn_options); if (params->track) burn_track_free (params->track); if (params->session) burn_session_free (params->session); if (params->disc) burn_disc_free (params->disc); g_free (params->iso_path); }
int telltoc_media(struct burn_drive *drive) { int ret, media_found = 0, profile_no = -1, num_profiles = 0, i; int profiles[64]; char is_current_profile[64]; double max_speed = 0.0, min_speed = 0.0, speed_conv; off_t available = 0; enum burn_disc_status s; char profile_name[80], speed_unit[40]; struct burn_multi_caps *caps = NULL; struct burn_write_opts *o = NULL; printf("Media current: "); ret = burn_disc_get_profile(drive, &profile_no, profile_name); if (profile_no > 0 && ret > 0) { if (profile_name[0]) printf("%s\n", profile_name); else printf("%4.4Xh\n", profile_no); } else printf("is not recognizable\n"); /* Determine speed unit before profile_name gets reused */ speed_conv = 176.4; strcpy(speed_unit,"176.4 kB/s (CD, data speed 150 KiB/s)"); if (strstr(profile_name, "DVD") == profile_name) { speed_conv = 1385.0; strcpy(speed_unit,"1385.0 kB/s (DVD)"); } else if (strstr(profile_name, "BD") == profile_name) { speed_conv = 4495.625; strcpy(speed_unit,"4495.625 kB/s (BD)"); } ret = burn_drive_get_all_profiles(drive, &num_profiles, profiles, is_current_profile); if (ret > 0) { for (i = 0; i < num_profiles; i++) { ret = burn_obtain_profile_name(profiles[i], profile_name); if (ret <= 0) sprintf(profile_name, "Unknown media type 0x%4.4X", (unsigned int) profiles[i]); printf("Drive can do : %s%s\n", profile_name, is_current_profile[i] ? " (current)" : ""); } } printf("Media status : "); s = burn_disc_get_status(drive); if (s == BURN_DISC_FULL) { printf("is written , is closed\n"); media_found = 1; } else if (s == BURN_DISC_APPENDABLE) { printf("is written , is appendable\n"); media_found = 1; } else if (s == BURN_DISC_BLANK) { printf("is blank\n"); media_found = 1; } else if (s == BURN_DISC_EMPTY) printf("is not present\n"); else printf("is not recognizable\n"); printf("Media reuse : "); if (media_found) { if (burn_disc_erasable(drive)) printf("is erasable\n"); else printf("is not erasable\n"); } else printf("is not recognizable\n"); ret = burn_disc_get_multi_caps(drive, BURN_WRITE_NONE, &caps, 0); if (ret > 0) { /* Media appears writeable */ printf("Write multi : "); printf("%s multi-session , ", caps->multi_session == 1 ? "offers" : "cannot do"); if (caps->multi_track) printf("offers multiple tracks\n"); else printf("offers only single track\n"); printf("Write start : "); if (caps->start_adr == 1) printf( "offers addresses [%.f , %.f]s , alignment=%.fs\n", (double) caps->start_range_low / 2048 , (double) caps->start_range_high / 2048 , (double) caps->start_alignment / 2048 ); else printf("prohibits write start addressing\n"); printf("Write modes : "); if (caps->might_do_tao) printf("TAO%s", caps->advised_write_mode == BURN_WRITE_TAO ? " (advised)" : ""); if (caps->might_do_sao) printf("%sSAO%s", caps->might_do_tao ? " , " : "", caps->advised_write_mode == BURN_WRITE_SAO ? " (advised)" : ""); if (caps->might_do_raw) printf("%sRAW%s", caps->might_do_tao | caps->might_do_sao ? " , " : "", caps->advised_write_mode == BURN_WRITE_RAW ? " (advised)" : ""); printf("\n"); printf("Write dummy : "); if (caps->might_simulate) printf("supposed to work with non-RAW modes\n"); else printf("will not work\n"); o= burn_write_opts_new(drive); if (o != NULL) { burn_write_opts_set_perform_opc(o, 0); if(caps->advised_write_mode == BURN_WRITE_TAO) burn_write_opts_set_write_type(o, BURN_WRITE_TAO, BURN_BLOCK_MODE1); else if (caps->advised_write_mode == BURN_WRITE_SAO) burn_write_opts_set_write_type(o, BURN_WRITE_SAO, BURN_BLOCK_SAO); else { burn_write_opts_free(o); o = NULL; } } available = burn_disc_available_space(drive, o); printf("Write space : %.1f MiB (%.fs)\n", ((double) available) / 1024.0 / 1024.0, ((double) available) / 2048.0); burn_disc_free_multi_caps(&caps); if (o != NULL) burn_write_opts_free(o); } ret = burn_drive_get_write_speed(drive); max_speed = ((double ) ret) / speed_conv; ret = burn_drive_get_min_write_speed(drive); min_speed = ((double ) ret) / speed_conv; if (!media_found) printf("Drive speed : max=%.1f , min=%.1f\n", max_speed, min_speed); else printf("Avail. speed : max=%.1f , min=%.1f\n", max_speed, min_speed); ret = 0; if (media_found) ret = burn_disc_read_atip(drive); if(ret>0) { ret = burn_drive_get_min_write_speed(drive); min_speed = ((double ) ret) / speed_conv; ret = burn_drive_get_write_speed(drive); max_speed = ((double ) ret) / speed_conv; printf("Media speed : max=%.1f , min=%.1f\n", max_speed, min_speed); } printf("Speed unit 1x: %s\n", speed_unit); if (caps != NULL) burn_disc_free_multi_caps(&caps); return 1; }
/** 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. */ int libburner_payload(struct burn_drive *drive, char source_adr[][4096], int source_adr_count, int multi, int simulate_burn, int all_tracks_type) { struct burn_source *data_src = NULL, *fifo_src[99]; struct burn_disc *target_disc = NULL; struct burn_session *session = NULL; struct burn_write_opts *burn_options = NULL; enum burn_disc_status disc_state; struct burn_track *track, *tracklist[99]; struct burn_progress progress; time_t start_time; int last_sector = 0, padding = 0, trackno, unpredicted_size = 0, fd; int fifo_chunksize = 2352, fifo_chunks = 1783; /* ~ 4 MB fifo */ int ret; off_t fixed_size; char *adr, reasons[BURN_REASONS_LEN]; struct stat stbuf; for (trackno = 0 ; trackno < source_adr_count; trackno++) { fifo_src[trackno] = NULL; tracklist[trackno] = NULL; } if (all_tracks_type != BURN_AUDIO) { all_tracks_type = BURN_MODE1; /* a padding of 300 kiB helps to avoid the read-ahead bug */ padding = 300*1024; fifo_chunksize = 2048; fifo_chunks = 2048; /* 4 MB fifo */ } target_disc = burn_disc_create(); session = burn_session_create(); burn_disc_add_session(target_disc, session, BURN_POS_END); for (trackno = 0 ; trackno < source_adr_count; trackno++) { tracklist[trackno] = track = burn_track_create(); burn_track_define_data(track, 0, padding, 1, all_tracks_type); /* Open file descriptor to source of track data */ adr = source_adr[trackno]; fixed_size = 0; if (adr[0] == '-' && adr[1] == 0) { fd = 0; } else { fd = open(adr, O_RDONLY); if (fd>=0) if (fstat(fd,&stbuf)!=-1) if((stbuf.st_mode&S_IFMT)==S_IFREG) fixed_size = stbuf.st_size; } if (fixed_size==0) unpredicted_size = 1; /* Convert this filedescriptor into a burn_source object */ data_src = NULL; if (fd >= 0) data_src = burn_fd_source_new(fd, -1, fixed_size); if (data_src == NULL) { fprintf(stderr, "FATAL: Could not open data source '%s'.\n",adr); if(errno!=0) fprintf(stderr,"(Most recent system error: %s )\n", strerror(errno)); {ret = 0; goto ex;} } /* Install a fifo object on top of that data source object */ fifo_src[trackno] = burn_fifo_source_new(data_src, fifo_chunksize, fifo_chunks, 0); if (fifo_src[trackno] == NULL) { fprintf(stderr, "FATAL: Could not create fifo object of 4 MB\n"); {ret = 0; goto ex;} } /* Use the fifo object as data source for the track */ if (burn_track_set_source(track, fifo_src[trackno]) != BURN_SOURCE_OK) { fprintf(stderr, "FATAL: Cannot attach source object to track object\n"); {ret = 0; goto ex;} } burn_session_add_track(session, track, BURN_POS_END); printf("Track %d : source is '%s'\n", trackno+1, adr); /* Give up local reference to the data burn_source object */ burn_source_free(data_src); data_src = NULL; } /* trackno loop end */ /* Evaluate drive and media */ disc_state = burn_disc_get_status(drive); if (disc_state != BURN_DISC_BLANK && disc_state != BURN_DISC_APPENDABLE) { if (disc_state == BURN_DISC_FULL) { fprintf(stderr, "FATAL: Closed media with data detected. Need blank or appendable media.\n"); if (burn_disc_erasable(drive)) fprintf(stderr, "HINT: Try --blank_fast\n\n"); } else if (disc_state == BURN_DISC_EMPTY) fprintf(stderr,"FATAL: No media detected in drive\n"); else fprintf(stderr, "FATAL: Cannot recognize state of drive and media\n"); {ret = 0; goto ex;} } burn_options = burn_write_opts_new(drive); burn_write_opts_set_perform_opc(burn_options, 0); burn_write_opts_set_multi(burn_options, !!multi); if(simulate_burn) printf("\n*** Will TRY to SIMULATE burning ***\n\n"); burn_write_opts_set_simulate(burn_options, simulate_burn); burn_drive_set_speed(drive, 0, 0); burn_write_opts_set_underrun_proof(burn_options, 1); if (burn_write_opts_auto_write_type(burn_options, target_disc, reasons, 0) == BURN_WRITE_NONE) { fprintf(stderr, "FATAL: Failed to find a suitable write mode with this media.\n"); fprintf(stderr, "Reasons given:\n%s\n", reasons); {ret = 0; goto ex;} } burn_set_signal_handling("libburner : ", NULL, 0x30); printf("Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n"); start_time = time(0); burn_disc_write(burn_options, target_disc); while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING) usleep(100002); while (burn_drive_get_status(drive, &progress) != BURN_DRIVE_IDLE) { if (progress.sectors <= 0 || (progress.sector >= progress.sectors - 1 && !unpredicted_size) || (unpredicted_size && progress.sector == last_sector)) printf( "Thank you for being patient since %d seconds.", (int) (time(0) - start_time)); else if(unpredicted_size) printf("Track %d : sector %d", progress.track+1, progress.sector); else printf("Track %d : sector %d of %d",progress.track+1, progress.sector, progress.sectors); last_sector = progress.sector; if (progress.track >= 0 && progress.track < source_adr_count) { int size, free_bytes, ret; char *status_text; ret = burn_fifo_inquire_status( fifo_src[progress.track], &size, &free_bytes, &status_text); if (ret >= 0 ) printf(" [fifo %s, %2d%% fill]", status_text, (int) (100.0 - 100.0 * ((double) free_bytes) / (double) size)); } printf("\n"); sleep(1); } printf("\n"); if (burn_is_aborting(0) > 0) {ret = -1; goto ex;} if (multi && current_profile != 0x1a && current_profile != 0x13 && current_profile != 0x12 && current_profile != 0x43) /* not with DVD+RW, formatted DVD-RW, DVD-RAM, BD-RE */ printf("NOTE: Media left appendable.\n"); if (simulate_burn) printf("\n*** Did TRY to SIMULATE burning ***\n\n"); ret = 1; ex:; /* Dispose objects */ if (burn_options != NULL) burn_write_opts_free(burn_options); for (trackno = 0 ; trackno < source_adr_count; trackno++) { if (fifo_src[trackno] != NULL) burn_source_free(fifo_src[trackno]); if (tracklist[trackno]) burn_track_free(tracklist[trackno]); } if (data_src != NULL) burn_source_free(data_src); if (session != NULL) burn_session_free(session); if (target_disc != NULL) burn_disc_free(target_disc); return ret; }