#include "ecdb.h" typedef struct Burn_Data Burn_Data; struct Burn_Data { BurnDisc *disc; BurnSession *session; Ecore_List *sources; Ecore_List *tracks; Ecdb_Project *proj; }; void *_progress_update(void *d); int _progress_gui_update(void *d); int ecdb_burn_finished(void *data, int type, void *event); int ecdb_burn_project_init(Ecdb_Burn_Project *proj); int ecdb_erase_project_init(Ecdb_Erase_Project *proj); Ecdb_Burn_Project * ecdb_burn_project_new(void) { Ecdb_Burn_Project *proj; proj = calloc(1, sizeof(Ecdb_Burn_Project)); if (!proj) return NULL; if (!ecdb_burn_project_init(proj)) { FREE(proj); return NULL; } return proj; } int ecdb_burn_project_init(Ecdb_Burn_Project *proj) { if (!ecdb_project_init(ECDB_PROJECT(proj))) return FALSE; /* Create some sane defaults */ proj->burn_mode = BURN_MODE1; proj->fifo_chunksize = 2048; proj->fifo_chunks = 2048; proj->underrun_proof = TRUE; proj->opc = TRUE; proj->multi = TRUE; proj->files = ecdb_source_new(); return TRUE; } Ecdb_Erase_Project * ecdb_erase_project_new(void) { Ecdb_Erase_Project *proj; proj = calloc(1, sizeof(Ecdb_Erase_Project)); if (!proj) return NULL; if (!ecdb_erase_project_init(proj)) { FREE(proj); return NULL; } return proj; } int ecdb_erase_project_init(Ecdb_Erase_Project *proj) { if (!ecdb_project_init(ECDB_PROJECT(proj))) return FALSE; /* Proper defaults */ proj->quick = TRUE; proj->format = FALSE; return TRUE; } void ecdb_burn_project_destroy(Ecdb_Burn_Project *proj) { ecdb_source_destroy(proj->files); FREE(proj->volume_id); FREE(proj->publisher_id); FREE(proj->data_preparer_id); FREE(proj->system_id); FREE(proj->application_id); FREE(proj->copywrite_id); FREE(proj->abstract_id); FREE(proj->biblio_id); ecdb_project_destroy(ECDB_PROJECT(proj)); free(proj); } void ecdb_erase_project_destroy(Ecdb_Erase_Project *proj) { ecdb_project_destroy(ECDB_PROJECT(proj)); free(proj); } /* Erase and Burn Function */ int ecdb_burn_project(Ecdb_Burn_Project *proj) { char reasons[BURN_REASONS_LEN]; int padding, i; Burn_Data *data; BurnTrack *track; BurnSource *source; BurnWriteOpts *opts; pthread_t progress_update; i = 0; data = calloc(1, sizeof(Burn_Data)); if (!data) { printf("Error: Cannot create burn data structure!\n"); return FALSE; } data->sources = ecore_list_new(); data->tracks = ecore_list_new(); data->proj = ECDB_PROJECT(proj); if (proj->burn_mode != BURN_AUDIO) padding = 300*1024; data->disc = burn_disc_create(); data->session = burn_session_create(); burn_disc_add_session(data->disc, data->session, BURN_POS_END); track = burn_track_create(); burn_track_define_data(track, 0, padding, 1, proj->burn_mode); source = ecdb_image_project(proj); if (!source) { printf("Failed to add any files to burn disc!\n"); return FALSE; } if (burn_track_set_source(track, source) != BURN_SOURCE_OK) { printf("Error: Cannot attach source object to track " "object!\n"); return FALSE; } burn_session_add_track(data->session, track, BURN_POS_END); ecore_list_append(data->sources, source); ecore_list_append(data->tracks, track); opts = burn_write_opts_new(ECDB_PROJECT(proj)->drive-> tangible[0].drive); burn_write_opts_set_perform_opc(opts, proj->opc); burn_write_opts_set_multi(opts, proj->multi); if (proj->simulate) printf("Simulating Burn!\n"); burn_write_opts_set_simulate(opts, proj->simulate); burn_drive_set_speed(ECDB_PROJECT(proj)->drive->tangible->drive, 0, proj->speed); burn_write_opts_set_underrun_proof(opts, proj->underrun_proof); printf("Searching for burn mode\n"); if (burn_write_opts_auto_write_type(opts, data->disc, reasons, 0) == BURN_WRITE_NONE) { printf("Error: Failed to find a suitable write mode for " "disc!\n"); return FALSE; } burn_disc_write(opts, data->disc); burn_write_opts_free(opts); printf("Disc now burning\n"); pthread_create(&progress_update, NULL, _progress_update, proj); pthread_detach(progress_update); ecore_timer_add(0.5, _progress_gui_update, proj); ECDB_PROJECT(proj)->ev_handler = ecore_event_handler_add (ECDB_DRIVE_ACTION_FINISHED, ecdb_burn_finished, data); return TRUE; } int ecdb_erase_disc(Ecdb_Erase_Project *proj) { BurnDriveStatus disc_state; pthread_t progress_update; disc_state = burn_disc_get_status(ECDB_PROJECT(proj)->drive-> tangible[0].drive); if (disc_state == BURN_DISC_BLANK) { printf("Disc is already blank!\n"); return FALSE; } else if (disc_state == BURN_DISC_EMPTY) { printf("No disc!\n"); return FALSE; } else if (!burn_disc_erasable(ECDB_PROJECT(proj)->drive-> tangible[0].drive)) { printf("Not able to erase!\n"); return FALSE; } else if (disc_state == BURN_DISC_FULL || BURN_DISC_APPENDABLE) { printf("Beginning to erase disc!\n"); burn_disc_erase(ECDB_PROJECT(proj)->drive-> tangible[0].drive, proj->quick); pthread_create(&progress_update, NULL, _progress_update, proj); pthread_detach(progress_update); ecore_timer_add(0.5, _progress_gui_update, proj); return TRUE; } else { printf("Not of erasable type\n"); return FALSE; } } /* Hopefully at some point EFL will become thread-safe, or ecore_timer will * work with burn_drive_get_status without segfaulting. At that point we can * do away with this. */ /* Event handlers */ void * _progress_update(void *d) { Ecdb_Project *proj; BurnProgress p; struct burn_drive *drive; proj = d; if (!proj->drive->tangible) { printf("No tangible drive!\n"); pthread_exit(NULL); } drive = proj->drive->tangible[0].drive; printf("Progress update active\n"); while (TRUE) { proj->stat = burn_drive_get_status(drive, &p); if (proj->stat == BURN_DRIVE_SPAWNING) { sleep(3); continue; } else if (proj->stat == BURN_DRIVE_IDLE) { pthread_exit(NULL); break; } proj->progress = p; sleep(5); } } int _progress_gui_update(void *data) { Ecdb_Project *proj; proj = data; if (proj->stat == BURN_DRIVE_IDLE) { /* These don't enjoy being called before * ecore_main_loop_begin */ //ecore_event_add(ECDB_DRIVE_ACTION_FINISHED, data, NULL, NULL); ecore_event_add(ECDB_DRIVE_ACTION_FINISHED, NULL, NULL, NULL); printf("Burn finished\n"); return ECORE_CALLBACK_CANCEL; } else ecore_event_add(ECDB_DRIVE_ACTION_UPDATE, NULL, NULL, NULL); //ecore_event_add(ECDB_DRIVE_ACTION_UPDATE, data, NULL, NULL); return ECORE_CALLBACK_RENEW; } int ecdb_burn_finished(void *data, int type, void *event) { Burn_Data *proj; BurnTrack *track; BurnSource *source; proj = data; ecore_list_first_goto(proj->sources); ecore_list_first_goto(proj->tracks); printf("Freeing source and tracks\n"); while ((source = ecore_list_remove(proj->sources))) { burn_source_free(source); track = ecore_list_remove(proj->tracks); burn_track_free(track); } ecore_list_destroy(proj->sources); ecore_list_destroy(proj->tracks); printf("Freeing session and disc\n"); burn_session_free(proj->session); burn_disc_free(proj->disc); printf("Releasing drive\n"); burn_drive_release(proj->proj->drive->tangible[0].drive, 1); burn_drive_info_free(proj->proj->drive->tangible); printf("Burn Complete\n"); ecore_event_handler_del(ECDB_PROJECT(proj)->ev_handler); /* To be removed from here at some point */ Ecdb_Burn_Project *t; t = ECDB_BURN(proj->proj); FREE(t->files); FREE(t); FREE(proj); ecore_event_add(ECORE_EVENT_SIGNAL_EXIT, NULL, NULL, NULL); return TRUE; }