From: Rocky Bernstein Date: Wed, 26 Nov 2003 03:35:26 +0000 (+0000) Subject: Split out cdda to facilitate later changes. X-Git-Tag: 0.7.0~343 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=c2323552a23efcebbd28a1432279a1263b88b522;hp=11337d43d80d34bfe7544ac8de4deb1a3f9025eb;p=vlc Split out cdda to facilitate later changes. --- diff --git a/modules/access/cdda/.cvsignore b/modules/access/cdda/.cvsignore new file mode 100644 index 0000000000..aeeac7e2c4 --- /dev/null +++ b/modules/access/cdda/.cvsignore @@ -0,0 +1,4 @@ +Makefile +Makefile.am +Makefile.in +.deps diff --git a/modules/access/cdda/Modules.am b/modules/access/cdda/Modules.am index a00cec1fe7..bf6e8d9b98 100644 --- a/modules/access/cdda/Modules.am +++ b/modules/access/cdda/Modules.am @@ -1,3 +1,8 @@ SOURCES_cddax = \ + ../vcdx/cdrom.c \ + ../vcdx/cdrom.h \ cdda.c \ + cdda.h \ + access.c \ + intf.c \ $(NULL) diff --git a/modules/access/cdda/access.c b/modules/access/cdda/access.c new file mode 100644 index 0000000000..91bf6d0f62 --- /dev/null +++ b/modules/access/cdda/access.c @@ -0,0 +1,571 @@ +/***************************************************************************** + * cddax.c : CD digital audio input module for vlc using libcdio + ***************************************************************************** + * Copyright (C) 2000,2003 VideoLAN + * $Id: access.c,v 1.1 2003/11/26 03:35:26 rocky Exp $ + * + * Authors: Rocky Bernstein + * Laurent Aimar + * Gildas Bazin + * + * 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 +#include + +#include +#include +#include +#include +#include +#include + +#include "codecs.h" +#include "vlc_keys.h" + +#ifdef HAVE_UNISTD_H +# include +#endif + +#include + +#include "cdda.h" + +/* how many blocks Open will read in each loop */ +#define CDDA_BLOCKS_ONCE 1 +#define CDDA_DATA_ONCE (CDDA_BLOCKS_ONCE * CDIO_CD_FRAMESIZE_RAW) + +#define DEBUG_TEXT N_("set debug mask for additional debugging.") +#define DEBUG_LONGTEXT N_( \ + "This integer when viewed in binary is a debugging mask\n" \ + "MRL 1\n" \ + "events 2\n" \ + "external call 4\n" \ + "all calls 8\n" \ + "LSN (10) 16\n" \ + "libcdio (20) 32\n" \ + "seeks (40) 64\n" ) + +#define DEV_TEXT N_("CD-ROM device name") +#define DEV_LONGTEXT N_( \ + "Specify the name of the CD-ROM device that will be used by default. " \ + "If you don't specify anything, we'll scan for a suitable CD-ROM device.") + +/***************************************************************************** + * intf_sys_t: description and status of interface + *****************************************************************************/ +struct intf_sys_t +{ + input_thread_t * p_input; + cdda_data_t * p_cdda; + vlc_bool_t b_click, b_move, b_key_pressed; +}; + +/* 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 * ); + +/**************************************************************************** + * Private functions + ****************************************************************************/ + +int +E_(DebugCallback) ( vlc_object_t *p_this, const char *psz_name, + vlc_value_t oldval, vlc_value_t val, void *p_data ) +{ + cdda_data_t *p_cdda; + + if (NULL == p_cdda_input) return VLC_EGENERIC; + + p_cdda = (cdda_data_t *)p_cdda_input->p_access_data; + + if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) { + msg_Dbg( p_cdda_input, "Old debug (x%0x) %d, new debug (x%0x) %d", + p_cdda->i_debug, p_cdda->i_debug, val.i_int, val.i_int); + } + p_cdda->i_debug = val.i_int; + return VLC_SUCCESS; +} + +/* process messages that originate from libcdio. */ +static void +cdio_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; +} + + +/***************************************************************************** + * Open: open cdda + *****************************************************************************/ +int +E_(Open)( vlc_object_t *p_this ) +{ + input_thread_t * p_input = (input_thread_t *)p_this; + char * psz_orig; + char * psz_parser; + char * psz_source; + cdda_data_t * p_cdda; + int i; + int i_title = 1; + cddev_t *p_cddev; + + /* Set where to log errors messages from libcdio. */ + p_cdda_input = (input_thread_t *)p_this; + + /* parse the options passed in command line : */ + psz_orig = psz_parser = psz_source = strdup( p_input->psz_name ); + + if( !psz_orig ) + { + return( -1 ); + } + + while( *psz_parser && *psz_parser != '@' ) + { + psz_parser++; + } + + if( *psz_parser == '@' ) + { + /* Found options */ + *psz_parser = '\0'; + ++psz_parser; + + if ('T' == *psz_parser || 't' == *psz_parser ) + ++psz_parser; + + i_title = (int)strtol( psz_parser, NULL, 10 ); + i_title = i_title ? i_title : 1; + } + + if( !*psz_source ) { + /* No source specified, so figure it out. */ + if( !p_input->psz_access ) { + free( psz_orig ); + return -1; + } + psz_source = config_GetPsz( p_input, MODULE_STRING "-device" ); + + if( !psz_source || 0==strlen(psz_source) ) { + /* Scan for a CD-ROM drive with a CD-DA in it. */ + char **cd_drives = + cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false); + if (NULL == cd_drives) return -1; + if (cd_drives[0] == NULL) { + cdio_free_device_list(cd_drives); + return -1; + } + psz_source = strdup(cd_drives[0]); + cdio_free_device_list(cd_drives); + } + } + + /* Open CDDA */ + cdio_log_set_handler ( cdio_log_handler ); + + if( !(p_cddev = ioctl_Open( p_this, psz_source )) ) + { + msg_Warn( p_input, "could not open %s", psz_source ); + free( psz_source ); + return -1; + } + free( psz_source ); + + p_cdda = malloc( sizeof(cdda_data_t) ); + if( p_cdda == NULL ) + { + msg_Err( p_input, "out of memory" ); + free( psz_source ); + return -1; + } + + p_cdda->p_cddev = p_cddev; + p_cdda->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" ); + p_input->p_access_data = (void *)p_cdda; + + dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source ); + + p_input->i_mtu = CDDA_DATA_ONCE; + + /* We read the Table Of Content information */ + p_cdda->i_nb_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input), + p_cdda->p_cddev->cdio, &p_cdda->p_sectors ); + if( p_cdda->i_nb_tracks < 0 ) + msg_Err( p_input, "unable to count tracks" ); + else if( p_cdda->i_nb_tracks <= 0 ) + msg_Err( p_input, "no audio tracks found" ); + + if( p_cdda->i_nb_tracks <= 1) + { + ioctl_Close( p_cdda->p_cddev ); + free( p_cdda ); + return -1; + } + + if( i_title >= p_cdda->i_nb_tracks || i_title < 1 ) + i_title = 1; + + /* Set stream and area data */ + vlc_mutex_lock( &p_input->stream.stream_lock ); + + /* Initialize ES structures */ + input_InitStream( p_input, 0 ); + + /* cdda input method */ + p_input->stream.i_method = INPUT_METHOD_CDDA; + + p_input->stream.b_pace_control = 1; + p_input->stream.b_seekable = 1; + p_input->stream.i_mux_rate = 44100 * 4 / 50; + +#define area p_input->stream.pp_areas + for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ ) + { + input_AddArea( p_input, i, 1 ); + + /* Absolute start offset and size */ + area[i]->i_start = + (off_t)p_cdda->p_sectors[i-1] * (off_t)CDIO_CD_FRAMESIZE_RAW; + area[i]->i_size = + (off_t)(p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1]) + * (off_t)CDIO_CD_FRAMESIZE_RAW; + } +#undef area + + CDDAPlay( p_input, i_title); + + vlc_mutex_unlock( &p_input->stream.stream_lock ); + + if( !p_input->psz_demux || !*p_input->psz_demux ) + { + p_input->psz_demux = "cdda"; + } + + p_input->pf_read = CDDARead; + p_input->pf_seek = CDDASeek; + p_input->pf_set_area = CDDASetArea; + p_input->pf_set_program = CDDASetProgram; + + /* Update default_pts to a suitable value for cdda access */ + p_input->i_pts_delay = config_GetInt( p_input, + MODULE_STRING "-caching" ) * 1000; + + p_cdda->p_intf = intf_Create( p_input, "cddax" ); + intf_RunThread( p_cdda->p_intf ); + + return 0; +} + +/***************************************************************************** + * CDDAPlay: Arrange things so we play the specified track. + * VLC_TRUE is returned if there was no error. + *****************************************************************************/ +vlc_bool_t +CDDAPlay( 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; +} + +/***************************************************************************** + * CDDAClose: closes cdda + *****************************************************************************/ +void +E_(Close)( vlc_object_t *p_this ) +{ + input_thread_t * p_input = (input_thread_t *)p_this; + cdda_data_t *p_cdda = (cdda_data_t *)p_input->p_access_data; + + dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" ); + ioctl_Close( p_cdda->p_cddev ); + free( p_cdda ); + p_cdda_input = NULL; +} + +/***************************************************************************** + * 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; + + i_read = 0; + + /* Compute the number of blocks we have to read */ + + i_blocks = i_len / CDIO_CD_FRAMESIZE_RAW; + + 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; + } + + 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; + + dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), ""); + + /* 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 ); + +} + +/***************************************************************************** + * Demux: local prototypes + *****************************************************************************/ +struct demux_sys_t +{ + es_out_id_t *p_es; + mtime_t i_pts; +}; + +static int Demux ( input_thread_t * p_input ); + +/**************************************************************************** + * DemuxOpen: + ****************************************************************************/ +int +E_(DemuxOpen) ( vlc_object_t * p_this) +{ + input_thread_t *p_input = (input_thread_t *)p_this; + demux_sys_t *p_sys; + + es_format_t fmt; + + if( p_input->stream.i_method != INPUT_METHOD_CDDA ) + { + return VLC_EGENERIC; + } + + p_input->pf_demux = Demux; + p_input->pf_rewind = NULL; + p_input->pf_demux_control = demux_vaControlDefault; + p_input->p_demux_data = p_sys = malloc( sizeof( es_descriptor_t ) ); + p_sys->i_pts = 0; + + vlc_mutex_lock( &p_input->stream.stream_lock ); + if( input_InitStream( p_input, 0 ) == -1) + { + vlc_mutex_unlock( &p_input->stream.stream_lock ); + msg_Err( p_input, "cannot init stream" ); + free( p_sys ); + return VLC_EGENERIC; + } + p_input->stream.i_mux_rate = 4 * 44100 / 50; + vlc_mutex_unlock( &p_input->stream.stream_lock ); + + es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'a', 'r', 'a', 'w' ) ); + fmt.audio.i_channels = 2; + fmt.audio.i_rate = 44100; + fmt.audio.i_bitspersample = 16; + fmt.audio.i_blockalign = 4; + fmt.i_bitrate = 4 * 44100 * 8; + + p_sys->p_es = es_out_Add( p_input->p_es_out, &fmt ); + + return VLC_SUCCESS; +} + +/**************************************************************************** + * DemuxClose: + ****************************************************************************/ +void +E_(DemuxClose)( vlc_object_t * p_this) +{ + input_thread_t *p_input = (input_thread_t*)p_this; + demux_sys_t *p_sys = (demux_sys_t*)p_input->p_demux_data; + + free( p_sys ); + return; +} + +/**************************************************************************** + * Demux: + ****************************************************************************/ +static int Demux( input_thread_t * p_input ) +{ + demux_sys_t *p_sys = (demux_sys_t*)p_input->p_demux_data; + block_t *p_block; + + + input_ClockManageRef( p_input, + p_input->stream.p_selected_program, + p_sys->i_pts ); + + if( ( p_block = stream_Block( p_input->s, CDIO_CD_FRAMESIZE_RAW ) ) == NULL ) + { + /* eof */ + return 0; + } + p_block->i_dts = + p_block->i_pts = input_ClockGetTS( p_input, + p_input->stream.p_selected_program, + p_sys->i_pts ); + p_block->i_length = (mtime_t)90000 * (mtime_t)p_block->i_buffer/44100/4; + + p_sys->i_pts += p_block->i_length; + + es_out_Send( p_input->p_es_out, p_sys->p_es, p_block ); + + return 1; +} + diff --git a/modules/access/cdda/cdda.c b/modules/access/cdda/cdda.c index ca7f4aebdb..c475398823 100644 --- a/modules/access/cdda/cdda.c +++ b/modules/access/cdda/cdda.c @@ -2,7 +2,7 @@ * cddax.c : CD digital audio input module for vlc using libcdio ***************************************************************************** * Copyright (C) 2000,2003 VideoLAN - * $Id: cdda.c,v 1.1 2003/11/26 01:32:52 rocky Exp $ + * $Id: cdda.c,v 1.2 2003/11/26 03:35:26 rocky Exp $ * * Authors: Laurent Aimar * Gildas Bazin @@ -26,57 +26,32 @@ /***************************************************************************** * Preamble *****************************************************************************/ -#include -#include #include -#include -#include -#include -#include -#include -#include "codecs.h" -#include "vlc_keys.h" -#ifdef HAVE_UNISTD_H -# include -#endif - -#include +/***************************************************************************** + * prototypes + *****************************************************************************/ +int E_(Open) ( vlc_object_t * ); +void E_(Close) ( vlc_object_t * ); -#include "../vcdx/cdrom.h" +int E_(OpenIntf) ( vlc_object_t * ); +void E_(CloseIntf) ( vlc_object_t * ); +int E_(DemuxOpen) ( vlc_object_t * p_this); +void E_(DemuxClose) ( vlc_object_t * p_this); -/* how many blocks E_(Open) will read in each loop */ -#define CDDA_BLOCKS_ONCE 1 -#define CDDA_DATA_ONCE (CDDA_BLOCKS_ONCE * CDIO_CD_FRAMESIZE_RAW) +int E_(DebugCallback) ( vlc_object_t *p_this, const char *psz_name, + vlc_value_t oldval, vlc_value_t val, + void *p_data ); /***************************************************************************** - * cdda_data_t: CD audio information + * Module descriptor *****************************************************************************/ -typedef struct cdda_data_s -{ - cddev_t *p_cddev; /* CD device descriptor */ - int i_nb_tracks; /* Nb of tracks (titles) */ - int i_track; /* Current track */ - lsn_t i_sector; /* Current Sector */ - lsn_t * p_sectors; /* Track sectors */ - vlc_bool_t b_end_of_track; /* If the end of track was reached */ - int i_debug; /* Debugging mask */ - intf_thread_t *p_intf; - -} cdda_data_t; /***************************************************************************** - * Debugging + * Option help text *****************************************************************************/ -#define INPUT_DBG_MRL 1 -#define INPUT_DBG_EVENT 2 /* Trace keyboard events */ -#define INPUT_DBG_EXT 4 /* Calls from external routines */ -#define INPUT_DBG_CALL 8 /* all calls */ -#define INPUT_DBG_LSN 16 /* LSN changes */ -#define INPUT_DBG_CDIO 32 /* Debugging from CDIO */ -#define INPUT_DBG_SEEK 64 /* Seeks to set location */ #define DEBUG_TEXT N_("set debug mask for additional debugging.") #define DEBUG_LONGTEXT N_( \ @@ -94,84 +69,40 @@ typedef struct cdda_data_s "Specify the name of the CD-ROM device that will be used by default. " \ "If you don't specify anything, we'll scan for a suitable CD-ROM device.") -#define INPUT_DEBUG 1 -#if INPUT_DEBUG -#define dbg_print(mask, s, args...) \ - if (p_cdda->i_debug & mask) \ - msg_Dbg(p_input, "%s: "s, __func__ , ##args) -#else -#define dbg_print(mask, s, args...) -#endif - -/***************************************************************************** - * intf_sys_t: description and status of interface - *****************************************************************************/ -struct intf_sys_t -{ - input_thread_t * p_input; - cdda_data_t * p_cdda; - vlc_bool_t b_click, b_move, b_key_pressed; -}; - -/* FIXME: This variable is a hack. Would be nice to eliminate. */ -static input_thread_t *p_cdda_input = NULL; - -/***************************************************************************** - * Local prototypes - *****************************************************************************/ -static int E_(Open) ( vlc_object_t * ); -static void E_(Close) ( vlc_object_t * ); -static int E_(OpenIntf) ( vlc_object_t * ); -static void E_(CloseIntf) ( vlc_object_t * ); - -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 CDDAPlay ( input_thread_t *, int ); -static int CDDASetProgram ( input_thread_t *, pgrm_descriptor_t * ); - -static int InitThread ( intf_thread_t *p_intf ); -static int KeyEvent ( vlc_object_t *, char const *, - vlc_value_t, vlc_value_t, void * ); - -static void RunIntf ( intf_thread_t *p_intf ); - -static int E_(DebugCallback) ( vlc_object_t *p_this, const char *psz_name, - vlc_value_t oldval, vlc_value_t val, - void *p_data ); +#define CACHING_TEXT N_("Caching value in ms") +#define CACHING_LONGTEXT N_( \ + "Allows you to modify the default caching value for cdda streams. This " \ + "value should be set in millisecond units." ) /***************************************************************************** * Module descriptor *****************************************************************************/ -static int DemuxOpen ( vlc_object_t * ); -static void DemuxClose ( vlc_object_t * ); - -#define CACHING_TEXT N_("Caching value in ms") -#define CACHING_LONGTEXT N_( \ - "Allows you to modify the default caching value for cdda streams. This " \ - "value should be set in miliseconds units." ) - vlc_module_begin(); add_usage_hint( N_("cddax://[device-or-file][@num]") ); set_description( _("Compact Disc Digital Audio (CD-DA) input") ); set_capability( "access", 75 /* slightly higher than cdda */ ); - add_integer( "cddax-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE ); set_callbacks( E_(Open), E_(Close) ); add_shortcut( "cdda" ); add_shortcut( "cddax" ); /* Configuration options */ add_category_hint( N_("CDX"), NULL, VLC_TRUE ); + add_integer ( MODULE_STRING "-debug", 0, E_(DebugCallback), DEBUG_TEXT, DEBUG_LONGTEXT, VLC_TRUE ); + + add_integer( MODULE_STRING "-caching", + DEFAULT_PTS_DELAY / 1000, NULL, + CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE ); + add_string( MODULE_STRING "-device", "", NULL, DEV_TEXT, DEV_LONGTEXT, VLC_TRUE ); add_submodule(); set_description( _("CD Audio demux") ); set_capability( "demux", 0 ); - set_callbacks( DemuxOpen, DemuxClose ); + set_callbacks( E_(DemuxOpen), E_(DemuxClose) ); add_shortcut( "cdda" ); add_submodule(); @@ -179,731 +110,3 @@ vlc_module_begin(); set_callbacks( E_(OpenIntf), E_(CloseIntf) ); vlc_module_end(); - -/**************************************************************************** - * Private functions - ****************************************************************************/ - -static int -E_(DebugCallback) ( vlc_object_t *p_this, const char *psz_name, - vlc_value_t oldval, vlc_value_t val, void *p_data ) -{ - cdda_data_t *p_cdda; - - if (NULL == p_cdda_input) return VLC_EGENERIC; - - p_cdda = (cdda_data_t *)p_cdda_input->p_access_data; - - if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) { - msg_Dbg( p_cdda_input, "Old debug (x%0x) %d, new debug (x%0x) %d", - p_cdda->i_debug, p_cdda->i_debug, val.i_int, val.i_int); - } - p_cdda->i_debug = val.i_int; - return VLC_SUCCESS; -} - -/* process messages that originate from libcdio. */ -static void -cdio_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; -} - - -/***************************************************************************** - * E_(Open): open cdda - *****************************************************************************/ -static int E_(Open)( vlc_object_t *p_this ) -{ - input_thread_t * p_input = (input_thread_t *)p_this; - char * psz_orig; - char * psz_parser; - char * psz_source; - cdda_data_t * p_cdda; - int i; - int i_title = 1; - cddev_t *p_cddev; - - /* Set where to log errors messages from libcdio. */ - p_cdda_input = (input_thread_t *)p_this; - - /* parse the options passed in command line : */ - psz_orig = psz_parser = psz_source = strdup( p_input->psz_name ); - - if( !psz_orig ) - { - return( -1 ); - } - - while( *psz_parser && *psz_parser != '@' ) - { - psz_parser++; - } - - if( *psz_parser == '@' ) - { - /* Found options */ - *psz_parser = '\0'; - ++psz_parser; - - if ('T' == *psz_parser || 't' == *psz_parser ) - ++psz_parser; - - i_title = (int)strtol( psz_parser, NULL, 10 ); - i_title = i_title ? i_title : 1; - } - - if( !*psz_source ) { - /* No source specified, so figure it out. */ - if( !p_input->psz_access ) { - free( psz_orig ); - return -1; - } - psz_source = config_GetPsz( p_input, MODULE_STRING "-device" ); - - if( !psz_source || 0==strlen(psz_source) ) { - /* Scan for a CD-ROM drive with a CD-DA in it. */ - char **cd_drives = - cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false); - if (NULL == cd_drives) return -1; - if (cd_drives[0] == NULL) { - cdio_free_device_list(cd_drives); - return -1; - } - psz_source = strdup(cd_drives[0]); - cdio_free_device_list(cd_drives); - } - } - - /* Open CDDA */ - cdio_log_set_handler ( cdio_log_handler ); - - if( !(p_cddev = ioctl_Open( p_this, psz_source )) ) - { - msg_Warn( p_input, "could not open %s", psz_source ); - free( psz_source ); - return -1; - } - free( psz_source ); - - p_cdda = malloc( sizeof(cdda_data_t) ); - if( p_cdda == NULL ) - { - msg_Err( p_input, "out of memory" ); - free( psz_source ); - return -1; - } - - p_cdda->p_cddev = p_cddev; - p_cdda->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" ); - p_input->p_access_data = (void *)p_cdda; - - dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source ); - - p_input->i_mtu = CDDA_DATA_ONCE; - - /* We read the Table Of Content information */ - p_cdda->i_nb_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input), - p_cdda->p_cddev->cdio, &p_cdda->p_sectors ); - if( p_cdda->i_nb_tracks < 0 ) - msg_Err( p_input, "unable to count tracks" ); - else if( p_cdda->i_nb_tracks <= 0 ) - msg_Err( p_input, "no audio tracks found" ); - - if( p_cdda->i_nb_tracks <= 1) - { - ioctl_Close( p_cdda->p_cddev ); - free( p_cdda ); - return -1; - } - - if( i_title >= p_cdda->i_nb_tracks || i_title < 1 ) - i_title = 1; - - /* Set stream and area data */ - vlc_mutex_lock( &p_input->stream.stream_lock ); - - /* Initialize ES structures */ - input_InitStream( p_input, 0 ); - - /* cdda input method */ - p_input->stream.i_method = INPUT_METHOD_CDDA; - - p_input->stream.b_pace_control = 1; - p_input->stream.b_seekable = 1; - p_input->stream.i_mux_rate = 44100 * 4 / 50; - -#define area p_input->stream.pp_areas - for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ ) - { - input_AddArea( p_input, i, 1 ); - - /* Absolute start offset and size */ - area[i]->i_start = - (off_t)p_cdda->p_sectors[i-1] * (off_t)CDIO_CD_FRAMESIZE_RAW; - area[i]->i_size = - (off_t)(p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1]) - * (off_t)CDIO_CD_FRAMESIZE_RAW; - } -#undef area - - CDDAPlay( p_input, i_title); - - vlc_mutex_unlock( &p_input->stream.stream_lock ); - - if( !p_input->psz_demux || !*p_input->psz_demux ) - { - p_input->psz_demux = "cdda"; - } - - p_input->pf_read = CDDARead; - p_input->pf_seek = CDDASeek; - p_input->pf_set_area = CDDASetArea; - p_input->pf_set_program = CDDASetProgram; - - /* Update default_pts to a suitable value for cdda access */ - p_input->i_pts_delay = config_GetInt( p_input, - MODULE_STRING "-caching" ) * 1000; - - p_cdda->p_intf = intf_Create( p_input, "cddax" ); - intf_RunThread( p_cdda->p_intf ); - - return 0; -} - -/***************************************************************************** - * CDDAPlay: Arrange things play track - *****************************************************************************/ -static vlc_bool_t -CDDAPlay( 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; -} - -/***************************************************************************** - * E_(Close): closes cdda - *****************************************************************************/ -static void -E_(Close)( vlc_object_t *p_this ) -{ - input_thread_t * p_input = (input_thread_t *)p_this; - cdda_data_t *p_cdda = (cdda_data_t *)p_input->p_access_data; - - dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" ); - ioctl_Close( p_cdda->p_cddev ); - free( p_cdda ); - p_cdda_input = NULL; -} - -/***************************************************************************** - * 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; - - i_read = 0; - - /* Compute the number of blocks we have to read */ - - i_blocks = i_len / CDIO_CD_FRAMESIZE_RAW; - - 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; - } - - 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; - - dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), ""); - - /* 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 ); - -} - -/***************************************************************************** - * Demux: local prototypes - *****************************************************************************/ -struct demux_sys_t -{ - es_out_id_t *p_es; - mtime_t i_pts; -}; - -static int Demux ( input_thread_t * p_input ); - -/**************************************************************************** - * DemuxOpen: - ****************************************************************************/ -static int DemuxOpen ( vlc_object_t * p_this) -{ - input_thread_t *p_input = (input_thread_t *)p_this; - demux_sys_t *p_sys; - - es_format_t fmt; - - if( p_input->stream.i_method != INPUT_METHOD_CDDA ) - { - return VLC_EGENERIC; - } - - p_input->pf_demux = Demux; - p_input->pf_rewind = NULL; - p_input->pf_demux_control = demux_vaControlDefault; - p_input->p_demux_data = p_sys = malloc( sizeof( es_descriptor_t ) ); - p_sys->i_pts = 0; - - vlc_mutex_lock( &p_input->stream.stream_lock ); - if( input_InitStream( p_input, 0 ) == -1) - { - vlc_mutex_unlock( &p_input->stream.stream_lock ); - msg_Err( p_input, "cannot init stream" ); - free( p_sys ); - return VLC_EGENERIC; - } - p_input->stream.i_mux_rate = 4 * 44100 / 50; - vlc_mutex_unlock( &p_input->stream.stream_lock ); - - es_format_Init( &fmt, AUDIO_ES, VLC_FOURCC( 'a', 'r', 'a', 'w' ) ); - fmt.audio.i_channels = 2; - fmt.audio.i_rate = 44100; - fmt.audio.i_bitspersample = 16; - fmt.audio.i_blockalign = 4; - fmt.i_bitrate = 4 * 44100 * 8; - - p_sys->p_es = es_out_Add( p_input->p_es_out, &fmt ); - - return VLC_SUCCESS; -} - -/**************************************************************************** - * DemuxClose: - ****************************************************************************/ -static void DemuxClose( vlc_object_t * p_this) -{ - input_thread_t *p_input = (input_thread_t*)p_this; - demux_sys_t *p_sys = (demux_sys_t*)p_input->p_demux_data; - - free( p_sys ); - return; -} - -/**************************************************************************** - * Demux: - ****************************************************************************/ -static int Demux( input_thread_t * p_input ) -{ - demux_sys_t *p_sys = (demux_sys_t*)p_input->p_demux_data; - block_t *p_block; - - - input_ClockManageRef( p_input, - p_input->stream.p_selected_program, - p_sys->i_pts ); - - if( ( p_block = stream_Block( p_input->s, CDIO_CD_FRAMESIZE_RAW ) ) == NULL ) - { - /* eof */ - return 0; - } - p_block->i_dts = - p_block->i_pts = input_ClockGetTS( p_input, - p_input->stream.p_selected_program, - p_sys->i_pts ); - p_block->i_length = (mtime_t)90000 * (mtime_t)p_block->i_buffer/44100/4; - - p_sys->i_pts += p_block->i_length; - - es_out_Send( p_input->p_es_out, p_sys->p_es, p_block ); - - return 1; -} - -/***************************************************************************** - * OpenIntf: initialize dummy interface - *****************************************************************************/ -int E_(OpenIntf) ( vlc_object_t *p_this ) -{ - intf_thread_t *p_intf = (intf_thread_t *)p_this; - - /* Allocate instance and initialize some members */ - p_intf->p_sys = malloc( sizeof( intf_sys_t ) ); - if( p_intf->p_sys == NULL ) - { - return( 1 ); - }; - - p_intf->pf_run = RunIntf; - - var_AddCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf ); - - return( 0 ); -} - -/***************************************************************************** - * CloseIntf: destroy dummy interface - *****************************************************************************/ -void E_(CloseIntf) ( vlc_object_t *p_this ) -{ - intf_thread_t *p_intf = (intf_thread_t *)p_this; - - /* Destroy structure */ - free( p_intf->p_sys ); -} - - -/***************************************************************************** - * RunIntf: main loop - *****************************************************************************/ -static void RunIntf( intf_thread_t *p_intf ) -{ - vlc_object_t * p_vout = NULL; - cdda_data_t * p_cdda; - input_thread_t * p_input; - - /* What you add to the last input number entry. It accumulates all of - the 10_ADD keypresses */ - int number_addend = 0; - - if( InitThread( p_intf ) < 0 ) - { - msg_Err( p_intf, "can't initialize intf" ); - return; - } - - p_input = p_intf->p_sys->p_input; - p_cdda = p_intf->p_sys->p_cdda = - (cdda_data_t *) p_input->p_access_data; - - dbg_print( INPUT_DBG_CALL, "intf initialized" ); - - /* Main loop */ - while( !p_intf->b_die ) - { - vlc_mutex_lock( &p_intf->change_lock ); - - /* - * keyboard event - */ - if( p_vout && p_intf->p_sys->b_key_pressed ) - { - vlc_value_t val; - int i, i_action = -1; - struct hotkey *p_hotkeys = p_intf->p_vlc->p_hotkeys; - - p_intf->p_sys->b_key_pressed = VLC_FALSE; - - /* Find action triggered by hotkey (if any) */ - var_Get( p_intf->p_vlc, "key-pressed", &val ); - - dbg_print( INPUT_DBG_EVENT, "Key pressed %d", val.i_int ); - - for( i = 0; p_hotkeys[i].psz_action != NULL; i++ ) - { - if( p_hotkeys[i].i_key == val.i_int ) - { - i_action = p_hotkeys[i].i_action; - } - } - - if( i_action != -1) { - switch (i_action) { - - case ACTIONID_NAV_LEFT: - dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_LEFT (%d)", - number_addend ); - do { - if ( CDDAPlay( p_input, p_cdda->i_track-1 ) ) { - p_cdda->i_track--; - } else { - break; - } - } while (number_addend-- > 0); - break; - - case ACTIONID_NAV_RIGHT: - dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_RIGHT (%d)", - number_addend ); - do { - if ( CDDAPlay( p_input, p_cdda->i_track+1 ) ) { - p_cdda->i_track++; - } else { - break; - } - } while (number_addend-- > 0); - break; - - case ACTIONID_NAV_UP: - dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_UP" ); - do { - ; - } while (number_addend-- > 0); - break; - - case ACTIONID_NAV_DOWN: - dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_DOWN" ); - break; - - case ACTIONID_NAV_ACTIVATE: - { - dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_ACTIVATE" ); - if ( CDDAPlay( p_input, number_addend ) ) { - p_cdda->i_track = number_addend; - } else { - break; - } - break; - } - } - number_addend = 0; - } else { - unsigned int digit_entered=0; - - switch (val.i_int) { - case '9': - digit_entered++; - case '8': - digit_entered++; - case '7': - digit_entered++; - case '6': - digit_entered++; - case '5': - digit_entered++; - case '4': - digit_entered++; - case '3': - digit_entered++; - case '2': - digit_entered++; - case '1': - digit_entered++; - case '0': - { - number_addend *= 10; - number_addend += digit_entered; - dbg_print( INPUT_DBG_EVENT, - "Added %d. Number is now: %d\n", - digit_entered, number_addend); - break; - } - } - } - } - - - vlc_mutex_unlock( &p_intf->change_lock ); - - if( p_vout == NULL ) - { - p_vout = vlc_object_find( p_intf->p_sys->p_input, - VLC_OBJECT_VOUT, FIND_ANYWHERE ); - if( p_vout ) - { - var_AddCallback( p_vout, "key-pressed", KeyEvent, p_intf ); - } - } - - - /* Wait a bit */ - msleep( INTF_IDLE_SLEEP ); - } - - if( p_vout ) - { - var_DelCallback( p_vout, "key-pressed", KeyEvent, p_intf ); - vlc_object_release( p_vout ); - } - - vlc_object_release( p_intf->p_sys->p_input ); -} - -/***************************************************************************** - * InitThread: - *****************************************************************************/ -static int InitThread( intf_thread_t * p_intf ) -{ - /* We might need some locking here */ - if( !p_intf->b_die ) - { - input_thread_t * p_input; - - p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_PARENT ); - - /* Maybe the input just died */ - if( p_input == NULL ) - { - return VLC_EGENERIC; - } - - vlc_mutex_lock( &p_intf->change_lock ); - - p_intf->p_sys->p_input = p_input; - - p_intf->p_sys->b_move = VLC_FALSE; - p_intf->p_sys->b_click = VLC_FALSE; - p_intf->p_sys->b_key_pressed = VLC_FALSE; - - vlc_mutex_unlock( &p_intf->change_lock ); - - return VLC_SUCCESS; - } - else - { - return VLC_EGENERIC; - } -} - -/***************************************************************************** - * KeyEvent: callback for keyboard events - *****************************************************************************/ -static int KeyEvent( vlc_object_t *p_this, char const *psz_var, - vlc_value_t oldval, vlc_value_t newval, void *p_data ) -{ - intf_thread_t *p_intf = (intf_thread_t *)p_data; - vlc_mutex_lock( &p_intf->change_lock ); - - p_intf->p_sys->b_key_pressed = VLC_TRUE; - - vlc_mutex_unlock( &p_intf->change_lock ); - - return VLC_SUCCESS; -} diff --git a/modules/access/cdda/cdda.h b/modules/access/cdda/cdda.h new file mode 100644 index 0000000000..593912dc20 --- /dev/null +++ b/modules/access/cdda/cdda.h @@ -0,0 +1,67 @@ +/***************************************************************************** + * cdda.h : CD-DA input module header for vlc + * using libcdio, libvcd and libvcdinfo + ***************************************************************************** + * Copyright (C) 2003 VideoLAN + * $Id: cdda.h,v 1.1 2003/11/26 03:35:26 rocky Exp $ + * + * Authors: Rocky Bernstein + * + * 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. + *****************************************************************************/ + +#include "../vcdx/cdrom.h" + +/***************************************************************************** + * Debugging + *****************************************************************************/ +#define INPUT_DBG_MRL 1 +#define INPUT_DBG_EVENT 2 /* Trace keyboard events */ +#define INPUT_DBG_EXT 4 /* Calls from external routines */ +#define INPUT_DBG_CALL 8 /* all calls */ +#define INPUT_DBG_LSN 16 /* LSN changes */ +#define INPUT_DBG_CDIO 32 /* Debugging from CDIO */ +#define INPUT_DBG_SEEK 64 /* Seeks to set location */ + +#define INPUT_DEBUG 1 +#if INPUT_DEBUG +#define dbg_print(mask, s, args...) \ + if (p_cdda->i_debug & mask) \ + msg_Dbg(p_input, "%s: "s, __func__ , ##args) +#else +#define dbg_print(mask, s, args...) +#endif + +/***************************************************************************** + * cdda_data_t: CD audio information + *****************************************************************************/ +typedef struct cdda_data_s +{ + cddev_t *p_cddev; /* CD device descriptor */ + int i_nb_tracks; /* Nb of tracks (titles) */ + int i_track; /* Current track */ + lsn_t i_sector; /* Current Sector */ + lsn_t * p_sectors; /* Track sectors */ + vlc_bool_t b_end_of_track; /* If the end of track was reached */ + int i_debug; /* Debugging mask */ + intf_thread_t *p_intf; + +} cdda_data_t; + +/***************************************************************************** + * CDDAPlay: Arrange things so we play the specified track. + * VLC_TRUE is returned if there was no error. + *****************************************************************************/ +vlc_bool_t CDDAPlay ( input_thread_t *, int ); diff --git a/modules/access/cdda/intf.c b/modules/access/cdda/intf.c new file mode 100644 index 0000000000..2e3d790faa --- /dev/null +++ b/modules/access/cdda/intf.c @@ -0,0 +1,305 @@ +/***************************************************************************** + * intf.c: Video CD interface to handle user interaction and still time + ***************************************************************************** + * Copyright (C) 2003 VideoLAN + * $Id: intf.c,v 1.1 2003/11/26 03:35:26 rocky Exp $ + * + * Authors: Rocky Bernstein + * + * 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 +#include + +#include "stream_control.h" +#include "input_ext-intf.h" +#include "input_ext-dec.h" +#include "vlc_keys.h" + +#include "cdda.h" + +/***************************************************************************** + * intf_sys_t: description and status of interface + *****************************************************************************/ +struct intf_sys_t +{ + input_thread_t * p_input; + cdda_data_t * p_cdda; + vlc_bool_t b_click, b_move, b_key_pressed; +}; + +/***************************************************************************** + * Local prototypes. + *****************************************************************************/ +static int InitThread ( intf_thread_t *p_intf ); +static int KeyEvent ( vlc_object_t *, char const *, + vlc_value_t, vlc_value_t, void * ); + +/* Exported functions */ +static void RunIntf ( intf_thread_t *p_intf ); + +/***************************************************************************** + * OpenIntf: initialize dummy interface + *****************************************************************************/ +int E_(OpenIntf) ( vlc_object_t *p_this ) +{ + intf_thread_t *p_intf = (intf_thread_t *)p_this; + + /* Allocate instance and initialize some members */ + p_intf->p_sys = malloc( sizeof( intf_sys_t ) ); + if( p_intf->p_sys == NULL ) + { + return( 1 ); + }; + + p_intf->pf_run = RunIntf; + + var_AddCallback( p_intf->p_vlc, "key-pressed", KeyEvent, p_intf ); + + return( 0 ); +} + +/***************************************************************************** + * CloseIntf: destroy dummy interface + *****************************************************************************/ +void E_(CloseIntf) ( vlc_object_t *p_this ) +{ + intf_thread_t *p_intf = (intf_thread_t *)p_this; + + /* Destroy structure */ + free( p_intf->p_sys ); +} + +/***************************************************************************** + * RunIntf: main loop + *****************************************************************************/ +static void RunIntf( intf_thread_t *p_intf ) +{ + vlc_object_t * p_vout = NULL; + cdda_data_t * p_cdda; + input_thread_t * p_input; + + /* What you add to the last input number entry. It accumulates all of + the 10_ADD keypresses */ + int number_addend = 0; + + if( InitThread( p_intf ) < 0 ) + { + msg_Err( p_intf, "can't initialize intf" ); + return; + } + + p_input = p_intf->p_sys->p_input; + p_cdda = p_intf->p_sys->p_cdda = + (cdda_data_t *) p_input->p_access_data; + + dbg_print( INPUT_DBG_CALL, "intf initialized" ); + + /* Main loop */ + while( !p_intf->b_die ) + { + vlc_mutex_lock( &p_intf->change_lock ); + + /* + * keyboard event + */ + if( p_vout && p_intf->p_sys->b_key_pressed ) + { + vlc_value_t val; + int i, i_action = -1; + struct hotkey *p_hotkeys = p_intf->p_vlc->p_hotkeys; + + p_intf->p_sys->b_key_pressed = VLC_FALSE; + + /* Find action triggered by hotkey (if any) */ + var_Get( p_intf->p_vlc, "key-pressed", &val ); + + dbg_print( INPUT_DBG_EVENT, "Key pressed %d", val.i_int ); + + for( i = 0; p_hotkeys[i].psz_action != NULL; i++ ) + { + if( p_hotkeys[i].i_key == val.i_int ) + { + i_action = p_hotkeys[i].i_action; + } + } + + if( i_action != -1) { + switch (i_action) { + + case ACTIONID_NAV_LEFT: + dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_LEFT (%d)", + number_addend ); + do { + if ( CDDAPlay( p_input, p_cdda->i_track-1 ) ) { + p_cdda->i_track--; + } else { + break; + } + } while (number_addend-- > 0); + break; + + case ACTIONID_NAV_RIGHT: + dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_RIGHT (%d)", + number_addend ); + do { + if ( CDDAPlay( p_input, p_cdda->i_track+1 ) ) { + p_cdda->i_track++; + } else { + break; + } + } while (number_addend-- > 0); + break; + + case ACTIONID_NAV_UP: + dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_UP" ); + do { + ; + } while (number_addend-- > 0); + break; + + case ACTIONID_NAV_DOWN: + dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_DOWN" ); + break; + + case ACTIONID_NAV_ACTIVATE: + { + dbg_print( INPUT_DBG_EVENT, "ACTIONID_NAV_ACTIVATE" ); + if ( CDDAPlay( p_input, number_addend ) ) { + p_cdda->i_track = number_addend; + } else { + break; + } + break; + } + } + number_addend = 0; + } else { + unsigned int digit_entered=0; + + switch (val.i_int) { + case '9': + digit_entered++; + case '8': + digit_entered++; + case '7': + digit_entered++; + case '6': + digit_entered++; + case '5': + digit_entered++; + case '4': + digit_entered++; + case '3': + digit_entered++; + case '2': + digit_entered++; + case '1': + digit_entered++; + case '0': + { + number_addend *= 10; + number_addend += digit_entered; + dbg_print( INPUT_DBG_EVENT, + "Added %d. Number is now: %d\n", + digit_entered, number_addend); + break; + } + } + } + } + + + vlc_mutex_unlock( &p_intf->change_lock ); + + if( p_vout == NULL ) + { + p_vout = vlc_object_find( p_intf->p_sys->p_input, + VLC_OBJECT_VOUT, FIND_ANYWHERE ); + if( p_vout ) + { + var_AddCallback( p_vout, "key-pressed", KeyEvent, p_intf ); + } + } + + + /* Wait a bit */ + msleep( INTF_IDLE_SLEEP ); + } + + if( p_vout ) + { + var_DelCallback( p_vout, "key-pressed", KeyEvent, p_intf ); + vlc_object_release( p_vout ); + } + + vlc_object_release( p_intf->p_sys->p_input ); +} + +/***************************************************************************** + * InitThread: + *****************************************************************************/ +static int InitThread( intf_thread_t * p_intf ) +{ + /* We might need some locking here */ + if( !p_intf->b_die ) + { + input_thread_t * p_input; + + p_input = vlc_object_find( p_intf, VLC_OBJECT_INPUT, FIND_PARENT ); + + /* Maybe the input just died */ + if( p_input == NULL ) + { + return VLC_EGENERIC; + } + + vlc_mutex_lock( &p_intf->change_lock ); + + p_intf->p_sys->p_input = p_input; + + p_intf->p_sys->b_move = VLC_FALSE; + p_intf->p_sys->b_click = VLC_FALSE; + p_intf->p_sys->b_key_pressed = VLC_FALSE; + + vlc_mutex_unlock( &p_intf->change_lock ); + + return VLC_SUCCESS; + } + else + { + return VLC_EGENERIC; + } +} + +/***************************************************************************** + * KeyEvent: callback for keyboard events + *****************************************************************************/ +static int KeyEvent( vlc_object_t *p_this, char const *psz_var, + vlc_value_t oldval, vlc_value_t newval, void *p_data ) +{ + intf_thread_t *p_intf = (intf_thread_t *)p_data; + vlc_mutex_lock( &p_intf->change_lock ); + + p_intf->p_sys->b_key_pressed = VLC_TRUE; + + vlc_mutex_unlock( &p_intf->change_lock ); + + return VLC_SUCCESS; +}