Commit 4fcaafa3 authored by Rocky Bernstein's avatar Rocky Bernstein

First attempt to reinstate a libcdio cdda.

vlc_meta.h: added CD-Text, ISO 9660, and CDDB fields. Separate email
will be sent about this.

Note: sound may be off by 2 seconds (150 sectors or pregap
amount). The sound for both this and the other cdda plugin don't work
for me. Before the last SVN update though that's what it sounded like.
parent 7adeecde
......@@ -1486,46 +1486,46 @@ then
VLC_ADD_PLUGINS([pvr])
fi
dnl dnl
dnl dnl VCDX and CDDAX modules
dnl dnl
dnl AC_ARG_ENABLE(libcdio,
dnl [ --enable-libcdio CDDA support via libcdio (default enabled)])
dnl
dnl AC_ARG_ENABLE(libcddb,
dnl [ --enable-libcddb CDDB support for CDDAX (default enabled)])
dnl
dnl
dnl VCDX and CDDAX modules
dnl
AC_ARG_ENABLE(libcdio,
[ --enable-libcdio CDDA support via libcdio (default enabled)])
AC_ARG_ENABLE(libcddb,
[ --enable-libcddb CDDB support for CDDAX (default enabled)])
dnl AC_ARG_ENABLE(vcdx,
dnl [ --enable-vcdx VCD support with Navigation (default enabled)])
dnl
dnl AC_ARG_ENABLE(cdda,
dnl [ --enable-cdda CDDA plugin support (default enabled)])
dnl
dnl AC_ARG_ENABLE(cddax,
dnl [ --enable-cddax CDDAX plugin support (default enabled)])
dnl
dnl if test "${enable_cddax}" != "no"
dnl then
dnl PKG_CHECK_MODULES(LIBCDIO, libcdio >= 0.65,
dnl [enable_cddax="no"
dnl AC_DEFINE(HAVE_CDDAX, [], [Define for the CD-DA plugin using libcdio])
dnl VLC_ADD_LDFLAGS([cddax],[$LIBCDIO_LIBS])
dnl VLC_ADD_CFLAGS([cddax],[$LIBCDIO_CFLAGS])
dnl VLC_ADD_PLUGINS([cddax])],
dnl [AC_MSG_WARN(libcdio library not found)
dnl HAVE_CDDAX=no])
dnl
dnl if test "$enable_libcddb" != "no"; then
dnl PKG_CHECK_MODULES(LIBCDDB, libcddb >= 0.9.4, [
dnl HAVE_LIBCDDB=yes
dnl AC_DEFINE(HAVE_LIBCDDB, [], [Define this if you have libcddb installed])
dnl VLC_ADD_LDFLAGS([cddax],[$LIBCDDB_LIBS])
dnl VLC_ADD_CFLAGS([cddax],[$LIBCDDB_CFLAGS])
dnl ],
dnl [AC_MSG_WARN(new enough libcddb not found. CDDB access disabled)
dnl HAVE_LIBCDDB=no])
dnl fi
dnl
AC_ARG_ENABLE(cdda,
[ --enable-cdda CDDA plugin support (default enabled)])
AC_ARG_ENABLE(cddax,
[ --enable-cddax CDDAX plugin support (default enabled)])
if test "${enable_cddax}" != "no"
then
PKG_CHECK_MODULES(LIBCDIO, libcdio >= 0.70,
[enable_cddax="no"
AC_DEFINE(HAVE_CDDAX, [], [Define for the CD-DA plugin using libcdio])
VLC_ADD_LDFLAGS([cddax],[$LIBCDIO_LIBS])
VLC_ADD_CFLAGS([cddax],[$LIBCDIO_CFLAGS])
VLC_ADD_PLUGINS([cddax])],
[AC_MSG_WARN(libcdio library not found)
HAVE_CDDAX=no])
if test "$enable_libcddb" != "no"; then
PKG_CHECK_MODULES(LIBCDDB, libcddb >= 0.9.4, [
HAVE_LIBCDDB=yes
AC_DEFINE(HAVE_LIBCDDB, [], [Define this if you have libcddb installed])
VLC_ADD_LDFLAGS([cddax],[$LIBCDDB_LIBS])
VLC_ADD_CFLAGS([cddax],[$LIBCDDB_CFLAGS])
],
[AC_MSG_WARN(new enough libcddb not found. CDDB access disabled)
HAVE_LIBCDDB=no])
fi
dnl if test "${enable_vcdx}" != "no"
dnl then
dnl PKG_CHECK_MODULES(VCDINFO, libvcdinfo >= 0.7.20,
......@@ -1538,7 +1538,7 @@ dnl VLC_ADD_PLUGINS([vcdx])],
dnl [AC_MSG_WARN(vcdinfo library not found)
dnl HAVE_VCDX=no])
dnl fi
dnl fi
fi
dnl
dnl VCD module
......
......@@ -36,6 +36,30 @@
#define VLC_META_SETTING N_("Setting")
#define VLC_META_URL N_("URL")
#define VLC_META_LANGUAGE N_("Language")
#define VLC_META_CDDB_ARTIST N_("CDDB Artist")
#define VLC_META_CDDB_CATEGORY N_("CDDB Category")
#define VLC_META_CDDB_DISCID N_("CDDB Disc ID")
#define VLC_META_CDDB_EXT_DATA N_("CDDB Extended Data")
#define VLC_META_CDDB_GENRE N_("CDDB Genre")
#define VLC_META_CDDB_YEAR N_("CDDB Year")
#define VLC_META_CDDB_TITLE N_("CDDB Title")
#define VLC_META_CDTEXT_ARRANGER N_("CD-Text Arranger")
#define VLC_META_CDTEXT_COMPOSER N_("CD-Text Composer")
#define VLC_META_CDTEXT_DISCID N_("CD-Text Disc ID")
#define VLC_META_CDTEXT_GENRE N_("CD-Text Genre")
#define VLC_META_CDTEXT_MESSAGE N_("CD-Text Message")
#define VLC_META_CDTEXT_SONGWRITER N_("CD-Text Songwriter")
#define VLC_META_CDTEXT_PERFORMER N_("CD-Text Performer")
#define VLC_META_CDTEXT_TITLE N_("CD-Text Title")
#define VLC_META_ISO_APPLICATION_ID N_("ISO-9660 Application ID")
#define VLC_META_ISO_PREPARER N_("ISO-9660 Preparer")
#define VLC_META_ISO_PUBLISHER N_("ISO-9660 Publisher")
#define VLC_META_ISO_VOLUME N_("ISO-9660 Volume")
#define VLC_META_ISO_VOLUMESET N_("ISO-9660 Volume Set")
#define VLC_META_CODEC_NAME N_("Codec Name")
#define VLC_META_CODEC_DESCRIPTION N_("Codec Description")
......
......@@ -30,7 +30,7 @@
#include <stdlib.h>
#include <vlc/vlc.h>
#include <vlc/intf.h>
#include <vlc/input.h>
#include <sys/types.h>
#include <cdio/cdio.h>
......@@ -58,26 +58,16 @@
#define CDDA_MRL_PREFIX "cddax://"
/* FIXME: This variable is a hack. Would be nice to eliminate. */
static input_thread_t *p_cdda_input = NULL;
static access_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);
#if NEED_UPDATE_VAR
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 );
#endif
static block_t *CDDABlock( 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 void CDDAMetaInfo( access_t *p_access );
/****************************************************************************
* Private functions
......@@ -87,7 +77,7 @@ static void CDDAUpdateVar( input_thread_t *p_input, int i_entry, int i_action,
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;
cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
switch (level) {
case CDIO_LOG_DEBUG:
case CDIO_LOG_INFO:
......@@ -103,7 +93,7 @@ cdio_log_handler (cdio_log_level_t level, const char message[])
break;
default:
msg_Warn( p_cdda_input, message,
_("The above message had unknown vcdimager log level"),
_("The above message had unknown cdio log level"),
level);
}
return;
......@@ -117,7 +107,7 @@ cdio_log_handler (cdio_log_level_t level, const char message[])
static void
cddb_log_handler (cddb_log_level_t level, const char message[])
{
cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
switch (level) {
case CDDB_LOG_DEBUG:
case CDDB_LOG_INFO:
......@@ -136,7 +126,7 @@ cddb_log_handler (cddb_log_level_t level, const char message[])
static void
uninit_log_handler (cdio_log_level_t level, const char message[])
{
cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
cdda_data_t *p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
switch (level) {
case CDIO_LOG_DEBUG:
case CDIO_LOG_INFO:
......@@ -163,283 +153,107 @@ uninit_log_handler (cdio_log_level_t level, const char message[])
}
/*****************************************************************************
* CDDAPlay: Arrange things so we play the specified track.
* VLC_TRUE is returned if there was no error.
* CDDARead: reads CDDA_BLOCKS_ONCE 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.
*****************************************************************************/
vlc_bool_t
CDDAPlay( input_thread_t *p_input, int i_track )
static block_t *
CDDABlock( access_t * p_access )
{
cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
block_t *p_block;
cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
int i_blocks = CDDA_BLOCKS_ONCE;
if( i_track > p_cdda->i_nb_tracks || i_track < 1 )
return VLC_FALSE;
dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_LSN), "called %d",
p_cdda->i_sector);
CDDASetArea( p_input, p_input->stream.pp_areas[i_track] );
return VLC_TRUE;
}
/* Check end of file */
if( p_access->info.b_eof ) return 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;
/* 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);
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;
}
for( i_index = 0; i_index < i_blocks; i_index++ )
/* Check end of track */
while( p_cdda->i_sector >= p_cdda->p_sectors[p_access->info.i_title + 1] )
{
if( cdio_read_audio_sector( p_cdda->p_cddev->cdio, p_buffer,
p_cdda->i_sector) != 0 )
if( p_access->info.i_title + 1 >= p_cdda->i_tracks )
{
msg_Err( p_input, "could not read sector %lu",
(long unsigned int) p_cdda->i_sector );
return -1;
p_access->info.b_eof = VLC_TRUE;
return NULL;
}
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: %lu",
(long unsigned int) 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;
p_access->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SIZE;
p_access->info.i_title++;
p_access->info.i_size =
p_cdda->p_title[p_access->info.i_title]->i_size;
p_access->info.i_pos = 0;
}
if ( i_len % CDIO_CD_FRAMESIZE_RAW ) /* this should not happen */
/* Don't read after the end of a title */
if( p_cdda->i_sector + i_blocks >=
p_cdda->p_sectors[p_access->info.i_title + 1] )
{
msg_Err( p_input, "must read full sectors" );
i_blocks = p_cdda->p_sectors[p_access->info.i_title + 1 ] -
p_cdda->i_sector;
}
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 )
/* Do the actual reading */
p_block = block_New( p_access, i_blocks * CDIO_CD_FRAMESIZE_RAW );
if( !p_block)
{
/* 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 );
msg_Err( p_access, "cannot get a new block of size: %i",
i_blocks * CDIO_CD_FRAMESIZE_RAW );
return 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;
if( cdio_read_audio_sectors( p_cdda->p_cddev->cdio, p_block->p_buffer,
p_cdda->i_sector, i_blocks) != 0 )
{
msg_Err( p_access, "could not read sector %lu",
(long unsigned int) p_cdda->i_sector );
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_sector++;
p_access->info.i_pos += CDIO_CD_FRAMESIZE_RAW;
return NULL;
}
/* warn interface that something has changed */
p_input->stream.b_seekable = 1;
p_input->stream.b_changed = 1;
p_cdda->i_sector += i_blocks;
p_access->info.i_pos += p_block->i_buffer;
return 0;
return p_block;
}
/****************************************************************************
* CDDASeek
* CDDASeek - change position for subsequent reads. For example, this
* can happen if the user moves a position slider bar in a GUI.
****************************************************************************/
static void CDDASeek( input_thread_t * p_input, off_t i_off )
static int
CDDASeek( access_t * p_access, int64_t i_pos )
{
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;
cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
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 );
p_cdda->i_sector = p_cdda->p_sectors[p_access->info.i_title]
+ i_pos / CDIO_CD_FRAMESIZE_RAW;
p_access->info.i_pos = i_pos;
dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
"sector %lu, offset: %lld, i_tell: %lld",
(long unsigned int) p_cdda->i_sector, i_off,
p_input->stream.p_selected_area->i_tell );
}
#if NEED_UPDATE_VAR
/****************************************************************************
Update the "varname" variable to i_num without triggering a callback.
****************************************************************************/
static void
CDDAUpdateVar( 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 );
}
#endif
static void InformationCreate( input_thread_t *p_input )
{
cdda_data_t *p_cdda = (cdda_data_t *) p_input->p_access_data;
#ifdef HAVE_LIBCDDB
if (p_cdda->i_cddb_enabled) {
dbg_print( INPUT_DBG_META, "field %s: %s\n", "Title",
p_cdda->cddb.disc->title );
input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Title"),
"%s", p_cdda->cddb.disc->title );
dbg_print( INPUT_DBG_META, "field %s: %s\n", "Artist",
p_cdda->cddb.disc->artist );
input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Artist"),
"%s", p_cdda->cddb.disc->artist );
dbg_print( INPUT_DBG_META, "field %s: %s\n", "Genre",
p_cdda->cddb.disc->genre );
input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Genre"),
"%s", p_cdda->cddb.disc->genre );
dbg_print( INPUT_DBG_META, "field %s: %s\n", "Extended Data",
p_cdda->cddb.disc->ext_data );
input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Extended Data"),
"%s", p_cdda->cddb.disc->ext_data );
if (p_cdda->cddb.disc->year != 0)
input_Control( p_input, INPUT_ADD_INFO, _("General"),
_("Year"), "%d", p_cdda->cddb.disc->year );
if ( p_cdda->cddb.disc->discid )
input_Control( p_input, INPUT_ADD_INFO, _("General"),
_("CDDB Disc ID"), "%x", p_cdda->cddb.disc->discid );
if ( p_cdda->cddb.disc->category != CDDB_CAT_INVALID )
input_Control( p_input, INPUT_ADD_INFO, _("General"),
_("CDDB Disc Category"), "%s",
CDDB_CATEGORY[p_cdda->cddb.disc->category] );
}
#endif /*HAVE_LIBCDDB*/
#define TITLE_MAX 30
{
track_t i_track = p_cdda->i_nb_tracks;
char psz_buffer[MSTRTIME_MAX_SIZE];
mtime_t i_duration =
(p_cdda->p_sectors[i_track] - p_cdda->p_sectors[0])
/ CDIO_CD_FRAMES_PER_SEC;
dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
input_Control( p_input, INPUT_ADD_INFO, _("General"), _("Duration"), "%s",
secstotimestr( psz_buffer, i_duration ) );
for( i_track = 0 ; i_track < p_cdda->i_nb_tracks ; i_track++ ) {
char track_str[TITLE_MAX];
mtime_t i_duration =
(p_cdda->p_sectors[i_track+1] - p_cdda->p_sectors[i_track])
/ CDIO_CD_FRAMES_PER_SEC;
snprintf(track_str, TITLE_MAX, "%s %02d", _("Track"), i_track+1);
input_Control( p_input, INPUT_ADD_INFO, track_str, _("Duration"), "%s",
secstotimestr( psz_buffer, i_duration ) );
#ifdef HAVE_LIBCDDB
if (p_cdda->i_cddb_enabled) {
cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
i_track);
if (t != NULL) {
if ( t->artist != NULL && strlen(t->artist) ) {
input_Control( p_input, INPUT_ADD_INFO, track_str,
_("Artist"), "%s", t->artist );
}
if ( t->title != NULL && strlen(t->title) ) {
input_Control( p_input, INPUT_ADD_INFO, track_str,
_("Title"), "%s", t->title );
}
if ( t->ext_data != NULL && strlen(t->ext_data) ) {
input_Control( p_input, INPUT_ADD_INFO, track_str,
_("Extended Data"), "%s", t->ext_data );
}
}
}
#endif
}
}
"sector %lu, offset: %lld",
(long unsigned int) p_cdda->i_sector, i_pos );
return VLC_SUCCESS;
}
#ifdef HAVE_LIBCDDB
#define free_and_dup(var, val) \
......@@ -448,80 +262,82 @@ static void InformationCreate( input_thread_t *p_input )
static void
GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
GetCDDBInfo( access_t *p_access, cdda_data_t *p_cdda )
{
dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
if (config_GetInt( p_input, MODULE_STRING "-cddb-enabled" )) {
if (config_GetInt( p_access, MODULE_STRING "-cddb-enabled" )) {
int i, i_matches;
cddb_conn_t *conn = cddb_new();
const CdIo *cdio = p_cdda->p_cddev->cdio;
const CdIo *p_cdio = p_cdda->p_cddev->cdio;
cddb_log_set_handler (uninit_log_handler);
if (!conn) {
msg_Warn( p_input, "unable to initialize libcddb" );
msg_Warn( p_access, "unable to initialize libcddb" );
goto cddb_destroy;
}
cddb_set_email_address( conn,
config_GetPsz( p_input,
config_GetPsz( p_access,
MODULE_STRING "-cddb-email") );
cddb_set_server_name( conn,
config_GetPsz( p_input,
config_GetPsz( p_access,
MODULE_STRING "-cddb-server") );
cddb_set_server_port(conn,
config_GetInt( p_input,
config_GetInt( p_access,
MODULE_STRING "-cddb-port") );
/* Set the location of the local CDDB cache directory.
The default location of this directory is */
if (!config_GetInt( p_input, MODULE_STRING "-cddb-enable-cache" ))
if (!config_GetInt( p_access, MODULE_STRING "-cddb-enable-cache" ))
cddb_cache_disable(conn);
cddb_cache_set_dir(conn,
config_GetPsz( p_input,
config_GetPsz( p_access,
MODULE_STRING "-cddb-cachedir") );
cddb_set_timeout(conn,
config_GetInt( p_input, MODULE_STRING "-cddb-timeout") );
config_GetInt( p_access, MODULE_STRING "-cddb-timeout") );
if (config_GetInt( p_input, MODULE_STRING "-cddb-httpd" )) {
if (config_GetInt( p_access, MODULE_STRING "-cddb-httpd" )) {
cddb_http_enable(conn);
} else
cddb_http_disable(conn);
p_cdda->cddb.disc = cddb_disc_new();
if (!p_cdda->cddb.disc) {
msg_Err( p_input, "Unable to create CDDB disc structure." );
msg_Err( p_access, "Unable to create CDDB disc structure." );
goto cddb_end;
}
for(i = 1; i <= p_cdda->i_nb_tracks; i++) {
p_cdda->psz_mcn = cdio_get_mcn(p_cdio);
for(i = 1; i <= p_cdda->i_tracks; i++) {
cddb_track_t *t = cddb_track_new();
t->frame_offset = cdio_get_track_lba(cdio, i);
t->frame_offset = cdio_get_track_lba(p_cdio, i);
cddb_disc_add_track(p_cdda->cddb.disc, t);
}
p_cdda->cddb.disc->length =
cdio_get_track_lba(cdio, CDIO_CDROM_LEADOUT_TRACK)
cdio_get_track_lba(p_cdio, CDIO_CDROM_LEADOUT_TRACK)
/ CDIO_CD_FRAMES_PER_SEC;
if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) {
msg_Err( p_input, "CDDB disc calc failed" );
msg_Err( p_access, "CDDB disc calc failed" );
goto cddb_destroy;
}
i_matches = cddb_query(conn, p_cdda->cddb.disc);
if (i_matches > 0) {
if (i_matches > 1)
msg_Warn( p_input, "Found %d matches in CDDB. Using first one.",
msg_Warn( p_access, "Found %d matches in CDDB. Using first one.",
i_matches);
cddb_read(conn, p_cdda->cddb.disc);
......@@ -529,7 +345,7 @@ GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
cddb_disc_print(p_cdda->cddb.disc);
} else {
msg_Warn( p_input, "CDDB error: %s", cddb_error_str(errno));
msg_Warn( p_access, "CDDB error: %s", cddb_error_str(errno));
}
cddb_destroy:
......@@ -539,6 +355,101 @@ GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
}
#endif /*HAVE_LIBCDDB*/
#define add_meta_val(FIELD, VLC_META, VAL) \
if ( p_cdda->p_meta ) { \
vlc_meta_Add( p_cdda->p_meta, VLC_META, VAL ); \
dbg_print( INPUT_DBG_META, "field %s: %s\n", VLC_META, VAL ); \
} \
#define add_cddb_meta(FIELD, VLC_META) \
add_meta_val(FIELD, VLC_META, p_cdda->cddb.disc->FIELD);
#define add_cddb_meta_fmt(FIELD, FORMAT_SPEC, VLC_META) \
{ \
char psz_buf[100]; \
snprintf( psz_buf, sizeof(psz_buf)-1, FORMAT_SPEC, \
p_cdda->cddb.disc->FIELD ); \
psz_buf[sizeof(psz_buf)-1] = '\0'; \
add_meta_val(FIELD, VLC_META, psz_buf); \
}
/*
Gets and saves CDDA Meta Information. In the Control routine,
we handle Meta Information requests and basically copy what we've
saved here.
*/
static void CDDAMetaInfo( access_t *p_access )
{
cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
#ifdef HAVE_LIBCDDB
if ( p_cdda && p_cdda->i_cddb_enabled ) {
GetCDDBInfo(p_access, p_cdda);
if ( p_cdda->cddb.disc ) {
p_cdda->p_meta = vlc_meta_New();
add_cddb_meta(title, VLC_META_CDDB_TITLE);
add_cddb_meta(artist, VLC_META_CDDB_ARTIST);
add_cddb_meta(genre, VLC_META_CDDB_GENRE);
add_cddb_meta(ext_data, VLC_META_CDDB_EXT_DATA);
add_cddb_meta_fmt(year, "%d", VLC_META_CDDB_YEAR);
add_cddb_meta_fmt(discid, "%x", VLC_META_CDDB_DISCID);
}
}
#endif /*HAVE_LIBCDDB*/
#define TITLE_MAX 30
#if UPDATE_TRACK_INFORMATION_FINISHED
{
track_t i_track = p_cdda->i_tracks;
char psz_buffer[MSTRTIME_MAX_SIZE];
mtime_t i_duration =
(p_cdda->p_sectors[i_track] - p_cdda->p_sectors[0])
/ CDIO_CD_FRAMES_PER_SEC;
dbg_print( INPUT_DBG_META, "Duration %ld", (long int) i_duration );
input_Control( p_access, INPUT_ADD_INFO, _("General"), _("Duration"), "%s",
secstotimestr( psz_buffer, i_duration ) );
for( i_track = 0 ; i_track < p_cdda->i_tracks ; i_track++ ) {
char track_str[TITLE_MAX];
mtime_t i_duration =
(p_cdda->p_sectors[i_track+1] - p_cdda->p_sectors[i_track])
/ CDIO_CD_FRAMES_PER_SEC;
snprintf(track_str, TITLE_MAX, "%s %02d", _("Track"), i_track+1);
input_Control( p_access, INPUT_ADD_INFO, track_str, _("Duration"), "%s",
secstotimestr( psz_buffer, i_duration ) );
#ifdef HAVE_LIBCDDB
if (p_cdda->i_cddb_enabled) {
cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
i_track);
if (t != NULL) {
if ( t->artist != NULL && strlen(t->artist) ) {
input_Control( p_access, INPUT_ADD_INFO, track_str,
_("Artist"), "%s", t->artist );
}
if ( t->title != NULL && strlen(t->title) ) {
input_Control( p_access, INPUT_ADD_INFO, track_str,
_("Title"), "%s", t->title );
}
if ( t->ext_data != NULL && strlen(t->ext_data) ) {
input_Control( p_access, INPUT_ADD_INFO, track_str,
_("Extended Data"), "%s", t->ext_data );
}
}
}
#endif /*HAVE_LIBCDDB*/
}
}
#endif /* UPDATE_TRACK_INFORMATION_FINISHED */
}
#define add_format_str_info(val) \
{ \
const char *str = val; \
......@@ -587,8 +498,8 @@ GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
%% : a %
*/
static char *
CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
const char format_str[], const char *mrl, int i_track)
CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
const char format_str[], const char *mrl, int i_track)
{
#define TEMP_STR_SIZE 256
#define TEMP_STR_LEN (TEMP_STR_SIZE-1)
......@@ -618,30 +529,36 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
#ifdef HAVE_LIBCDDB
case 'a':
if (!p_cdda->i_cddb_enabled) goto not_special;
add_format_str_info(p_cdda->cddb.disc->artist);
if (p_cdda->cddb.disc)
add_format_str_info(p_cdda->cddb.disc->artist);
break;
case 'A':
if (!p_cdda->i_cddb_enabled) goto not_special;
add_format_str_info(p_cdda->cddb.disc->title);
if (p_cdda->cddb.disc)
add_format_str_info(p_cdda->cddb.disc->title);
break;
case 'C':
if (!p_cdda->i_cddb_enabled) goto not_special;
add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
if (p_cdda->cddb.disc)
add_format_str_info(CDDB_CATEGORY[p_cdda->cddb.disc->category]);
break;
case 'G':
if (!p_cdda->i_cddb_enabled) goto not_special;
add_format_str_info(p_cdda->cddb.disc->genre);
if (p_cdda->cddb.disc)
add_format_str_info(p_cdda->cddb.disc->genre);
break;
case 'I':
if (!p_cdda->i_cddb_enabled) goto not_special;
add_format_num_info(p_cdda->cddb.disc->discid, "%x");
if (p_cdda->cddb.disc)
add_format_num_info(p_cdda->cddb.disc->discid, "%x");
break;
case 'Y':
if (!p_cdda->i_cddb_enabled) goto not_special;
add_format_num_info(p_cdda->cddb.disc->year, "%5d");
if (p_cdda->cddb.disc)
add_format_num_info(p_cdda->cddb.disc->year, "%5d");
break;
case 't':
if (p_cdda->i_cddb_enabled) {
if (p_cdda && p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
i_track-1);
if (t != NULL && t->title != NULL)
......@@ -649,7 +566,7 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
} else goto not_special;
break;
case 'p':
if (p_cdda->i_cddb_enabled) {
if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
i_track-1);
if (t != NULL && t->artist != NULL)
......@@ -657,7 +574,7 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
} else goto not_special;
break;
case 'e':
if (p_cdda->i_cddb_enabled) {
if (p_cdda->i_cddb_enabled && p_cdda->cddb.disc) {
cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
i_track-1);
if (t != NULL && t->ext_data != NULL)
......@@ -670,17 +587,14 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
add_format_str_info(mrl);
break;
#if FINISHED
case 'm':
add_format_str_info(p_cdda->mcn);
add_format_str_info(p_cdda->psz_mcn);
break;
#endif
case 'n':
add_format_num_info(p_cdda->i_nb_tracks, "%d");
add_format_num_info(p_cdda->i_tracks, "%d");
break;
#ifdef HAVE_LIBCDDB
case 's':
if (p_cdda->i_cddb_enabled) {
char psz_buffer[MSTRTIME_MAX_SIZE];
......@@ -690,7 +604,6 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
} else goto not_special;
break;
#endif
case 'T':
add_format_num_info(i_track, "%02d");
......@@ -707,8 +620,9 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
return strdup(temp_str);
}
#ifdef TRACK_META_INFORMATION_FINISHED
static void
CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
CDDACreatePlayListItem(const input_thread_t *p_access, cdda_data_t *p_cdda,
playlist_t *p_playlist, unsigned int i_track,
char *psz_mrl, int psz_mrl_max,
const char *psz_source, int playlist_operation,
......@@ -731,8 +645,8 @@ CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
CDDA_MRL_PREFIX, psz_source, i_track);
p_title = CDDAFormatStr(p_input, p_cdda,
config_GetPsz( p_input, config_varname ),
p_title = CDDAFormatStr(p_access, p_cdda,
config_GetPsz( p_access, config_varname ),
psz_mrl, i_track);
dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld, pos %d",
......@@ -751,8 +665,8 @@ CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
vlc_mutex_lock( &p_item->input.lock );
p_author =
CDDAFormatStr( p_input, p_cdda,
config_GetPsz( p_input, MODULE_STRING "-author-format" ),
CDDAFormatStr( p_access, p_cdda,
config_GetPsz( p_access, MODULE_STRING "-author-format" ),
psz_mrl, i_track );
playlist_ItemAddInfo( p_item , _("General"),_("Author"), p_author);
......@@ -797,89 +711,54 @@ CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
}
static int
CDDAFixupPlayList( input_thread_t *p_input, cdda_data_t *p_cdda,
const char *psz_source, bool play_single_track)
CDDAFixupPlayList( access_t *p_access, cdda_data_t *p_cdda,
const char *psz_source, track_t i_track)
{
int i;
playlist_t * p_playlist;
char * psz_mrl;
unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
strlen("@T") + strlen("100") + 1;
#ifdef HAVE_LIBCDDB
p_cdda->i_cddb_enabled =
config_GetInt( p_input, MODULE_STRING "-cddb-enabled" );
if( play_single_track && !p_cdda->i_cddb_enabled ) return 0;
#else
if( play_single_track ) return 0;
#endif
psz_mrl = malloc( psz_mrl_max );
if( psz_mrl == NULL )
{
msg_Warn( p_input, "out of memory" );
msg_Warn( p_access, "out of memory" );
return -1;
}
p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST,
FIND_ANYWHERE );
if( !p_playlist )
CDDAMetaInfo(p_access);
for( i = 1 ; i <= p_cdda->i_tracks ; i++ )
{
msg_Warn( p_input, "can't find playlist" );
free(psz_mrl);
return -1;
input_title_t *t = p_cdda->p_sectors[i-1] = vlc_input_title_New();
asprintf( &t->psz_name, _("Track %i"), i );
t->i_size = ( p_sys->p_sectors[i] - p_sys->p_sectors[i-1] ) *
(int64_t)CDIO_CD_FRAMESIZE_RAW;
t->i_length = I64C(1000000) * t->i_size / 44100 / 4;
CDDACreatePlayListItem(p_access, p_cdda, i, psz_mrl,
psz_mrl_max, psz_source, PLAYLIST_APPEND,
PLAYLIST_END);
}
#ifdef HAVE_LIBCDDB
if (p_cdda->i_cddb_enabled)
GetCDDBInfo(p_input, p_cdda);
else
p_cdda->cddb.disc = NULL;
#endif
InformationCreate(p_input);
if (play_single_track) {
/* May fill out more information when the playlist user interface becomes
more mature.
*/
CDDACreatePlayListItem(p_input, p_cdda, p_playlist, p_cdda->i_track+1,
psz_mrl, psz_mrl_max, psz_source, PLAYLIST_REPLACE,
p_playlist->i_index);
} else {
playlist_Delete( p_playlist, p_playlist->i_index);
for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ )
{
CDDACreatePlayListItem(p_input, p_cdda, p_playlist, i, psz_mrl,
psz_mrl_max, psz_source, PLAYLIST_APPEND,
PLAYLIST_END);
}
playlist_Command( p_playlist, PLAYLIST_GOTO, 0 );
}
vlc_object_release( p_playlist );
free(psz_mrl);
return 0;
}
#endif /* TRACK_META_INFORMATION_FINISHED*/
/****************************************************************************
* Public functions
****************************************************************************/
int
E_(DebugCB) ( vlc_object_t *p_this, const char *psz_name,
vlc_value_t oldval, vlc_value_t val, void *p_data )
E_(CDDADebugCB) ( 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;
p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
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",
......@@ -897,7 +776,7 @@ E_(CDDBEnabledCB) ( vlc_object_t *p_this, const char *psz_name,
if (NULL == p_cdda_input) return VLC_EGENERIC;
p_cdda = (cdda_data_t *)p_cdda_input->p_access_data;
p_cdda = (cdda_data_t *)p_cdda_input->p_sys;
#ifdef HAVE_LIBCDDB
if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) {
......@@ -910,83 +789,30 @@ E_(CDDBEnabledCB) ( vlc_object_t *p_this, const char *psz_name,
return VLC_SUCCESS;
}
/*FIXME*/
#if PLAYLIST_INTERFACE_IS_FIXED
int
E_(TitleFormatCB) ( 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 CDDB Enabled (%s), new (%s)",
oldval.psz_string, val.psz_string);
}
????
return VLC_SUCCESS;
}
#endif
/*****************************************************************************
* Open: open cdda
* Open: open cdda device or image file and initialize structures
* for subsequent operations.
*****************************************************************************/
int
E_(Open)( vlc_object_t *p_this )
E_(CDDAOpen)( vlc_object_t *p_this )
{
input_thread_t * p_input = (input_thread_t *)p_this;
char * psz_orig;
char * psz_parser;
access_t *p_access = (access_t*)p_this;
char * psz_source;
cdda_data_t * p_cdda;
int i;
int i_track = 1;
cddev_t *p_cddev;
vlc_value_t val;
bool play_single_track = false;
/* Set where to log errors messages from libcdio. */
p_cdda_input = (input_thread_t *)p_this;
p_cdda_input = p_access;
/* 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 != '@' )
if( !p_access->psz_path || !*p_access->psz_path )
{
psz_parser++;
}
if( *psz_parser == '@' )
{
/* Found options */
*psz_parser = '\0';
++psz_parser;
if ('T' == *psz_parser || 't' == *psz_parser )
++psz_parser;
/* Only when selected */
if( !p_this->b_force ) return VLC_EGENERIC;
i_track = (int)strtol( psz_parser, NULL, 10 );
i_track = i_track ? i_track : 1;
play_single_track = true;
}
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, "cd-audio" );
psz_source = var_CreateGetString( p_this, "cd-audio" );
if( !psz_source || 0==strlen(psz_source) ) {
if( !psz_source || !*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);
......@@ -999,101 +825,108 @@ E_(Open)( vlc_object_t *p_this )
cdio_free_device_list(cd_drives);
}
}
else
psz_source = strdup( p_access->psz_path );
/* Open CDDA */
cdio_log_set_handler ( cdio_log_handler );
#ifdef HAVE_LIBCDDB
cddb_log_set_handler ( cddb_log_handler );
#endif
/* Open CDDA */
if( !(p_cddev = ioctl_Open( p_this, psz_source )) )
{
msg_Warn( p_input, "could not open %s", psz_source );
free( psz_source );
return VLC_EGENERIC;
msg_Warn( p_access, "could not open %s", psz_source );
goto error2;
}
p_cdda = malloc( sizeof(cdda_data_t) );
if( p_cdda == NULL )
{
msg_Err( p_input, "out of memory" );
msg_Err( p_access, "out of memory" );
free( psz_source );
return VLC_ENOMEM;
}
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;
#ifdef HAVE_LIBCDDB
cddb_log_set_handler ( cddb_log_handler );
p_cdda->cddb.disc = NULL;
p_cdda->i_cddb_enabled =
config_GetInt( p_access, MODULE_STRING "-cddb-enabled" );
#endif
p_cdda->b_header = VLC_FALSE;
p_cdda->p_cddev = p_cddev;
p_cdda->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" );
dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
printf("+++debug: %d\n", p_cdda->i_debug);
p_input->i_mtu = CDDA_DATA_ONCE;
dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "%s", psz_source );
/* We read the Table Of Content information */
p_cdda->i_nb_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_input),
p_cdda->i_tracks = ioctl_GetTracksMap( VLC_OBJECT(p_access),
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 <= 0 )
{
ioctl_Close( p_cdda->p_cddev );
free( p_cdda );
free( psz_source );
return VLC_EGENERIC;
if( p_cdda->i_tracks < 0 ) {
msg_Err( p_access, "unable to count tracks" );
goto error;
} else if( p_cdda->i_tracks <= 0 ) {
msg_Err( p_access, "no audio tracks found" );
goto error;
}
if( i_track > p_cdda->i_nb_tracks || i_track < 1 )
i_track = 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;
/* Set up p_access */
p_access->pf_read = NULL;
p_access->pf_block = CDDABlock;
p_access->pf_control = CDDAControl;
p_access->pf_seek = CDDASeek;
p_access->info.i_update = 0;
p_access->info.i_size = 0;
p_access->info.i_pos = 0;
p_access->info.b_eof = VLC_FALSE;
p_access->info.i_title = 0;
p_access->info.i_seekpoint = 0;
p_access->p_sys = (access_sys_t *) p_cdda;
CDDAMetaInfo(p_access);
{
char *psz_config_title_fmt = MODULE_STRING "-title-format";
const char *psz_title_fmt =
config_GetPsz( p_access, psz_config_title_fmt );
#ifdef HAVE_LIBCDDB
if (p_cdda->i_cddb_enabled) {
psz_config_title_fmt = MODULE_STRING "-cddb-title-format";
}
#endif /*HAVE_LIBCDDB*/
#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;
for( i = 1 ; i <= p_cdda->i_tracks ; i++ )
{
char * psz_title;
input_title_t *t = p_cdda->p_title[i-1] = vlc_input_title_New();
char *psz_mrl;
asprintf(&psz_mrl, "%s%s@T%u", CDDA_MRL_PREFIX, psz_source, i);
psz_title = CDDAFormatStr(p_access, p_cdda, psz_title_fmt,
psz_mrl, i);
t->psz_name = strdup(psz_title);
t->i_size = ( p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1] ) *
(int64_t)CDIO_CD_FRAMESIZE_RAW;
t->i_length = I64C(1000000) * t->i_size / 44100 / 4;
dbg_print((INPUT_DBG_MRL), "track %d, start=%d, mrl %s",
i, p_cdda->p_sectors[i-1], psz_mrl );
free (psz_mrl);
}
}
#undef area
CDDAPlay( p_input, i_track);
vlc_mutex_unlock( &p_input->stream.stream_lock );
CDDAFixupPlayList(p_input, p_cdda, psz_source, play_single_track);
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 */
var_Create( p_input, MODULE_STRING "-caching",
VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Get( p_input, MODULE_STRING "-caching", &val );
p_input->i_pts_delay = val.i_int * 1000;
free( psz_source );
/* Build a WAV header for the output data */
/* Build a WAV header to put in front of the output data.
This gets sent back in the Block (read) routine.
*/
memset( &p_cdda->waveheader, 0, sizeof(WAVEHEADER) );
SetWLE( &p_cdda->waveheader.Format, 1 ); /*WAVE_FORMAT_PCM*/
SetWLE( &p_cdda->waveheader.BitsPerSample, 16);
......@@ -1109,22 +942,40 @@ E_(Open)( vlc_object_t *p_this )
SetDWLE( &p_cdda->waveheader.BytesPerSec,
2*16/8 /*BytesPerSample*/ * 44100 /*SampleFreq*/ );
p_cdda->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
p_cdda->waveheader.DataLength = 0; /* we just don't know */
p_cdda->i_header_pos = 0;
p_cdda->waveheader.DataLength = 0; /* we just don't know */
/* PTS delay */
var_Create( p_access, MODULE_STRING "-caching",
VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
return VLC_SUCCESS;
error:
ioctl_Close( p_cdda->p_cddev );
free( p_cdda );
error2:
free( psz_source );
return VLC_EGENERIC;
}
/*****************************************************************************
* CDDAClose: closes cdda
* CDDAClose: closes cdda and frees any resources associded with it.
*****************************************************************************/
void
E_(Close)( vlc_object_t *p_this )
E_(CDDAClose)( 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;
access_t *p_access = (access_t *) p_this;
cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
track_t i;
dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
/* Remove playlist titles */
for( i = 0; i < p_cdda->i_tracks; i++ )
{
vlc_input_title_Delete( p_cdda->p_title[i] );
}
ioctl_Close( p_cdda->p_cddev );
cdio_log_set_handler (uninit_log_handler);
......@@ -1136,6 +987,108 @@ E_(Close)( vlc_object_t *p_this )
#endif
free( p_cdda->p_sectors );
if (p_cdda->psz_mcn) free( p_cdda->psz_mcn );
free( p_cdda );
p_cdda_input = NULL;
}
/*****************************************************************************
* Control: The front-end or vlc engine calls here to ether get
* information such as meta information or plugin capabilities or to
* issue miscellaneous "set" requests.
*****************************************************************************/
static int CDDAControl( access_t *p_access, int i_query, va_list args )
{
cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
vlc_bool_t *pb_bool;
int *pi_int;
int i;
dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_EVENT),
"query %d", i_query );
switch( i_query )
{
/* Pass back a copy of meta information that was gathered when we
during the Open/Initialize call.
*/
case ACCESS_GET_META:
{
vlc_meta_t **pp_meta;
pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
dbg_print( INPUT_DBG_META, "Meta copied");
*pp_meta = vlc_meta_Duplicate( p_cdda->p_meta );
return VLC_SUCCESS;
}
return VLC_EGENERIC;
case ACCESS_CAN_SEEK:
case ACCESS_CAN_FASTSEEK:
case ACCESS_CAN_PAUSE:
case ACCESS_CAN_CONTROL_PACE:
pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
*pb_bool = VLC_TRUE;
break;
/* */
case ACCESS_GET_MTU:
pi_int = (int*)va_arg( args, int * );
*pi_int = CDDA_DATA_ONCE;
break;
case ACCESS_GET_PTS_DELAY:
{
int64_t *pi_64;
pi_64 = (int64_t*)va_arg( args, int64_t * );
*pi_64 = 1000 * var_GetInteger( p_access,
MODULE_STRING "-caching" );
break;
}
/* */
case ACCESS_SET_PAUSE_STATE:
break;
case ACCESS_GET_TITLE_INFO:
{ input_title_t ***ppp_title;
ppp_title = (input_title_t***)va_arg( args, input_title_t*** );
pi_int = (int*)va_arg( args, int* );
*((int*)va_arg( args, int* )) = 1; /* Title offset */
/* Duplicate track info */
*pi_int = p_cdda->i_tracks;
*ppp_title = malloc(sizeof( input_title_t **) * p_cdda->i_tracks );
for( i = 0; i < p_cdda->i_tracks; i++ )
{
(*ppp_title)[i] =
vlc_input_title_Duplicate( p_cdda->p_title[i] );
}
}
break;
case ACCESS_SET_TITLE:
i = (int)va_arg( args, int );
if( i != p_access->info.i_title )
{
/* Update info */
p_access->info.i_update |=
INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE;
p_access->info.i_title = i;
p_access->info.i_size = p_cdda->p_title[i]->i_size;
p_access->info.i_pos = 0;
/* Next sector to read */
p_cdda->i_sector = p_cdda->p_sectors[i];
}
break;
case ACCESS_SET_SEEKPOINT:
case ACCESS_SET_PRIVATE_ID_STATE:
return VLC_EGENERIC;
default:
msg_Warn( p_access, "unimplemented query in control" );
return VLC_EGENERIC;
}
return VLC_SUCCESS;
}
......@@ -32,13 +32,10 @@
/*****************************************************************************
* prototypes
*****************************************************************************/
int E_(Open) ( vlc_object_t * );
void E_(Close) ( vlc_object_t * );
int E_(CDDAOpen) ( vlc_object_t * );
void E_(CDDAClose) ( vlc_object_t * );
int E_(OpenIntf) ( vlc_object_t * );
void E_(CloseIntf) ( vlc_object_t * );
int E_(DebugCB) ( vlc_object_t *p_this, const char *psz_name,
int E_(CDDADebugCB) ( vlc_object_t *p_this, const char *psz_name,
vlc_value_t oldval, vlc_value_t val,
void *p_data );
......@@ -104,15 +101,15 @@ int E_(CDDBEnabledCB)( vlc_object_t *p_this, const char *psz_name,
*****************************************************************************/
vlc_module_begin();
add_usage_hint( N_("cddax://[device-or-file][@[T]num]") );
add_usage_hint( N_("cddax://[device-or-file][@[T]track]") );
set_description( _("Compact Disc Digital Audio (CD-DA) input") );
set_capability( "access", 75 /* slightly higher than cdda */ );
set_callbacks( E_(Open), E_(Close) );
add_shortcut( "cdda" );
set_capability( "access2", 10 /* slightly higher than cdda */ );
set_callbacks( E_(CDDAOpen), E_(CDDAClose) );
add_shortcut( "cddax" );
add_shortcut( "cd" );
/* Configuration options */
add_integer ( MODULE_STRING "-debug", 0, E_(DebugCB),
add_integer ( MODULE_STRING "-debug", 0, E_(CDDADebugCB),
N_("If nonzero, this gives additional debug information."),
DEBUG_LONGTEXT, VLC_TRUE );
......
......@@ -3,7 +3,7 @@
* using libcdio, libvcd and libvcdinfo
*****************************************************************************
* Copyright (C) 2003 VideoLAN
* $Id: cdda.h,v 1.6 2004/02/14 17:25:39 gbazin Exp $
* $Id$
*
* Author: Rocky Bernstein <rocky@panix.com>
*
......@@ -23,6 +23,7 @@
*****************************************************************************/
#include "../vcdx/cdrom.h"
#include "vlc_meta.h"
#ifdef HAVE_LIBCDDB
#include <cddb/cddb.h>
......@@ -45,7 +46,7 @@
#if INPUT_DEBUG
#define dbg_print(mask, s, args...) \
if (p_cdda->i_debug & mask) \
msg_Dbg(p_input, "%s: "s, __func__ , ##args)
msg_Dbg(p_access, "%s: "s, __func__ , ##args)
#else
#define dbg_print(mask, s, args...)
#endif
......@@ -55,15 +56,20 @@
*****************************************************************************/
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 */
cddev_t *p_cddev; /* CD device descriptor */
int i_tracks; /* # of tracks (titles) */
/* Current position */
int i_track; /* Current track */
lsn_t i_sector; /* Current Sector */
lsn_t * p_sectors; /* Track sectors */
int i_debug; /* Debugging mask */
char * mcn; /* Media Catalog Number */
intf_thread_t *p_intf;
char * psz_mcn; /* Media Catalog Number */
vlc_meta_t *p_meta;
input_title_t *p_title[CDIO_CD_MAX_TRACKS];
#ifdef HAVE_LIBCDDB
int i_cddb_enabled;
......@@ -76,7 +82,7 @@ typedef struct cdda_data_s
#endif
WAVEHEADER waveheader; /* Wave header for the output data */
int i_header_pos;
vlc_bool_t b_header;
} cdda_data_t;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment