📄 access.c
字号:
/***************************************************************************** * access.c : CD digital audio input module for vlc using libcdio ***************************************************************************** * Copyright (C) 2000, 2003, 2004, 2005 VideoLAN * $Id: access.c 10862 2005-05-01 14:48:08Z rocky $ * * Authors: Rocky Bernstein <rocky@panix.com> * Laurent Aimar <fenrir@via.ecp.fr> * Gildas Bazin <gbazin@netcourrier.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include "callback.h" /* FIXME - reorganize callback.h, cdda.h better */#include "cdda.h" /* private structures. Also #includes vlc things */#include "info.h" /* headers for meta info retrieval */#include <vlc_playlist.h> /* Has to come *after* cdda.h */#include "vlc_keys.h"#include <cdio/cdio.h>#include <cdio/logging.h>#include <cdio/cd_types.h>#include <stdio.h>/* #ifdef variables below are defined via config.h via #include vlc above. */#ifdef HAVE_STDLIB_H#include <stdlib.h>#endif#ifdef HAVE_SYS_TYPES_H#include <sys/types.h>#endif#ifdef HAVE_STRING_H#include <string.h>#endif#ifdef HAVE_UNISTD_H# include <unistd.h>#endif/* FIXME: This variable is a hack. Would be nice to eliminate. */access_t *p_cdda_input = NULL;/***************************************************************************** * Local prototypes *****************************************************************************/static int CDDARead( access_t *, uint8_t *, int );static block_t *CDDAReadBlocks( access_t * p_access );static int CDDASeek( access_t * p_access, int64_t i_pos );static int CDDAControl( access_t *p_access, int i_query, va_list args );static int CDDAInit( access_t *p_access, cdda_data_t *p_cdda ) ;/**************************************************************************** * Private functions ****************************************************************************//* process messages that originate from libcdio. called by CDDAOpen*/static voidcdio_log_handler (cdio_log_level_t level, const char message[]){ cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys; if( p_cdda == NULL ) return; switch (level) { case CDIO_LOG_DEBUG: case CDIO_LOG_INFO: if (p_cdda->i_debug & INPUT_DBG_CDIO) msg_Dbg( p_cdda_input, message); break; case CDIO_LOG_WARN: msg_Warn( p_cdda_input, message); break; case CDIO_LOG_ERROR: case CDIO_LOG_ASSERT: msg_Err( p_cdda_input, message); break; default: msg_Warn( p_cdda_input, message, "The above message had unknown cdio log level", level); } return;}#ifdef HAVE_LIBCDDB/*! This routine is called by libcddb routines on error. called by CDDAOpen*/static voidcddb_log_handler (cddb_log_level_t level, const char message[]){ cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys; switch (level) { case CDDB_LOG_DEBUG: case CDDB_LOG_INFO: if (!(p_cdda->i_debug & INPUT_DBG_CDDB)) return; /* Fall through if to warn case */ default: cdio_log_handler (level, message); }}#endif /*HAVE_LIBCDDB*//*! This routine is when vlc is not fully set up (before full initialization) or is not around (before finalization).*/static voiduninit_log_handler (cdio_log_level_t level, const char message[]){ cdda_data_t *p_cdda = NULL; if (p_cdda_input) p_cdda = (cdda_data_t *)p_cdda_input->p_sys; switch (level) { case CDIO_LOG_DEBUG: case CDIO_LOG_INFO: if (!p_cdda || !(p_cdda->i_debug & (INPUT_DBG_CDIO|INPUT_DBG_CDDB))) return; /* Fall through if to warn case */ case CDIO_LOG_WARN: fprintf(stderr, "WARN: %s\n", message); break; case CDIO_LOG_ERROR: fprintf(stderr, "ERROR: %s\n", message); break; case CDIO_LOG_ASSERT: fprintf(stderr, "ASSERT ERROR: %s\n", message); break; default: fprintf(stderr, "UNKNOWN ERROR: %s\n%s %d\n", message, "The above message had unknown cdio log level", level); } /* gl_default_cdio_log_handler (level, message); */}/* Only used in audio control mode. Gets the current LSN from the CD-ROM drive. */static int64_tget_audio_position ( access_t *p_access ) { cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys; lsn_t i_offset;#if LIBCDIO_VERSION_NUM >= 73 if (p_cdda->b_audio_ctl) { cdio_subchannel_t sub; CdIo_t *p_cdio = p_cdda->p_cdio; if (DRIVER_OP_SUCCESS == cdio_audio_read_subchannel(p_cdio, &sub)) { if (sub.audio_status != CDIO_MMC_READ_SUB_ST_PAUSED && sub.audio_status != CDIO_MMC_READ_SUB_ST_PLAY) return CDIO_INVALID_LSN; if ( ! p_cdda->b_nav_mode ) { // char *psz = cdio_msf_to_str(&sub.abs_addr); // fprintf(stderr, "+++disk mode abs msf %s", psz); // free(psz); i_offset = cdio_msf_to_lba((&sub.abs_addr)); // fprintf(stderr, " frame offset %d\n", i_offset); } else { // char *psz = cdio_msf_to_str(&sub.rel_addr); // fprintf(stderr, "+++track abs msf %s", psz); // free(psz); i_offset = cdio_msf_to_lba((&sub.rel_addr)); // fprintf(stderr, " frame offset %d\n", i_offset); } } else { // fprintf(stderr, "+++Error reading current pos\n"); i_offset = p_cdda->i_lsn; } } else i_offset = p_cdda->i_lsn;#else i_offset = p_cdda->i_lsn; ;#endif return i_offset;}/***************************************************************************** * CDDAReadBlocks: reads a group of blocks from the CD-DA and returns * an allocated pointer to the data. NULL is returned if no data * read. It is also possible if we haven't read a RIFF header in which * case one that we creaded during Open/Initialization is returned. *****************************************************************************/static block_t * CDDAReadBlocks( access_t * p_access ){ block_t *p_block; cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys; int i_blocks = p_cdda->i_blocks_per_read; dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_LSN), "called i_lsn: %d i_pos: %lld, size: %lld", p_cdda->i_lsn, p_access->info.i_pos, p_access->info.i_size); /* Check end of file */ if( p_access->info.b_eof ) return NULL; if( !p_cdda->b_header ) { /* Return only the dummy RIFF header we created in Open/Init */ p_block = block_New( p_access, sizeof( WAVEHEADER ) ); memcpy( p_block->p_buffer, &p_cdda->waveheader, sizeof(WAVEHEADER) ); p_cdda->b_header = VLC_TRUE; return p_block; } /* Check end of track */ while( p_cdda->i_lsn > cdio_get_track_last_lsn(p_cdda->p_cdio, p_cdda->i_track) ) { bool go_on; if( p_cdda->b_nav_mode ) go_on = p_cdda->i_lsn > p_cdda->last_disc_frame; else go_on = p_cdda->i_track >= p_cdda->i_first_track+p_cdda->i_titles-1 ; if( go_on ) { dbg_print( (INPUT_DBG_LSN), "EOF"); p_access->info.b_eof = VLC_TRUE; return NULL; } p_access->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_META; p_access->info.i_title++; p_cdda->i_track++; if ( p_cdda-> b_nav_mode ) { char *psz_title = CDDAFormatTitle( p_access, p_cdda->i_track ); input_Control( p_cdda->p_input, INPUT_SET_NAME, psz_title ); free(psz_title); } else { p_access->info.i_size = p_cdda->p_title[p_access->info.i_title]->i_size; p_access->info.i_pos = 0; p_access->info.i_update |= INPUT_UPDATE_SIZE; } } /* Possibly adjust i_blocks so we don't read past the end of a track. */ if( p_cdda->i_lsn + i_blocks >= cdio_get_track_lsn(p_cdda->p_cdio, p_cdda->i_track+1) ) { i_blocks = cdio_get_track_lsn( p_cdda->p_cdio, p_cdda->i_track+1 ) - p_cdda->i_lsn; } /* Do the actual reading */ p_block = block_New( p_access, i_blocks * CDIO_CD_FRAMESIZE_RAW ); if( !p_block) { msg_Err( p_access, "Cannot get a new block of size: %i", i_blocks * CDIO_CD_FRAMESIZE_RAW ); return NULL; } {#if LIBCDIO_VERSION_NUM >= 72 driver_return_code_t rc = DRIVER_OP_SUCCESS; if ( p_cdda->e_paranoia && p_cdda->paranoia ) { int i; for( i = 0; i < i_blocks; i++ ) { int16_t *p_readbuf = cdio_paranoia_read(p_cdda->paranoia, NULL); char *psz_err=cdio_cddap_errors(p_cdda->paranoia_cd); char *psz_mes=cdio_cddap_messages(p_cdda->paranoia_cd); if (psz_mes || psz_err) msg_Err( p_access, "%s%s\n", psz_mes ? psz_mes: "", psz_err ? psz_err: "" ); if (psz_err) free(psz_err); if (psz_mes) free(psz_mes); if( !p_readbuf ) { msg_Err( p_access, "paranoia read error on frame %i\n", p_cdda->i_lsn+i ); } else memcpy(p_block->p_buffer + i * CDIO_CD_FRAMESIZE_RAW, p_readbuf, CDIO_CD_FRAMESIZE_RAW); } } else rc = cdio_read_audio_sectors( p_cdda->p_cdio, p_block->p_buffer, p_cdda->i_lsn, i_blocks);#else#define DRIVER_OP_SUCCESS 0 int rc; rc = cdio_read_audio_sectors( p_cdda->p_cdio, p_block->p_buffer, p_cdda->i_lsn, i_blocks);#endif if( rc != DRIVER_OP_SUCCESS ) { msg_Err( p_access, "could not read %d sectors starting from %lu", i_blocks, (long unsigned int) p_cdda->i_lsn ); block_Release( p_block ); /* If we had problems above, assume the problem is with the first sector of the read and set to skip it. In the future libcdio may have cdparanoia support. */ p_cdda->i_lsn++; p_access->info.i_pos += CDIO_CD_FRAMESIZE_RAW; return NULL; } } p_cdda->i_lsn += i_blocks; p_access->info.i_pos += i_blocks * CDIO_CD_FRAMESIZE_RAW; return p_block;}/***************************************************************************** * CDDARead: Handler for audio control reads the CD-DA. *****************************************************************************/static intCDDARead( access_t * p_access, uint8_t *p_buffer, int i_len ){ cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys; dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_LSN), "called lsn: %d pos: %lld, size: %lld", p_cdda->i_lsn, p_access->info.i_pos, p_access->info.i_size); /* Check end of file */ if( p_access->info.b_eof ) return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -