static PyObject * S_get_toc(PyObject *self, PyObject *args) { int fd; int newlist = 0; char *device_nodename; PyObject *tracks = NULL; if(!PyArg_ParseTuple(args, "s|O", &device_nodename, &tracks)) return NULL; fd = opendev(device_nodename, O_RDONLY | O_NONBLOCK, 0, &device_nodename); if(fd == -1) { PyErr_SetFromErrnoWithFilename(PyExc_IOError, device_nodename); goto end; } if (tracks == NULL) { tracks = PyList_New(0); newlist = 1; } if(read_toc(fd, _get_toc_callback, (void*)tracks) == -1) { PyErr_SetFromErrnoWithFilename(PyExc_IOError, device_nodename); goto error; } // catch exceptions from callbacks if(PyErr_Occurred() != NULL) goto error; end: close(fd); if (!newlist){ Py_INCREF(tracks); } return tracks; error: if (newlist){ Py_XDECREF(tracks); } tracks = NULL; goto end; }
/*! Play an audio track. */ static bool play_track(track_t i_start_track, track_t i_end_track) { bool b_ok = true; if (!b_cd) { cd_close(psz_device); read_toc(p_cdio); } read_subchannel(p_cdio); if (!b_cd || i_first_track == CDIO_CDROM_LEADOUT_TRACK) return false; if (debug) fprintf(stderr,"play tracks: %d-%d => ", i_start_track, i_end_track); if (i_start_track < i_first_track) i_start_track = i_first_track; if (i_start_track > i_last_audio_track) i_start_track = i_last_audio_track; if (i_end_track < i_first_track) i_end_track = i_first_track; if (i_end_track > i_last_audio_track) i_end_track = i_last_audio_track; if (debug) fprintf(stderr,"%d-%d\n",i_start_track, i_end_track); cd_pause(p_cdio); b_ok = (DRIVER_OP_SUCCESS == cdio_audio_play_msf(p_cdio, &(toc[i_start_track]), &(toc[i_end_track])) ); if (!b_ok) xperror("play"); return b_ok; }
/** Play an audio track. */ static bool play_track(track_t i_start_track, track_t i_end_track) { bool b_ok = true; char line[80]; if (!b_cd) { read_toc(p_cdio); } read_subchannel(p_cdio); if (!b_cd || i_first_track == CDIO_CDROM_LEADOUT_TRACK) return false; if (debug) fprintf(stderr,"play tracks: %d-%d => ", i_start_track, i_end_track-1); if (i_start_track < i_first_track) i_start_track = i_first_track; if (i_start_track > i_last_audio_track) i_start_track = i_last_audio_track; if (i_end_track < i_first_track) i_end_track = i_first_track; if (i_end_track > i_last_audio_track) i_end_track = i_last_audio_track; i_end_track++; if (debug) fprintf(stderr,"%d-%d\n",i_start_track, i_end_track-1); cd_pause(p_cdio); snprintf(line, sizeof(line), "play track %d to track %d.", i_start_track, i_end_track-1); action(line); b_ok = (DRIVER_OP_SUCCESS == cdio_audio_play_msf(p_cdio, &(toc[i_start_track]), &(toc[i_end_track])) ); if (!b_ok) xperror("play"); return b_ok; }
int cddb_resolve(const char *dev, char **xmcd_file) { char cddb_cache_dir[] = DEFAULT_CACHE_DIR; char *home_dir = NULL; cddb_data_t cddb_data; if (cdtoc_last_track <= 0) { cdtoc_last_track = read_toc(dev); if (cdtoc_last_track < 0) { mp_msg(MSGT_OPEN, MSGL_ERR, MSGTR_MPDEMUX_CDDB_FailedToOpenDevice, dev); return -1; } } cddb_data.tracks = cdtoc_last_track; cddb_data.disc_id = cddb_discid(cddb_data.tracks); cddb_data.anonymous = 1; // Don't send user info by default // Check if there is a CD in the drive // FIXME: That's not really a good way to check if( cddb_data.disc_id==0 ) { mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MPDEMUX_CDDB_NoCDInDrive); return -1; } home_dir = getenv("HOME"); #ifdef __MINGW32__ if( home_dir==NULL ) home_dir = getenv("USERPROFILE"); if( home_dir==NULL ) home_dir = getenv("HOMEPATH"); // Last resort, store the cddb cache in the mplayer directory if( home_dir==NULL ) home_dir = (char *)get_path(""); #endif if( home_dir==NULL ) { cddb_data.cache_dir = NULL; } else { cddb_data.cache_dir = malloc(strlen(home_dir)+strlen(cddb_cache_dir)+1); if( cddb_data.cache_dir==NULL ) { mp_msg(MSGT_DEMUX, MSGL_ERR, MSGTR_MemAllocFailed); return -1; } sprintf(cddb_data.cache_dir, "%s%s", home_dir, cddb_cache_dir ); } // Check for a cached file if( cddb_read_cache(&cddb_data)<0 ) { // No Cache found if( cddb_retrieve(&cddb_data)<0 ) { return -1; } } if( cddb_data.xmcd_file!=NULL ) { // printf("%s\n", cddb_data.xmcd_file ); *xmcd_file = cddb_data.xmcd_file; return 0; } return -1; }
void CddaImpl::open() { driver_id_t driver_id = DRIVER_UNKNOWN; if (_device.empty()) { char **ppsz_cd_drives = cdio_get_devices_with_cap_ret(NULL, CDIO_FS_AUDIO, false, &driver_id); if (ppsz_cd_drives && *ppsz_cd_drives) _device = ppsz_cd_drives[0]; cdio_free_device_list(ppsz_cd_drives); } _cdio = cdio_open(_device.c_str(), driver_id); if (_cdio == NULL) { THROW_EXCEPTION(CddaException, "Could not open device."); } // Detect empty drive if (cdio_get_first_track_num(_cdio) == CDIO_INVALID_TRACK) { close(); return; } _cdrom = cdio_cddap_identify_cdio(_cdio, CDDA_MESSAGE_LOGIT, NULL); if (_cdrom == NULL) { THROW_EXCEPTION(CddaException, "Could not read cdrom structure."); } cdio_cddap_verbose_set(_cdrom, CDDA_MESSAGE_LOGIT, CDDA_MESSAGE_LOGIT); int ret = cdio_cddap_open(_cdrom); if (ret != 0) { THROW_EXCEPTION(CddaException, cdda_error_message(ret)); } _is_open = true; read_toc(); //read_cddb(); }
static void read_outline (PopplerDocument *document, TrackerResource *metadata) { PopplerIndexIter *index; GString *toc = NULL; index = poppler_index_iter_new (document); if (!index) { return; } read_toc (index, &toc); if (toc) { if (toc->len > 0) { tracker_resource_set_string (metadata, "nfo:tableOfContents", toc->str); } g_string_free (toc, TRUE); } }
/** \brief Reads TOC from CD in the given device and prints the number of tracks and the length of each track in minute:second:frame format. \param *dev the device to analyse \return if the command line -identify is given, returns the last track of the TOC or -1 if the TOC can't be read, otherwise just returns 0 and let cddb_resolve the TOC */ int cdd_identify(const char *dev) { cdtoc_last_track = 0; if (mp_msg_test(MSGT_IDENTIFY, MSGL_INFO)) { int i, min, sec, frame; cdtoc_last_track = read_toc(dev); if (cdtoc_last_track < 0) { mp_tmsg(MSGT_OPEN, MSGL_ERR, "Failed to open %s device.\n", dev); return -1; } mp_msg(MSGT_GLOBAL, MSGL_INFO, "ID_CDDA_TRACKS=%d\n", cdtoc_last_track); for (i = 1; i <= cdtoc_last_track; i++) { frame = cdtoc[i].frame - cdtoc[i-1].frame; sec = frame / 75; frame -= sec * 75; min = sec / 60; sec -= min * 60; mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CDDA_TRACK_%d_MSF=%02d:%02d:%02d\n", i, min, sec, frame); } } return cdtoc_last_track; }
static void read_outline (PopplerDocument *document, TrackerSparqlBuilder *metadata) { PopplerIndexIter *index; GString *toc = NULL; index = poppler_index_iter_new (document); if (!index) { return; } read_toc (index, &toc); if (toc) { if (toc->len > 0) { tracker_sparql_builder_predicate (metadata, "nfo:tableOfContents"); tracker_sparql_builder_object_unvalidated (metadata, toc->str); } g_string_free (toc, TRUE); } }
static int open_vcd(bgav_input_context_t * ctx, const char * url, char ** r) { driver_return_code_t err; int i; vcd_priv * priv; const char * pos; // bgav_find_devices_vcd(); priv = calloc(1, sizeof(*priv)); ctx->priv = priv; #ifndef SECTOR_ACCESS priv->buffer = priv->sector + 8; priv->buffer_ptr = priv->buffer + SECTOR_SIZE; #endif pos = strrchr(url, '.'); if(pos && !strcasecmp(pos, ".cue")) priv->cdio = cdio_open (url, DRIVER_BINCUE); else { if((err = cdio_close_tray(url, NULL))) #if LIBCDIO_VERSION_NUM >= 77 bgav_log(ctx->opt, BGAV_LOG_ERROR, LOG_DOMAIN, "cdio_close_tray failed: %s", cdio_driver_errmsg(err)); #else bgav_log(ctx->opt, BGAV_LOG_ERROR, LOG_DOMAIN, "cdio_close_tray failed"); #endif priv->cdio = cdio_open (url, DRIVER_DEVICE); /* Close tray, hope this won't be harmful if the tray is already closed */ } if(!priv->cdio) { bgav_log(ctx->opt, BGAV_LOG_ERROR, LOG_DOMAIN, "cdio_open failed for %s", url); return 0; } /* Get some infos */ // dump_cdrom(priv->fd); /* Read TOC */ if(!read_toc(priv, &ctx->disc_name)) { bgav_log(ctx->opt, BGAV_LOG_ERROR, LOG_DOMAIN, "read_toc failed for %s", url); return 0; } toc_2_tt(ctx); /* Set up sector stuff */ #ifdef SECTOR_ACCESS ctx->sector_size = 2324; ctx->sector_size_raw = 2352; ctx->sector_header_size = 8; #endif /* Create demuxer */ ctx->demuxer = bgav_demuxer_create(ctx->opt, &bgav_demuxer_mpegps, ctx); ctx->demuxer->tt = ctx->tt; /* Now, loop through all tracks and let the demuxer find the durations */ for(i = 0; i < ctx->tt->num_tracks; i++) { select_track_vcd(ctx, i); bgav_track_table_select_track(ctx->tt, i); bgav_demuxer_start(ctx->demuxer, NULL); bgav_demuxer_stop(ctx->demuxer); } ctx->can_pause = 1; return 1; }
static dbus_bool_t probe_disc (int fd, LibHalContext *ctx, const char *udi, dbus_bool_t *has_data, dbus_bool_t *has_audio) { DBusError error; disc_info_t di; int profile; dbus_bool_t is_blank, is_appendable, is_rewritable; char *disc_type = "cd_rom"; uint64_t capacity = 0; int i; LibHalChangeSet *cs; dbus_error_init (&error); if (get_disc_info (fd, &di)) { is_blank = (di.disc_status == 0); is_appendable = (di.disc_status == 1); is_rewritable = (di.erasable != 0); } else { is_blank = is_appendable = is_rewritable = FALSE; } if (get_current_profile (fd, &profile)) { switch (profile) { case 0x08: /* CD-ROM */ disc_type = "cd_rom"; break; case 0x09: /* CD-R */ disc_type = "cd_r"; break; case 0x0A: /* CD-RW */ disc_type = "cd_rw"; is_rewritable = TRUE; break; case 0x10: /* DVD-ROM */ disc_type = "dvd_rom"; break; case 0x11: /* DVD-R Sequential */ disc_type = "dvd_r"; break; case 0x12: /* DVD-RAM */ disc_type = "dvd_ram"; is_rewritable = TRUE; break; case 0x13: /* DVD-RW Restricted Overwrite */ disc_type = "dvd_rw"; is_rewritable = TRUE; break; case 0x14: /* DVD-RW Sequential */ disc_type = "dvd_rw"; is_rewritable = TRUE; break; case 0x1A: /* DVD+RW */ disc_type = "dvd_plus_rw"; is_rewritable = TRUE; break; case 0x1B: /* DVD+R */ disc_type = "dvd_plus_r"; break; case 0x2B: /* DVD+R Double Layer */ disc_type = "dvd_plus_r_dl"; break; case 0x40: /* BD-ROM */ disc_type = "bd_rom"; break; case 0x41: /* BD-R Sequential */ disc_type = "bd_r"; break; case 0x42: /* BD-R Random */ disc_type = "bd_r"; break; case 0x43: /* BD-RE */ disc_type = "bd_re"; is_rewritable = TRUE; break; case 0x50: /* HD DVD-ROM */ disc_type = "hddvd_rom"; break; case 0x51: /* HD DVD-R */ disc_type = "hddvd_r"; break; case 0x52: /* HD DVD-Rewritable */ disc_type = "hddvd_rw"; is_rewritable = TRUE; break; } (void) get_disc_capacity_for_profile(fd, profile, &capacity); } *has_audio = *has_data = FALSE; if (!is_blank) { uchar_t smalltoc[12]; size_t toc_size; uchar_t *toc, *p; /* * XXX for some reason CDROMREADTOCENTRY fails on video DVDs, * but extracting the toc directly works okay. */ if (!read_toc(fd, 0, 1, 4, smalltoc)) { HAL_DEBUG(("read_toc failed")); *has_data = B_TRUE; /* probe for fs anyway */ } else { toc_size = smalltoc[0] * 256 + smalltoc[1] + 2; toc = (uchar_t *)calloc(1, toc_size); if (toc == NULL || !read_toc(fd, 0, 1, toc_size, toc)) { HAL_DEBUG (("read_toc again failed")); } else { for (p = &toc[4]; p < (toc + toc_size); p += 8) { /* skip leadout */ if (p[2] == 0xAA) { continue; } if (p[1] & 4) { *has_data = B_TRUE; } else { *has_audio = B_TRUE; } } } free(toc); } } if ((cs = libhal_device_new_changeset (udi)) == NULL) { return (FALSE); } libhal_changeset_set_property_string (cs, "volume.disc.type", disc_type); libhal_changeset_set_property_bool (cs, "volume.disc.is_blank", is_blank); libhal_changeset_set_property_bool (cs, "volume.disc.has_audio", *has_audio); libhal_changeset_set_property_bool (cs, "volume.disc.has_data", *has_data); libhal_changeset_set_property_bool (cs, "volume.disc.is_appendable", is_appendable); libhal_changeset_set_property_bool (cs, "volume.disc.is_rewritable", is_rewritable); libhal_changeset_set_property_uint64 (cs, "volume.disc.capacity", capacity); libhal_changeset_set_property_bool (cs, "volume.disc.is_videodvd", FALSE); libhal_changeset_set_property_bool (cs, "volume.disc.is_vcd", FALSE); libhal_changeset_set_property_bool (cs, "volume.disc.is_svcd", FALSE); libhal_device_commit_changeset (ctx, cs, &error); libhal_device_free_changeset (cs); out: my_dbus_error_free (&error); return (TRUE); }
int main(int argc, char *argv[]) { int c; char *h; int i_rc = 0; int i_volume_level = -1; cd_operation_t todo = NO_OP; /* operation to do in non-interactive mode */ psz_program = strrchr(argv[0],'/'); psz_program = psz_program ? psz_program+1 : argv[0]; /* parse options */ while ( 1 ) { if (-1 == (c = getopt(argc, argv, "aCdehkpL:sSt:vx"))) break; switch (c) { case 'v': b_verbose = true; break; case 'd': debug = 1; break; case 'a': auto_mode = 1; break; case 'L': if (NULL != strchr(optarg,'-')) { i_volume_level = atoi(optarg); todo = SET_VOLUME; } break; case 't': if (NULL != (h = strchr(optarg,'-'))) { *h = 0; start_track = atoi(optarg); stop_track = atoi(h+1)+1; if (0 == start_track) start_track = 1; if (1 == stop_track) stop_track = CDIO_CDROM_LEADOUT_TRACK; } else { start_track = atoi(optarg); stop_track = start_track+1; one_track = 1; } todo = PLAY_TRACK; break; case 'p': todo = PLAY_CD; break; case 'C': todo = CLOSE_CD; break; break; case 's': todo = STOP_PLAYING; break; case 'S': todo = LIST_SUBCHANNEL; break; case 'e': todo = EJECT_CD; break; case 'h': usage(psz_program); exit(1); default: usage(psz_program); exit(1); } } if (argc > optind) { psz_device = strdup(argv[optind]); } else { char **ppsz_cdda_drives=NULL; char **ppsz_all_cd_drives = cdio_get_devices_ret(&driver_id); if (!ppsz_all_cd_drives) { fprintf(stderr, "Can't find a CD-ROM drive\n"); exit(2); } ppsz_cdda_drives = cdio_get_devices_with_cap(ppsz_all_cd_drives, CDIO_FS_AUDIO, false); if (!ppsz_cdda_drives || !ppsz_cdda_drives[0]) { fprintf(stderr, "Can't find a CD-ROM drive with a CD-DA in it\n"); exit(3); } psz_device = strdup(ppsz_cdda_drives[0]); cdio_free_device_list(ppsz_all_cd_drives); cdio_free_device_list(ppsz_cdda_drives); } if (!b_cd && todo != EJECT_CD) { cd_close(psz_device); } /* open device */ if (b_verbose) fprintf(stderr,"open %s... ", psz_device); p_cdio = cdio_open (psz_device, driver_id); if (!p_cdio) { if (b_verbose) fprintf(stderr, "error: %s\n", strerror(errno)); else fprintf(stderr, "open %s: %s\n", psz_device, strerror(errno)); exit(1); } else if (b_verbose) fprintf(stderr,"ok\n"); if (EJECT_CD == todo) { i_rc = cd_eject() ? 0 : 1; } else { read_toc(p_cdio); if (!b_cd) { cd_close(psz_device); read_toc(p_cdio); } if (b_cd) switch (todo) { case NO_OP: break; case STOP_PLAYING: i_rc = cd_stop(p_cdio) ? 0 : 1; break; case EJECT_CD: /* Should have been handled above before case statement. gcc warns if we don't include this. And with this Coverty complains when we do - we can't win, so go with gcc. */ cd_eject(); break; case PLAY_TRACK: /* play just this one track */ play_track(start_track, stop_track); break; case PLAY_CD: play_track(1,CDIO_CDROM_LEADOUT_TRACK); break; case CLOSE_CD: i_rc = cdio_close_tray(psz_device, NULL) ? 0 : 1; break; case SET_VOLUME: { cdio_audio_volume_t volume; volume.level[0] = i_volume_level; i_rc = (DRIVER_OP_SUCCESS == cdio_audio_set_volume(p_cdio, &volume)) ? 0 : 1; break; } case LIST_SUBCHANNEL: if (read_subchannel(p_cdio)) { if (sub.audio_status == CDIO_MMC_READ_SUB_ST_PAUSED || sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY) { { printf("track %2d - %02x:%02x (%02x:%02x abs) ", sub.track, sub.rel_addr.m, sub.rel_addr.s, sub.abs_addr.m, sub.abs_addr.s); } } printf("drive state: %s\n", mmc_audio_state2str(sub.audio_status)); } else { i_rc = 1; } break; } else { fprintf(stderr,"no CD in drive (%s)\n", psz_device); } } oops("bye", i_rc); return 0; /* keep compiler happy */ }
/* * The size of the last track in one of the first N - 1 sessions of an * N-session (N > 1) disc is reported incorrectly by some drives and calculated * incorrectly for others, because a pre-gap/lead-out/lead-in section that ends * a session is erroneously considered part of that track. This function checks * for this corner case, and adjusts the track size if necessary. */ static int check_track_size(cd_device *dev, int trk_num, struct track_info *tip) { size_t raw_toc_len; uchar_t *raw_toc; rtoc_hdr_t hdr; uint32_t sess_leadout_lba; int sess_last_trk_num; int trk_sess_num; uint32_t trk_size; /* Request Raw TOC Header for session count. */ if (read_toc(dev->d_fd, FORMAT_RAW_TOC, 1, sizeof (rtoc_hdr_t), (uchar_t *)&hdr) != 1) return (0); /* Is this a multi-session medium? */ if (hdr.rh_last_sess_num > hdr.rh_first_sess_num) { /* Yes; request entire Raw TOC. */ raw_toc_len = read_scsi16(&hdr.rh_data_len1) + RTOC_DATA_LEN_SZ; raw_toc = (uchar_t *)my_zalloc(raw_toc_len); if (read_toc(dev->d_fd, FORMAT_RAW_TOC, 1, raw_toc_len, raw_toc) != 1) goto fail; if (rtoc_get_trk_sess_num(raw_toc, raw_toc_len, trk_num, &trk_sess_num) != 1) goto fail; tip->ti_session_no = trk_sess_num; tip->ti_flags |= TI_SESSION_NO_VALID; /* Is the track in one of the first N - 1 sessions? */ if (trk_sess_num < hdr.rh_last_sess_num) { if (rtoc_get_sess_last_trk_num(raw_toc, raw_toc_len, trk_sess_num, &sess_last_trk_num) != 1) goto fail; /* Is the track the last track in the session? */ if (trk_num == sess_last_trk_num) { if (rtoc_get_sess_leadout_lba(raw_toc, raw_toc_len, trk_sess_num, &sess_leadout_lba) != 1) goto fail; trk_size = sess_leadout_lba - tip->ti_start_address; /* Fix track size if it was too big. */ if (tip->ti_track_size > trk_size) tip->ti_track_size = trk_size; } } free(raw_toc); } return (1); fail: free(raw_toc); return (0); }
/* * Builds track information database for track trackno. If trackno is * -1, builds the database for next blank track. */ int build_track_info(cd_device *dev, int trackno, struct track_info *t_info) { uchar_t *ti; uchar_t toc[20]; /* 2 entries + 4 byte header */ int ret; (void) memset(t_info, 0, sizeof (*t_info)); /* 1st try READ TRACK INFORMATION */ ti = (uchar_t *)my_zalloc(TRACK_INFO_SIZE); t_info->ti_track_no = trackno; /* Gererate faked information for writing to DVD */ if (device_type != CD_RW) { uint_t bsize; t_info->ti_flags = 0x3000; t_info->ti_track_no = 1; t_info->ti_session_no = 1; t_info->ti_track_mode = 0x4; t_info->ti_data_mode = 1; t_info->ti_start_address = 0; /* only 1 track on DVD make it max size */ t_info->ti_track_size = read_format_capacity(target->d_fd, &bsize); if (t_info->ti_track_size < MAX_CD_BLKS) { t_info->ti_track_size = MAX_DVD_BLKS; } t_info->ti_nwa = 0; t_info->ti_lra = 0; t_info->ti_packet_size = 0x10; t_info->ti_free_blocks = 0; } if (read_track_info(dev->d_fd, trackno, ti)) { if (debug) (void) printf("using read_track_info for TOC \n"); t_info->ti_track_no = ti[2]; t_info->ti_session_no = ti[3]; t_info->ti_flags = (ti[6] >> 4) & 0xf; t_info->ti_flags |= (uint32_t)(ti[5] & 0xf0); t_info->ti_flags |= (uint32_t)(ti[7]) << 8; t_info->ti_flags |= TI_SESSION_NO_VALID | TI_FREE_BLOCKS_VALID; t_info->ti_track_mode = ti[5] & 0xf; if ((ti[6] & 0xf) == 0xf) t_info->ti_data_mode = 0xff; else t_info->ti_data_mode = ti[6] & 0xf; t_info->ti_start_address = read_scsi32(&ti[8]); t_info->ti_nwa = read_scsi32(&ti[12]); t_info->ti_free_blocks = read_scsi32(&ti[16]); t_info->ti_packet_size = read_scsi32(&ti[20]); t_info->ti_track_size = read_scsi32(&ti[24]); t_info->ti_lra = read_scsi32(&ti[28]); free(ti); return (1); } /* READ TRACK INFORMATION not supported, try other options */ free(ti); /* * We can get info for next blank track if READ TRACK INFO is not * supported. */ if (trackno == -1) return (0); if (debug) (void) printf("using READ_TOC for TOC\n"); /* Try Read TOC */ if (!read_toc(dev->d_fd, 0, trackno, 20, toc)) { return (0); } t_info->ti_start_address = read_scsi32(&toc[8]); t_info->ti_track_mode = toc[5] & 0xf; t_info->ti_track_size = read_scsi32(&toc[16]) - read_scsi32(&toc[8]); t_info->ti_data_mode = get_data_mode(dev->d_fd, read_scsi32(&toc[8])); /* Numbers for audio tracks are always in 2K chunks */ if ((dev->d_blksize == 512) && ((t_info->ti_track_mode & 4) == 0)) { t_info->ti_start_address /= 4; t_info->ti_track_size /= 4; } /* Now find out the session thing */ ret = read_toc(dev->d_fd, 1, trackno, 12, toc); /* * Make sure that the call succeeds and returns the requested * TOC size correctly. */ if ((ret == 0) || (toc[1] != 0x0a)) { /* For ATAPI drives or old Toshiba drives */ ret = read_toc_as_per_8020(dev->d_fd, 1, trackno, 12, toc); } /* If this goes through well TOC length will always be 0x0a */ if (ret && (toc[1] == 0x0a)) { if (trackno >= toc[6]) { t_info->ti_session_no = toc[3]; t_info->ti_flags |= TI_SESSION_NO_VALID; } /* * This might be the last track of this session. If so, * exclude the leadout and next lead in. */ if (trackno == (toc[6] - 1)) { /* * 1.5 Min leadout + 1 min. leadin + 2 sec. pre-gap. * For 2nd+ leadout it will be 0.5 min. But currently * there is no direct way. And it will not happen * for any normal case. * * 75 frames/sec, 60 sec/min, so leadin gap is * ((1.5 +1)*60 + 2)*75 = 11400 frames (blocks) */ t_info->ti_track_size -= 11400; } } return (1); }
int cddb_resolve(const char *dev, char **xmcd_file) { char cddb_cache_dir[] = DEFAULT_CACHE_DIR; char *home_dir = NULL; cddb_data_t cddb_data; void *talloc_ctx = talloc_new(NULL); if (cdtoc_last_track <= 0) { cdtoc_last_track = read_toc(dev); if (cdtoc_last_track < 0) { mp_tmsg(MSGT_OPEN, MSGL_ERR, "Failed to open %s device.\n", dev); return -1; } } cddb_data.tracks = cdtoc_last_track; cddb_data.disc_id = cddb_discid(cddb_data.tracks); cddb_data.anonymous = 1; // Don't send user info by default mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CDDB_DISCID=%08lx\n", cddb_data.disc_id); // Check if there is a CD in the drive // FIXME: That's not really a good way to check if (cddb_data.disc_id == 0) { mp_tmsg(MSGT_DEMUX, MSGL_ERR, "No CD in the drive.\n"); return -1; } home_dir = getenv("HOME"); #ifdef __MINGW32__ if (home_dir == NULL) home_dir = getenv("USERPROFILE"); if (home_dir == NULL) home_dir = getenv("HOMEPATH"); // Last resort, store the cddb cache in the mplayer directory if (home_dir == NULL) home_dir = (char *)talloc_steal(talloc_ctx, mp_find_user_config_file("")); #endif if (home_dir == NULL) { cddb_data.cache_dir = NULL; } else { unsigned len = strlen(home_dir) + strlen(cddb_cache_dir) + 1; cddb_data.cache_dir = malloc(len); if (cddb_data.cache_dir == NULL) { mp_tmsg(MSGT_DEMUX, MSGL_ERR, "Memory allocation failed.\n"); talloc_free(talloc_ctx); return -1; } snprintf(cddb_data.cache_dir, len, "%s%s", home_dir, cddb_cache_dir); } talloc_free(talloc_ctx); // Check for a cached file if (cddb_read_cache(&cddb_data) < 0) { // No Cache found if (cddb_retrieve(&cddb_data) < 0) { return -1; } } if (cddb_data.xmcd_file != NULL) { // printf("%s\n", cddb_data.xmcd_file); *xmcd_file = cddb_data.xmcd_file; return 0; } return -1; }
void info(void) { uchar_t *toc, *p, *conf; int ret, toc_size; uint_t bsize; size_t cap = 0; char *msg; struct track_info *ti; msg = gettext("Cannot read Table of contents\n"); get_media_type(target->d_fd); (void) printf(gettext("\nDevice : %.8s %.16s\n"), &target->d_inq[8], &target->d_inq[16]); (void) printf(gettext("Firmware : Rev. %.4s (%.12s)\n"), &target->d_inq[32], &target->d_inq[36]); if (check_device(target, CHECK_DEVICE_NOT_READY)) { (void) check_device(target, CHECK_NO_MEDIA | EXIT_IF_CHECK_FAILED); (void) check_device(target, CHECK_DEVICE_NOT_READY | EXIT_IF_CHECK_FAILED); } if (verbose != 0) { /* * Determine the media type by reading the active profile * from the profile list. */ (void) printf(gettext("Media Type : ")); conf = (uchar_t *)my_zalloc(MMC_FTR_HDR_LEN); if (get_configuration(target->d_fd, MMC_FTR_PRFL_LIST, MMC_FTR_HDR_LEN, conf)) print_profile_name(read_scsi16(&conf[6]), 0, 1); else (void) printf(gettext("UNKNOWN\n")); free(conf); /* * Get the start address of the last possible lead out. */ cap = get_last_possible_lba(target); /* * The start address of the last possible leadout will only * be zero if the disc is full or this drive does not support * this method of determining capacity. */ if (cap == 0) cap = read_format_capacity(target->d_fd, &bsize); /* * Since both methods of determining the capacity of the * media count the correct number of blocks, just multiply * the capacity by the block size. */ cap *= target->d_blksize; if (device_type == CD_RW) { (void) printf(gettext("Media Capacity : %.2f MB "), ((double)cap/ONE_MB_BASE2)); } else { /* * For DVD's make sure we print out "Formatted Media * Capacity". Don't do this for CD-RWs as only * DVDs are formatted. */ (void) printf(gettext("Formatted Media Capacity : " "%.2f GB "), ((double)cap/ONE_GB_BASE10)); } cap /= target->d_blksize; (void) printf(gettext("(%u blocks)\n"), (uint_t)cap); } if (!check_device(target, CHECK_MEDIA_IS_NOT_BLANK)) { (void) printf(gettext("Media is blank\n")); exit(0); } /* Find out the number of entries in the toc */ toc = (uchar_t *)my_zalloc(12); if (!read_toc(target->d_fd, 0, 1, 4, toc)) { err_msg(msg); } else { toc_size = 256*toc[0] + toc[1] + 2; free(toc); /* allocate enough space for each track entry */ toc = (uchar_t *)my_zalloc(toc_size); if (!read_toc(target->d_fd, 0, 1, toc_size, toc)) { err_msg(msg); exit(1); } (void) printf("\n"); /* l10n_NOTE : Preserve column numbers of '|' character */ (void) printf(gettext("Track No. |Type |Start address\n")); (void) printf("----------+--------+-------------\n"); /* look at each track and display it's type. */ for (p = &toc[4]; p < (toc + toc_size); p += 8) { if (p[2] != 0xAA) (void) printf(" %-3d |", p[2]); else (void) printf("Leadout |"); (void) printf("%s |", (p[1] & 4) ? gettext("Data ") : gettext("Audio")); (void) printf("%u\n", read_scsi32(&p[4])); } } (void) printf("\n"); ret = read_toc(target->d_fd, 1, 0, 12, toc); if ((ret == 0) || (toc[1] != 0x0a)) /* For ATAPI drives or old Toshiba drives */ ret = read_toc_as_per_8020(target->d_fd, 1, 0, 12, toc); if (ret && (toc[1] == 0x0a)) { (void) printf(gettext("Last session start address: %u\n"), read_scsi32(&toc[8])); } free(toc); ti = (struct track_info *)my_zalloc(sizeof (struct track_info)); if (build_track_info(target, -1, ti) && (ti->ti_flags & TI_NWA_VALID)) { (void) printf(gettext("Next writable address: %u\n"), ti->ti_nwa); } free(ti); exit(0); }
int main(int argc, char **argv) { iso_primary_descriptor_type ipd; char *dev = default_dev; char vendor[9],model[17],rev[5]; unsigned char reply[1024]; char tmpstr[255]; int replylen=sizeof(reply); int trackno = 0; int info_only = 0; unsigned char *buffer; int buffersize = READBLOCKS*BLOCKSIZE; int start,stop,imagesize=0,tracksize=0; int counter = 0; long readsize = 0; long imagesize_bytes = 0; int drive_block_size, init_bsize; int force_mode = 0; int scanbus_mode = 0; int dump_start, dump_count; MD5_CTX *MD5; char digest[16],digest_text[33]; int md5_mode = 0; int opt_index = 0; int audio_track = 0; int readblocksize = BLOCKSIZE; int file_format = AF_FILE_AIFFC; #ifdef IRIX CDPARSER *cdp = CDcreateparser(); CDFRAME cdframe; #endif int dev_type; int i,c,o; int len; int start_time,cur_time,kbps; if (rcsid); MD5 = malloc(sizeof(MD5_CTX)); buffer=(unsigned char*)malloc(READBLOCKS*AUDIOBLOCKSIZE); if (!buffer || !MD5) die("No memory"); if (argc<2) die("parameter(s) missing\n" "Try '%s --help' for more information.\n",PRGNAME); /* parse command line parameters */ while(1) { if ((c=getopt_long(argc,argv,"SMmvhid:",long_options,&opt_index)) == -1) break; switch (c) { case 'a': file_format=AF_FILE_AIFF; break; case 'A': file_format=AF_FILE_AIFFC; break; case 'v': verbose_mode=1; break; case 'h': p_usage(); break; case 'd': dev=strdup(optarg); break; case 't': if (sscanf(optarg,"%d",&trackno)!=1) trackno=0; break; case 'i': info_only=1; break; case 'c': if (sscanf(optarg,"%d,%d",&dump_start,&dump_count)!=2) die("invalid parameters"); dump_mode=1; break; #ifdef IRIX case 'C': if (sscanf(optarg,"%d,%d",&dump_start,&dump_count)!=2) die("invalid parameters"); dump_mode=2; break; #endif case 'f': if (sscanf(optarg,"%d",&force_mode)!=1) die("invalid parameters"); if (force_mode<1 || force_mode >2) { die("invalid parameters"); } break; case 'm': md5_mode=1; break; case 'M': md5_mode=2; break; case 's': audio_mode=1; break; case 'S': scanbus_mode=1; break; case 'V': printf(PRGNAME " " VERSION " " HOST_TYPE "\nCopyright (c) Timo Kokkonen, 1997-1998.\n\n"); exit(0); break; case '?': break; default: die("error parsing parameters"); } } if (!info_only) { if (md5_mode==2) outfile=fopen("/dev/null","w"); else outfile=fopen(argv[optind],"w"); if (!outfile) { if (argv[optind]) die("cannot open output file '%s'",argv[optind]); info_only=1; } } printf("readiso(9660) " VERSION "\n"); /* open the scsi device */ if (scsi_open(dev)) die("error opening scsi device '%s'",dev); if (scanbus_mode) { printf("\n"); scan_bus(); exit(0); } memset(reply,0,sizeof(reply)); if ((dev_type=inquiry(vendor,model,rev))<0) die("error accessing scsi device"); if (verbose_mode) { printf("device: %s\n",dev); printf("Vendor: %s\nModel: %s\nRevision: %s\n",vendor,model,rev); } if ( (dev_type&0x1f) != 0x5 ) { die("Device doesn't seem to be a CD-ROM!"); } #ifdef IRIX if (strcmp(vendor,"TOSHIBA")) { warn("NOTE! Audio track reading probably not supported on this device.\n"); } #endif test_ready(); if (test_ready()!=0) { sleep(2); if (test_ready()!=0) die("device not ready"); } fprintf(stderr,"Initializing...\n"); if (audio_mode) { #ifdef IRIX audioport=ALopenport("readiso","w",0); if (!audioport) { warn("Cannot initialize audio."); audio_mode=0; } #else audio_mode=0; #endif } #ifdef IRIX /* Make sure we get sane underflow exception handling */ sigfpe_[_UNDERFL].repls = _ZERO; handle_sigfpes(_ON, _EN_UNDERFL, NULL, _ABORT_ON_ERROR, NULL); #endif /* set_removable(1); */ #if 0 replylen=255; if (mode_sense10(reply,&replylen)==0) { printf("replylen=%d blocks=%d blocklen=%d\n",replylen, V3(&reply[8+1]),V3(&reply[8+5])); PRINT_BUF(reply,replylen); } replylen=255; /* sizeof(reply); */ if (mode_sense(reply,&replylen)==0) { printf("replylen=%d blocks=%d blocklen=%d\n",replylen, V3(&reply[4+1]),V3(&reply[4+5])); PRINT_BUF(reply,replylen); } #endif if (dump_mode==2) init_bsize=AUDIOBLOCKSIZE; else init_bsize=BLOCKSIZE; start_stop(0); if ( (drive_block_size=get_block_size()) < 0 ) { warn("cannot get current block size"); drive_block_size=init_bsize; } if (drive_block_size != init_bsize) { mode_select(init_bsize,(dump_mode==2?0x82:0x00)); drive_block_size=get_block_size(); if (drive_block_size!=init_bsize) warn("cannot set drive block size."); } start_stop(1); if (dump_mode && !info_only) { #ifdef IRIX CDFRAME buf; if (dump_mode==2) { if (cdp) { CDaddcallback(cdp, cd_audio, (CDCALLBACKFUNC)playaudio, 0); } else die("No audioparser"); } #endif fprintf(stderr,"Dumping %d sector(s) starting from LBA=%d\n", dump_count,dump_start); for (i=dump_start;i<dump_start+dump_count;i++) { len=buffersize; read_10(i,1,buffer,&len); if (len<init_bsize) break; #ifdef IRIX if (dump_mode==2) { memcpy(&buf,buffer,CDDA_BLOCKSIZE); CDparseframe(cdp,&buf); } #endif fwrite(buffer,len,1,outfile); fprintf(stderr,"."); } fprintf(stderr,"\ndone.\n"); goto quit; } fprintf(stderr,"Reading disc TOC..."); replylen=sizeof(reply); read_toc(reply,&replylen,verbose_mode); printf("\n"); if (trackno==0) { /* try to find first data track */ for (i=0;i<(reply[3]-reply[2]+1);i++) { o=4+i*8; if (reply[o+1]&DATA_TRACK) { trackno=i+1; break; } } if (trackno==0) die("No data track(s) found."); } fprintf(stderr,"Reading track %d...\n",trackno); if ( (trackno < reply[2]) || (trackno > reply[3]) ) die("Invalid track specified."); if ( ((reply[(trackno-1)*8+4+1]&DATA_TRACK)==0) ) { fprintf(stderr,"Not a data track.\n"); mode_select(AUDIOBLOCKSIZE,0x82); if (mode_sense(reply,&replylen)!=0) die("cannot get sense data"); drive_block_size=V3(&reply[9]); fprintf(stderr,"Selecting CD-DA mode, output file format: %s\n", file_format==AF_FILE_AIFFC?"AIFFC":"AIFF"); audio_track=1; } else { audio_track=0; } start=V4(&reply[(trackno-1)*8+4+4]); stop=V4(&reply[(trackno)*8+4+4]); tracksize=abs(stop-start); /* if (verbose_mode) printf("Start LBA=%d\nStop LBA=%d\n",start,stop); */ len=buffersize; read_10(start-0,1,buffer,&len); /* PRINT_BUF(buffer,32); */ if (!audio_track) { /* read the iso9660 primary descriptor */ fprintf(stderr,"Reading ISO9660 primary descriptor...\n"); len=buffersize; read_10(start+16,1,buffer,&len); if (len<sizeof(ipd)) die("cannot read iso9660 primary descriptor."); memcpy(&ipd,buffer,sizeof(ipd)); imagesize=ISONUM(ipd.volume_space_size); /* we should really check here if we really got a valid primary descriptor or not... */ if ( (imagesize>(stop-start)) || (imagesize<1) ) { fprintf(stderr,"\aInvalid ISO primary descriptor!!!\n"); if (!info_only) fprintf(stderr,"Copying entire track to image file.\n"); force_mode=2; } if (force_mode==1) {} /* use size from ISO primary descriptor */ else if (force_mode==2) imagesize=tracksize; /* use size from TOC */ else { if ( ( (tracksize-imagesize) > MAX_DIFF_ALLOWED ) || ( imagesize > tracksize ) ) { fprintf(stderr,"ISO primary descriptor has suspicious volume size" " (%d blocks)\n",imagesize); imagesize=tracksize; fprintf(stderr, "Using track size from TOC record (%d blocks) instead.\n", imagesize); fprintf(stderr, "(option -f can be used to override this behaviour.)\n"); } } imagesize_bytes=imagesize*BLOCKSIZE; if (verbose_mode||info_only) { printf("ISO9660 image info:\n"); printf("Type: %02xh\n",ipd.type[0]); ISOGETSTR(tmpstr,ipd.id,5); printf("ID: %s\n",tmpstr); printf("Version: %u\n",ipd.version[0]); ISOGETSTR(tmpstr,ipd.system_id,32); printf("System id: %s\n",tmpstr); ISOGETSTR(tmpstr,ipd.volume_id,32); printf("Volume id: %s\n",tmpstr); ISOGETSTR(tmpstr,ipd.volume_set_id,128); if (strlen(tmpstr)>0) printf("Volume set id: %s\n",tmpstr); ISOGETSTR(tmpstr,ipd.publisher_id,128); if (strlen(tmpstr)>0) printf("Publisher id: %s\n",tmpstr); ISOGETSTR(tmpstr,ipd.preparer_id,128); if (strlen(tmpstr)>0) printf("Preparer id: %s\n",tmpstr); ISOGETSTR(tmpstr,ipd.application_id,128); if (strlen(tmpstr)>0) printf("Application id: %s\n",tmpstr); ISOGETDATE(tmpstr,ipd.creation_date); printf("Creation date: %s\n",tmpstr); ISOGETDATE(tmpstr,ipd.modification_date); if (!NULLISODATE(ipd.modification_date)) printf("Modification date: %s\n",tmpstr); ISOGETDATE(tmpstr,ipd.expiration_date); if (!NULLISODATE(ipd.expiration_date)) printf("Expiration date: %s\n",tmpstr); ISOGETDATE(tmpstr,ipd.effective_date); if (!NULLISODATE(ipd.effective_date)) printf("Effective date: %s\n",tmpstr); printf("Image size: %02d:%02d:%02d, %d blocks (%ld bytes)\n", LBA_MIN(ISONUM(ipd.volume_space_size)), LBA_SEC(ISONUM(ipd.volume_space_size)), LBA_FRM(ISONUM(ipd.volume_space_size)), ISONUM(ipd.volume_space_size), (long)ISONUM(ipd.volume_space_size)*BLOCKSIZE ); printf("Track size: %02d:%02d:%02d, %d blocks (%ld bytes)\n", LBA_MIN(tracksize), LBA_SEC(tracksize), LBA_FRM(tracksize), tracksize, (long)tracksize*BLOCKSIZE ); } } else { #ifdef IRIX /* if reading audio track */ imagesize=tracksize; imagesize_bytes=imagesize*CDDA_DATASIZE; buffersize = READBLOCKS*AUDIOBLOCKSIZE; readblocksize = AUDIOBLOCKSIZE; if (cdp) { CDaddcallback(cdp, cd_audio, (CDCALLBACKFUNC)playaudio, 0); } else die("No audioparser"); fclose(outfile); aiffsetup=AFnewfilesetup(); AFinitrate(aiffsetup,AF_DEFAULT_TRACK,44100.0); /* 44.1 kHz */ AFinitfilefmt(aiffsetup,file_format); /* set file format */ AFinitchannels(aiffsetup,AF_DEFAULT_TRACK,2); /* stereo */ AFinitsampfmt(aiffsetup,AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP,16); /* 16bit */ aiffoutfile=AFopenfile(argv[optind],"w",aiffsetup); if (!aiffoutfile) die("Cannot open target file (%s).",argv[optind]); #endif } /* read the image */ if (md5_mode) MD5Init(MD5); if (!info_only) { start_time=(int)time(NULL); fprintf(stderr,"Reading %s (%ldMb)...\n", audio_track?"audio track":"ISO9660 image", imagesize_bytes/(1024*1024)); do { len=buffersize; if(readsize/readblocksize+READBLOCKS>imagesize) { read_10(start+counter,imagesize-readsize/readblocksize,buffer,&len); } else read_10(start+counter,READBLOCKS,buffer,&len); if ((counter%(1024*1024/readblocksize))<READBLOCKS) { cur_time=(int)time(NULL); if ((cur_time-start_time)>0) { kbps=(readsize/1024)/(cur_time-start_time); } else { kbps=0; } fprintf(stderr,"%3dM of %dM read. (%d kb/s) \r", counter/512,imagesize/512,kbps); } counter+=READBLOCKS; readsize+=len; if (!audio_track) { fwrite(buffer,len,1,outfile); } else { #ifdef IRIX /* audio track */ for(i=0;i<(len/CDDA_BLOCKSIZE);i++) { CDparseframe(cdp,(CDFRAME*)&buffer[i*CDDA_BLOCKSIZE]); } #endif } if (md5_mode) MD5Update(MD5,buffer,(readsize>imagesize_bytes? len-(readsize-imagesize_bytes):len) ); } while (len==readblocksize*READBLOCKS&&readsize<imagesize*readblocksize); fprintf(stderr,"\n"); if (!audio_track) { if (readsize > imagesize_bytes) ftruncate(fileno(outfile),imagesize_bytes); if (readsize < imagesize_bytes) fprintf(stderr,"Image not complete!\n"); else fprintf(stderr,"Image complete.\n"); fclose(outfile); } else { #ifdef IRIX AFclosefile(aiffoutfile); #endif } } if (md5_mode && !info_only) { MD5Final((unsigned char*)digest,MD5); md2str((unsigned char*)digest,digest_text); fprintf(stderr,"MD5 (%s) = %s\n",(md5_mode==2?"'image'":argv[optind]), digest_text); } quit: start_stop(0); /* set_removable(1); */ /* close the scsi device */ scsi_close(); return 0; }
int main(int argc, char *argv[]) { int c, nostop=0; char *h; int i_rc = 0; cd_operation_t cd_op = NO_OP; /* operation to do in non-interactive mode */ psz_program = strrchr(argv[0],'/'); psz_program = psz_program ? psz_program+1 : argv[0]; memset(&cddb_opts, 0, sizeof(cddb_opts)); cdio_loglevel_default = CDIO_LOG_WARN; /* parse options */ while ( 1 ) { if (-1 == (c = getopt(argc, argv, "acCdehkplL:sSt:vx"))) break; switch (c) { case 'v': b_verbose = true; if (cdio_loglevel_default > CDIO_LOG_INFO) cdio_loglevel_default = CDIO_LOG_INFO; break; case 'd': debug = 1; if (cdio_loglevel_default > CDIO_LOG_DEBUG) cdio_loglevel_default = CDIO_LOG_DEBUG; break; case 'a': auto_mode = 1; break; case 'L': i_volume_level = atoi(optarg); cd_op = SET_VOLUME; b_interactive = false; break; case 't': if (NULL != (h = strchr(optarg,'-'))) { *h = 0; start_track = atoi(optarg); stop_track = atoi(h+1)+1; if (0 == start_track) start_track = 1; if (1 == stop_track) stop_track = CDIO_CDROM_LEADOUT_TRACK; } else { start_track = atoi(optarg); stop_track = start_track+1; one_track = 1; } b_interactive = false; cd_op = PLAY_TRACK; break; case 'p': b_interactive = false; cd_op = PLAY_CD; break; case 'l': b_interactive = false; cd_op = LIST_TRACKS; break; case 'C': b_interactive = false; cd_op = CLOSE_CD; break; case 'c': b_interactive = false; cd_op = PS_LIST_TRACKS; break; case 's': b_interactive = false; cd_op = STOP_PLAYING; break; case 'S': b_interactive = false; cd_op = LIST_SUBCHANNEL; break; case 'e': b_interactive = false; cd_op = EJECT_CD; break; case 'k': print_keys(); exit(1); case 'h': usage(psz_program); exit(1); default: usage(psz_program); exit(1); } } if (argc > optind) { psz_device = strdup(argv[optind]); } else { char **ppsz_cdda_drives=NULL; char **ppsz_all_cd_drives = cdio_get_devices_ret(&driver_id); if (!ppsz_all_cd_drives) { fprintf(stderr, "Can't find a CD-ROM drive\n"); exit(2); } ppsz_cdda_drives = cdio_get_devices_with_cap(ppsz_all_cd_drives, CDIO_FS_AUDIO, false); if (!ppsz_cdda_drives || !ppsz_cdda_drives[0]) { fprintf(stderr, "Can't find a CD-ROM drive with a CD-DA in it\n"); exit(3); } psz_device = strdup(ppsz_cdda_drives[0]); cdio_free_device_list(ppsz_all_cd_drives); cdio_free_device_list(ppsz_cdda_drives); } if (!b_interactive) { b_sig = true; nostop=1; } tty_raw(); signal(SIGINT,ctrlc); signal(SIGQUIT,ctrlc); signal(SIGTERM,ctrlc); signal(SIGHUP,ctrlc); signal(SIGWINCH, sigwinch); if (CLOSE_CD != cd_op) { /* open device */ if (b_verbose) fprintf(stderr, "open %s... ", psz_device); p_cdio = cdio_open (psz_device, driver_id); if (!p_cdio && cd_op != EJECT_CD) { cd_close(psz_device); p_cdio = cdio_open (psz_device, driver_id); } if (p_cdio && b_verbose) fprintf(stderr,"ok\n"); } if (b_interactive) { #ifdef HAVE_CDDB cddb_log_set_handler (cddb_log_handler); #else ; #endif } else { b_sig = true; nostop=1; if (EJECT_CD == cd_op) { i_rc = cd_eject() ? 0 : 1; } else { switch (cd_op) { case PS_LIST_TRACKS: case LIST_TRACKS: case PLAY_TRACK: read_toc(p_cdio); default: break; } if (p_cdio) switch (cd_op) { case STOP_PLAYING: b_cd = true; i_rc = cd_stop(p_cdio) ? 0 : 1; break; case EJECT_CD: /* Should have been handled above. */ cd_eject(); break; case LIST_TRACKS: list_tracks(); break; case PS_LIST_TRACKS: ps_list_tracks(); break; case PLAY_TRACK: /* play just this one track */ if (b_record) { printf("%s / %s\n", artist, title); if (one_track) printf("%s\n", cd_info[start_track].title); } i_rc = play_track(start_track, stop_track) ? 0 : 1; break; case PLAY_CD: if (b_record) printf("%s / %s\n", artist, title); play_track(1,CDIO_CDROM_LEADOUT_TRACK); break; case SET_VOLUME: i_rc = set_volume_level(p_cdio, i_volume_level); break; case LIST_SUBCHANNEL: if (read_subchannel(p_cdio)) { if (sub.audio_status == CDIO_MMC_READ_SUB_ST_PAUSED || sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY) { { printf("track %2d - %02x:%02x (%02x:%02x abs) ", sub.track, sub.rel_addr.m, sub.rel_addr.s, sub.abs_addr.m, sub.abs_addr.s); } } printf("drive state: %s\n", mmc_audio_state2str(sub.audio_status)); } else { i_rc = 1; } break; case CLOSE_CD: /* Handled below */ case LIST_KEYS: case TOGGLE_PAUSE: case EXIT_PROGRAM: case NO_OP: break; } else if (CLOSE_CD == cd_op) { i_rc = (DRIVER_OP_SUCCESS == cdio_close_tray(psz_device, NULL)) ? 0 : 1; } else { fprintf(stderr,"no CD in drive (%s)\n", psz_device); } } } /* Play all tracks *unless* we have a play or paused status already. */ read_subchannel(p_cdio); if (sub.audio_status != CDIO_MMC_READ_SUB_ST_PAUSED && sub.audio_status != CDIO_MMC_READ_SUB_ST_PLAY) play_track(1, CDIO_CDROM_LEADOUT_TRACK); while ( !b_sig ) { int key; if (!b_cd) read_toc(p_cdio); read_subchannel(p_cdio); display_status(false); if (1 == select_wait(b_cd ? 1 : 5)) { switch (key = getch()) { case '-': decrease_volume_level(p_cdio); break; case '+': increase_volume_level(p_cdio); break; case 'A': case 'a': auto_mode = !auto_mode; break; case 'X': case 'x': nostop=1; /* fall through */ case 'Q': case 'q': b_sig = true; break; case 'E': case 'e': cd_eject(); break; case 's': cd_stop(p_cdio); break; case 'C': case 'c': cd_close(psz_device); break; case 'L': case 'l': b_all_tracks = !b_all_tracks; if (b_all_tracks) display_tracks(); else { i_last_display_track = CDIO_INVALID_TRACK; display_cdinfo(p_cdio, i_tracks, i_first_track); } break; case 'K': case 'k': case 'h': case 'H': case '?': list_keys(); break; case ' ': case 'P': case 'p': toggle_pause(); break; case KEY_RIGHT: if (b_cd && (sub.audio_status == CDIO_MMC_READ_SUB_ST_PAUSED || sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY)) play_track(sub.track+1, CDIO_CDROM_LEADOUT_TRACK); else play_track(1,CDIO_CDROM_LEADOUT_TRACK); break; case KEY_LEFT: if (b_cd && (sub.audio_status == CDIO_MMC_READ_SUB_ST_PAUSED || sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY)) play_track(sub.track-1,CDIO_CDROM_LEADOUT_TRACK); break; case KEY_UP: if (b_cd && sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY) skip(10); break; case KEY_DOWN: if (b_cd && sub.audio_status == CDIO_MMC_READ_SUB_ST_PLAY) skip(-10); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': play_track(key - '0', CDIO_CDROM_LEADOUT_TRACK); break; case '0': play_track(10, CDIO_CDROM_LEADOUT_TRACK); break; case KEY_F(1): case KEY_F(2): case KEY_F(3): case KEY_F(4): case KEY_F(5): case KEY_F(6): case KEY_F(7): case KEY_F(8): case KEY_F(9): case KEY_F(10): case KEY_F(11): case KEY_F(12): case KEY_F(13): case KEY_F(14): case KEY_F(15): case KEY_F(16): case KEY_F(17): case KEY_F(18): case KEY_F(19): case KEY_F(20): play_track(key - KEY_F(1) + 11, CDIO_CDROM_LEADOUT_TRACK); break; } } } if (!nostop) cd_stop(p_cdio); tty_restore(); finish("bye", i_rc); return 0; /* keep compiler happy */ }
static void read_toc (PopplerIndexIter *index, GString **toc) { if (!index) { return; } if (!*toc) { *toc = g_string_new (""); } do { PopplerAction *action; PopplerIndexIter *iter; action = poppler_index_iter_get_action (index); if (!action) { continue; } switch (action->type) { case POPPLER_ACTION_GOTO_DEST: { PopplerActionGotoDest *ag = (PopplerActionGotoDest *)action; PopplerDest *agd = ag->dest; if (!tracker_is_empty_string (ag->title)) { g_string_append_printf (*toc, "%s ", ag->title); } if (!tracker_is_empty_string (agd->named_dest)) { g_string_append_printf (*toc, "%s ", agd->named_dest); } break; } case POPPLER_ACTION_LAUNCH: { PopplerActionLaunch *al = (PopplerActionLaunch *)action; if (!tracker_is_empty_string (al->title)) { g_string_append_printf (*toc, "%s ", al->title); } if (!tracker_is_empty_string (al->file_name)) { g_string_append_printf (*toc, "%s ", al->file_name); } if (!tracker_is_empty_string (al->params)) { g_string_append_printf (*toc, "%s ", al->params); } break; } case POPPLER_ACTION_URI: { PopplerActionUri *au = (PopplerActionUri *)action; if (!tracker_is_empty_string (au->uri)) { g_string_append_printf (*toc, "%s ", au->uri); } break; } case POPPLER_ACTION_NAMED: { PopplerActionNamed *an = (PopplerActionNamed *)action; if (!tracker_is_empty_string (an->title)) { g_string_append_printf (*toc, "%s, ", an->title); } if (!tracker_is_empty_string (an->named_dest)) { g_string_append_printf (*toc, "%s ", an->named_dest); } break; } case POPPLER_ACTION_MOVIE: { PopplerActionMovie *am = (PopplerActionMovie *)action; if (!tracker_is_empty_string (am->title)) { g_string_append_printf (*toc, "%s ", am->title); } break; } case POPPLER_ACTION_NONE: case POPPLER_ACTION_UNKNOWN: case POPPLER_ACTION_GOTO_REMOTE: case POPPLER_ACTION_RENDITION: case POPPLER_ACTION_OCG_STATE: case POPPLER_ACTION_JAVASCRIPT: /* Do nothing */ break; } poppler_action_free (action); iter = poppler_index_iter_get_child (index); read_toc (iter, toc); } while (poppler_index_iter_next (index)); poppler_index_iter_free (index); }