void main_loop(void) { msgType dialog_type; char *message = (char *) malloc(512); sacd_reader_t *sacd_reader; scarletbook_handle_t *sb_handle = 0; int idx = 0; if (output_device_changed && output_device) { char file_path[100]; sprintf(file_path, "%s/sacd_log.txt", output_device); set_log_file(file_path); LOG(lm_main, LOG_NOTICE, ("SACD-Ripper Version " SACD_RIPPER_VERSION_STRING)); } // did the disc change? if (bd_contains_sacd_disc && bd_disc_changed) { // open the BD device sacd_reader = sacd_open("/dev_bdvd"); if (sacd_reader) { // read the scarletbook information sb_handle = scarletbook_open(sacd_reader, 0); if (sb_handle) { master_text_t *master_text = &sb_handle->master_text; master_toc_t *mtoc = sb_handle->master_toc; if (master_text->disc_title || master_text->disc_title_phonetic) { idx += snprintf(message_info + idx, 60, "Title: %s\n", substr((master_text->disc_title ? master_text->disc_title : master_text->disc_title_phonetic), 0, 50)); LOG(lm_main, LOG_NOTICE, ("Album Title: %s", substr((master_text->disc_title ? master_text->disc_title : master_text->disc_title_phonetic), 0, 50))); } if (message_info[idx - 1] != '\n') { message_info[idx++] = '\n'; message_info[idx] = '\0'; } if (master_text->disc_artist || master_text->disc_artist_phonetic) { idx += snprintf(message_info + idx, 60, "Artist: %s\n", substr((master_text->disc_artist ? master_text->disc_artist : master_text->disc_artist_phonetic), 0, 50)); LOG(lm_main, LOG_NOTICE, ("Album Artist: %s", substr((master_text->disc_artist ? master_text->disc_artist : master_text->disc_artist_phonetic), 0, 50))); } if (message_info[idx - 1] != '\n') { message_info[idx++] = '\n'; message_info[idx] = '\0'; } idx += snprintf(message_info + idx, 20, "Version: %02i.%02i\n", mtoc->version.major, mtoc->version.minor); LOG(lm_main, LOG_NOTICE, ("Disc Version: %02i.%02i\n", mtoc->version.major, mtoc->version.minor)); idx += snprintf(message_info + idx, 25, "Created: %4i-%02i-%02i\n", mtoc->disc_date_year, mtoc->disc_date_month, mtoc->disc_date_day); idx += snprintf(message_info + idx, 15, "Area 0:\n"); idx += snprintf(message_info + idx, 35, " Speakers: %s\n", get_speaker_config_string(sb_handle->area[0].area_toc)); idx += snprintf(message_info + idx, 35, " Encoding: %s\n", get_frame_format_string(sb_handle->area[0].area_toc)); idx += snprintf(message_info + idx, 25, " Tracks: %d (%.2fGB)\n", sb_handle->area[0].area_toc->track_count, ((double) (sb_handle->area[0].area_toc->track_end - sb_handle->area[0].area_toc->track_start) * SACD_LSN_SIZE) / 1073741824.00); if (has_both_channels(sb_handle)) { idx += snprintf(message_info + idx, 2, "\n"); idx += snprintf(message_info + idx, 15, "Area 1:\n"); idx += snprintf(message_info + idx, 35, " Speakers: %s\n", get_speaker_config_string(sb_handle->area[1].area_toc)); idx += snprintf(message_info + idx, 35, " Encoding: %s\n", get_frame_format_string(sb_handle->area[1].area_toc)); idx += snprintf(message_info + idx, 25, " Tracks: %d (%.2fGB)\n", sb_handle->area[1].area_toc->track_count, ((double) (sb_handle->area[1].area_toc->track_end - sb_handle->area[1].area_toc->track_start) * SACD_LSN_SIZE) / 1073741824.00); } idx += snprintf(message_info + idx, 50, "\nclick X to start ripping, O to change output"); current_ripping_flags = 0; if (has_two_channel(sb_handle)) { current_ripping_flags |= RIP_2CH; if (sb_handle->area[sb_handle->twoch_area_idx].area_toc->frame_format == FRAME_FORMAT_DST) { current_ripping_flags |= RIP_2CH_DST; } } if (has_multi_channel(sb_handle)) { current_ripping_flags |= RIP_MCH; } // validate output format as the ripping flags have changed output_format_changed = 1; validate_output_format(); scarletbook_close(sb_handle); sb_handle = 0; } else { bd_contains_sacd_disc = 0; } // close the input device asap sacd_close(sacd_reader); sacd_reader = 0; } else { bd_contains_sacd_disc = 0; } } if (output_device_changed || output_format_changed) { // output device if (output_device) idx = snprintf(message_output, 35, "Output: %s %.2fGB\n", output_device, output_device_space); else idx = snprintf(message_output, 35, "Output: NO DEVICE\n"); // output format idx += snprintf(message_output + idx, 20, "Format: "); switch (output_format) { case 0: idx += snprintf(message_output + idx, 20, "2ch DSDIFF (DSD)\n"); break; case 1: idx += snprintf(message_output + idx, 20, "2ch DSDIFF (DST)\n"); break; case 2: idx += snprintf(message_output + idx, 20, "2ch DSF (DSD)\n"); break; case 3: idx += snprintf(message_output + idx, 20, "mch DSDIFF (DSD)\n"); break; case 4: idx += snprintf(message_output + idx, 20, "mch DSDIFF (DST)\n"); break; case 5: idx += snprintf(message_output + idx, 20, "mch DSF (DSF)\n"); break; case 6: idx += snprintf(message_output + idx, 20, "ISO\n"); break; } idx += snprintf(message_output + idx, 2, "\n"); } // by default we have no user controls dialog_type = (MSG_DIALOG_NORMAL | MSG_DIALOG_DISABLE_CANCEL_ON); if (bd_contains_sacd_disc) { snprintf(message, 512, "%s%s", message_output, message_info); } else { snprintf(message, 512, "The current disc is empty or not recognized as an SACD, please re-insert.\n\n%s" , (output_device ? "" : "(Also make sure you connect an external fat32 formatted harddisk!)")); } // can we start ripping? if (bd_contains_sacd_disc) { dialog_type = (MSG_DIALOG_NORMAL | MSG_DIALOG_BTN_TYPE_OK); } msgDialogOpen2(dialog_type, message, dialog_handler, NULL, NULL); dialog_action = 0; bd_disc_changed = 0; output_device_changed = 0; output_format_changed = 0; while (!dialog_action && !user_requested_exit() && bd_disc_changed == 0 && output_device_changed == 0) { // poll for new output devices poll_output_devices(); sysUtilCheckCallback(); flip(); } msgDialogAbort(); // did user request to start the ripping process? if (dialog_action == 1 && bd_contains_sacd_disc) { start_ripping_gui(output_format_options[output_format]); reset_output_devices(); // action is handled dialog_action = 0; } else if (dialog_action == 2) { #if 0 output_format++; // max of 7 output options if (output_format > 6) { output_format = 0; } #endif // is the current selection valid? validate_output_format(); // action is handled output_format_changed = 1; dialog_action = 0; } free(message); }
int main(int argc, char* argv[]) { char *albumdir = 0, *musicfilename, *file_path = 0; int i, area_idx; sacd_reader_t *sacd_reader; #ifdef PTW32_STATIC_LIB pthread_win32_process_attach_np(); pthread_win32_thread_attach_np(); #endif init(); if (parse_options(argc, argv)) { setlocale(LC_ALL, ""); if (fwide(stdout, 1) < 0) { fprintf(stderr, "ERROR: Output not set to wide.\n"); } // default to 2 channel if (opts.two_channel == 0 && opts.multi_channel == 0) { opts.two_channel = 1; } sacd_reader = sacd_open(opts.input_device); if (sacd_reader) { handle = scarletbook_open(sacd_reader, 0); if (handle) { if (opts.print) { scarletbook_print(handle); } if (opts.output_dsf || opts.output_iso || opts.output_dsdiff || opts.output_dsdiff_em || opts.export_cue_sheet) { output = scarletbook_output_create(handle, handle_status_update_track_callback, handle_status_update_progress_callback, safe_fwprintf); // select the channel area area_idx = ((has_multi_channel(handle) && opts.multi_channel) || !has_two_channel(handle)) ? handle->mulch_area_idx : handle->twoch_area_idx; albumdir = (strlen(opts.output_file) > 0 ? strdup(opts.output_file) : get_album_dir(handle)); if (opts.output_iso) { uint32_t total_sectors = sacd_get_total_sectors(sacd_reader); #ifdef SECTOR_LIMIT #define FAT32_SECTOR_LIMIT 2090000 uint32_t sector_size = FAT32_SECTOR_LIMIT; uint32_t sector_offset = 0; if (total_sectors > FAT32_SECTOR_LIMIT) { musicfilename = (char *) malloc(512); file_path = make_filename(0, 0, albumdir, "iso"); for (i = 1; total_sectors != 0; i++) { sector_size = min(total_sectors, FAT32_SECTOR_LIMIT); snprintf(musicfilename, 512, "%s.%03d", file_path, i); scarletbook_output_enqueue_raw_sectors(output, sector_offset, sector_size, musicfilename, "iso"); sector_offset += sector_size; total_sectors -= sector_size; } free(musicfilename); } else #endif { get_unique_filename(&albumdir, "iso"); file_path = make_filename(0, 0, albumdir, "iso"); scarletbook_output_enqueue_raw_sectors(output, 0, total_sectors, file_path, "iso"); } } else if (opts.output_dsdiff_em) { get_unique_filename(&albumdir, "dff"); file_path = make_filename(0, 0, albumdir, "dff"); scarletbook_output_enqueue_track(output, area_idx, 0, file_path, "dsdiff_edit_master", (opts.convert_dst ? 1 : handle->area[area_idx].area_toc->frame_format != FRAME_FORMAT_DST)); } else if (opts.output_dsf || opts.output_dsdiff) { // create the output folder get_unique_dir(0, &albumdir); recursive_mkdir(albumdir, 0774); // fill the queue with items to rip for (i = 0; i < handle->area[area_idx].area_toc->track_count; i++) { if (opts.select_tracks && opts.selected_tracks[i] == 0) continue; musicfilename = get_music_filename(handle, area_idx, i, opts.output_file); if (opts.output_dsf) { file_path = make_filename(0, albumdir, musicfilename, "dsf"); scarletbook_output_enqueue_track(output, area_idx, i, file_path, "dsf", 1 /* always decode to DSD */); } else if (opts.output_dsdiff) { file_path = make_filename(0, albumdir, musicfilename, "dff"); scarletbook_output_enqueue_track(output, area_idx, i, file_path, "dsdiff", (opts.convert_dst ? 1 : handle->area[area_idx].area_toc->frame_format != FRAME_FORMAT_DST)); } free(musicfilename); free(file_path); file_path = 0; } } if (opts.export_cue_sheet) { char *cue_file_path = make_filename(0, 0, albumdir, "cue"); #ifdef _WIN32 wchar_t *wide_filename = (wchar_t *) charset_convert(cue_file_path, strlen(cue_file_path), "UTF-8", sizeof(wchar_t) == 2 ? "UCS-2-INTERNAL" : "UCS-4-INTERNAL"); #else wchar_t *wide_filename = (wchar_t *) charset_convert(cue_file_path, strlen(cue_file_path), "UTF-8", "WCHAR_T"); #endif fwprintf(stdout, L"Exporting CUE sheet [%ls]\n", wide_filename); if (!file_path) file_path = make_filename(0, 0, albumdir, "dff"); write_cue_sheet(handle, file_path, area_idx, cue_file_path); free(cue_file_path); free(wide_filename); } free(file_path); started_processing = time(0); scarletbook_output_start(output); scarletbook_output_destroy(output); fprintf(stdout, "\rWe are done.. \n"); } scarletbook_close(handle); free(albumdir); } } sacd_close(sacd_reader); #ifndef _WIN32 freopen(0, "w", stdout); #endif if (fwide(stdout, -1) >= 0) { fprintf(stderr, "ERROR: Output not set to byte oriented.\n"); } } free_lock(g_fwprintf_lock); destroy_logging(); #ifdef PTW32_STATIC_LIB pthread_win32_process_detach_np(); pthread_win32_thread_detach_np(); #endif printf("\n"); return 0; }
int start_ripping_gui(int ripping_flags) { char *albumdir, *musicfilename, *file_path = 0; sacd_reader_t *sacd_reader; scarletbook_handle_t *handle; scarletbook_output_t *output; msgType dialog_type; int area_idx, i, ret; uint32_t prev_upper_progress = 0; uint32_t prev_lower_progress = 0; uint32_t delta; int prev_current_track = 0; uint32_t prev_stats_total_sectors_processed = 0; uint32_t prev_stats_current_file_sectors_processed = 0; uint64_t tb_start, tb_freq; uint64_t tmp_total_ripping_sectors = 0; char progress_message[64]; sysAtomicSet(&stats_total_sectors, 0); sysAtomicSet(&stats_total_sectors_processed, 0); sysAtomicSet(&stats_current_file_total_sectors, 0); sysAtomicSet(&stats_current_file_sectors_processed, 0); sysAtomicSet(&stats_current_track, 0); sysAtomicSet(&stats_total_tracks, 0); sacd_reader = sacd_open("/dev_bdvd"); if (sacd_reader) { handle = scarletbook_open(sacd_reader, 0); if (check_disc_space(sacd_reader, handle, ripping_flags)) { ret = sacd_authenticate(sacd_reader); if (ret != 0) { LOG(lm_main, LOG_ERROR, ("authentication failed: %x", ret)); } // select the channel area area_idx = ((has_multi_channel(handle) && ripping_flags & RIP_MCH) || !has_two_channel(handle)) ? handle->mulch_area_idx : handle->twoch_area_idx; albumdir = get_album_dir(handle); output = scarletbook_output_create(handle, handle_status_update_track_callback, handle_status_update_progress_callback, safe_fwprintf); if (ripping_flags & RIP_ISO) { #define FAT32_SECTOR_LIMIT 2090000 uint32_t total_sectors = sacd_get_total_sectors(sacd_reader); uint32_t sector_size = FAT32_SECTOR_LIMIT; uint32_t sector_offset = 0; if (total_sectors > FAT32_SECTOR_LIMIT) { musicfilename = (char *) malloc(512); file_path = make_filename(output_device, 0, albumdir, "iso"); for (i = 1; total_sectors != 0; i++) { sector_size = min(total_sectors, FAT32_SECTOR_LIMIT); snprintf(musicfilename, 512, "%s.%03d", file_path, i); scarletbook_output_enqueue_raw_sectors(output, sector_offset, sector_size, musicfilename, "iso"); sector_offset += sector_size; total_sectors -= sector_size; } free(file_path); free(musicfilename); } else { file_path = make_filename(output_device, 0, albumdir, "iso"); scarletbook_output_enqueue_raw_sectors(output, 0, total_sectors, file_path, "iso"); free(file_path); } tmp_total_ripping_sectors = sacd_get_total_sectors(sacd_reader); } else { // do not overwrite previous dump get_unique_dir(output_device, &albumdir); // fill the queue with items to rip for (i = 0; i < handle->area[area_idx].area_toc->track_count; i++) { musicfilename = get_music_filename(handle, area_idx, i, 0); if (ripping_flags & RIP_DSF) { file_path = make_filename(output_device, albumdir, musicfilename, "dsf"); scarletbook_output_enqueue_track(output, area_idx, i, file_path, "dsf", 1 /* always decode to DSD */); } else if (ripping_flags & RIP_DSDIFF) { file_path = make_filename(output_device, albumdir, musicfilename, "dff"); scarletbook_output_enqueue_track(output, area_idx, i, file_path, "dsdiff", ((ripping_flags & RIP_2CH_DST || ripping_flags & RIP_MCH_DST) ? 0 : 1)); } tmp_total_ripping_sectors += handle->area[area_idx].area_tracklist_offset->track_length_lsn[i]; free(musicfilename); free(file_path); } file_path = make_filename(output_device, albumdir, 0, 0); LOG(lm_main, LOG_NOTICE, ("setting output folder to: %s", file_path)); recursive_mkdir(file_path, 0777); free(file_path); } scarletbook_output_start(output); tb_freq = sysGetTimebaseFrequency(); tb_start = __gettime(); { char *message = (char *) malloc(512); file_path = make_filename(output_device, albumdir, 0, 0); snprintf(message, 512, "Title: %s\nOutput: %s\nFormat: %s\nSize: %.2fGB\nArea: %s\nEncoding: %s", substr(albumdir, 0, 100), file_path, (ripping_flags & RIP_DSDIFF ? "DSDIFF" : (ripping_flags & RIP_DSF ? "DSF" : "ISO")), ((double) ((tmp_total_ripping_sectors * SACD_LSN_SIZE) / 1073741824.00)), (ripping_flags & RIP_2CH ? "2ch" : "mch"), (ripping_flags & RIP_2CH_DST || ripping_flags & RIP_MCH_DST ? "DST" : (ripping_flags & RIP_ISO ? "DECRYPTED" : "DSD")) ); free(file_path); dialog_action = 0; dialog_type = MSG_DIALOG_MUTE_ON | MSG_DIALOG_DOUBLE_PROGRESSBAR; msgDialogOpen2(dialog_type, message, dialog_handler, NULL, NULL); while (!user_requested_exit() && dialog_action == 0 && scarletbook_output_is_busy(output)) { uint32_t tmp_stats_total_sectors_processed = sysAtomicRead(&stats_total_sectors_processed); uint32_t tmp_stats_total_sectors = sysAtomicRead(&stats_total_sectors); uint32_t tmp_stats_current_file_sectors_processed = sysAtomicRead(&stats_current_file_sectors_processed); uint32_t tmp_stats_current_file_total_sectors = sysAtomicRead(&stats_current_file_total_sectors); int tmp_current_track = sysAtomicRead(&stats_current_track); if (tmp_current_track != 0 && tmp_current_track != prev_current_track) { memset(progress_message, 0, 64); musicfilename = get_music_filename(handle, area_idx, tmp_current_track - 1, 0); // HACK: substr is not thread safe, but it's only used in this thread.. snprintf(progress_message, 63, "Track (%d/%d): [%s...]", tmp_current_track, sysAtomicRead(&stats_total_tracks), substr(musicfilename, 0, 40)); free(musicfilename); msgDialogProgressBarReset(MSG_PROGRESSBAR_INDEX0); msgDialogProgressBarSetMsg(MSG_PROGRESSBAR_INDEX1, progress_message); prev_upper_progress = 0; prev_stats_current_file_sectors_processed = 0; prev_current_track = tmp_current_track; } if (tmp_stats_total_sectors != 0 && prev_stats_total_sectors_processed != tmp_stats_total_sectors_processed) { delta = (tmp_stats_current_file_sectors_processed + (tmp_stats_current_file_sectors_processed - prev_stats_current_file_sectors_processed)) * 100 / tmp_stats_current_file_total_sectors - prev_upper_progress; prev_upper_progress += delta; msgDialogProgressBarInc(MSG_PROGRESSBAR_INDEX0, delta); delta = (tmp_stats_total_sectors_processed + (tmp_stats_total_sectors_processed - prev_stats_total_sectors_processed)) * 100 / tmp_stats_total_sectors - prev_lower_progress; prev_lower_progress += delta; msgDialogProgressBarInc(MSG_PROGRESSBAR_INDEX1, delta); snprintf(progress_message, 64, "Ripping %.1fMB/%.1fMB at %.2fMB/sec", ((float)(tmp_stats_current_file_sectors_processed * SACD_LSN_SIZE) / 1048576.00), ((float)(tmp_stats_current_file_total_sectors * SACD_LSN_SIZE) / 1048576.00), (float)((float) tmp_stats_total_sectors_processed * SACD_LSN_SIZE / 1048576.00) / (float)((__gettime() - tb_start) / (float)(tb_freq))); msgDialogProgressBarSetMsg(MSG_PROGRESSBAR_INDEX0, progress_message); prev_stats_total_sectors_processed = tmp_stats_total_sectors_processed; prev_stats_current_file_sectors_processed = tmp_stats_current_file_sectors_processed; } sysUtilCheckCallback(); flip(); } msgDialogAbort(); free(message); } free(albumdir); scarletbook_output_destroy(output); } scarletbook_close(handle); } sacd_close(sacd_reader); if (user_requested_exit()) { return 0; } else if (1) { dialog_type = (MSG_DIALOG_NORMAL | MSG_DIALOG_BTN_TYPE_OK | MSG_DIALOG_DISABLE_CANCEL_ON); msgDialogOpen2(dialog_type, "ripping process completed.", dialog_handler, NULL, NULL); dialog_action = 0; while (!dialog_action && !user_requested_exit()) { sysUtilCheckCallback(); flip(); } msgDialogAbort(); } return 0; }
static void client_thread(void *userdata) { p_socket client = (p_socket) userdata; ServerRequest request; ServerResponse response; uint8_t zero = 0; uint8_t *output_buf = (uint8_t *) malloc(MAX_PROCESSING_BLOCK_SIZE * SACD_LSN_SIZE + 1024); pb_istream_t input = pb_istream_from_socket(client); pb_ostream_t output; sacd_reader_t *sacd_reader = 0; scarletbook_handle_t *handle = 0; int non_encrypted_disc = 0; int checked_for_non_encrypted_disc = 0; uint32_t encrypted_start_1 = 0; uint32_t encrypted_start_2 = 0; uint32_t encrypted_end_1 = 0; uint32_t encrypted_end_2 = 0; uint32_t block_size = 0; uint32_t end_lsn = 0; client_connected = 1; response.data.bytes = (uint8_t *) malloc(MAX_PROCESSING_BLOCK_SIZE * SACD_LSN_SIZE); for (;;) { if (!pb_decode(&input, ServerRequest_fields, &request)) { break; } response.has_data = false; response.data.size = 0; response.result = -1; switch(request.type) { case ServerRequest_Type_DISC_READ: { response.type = ServerResponse_Type_DISC_READ; if (handle && sacd_reader) { int encrypted = 0; end_lsn = request.sector_offset + request.sector_count; // check what block ranges are encrypted.. if (request.sector_offset < encrypted_start_1) { block_size = min(encrypted_start_1 - request.sector_offset, MAX_PROCESSING_BLOCK_SIZE); encrypted = 0; } else if (request.sector_offset >= encrypted_start_1 && request.sector_offset <= encrypted_end_1) { block_size = min(encrypted_end_1 + 1 - request.sector_offset, MAX_PROCESSING_BLOCK_SIZE); encrypted = 1; } else if (request.sector_offset > encrypted_end_1 && request.sector_offset < encrypted_start_2) { block_size = min(encrypted_start_2 - request.sector_offset, MAX_PROCESSING_BLOCK_SIZE); encrypted = 0; } else if (request.sector_offset >= encrypted_start_2 && request.sector_offset <= encrypted_end_2) { block_size = min(encrypted_end_2 + 1 - request.sector_offset, MAX_PROCESSING_BLOCK_SIZE); encrypted = 1; } block_size = min(end_lsn - request.sector_offset, block_size); response.result = sacd_read_block_raw(sacd_reader, request.sector_offset, block_size, response.data.bytes); response.has_data = response.result > 0; response.data.size = response.result * SACD_LSN_SIZE; // the ATAPI call which returns the flag if the disc is encrypted or not is unknown at this point. // user reports tell me that the only non-encrypted discs out there are DSD 3 14/16 discs. // this is a quick hack/fix for these discs. if (encrypted && checked_for_non_encrypted_disc == 0) { switch (handle->area[0].area_toc->frame_format) { case FRAME_FORMAT_DSD_3_IN_14: case FRAME_FORMAT_DSD_3_IN_16: non_encrypted_disc = *(uint64_t *)(response.data.bytes + 16) == 0; break; } checked_for_non_encrypted_disc = 1; } // encrypted blocks need to be decrypted first if (encrypted && non_encrypted_disc == 0) { sacd_decrypt(sacd_reader, response.data.bytes, block_size); } } } break; case ServerRequest_Type_DISC_OPEN: response.type = ServerResponse_Type_DISC_OPENED; sacd_reader = sacd_open("/dev_bdvd"); if (sacd_reader) { handle = scarletbook_open(sacd_reader, 0); checked_for_non_encrypted_disc = 0; non_encrypted_disc = 0; if (handle) { // set the encryption range if (handle->area[0].area_toc != 0) { encrypted_start_1 = handle->area[0].area_toc->track_start; encrypted_end_1 = handle->area[0].area_toc->track_end; } if (handle->area[1].area_toc != 0) { encrypted_start_2 = handle->area[1].area_toc->track_start; encrypted_end_2 = handle->area[1].area_toc->track_end; } response.result = sacd_authenticate(sacd_reader); } } break; case ServerRequest_Type_DISC_CLOSE: { response.type = ServerResponse_Type_DISC_CLOSED; if (handle) { scarletbook_close(handle); handle = 0; } if (sacd_reader) { sacd_close(sacd_reader); sacd_reader = 0; } response.result = 0; } break; case ServerRequest_Type_DISC_SIZE: response.type = ServerResponse_Type_DISC_SIZE; if (sacd_reader) { response.result = sacd_get_total_sectors(sacd_reader); } break; } // reset output stream output = pb_ostream_from_buffer(output_buf, MAX_PROCESSING_BLOCK_SIZE * SACD_LSN_SIZE + 1024); if (!pb_encode(&output, ServerResponse_fields, &response)) { break; } /* We signal the end of a request with a 0 tag. */ pb_write(&output, &zero, 1); // write the output buffer to the opened socket { bool ret; size_t written; ret = (socket_send(client, (char *) output_buf, output.bytes_written, &written, 0, 0) == IO_DONE && written == output.bytes_written); if (!ret) break; } if (request.type == ServerRequest_Type_DISC_CLOSE) { break; } } if (handle) scarletbook_close(handle); if (sacd_reader) sacd_close(sacd_reader); free(response.data.bytes); free(output_buf); closesocket((int) *client); client_connected = 0; sysThreadExit(0); }