📄 access.c
字号:
/***************************************************************************** * cddax.c : CD digital audio input module for vlc using libcdio ***************************************************************************** * Copyright (C) 2000, 2003, 2004 VideoLAN * $Id: access.c,v 1.28 2004/02/23 00:10:50 rocky Exp $ * * 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 <stdio.h>#include <stdlib.h>#include <vlc/vlc.h>#include <vlc/intf.h>#include <sys/types.h>#include <cdio/cdio.h>#include <cdio/cd_types.h>#include "codecs.h"#include "vlc_keys.h"#ifdef HAVE_UNISTD_H# include <unistd.h>#endif#ifdef HAVE_ERRNO_H# include <errno.h>#endif#include <string.h>#include "cdda.h"/* how many blocks Open will read in each loop */#define CDDA_BLOCKS_ONCE 20#define CDDA_DATA_ONCE (CDDA_BLOCKS_ONCE * CDIO_CD_FRAMESIZE_RAW)#define CDDA_MRL_PREFIX "cddax://"/* FIXME: This variable is a hack. Would be nice to eliminate. */static input_thread_t *p_cdda_input = NULL;/***************************************************************************** * Local prototypes *****************************************************************************/static int CDDARead ( input_thread_t *, byte_t *, size_t );static void CDDASeek ( input_thread_t *, off_t );static int CDDASetArea ( input_thread_t *, input_area_t * );static int CDDASetProgram ( input_thread_t *, pgrm_descriptor_t * );static int CDDAFixupPlayList( input_thread_t *p_input, cdda_data_t *p_cdda, const char *psz_source, bool play_single_track);static void CDDAUpdateVar( input_thread_t *p_input, int i_entry, int i_action, const char *p_varname, char *p_label, const char *p_debug_label );/**************************************************************************** * Private functions ****************************************************************************//* process messages that originate from libcdio. */static voidcdio_log_handler (cdio_log_level_t level, const char message[]){ cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data; 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 vcdimager log level"), level); } return;}#ifdef HAVE_LIBCDDB/*! This routine is called by libcddb routines on error. Setup is done by init_input_plugin.*/static voidcddb_log_handler (cddb_log_level_t level, const char message[]){ cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data; 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 xine 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 = (cdda_data_t *)p_cdda_input->p_access_data; switch (level) { case CDIO_LOG_DEBUG: case CDIO_LOG_INFO: if (!(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); */}/***************************************************************************** * CDDAPlay: Arrange things so we play the specified track. * VLC_TRUE is returned if there was no error. *****************************************************************************/vlc_bool_tCDDAPlay( input_thread_t *p_input, int i_track ){ cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data; if( i_track > p_cdda->i_nb_tracks || i_track < 1 ) return VLC_FALSE; CDDASetArea( p_input, p_input->stream.pp_areas[i_track] ); return VLC_TRUE;}/***************************************************************************** * CDDARead: reads from the CDDA into PES packets. ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, otherwise the number of * bytes. *****************************************************************************/static int CDDARead( input_thread_t * p_input, byte_t * p_buffer, size_t i_len ){ cdda_data_t * p_cdda; int i_blocks; int i_index; int i_read; p_cdda = (cdda_data_t *)p_input->p_access_data; /* Compute the number of blocks we have to read */ i_blocks = i_len / CDIO_CD_FRAMESIZE_RAW; i_read = 0; if( !p_cdda->i_header_pos ) { p_cdda->i_header_pos = sizeof(WAVEHEADER); i_blocks = (i_len - sizeof(WAVEHEADER)) / CDIO_CD_FRAMESIZE_RAW; memcpy( p_buffer, &p_cdda->waveheader, sizeof(WAVEHEADER) ); p_buffer += sizeof(WAVEHEADER); i_read += sizeof(WAVEHEADER); } for( i_index = 0; i_index < i_blocks; i_index++ ) { if( cdio_read_audio_sector( p_cdda->p_cddev->cdio, p_buffer, p_cdda->i_sector) != 0 ) { msg_Err( p_input, "could not read sector %d", p_cdda->i_sector ); return -1; } p_cdda->i_sector ++; if( p_cdda->i_sector == p_cdda->p_sectors[p_cdda->i_track + 1] ) { input_area_t *p_area; dbg_print( (INPUT_DBG_LSN|INPUT_DBG_CALL), "end of track, cur: %u", p_cdda->i_sector ); /*???? if ( p_cdda->i_track >= p_cdda->i_nb_tracks - 1 )*/ return 0; /* EOF */ vlc_mutex_lock( &p_input->stream.stream_lock ); p_area = p_input->stream.pp_areas[ p_input->stream.p_selected_area->i_id + 1 ]; p_area->i_part = 1; CDDASetArea( p_input, p_area ); vlc_mutex_unlock( &p_input->stream.stream_lock ); } i_read += CDIO_CD_FRAMESIZE_RAW; p_buffer += CDIO_CD_FRAMESIZE_RAW; } if ( i_len % CDIO_CD_FRAMESIZE_RAW ) /* this should not happen */ { msg_Err( p_input, "must read full sectors" ); } return i_read;}/***************************************************************************** * CDDASetProgram: Does nothing since a CDDA is mono_program *****************************************************************************/static int CDDASetProgram( input_thread_t * p_input, pgrm_descriptor_t * p_program){ cdda_data_t * p_cdda= (cdda_data_t *) p_input->p_access_data; dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" ); return 0;}/***************************************************************************** * CDDASetArea: initialize input data for title x. * It should be called for each user navigation request. ****************************************************************************/static int CDDASetArea( input_thread_t * p_input, input_area_t * p_area ){ cdda_data_t *p_cdda = (cdda_data_t*) p_input->p_access_data; vlc_value_t val; vlc_value_t text; dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), ""); text.psz_string = _("Track"); var_Change( p_input, "title", VLC_VAR_SETTEXT, &text, NULL ); /* we can't use the interface slider until initilization is complete */ p_input->stream.b_seekable = 0; if( p_area != p_input->stream.p_selected_area ) { /* Change the default area */ p_input->stream.p_selected_area = p_area; /* Change the current track */ p_cdda->i_track = p_area->i_id - 1; p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track]; /* Update the navigation variables without triggering a callback */ val.i_int = p_area->i_id; var_Change( p_input, "title", VLC_VAR_SETVALUE, &val, NULL ); } p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track]; p_input->stream.p_selected_area->i_tell = (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW - p_input->stream.p_selected_area->i_start; /* warn interface that something has changed */ p_input->stream.b_seekable = 1; p_input->stream.b_changed = 1; return 0;}/**************************************************************************** * CDDASeek ****************************************************************************/static void CDDASeek( input_thread_t * p_input, off_t i_off ){ cdda_data_t * p_cdda; p_cdda = (cdda_data_t *) p_input->p_access_data; p_cdda->i_sector = p_cdda->p_sectors[p_cdda->i_track] + i_off / (off_t)CDIO_CD_FRAMESIZE_RAW; vlc_mutex_lock( &p_input->stream.stream_lock ); p_input->stream.p_selected_area->i_tell = (off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW - p_input->stream.p_selected_area->i_start; vlc_mutex_unlock( &p_input->stream.stream_lock ); dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK), "sector %ud, offset: %lld, i_tell: %lld", p_cdda->i_sector, i_off, p_input->stream.p_selected_area->i_tell );}/**************************************************************************** Update the "varname" variable to i_num without triggering a callback.****************************************************************************/static voidCDDAUpdateVar( input_thread_t *p_input, int i_num, int i_action, const char *p_varname, char *p_label, const char *p_debug_label){ vlc_value_t val; val.i_int = i_num; if (p_label) { vlc_value_t text; text.psz_string = p_label; var_Change( p_input, p_varname, VLC_VAR_SETTEXT, &text, NULL ); } var_Change( p_input, p_varname, i_action, &val, NULL );}#define meta_info_add_str(title, str) \ if ( str ) { \ dbg_print( INPUT_DBG_META, "field %s: %s\n", title, str); \ input_AddInfo( p_cat, _(title), "%s", str ); \ vlc_mutex_lock( &p_playlist->object_lock ); \ p_item = playlist_ItemGetByPos( p_playlist, -1 ); \ vlc_mutex_unlock( &p_playlist->object_lock ); \ vlc_mutex_lock( &p_item->lock ); \ playlist_ItemAddInfo( p_item, p_cat->psz_name, \ _(title), "%s" , str ); \ vlc_mutex_unlock( &p_item->lock ); \ }static void InformationCreate( input_thread_t *p_input ){ cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data; playlist_t *p_playlist = vlc_object_find( p_input, VLC_OBJECT_PLAYLIST, FIND_PARENT ); input_info_category_t *p_cat; playlist_item_t *p_item; p_cat = input_InfoCategory( p_input, "General" );#ifdef HAVE_LIBCDDB if (p_cdda->i_cddb_enabled) { meta_info_add_str( "Title", p_cdda->cddb.disc->title ); meta_info_add_str( "Artist", p_cdda->cddb.disc->artist );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -