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 ...@@ -1486,46 +1486,46 @@ then
VLC_ADD_PLUGINS([pvr]) VLC_ADD_PLUGINS([pvr])
fi fi
dnl dnl dnl
dnl dnl VCDX and CDDAX modules dnl VCDX and CDDAX modules
dnl dnl dnl
dnl AC_ARG_ENABLE(libcdio, AC_ARG_ENABLE(libcdio,
dnl [ --enable-libcdio CDDA support via libcdio (default enabled)]) [ --enable-libcdio CDDA support via libcdio (default enabled)])
dnl
dnl AC_ARG_ENABLE(libcddb, AC_ARG_ENABLE(libcddb,
dnl [ --enable-libcddb CDDB support for CDDAX (default enabled)]) [ --enable-libcddb CDDB support for CDDAX (default enabled)])
dnl
dnl AC_ARG_ENABLE(vcdx, dnl AC_ARG_ENABLE(vcdx,
dnl [ --enable-vcdx VCD support with Navigation (default enabled)]) dnl [ --enable-vcdx VCD support with Navigation (default enabled)])
dnl
dnl AC_ARG_ENABLE(cdda, AC_ARG_ENABLE(cdda,
dnl [ --enable-cdda CDDA plugin support (default enabled)]) [ --enable-cdda CDDA plugin support (default enabled)])
dnl
dnl AC_ARG_ENABLE(cddax, AC_ARG_ENABLE(cddax,
dnl [ --enable-cddax CDDAX plugin support (default enabled)]) [ --enable-cddax CDDAX plugin support (default enabled)])
dnl
dnl if test "${enable_cddax}" != "no" if test "${enable_cddax}" != "no"
dnl then then
dnl PKG_CHECK_MODULES(LIBCDIO, libcdio >= 0.65, PKG_CHECK_MODULES(LIBCDIO, libcdio >= 0.70,
dnl [enable_cddax="no" [enable_cddax="no"
dnl AC_DEFINE(HAVE_CDDAX, [], [Define for the CD-DA plugin using libcdio]) AC_DEFINE(HAVE_CDDAX, [], [Define for the CD-DA plugin using libcdio])
dnl VLC_ADD_LDFLAGS([cddax],[$LIBCDIO_LIBS]) VLC_ADD_LDFLAGS([cddax],[$LIBCDIO_LIBS])
dnl VLC_ADD_CFLAGS([cddax],[$LIBCDIO_CFLAGS]) VLC_ADD_CFLAGS([cddax],[$LIBCDIO_CFLAGS])
dnl VLC_ADD_PLUGINS([cddax])], VLC_ADD_PLUGINS([cddax])],
dnl [AC_MSG_WARN(libcdio library not found) [AC_MSG_WARN(libcdio library not found)
dnl HAVE_CDDAX=no]) HAVE_CDDAX=no])
dnl
dnl if test "$enable_libcddb" != "no"; then if test "$enable_libcddb" != "no"; then
dnl PKG_CHECK_MODULES(LIBCDDB, libcddb >= 0.9.4, [ PKG_CHECK_MODULES(LIBCDDB, libcddb >= 0.9.4, [
dnl HAVE_LIBCDDB=yes HAVE_LIBCDDB=yes
dnl AC_DEFINE(HAVE_LIBCDDB, [], [Define this if you have libcddb installed]) AC_DEFINE(HAVE_LIBCDDB, [], [Define this if you have libcddb installed])
dnl VLC_ADD_LDFLAGS([cddax],[$LIBCDDB_LIBS]) VLC_ADD_LDFLAGS([cddax],[$LIBCDDB_LIBS])
dnl VLC_ADD_CFLAGS([cddax],[$LIBCDDB_CFLAGS]) VLC_ADD_CFLAGS([cddax],[$LIBCDDB_CFLAGS])
dnl ], ],
dnl [AC_MSG_WARN(new enough libcddb not found. CDDB access disabled) [AC_MSG_WARN(new enough libcddb not found. CDDB access disabled)
dnl HAVE_LIBCDDB=no]) HAVE_LIBCDDB=no])
dnl fi fi
dnl
dnl if test "${enable_vcdx}" != "no" dnl if test "${enable_vcdx}" != "no"
dnl then dnl then
dnl PKG_CHECK_MODULES(VCDINFO, libvcdinfo >= 0.7.20, dnl PKG_CHECK_MODULES(VCDINFO, libvcdinfo >= 0.7.20,
...@@ -1538,7 +1538,7 @@ dnl VLC_ADD_PLUGINS([vcdx])], ...@@ -1538,7 +1538,7 @@ dnl VLC_ADD_PLUGINS([vcdx])],
dnl [AC_MSG_WARN(vcdinfo library not found) dnl [AC_MSG_WARN(vcdinfo library not found)
dnl HAVE_VCDX=no]) dnl HAVE_VCDX=no])
dnl fi dnl fi
dnl fi fi
dnl dnl
dnl VCD module dnl VCD module
......
...@@ -36,6 +36,30 @@ ...@@ -36,6 +36,30 @@
#define VLC_META_SETTING N_("Setting") #define VLC_META_SETTING N_("Setting")
#define VLC_META_URL N_("URL") #define VLC_META_URL N_("URL")
#define VLC_META_LANGUAGE N_("Language") #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_NAME N_("Codec Name")
#define VLC_META_CODEC_DESCRIPTION N_("Codec Description") #define VLC_META_CODEC_DESCRIPTION N_("Codec Description")
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <vlc/vlc.h> #include <vlc/vlc.h>
#include <vlc/intf.h> #include <vlc/input.h>
#include <sys/types.h> #include <sys/types.h>
#include <cdio/cdio.h> #include <cdio/cdio.h>
...@@ -58,26 +58,16 @@ ...@@ -58,26 +58,16 @@
#define CDDA_MRL_PREFIX "cddax://" #define CDDA_MRL_PREFIX "cddax://"
/* FIXME: This variable is a hack. Would be nice to eliminate. */ /* 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 * Local prototypes
*****************************************************************************/ *****************************************************************************/
static int CDDARead ( input_thread_t *, byte_t *, size_t ); static block_t *CDDABlock( access_t * p_access );
static void CDDASeek ( input_thread_t *, off_t ); static int CDDASeek( access_t * p_access, int64_t i_pos );
static int CDDASetArea ( input_thread_t *, input_area_t * ); static int CDDAControl( access_t *p_access, int i_query,
static int CDDASetProgram ( input_thread_t *, pgrm_descriptor_t * ); va_list args );
static void CDDAMetaInfo( access_t *p_access );
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
/**************************************************************************** /****************************************************************************
* Private functions * Private functions
...@@ -87,7 +77,7 @@ static void CDDAUpdateVar( input_thread_t *p_input, int i_entry, int i_action, ...@@ -87,7 +77,7 @@ static void CDDAUpdateVar( input_thread_t *p_input, int i_entry, int i_action,
static void static void
cdio_log_handler (cdio_log_level_t level, const char message[]) 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) { switch (level) {
case CDIO_LOG_DEBUG: case CDIO_LOG_DEBUG:
case CDIO_LOG_INFO: case CDIO_LOG_INFO:
...@@ -103,7 +93,7 @@ cdio_log_handler (cdio_log_level_t level, const char message[]) ...@@ -103,7 +93,7 @@ cdio_log_handler (cdio_log_level_t level, const char message[])
break; break;
default: default:
msg_Warn( p_cdda_input, message, msg_Warn( p_cdda_input, message,
_("The above message had unknown vcdimager log level"), _("The above message had unknown cdio log level"),
level); level);
} }
return; return;
...@@ -117,7 +107,7 @@ cdio_log_handler (cdio_log_level_t level, const char message[]) ...@@ -117,7 +107,7 @@ cdio_log_handler (cdio_log_level_t level, const char message[])
static void static void
cddb_log_handler (cddb_log_level_t level, const char message[]) 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) { switch (level) {
case CDDB_LOG_DEBUG: case CDDB_LOG_DEBUG:
case CDDB_LOG_INFO: case CDDB_LOG_INFO:
...@@ -136,7 +126,7 @@ cddb_log_handler (cddb_log_level_t level, const char message[]) ...@@ -136,7 +126,7 @@ cddb_log_handler (cddb_log_level_t level, const char message[])
static void static void
uninit_log_handler (cdio_log_level_t level, const char message[]) 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) { switch (level) {
case CDIO_LOG_DEBUG: case CDIO_LOG_DEBUG:
case CDIO_LOG_INFO: case CDIO_LOG_INFO:
...@@ -163,283 +153,107 @@ uninit_log_handler (cdio_log_level_t level, const char message[]) ...@@ -163,283 +153,107 @@ uninit_log_handler (cdio_log_level_t level, const char message[])
} }
/***************************************************************************** /*****************************************************************************
* CDDAPlay: Arrange things so we play the specified track. * CDDARead: reads CDDA_BLOCKS_ONCE from the CD-DA and returns an
* VLC_TRUE is returned if there was no error. * 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 static block_t *
CDDAPlay( input_thread_t *p_input, int i_track ) 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 ) dbg_print((INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_LSN), "called %d",
return VLC_FALSE; p_cdda->i_sector);
CDDASetArea( p_input, p_input->stream.pp_areas[i_track] ); /* Check end of file */
return VLC_TRUE; if( p_access->info.b_eof ) return NULL;
}
/***************************************************************************** if( !p_cdda->b_header )
* CDDARead: reads from the CDDA into PES packets. {
***************************************************************************** /* Return only the dummy RIFF header we created in Open/Init */
* Returns -1 in case of error, 0 in case of EOF, otherwise the number of p_block = block_New( p_access, sizeof( WAVEHEADER ) );
* bytes. memcpy( p_block->p_buffer, &p_cdda->waveheader, sizeof(WAVEHEADER) );
*****************************************************************************/ p_cdda->b_header = VLC_TRUE;
static int CDDARead( input_thread_t * p_input, byte_t * p_buffer, return p_block;
size_t i_len )
{
cdda_data_t * p_cdda;
int i_blocks;
int i_index;
int i_read;
p_cdda = (cdda_data_t *)p_input->p_access_data;
/* Compute the number of blocks we have to read */
i_blocks = i_len / CDIO_CD_FRAMESIZE_RAW;
i_read = 0;
if( !p_cdda->i_header_pos )
{
p_cdda->i_header_pos = sizeof(WAVEHEADER);
i_blocks = (i_len - sizeof(WAVEHEADER)) / CDIO_CD_FRAMESIZE_RAW;
memcpy( p_buffer, &p_cdda->waveheader, sizeof(WAVEHEADER) );
p_buffer += sizeof(WAVEHEADER);
i_read += sizeof(WAVEHEADER);
} }
for( i_index = 0; i_index < i_blocks; i_index++ ) /* Check end of track */
while( p_cdda->i_sector >= p_cdda->p_sectors[p_access->info.i_title + 1] )
{ {
if( p_access->info.i_title + 1 >= p_cdda->i_tracks )
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 %lu", p_access->info.b_eof = VLC_TRUE;
(long unsigned int) p_cdda->i_sector ); return NULL;
return -1;
} }
p_cdda->i_sector ++; p_access->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SIZE;
if( p_cdda->i_sector == p_cdda->p_sectors[p_cdda->i_track + 1] ) p_access->info.i_title++;
{ p_access->info.i_size =
input_area_t *p_area; p_cdda->p_title[p_access->info.i_title]->i_size;
p_access->info.i_pos = 0;
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;
} }
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; /* Do the actual reading */
} p_block = block_New( p_access, i_blocks * CDIO_CD_FRAMESIZE_RAW );
if( !p_block)
/*****************************************************************************
* CDDASetProgram: Does nothing since a CDDA is mono_program
*****************************************************************************/
static int CDDASetProgram( input_thread_t * p_input,
pgrm_descriptor_t * p_program)
{
cdda_data_t * p_cdda= (cdda_data_t *) p_input->p_access_data;
dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" );
return 0;
}
/*****************************************************************************
* CDDASetArea: initialize input data for title x.
* It should be called for each user navigation request.
****************************************************************************/
static int CDDASetArea( input_thread_t * p_input, input_area_t * p_area )
{
cdda_data_t *p_cdda = (cdda_data_t*) p_input->p_access_data;
vlc_value_t val;
vlc_value_t text;
dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "");
text.psz_string = _("Track");
var_Change( p_input, "title", VLC_VAR_SETTEXT, &text, NULL );
/* we can't use the interface slider until initilization is complete */
p_input->stream.b_seekable = 0;
if( p_area != p_input->stream.p_selected_area )
{ {
/* Change the default area */ msg_Err( p_access, "cannot get a new block of size: %i",
p_input->stream.p_selected_area = p_area; i_blocks * CDIO_CD_FRAMESIZE_RAW );
return NULL;
/* 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]; if( cdio_read_audio_sectors( p_cdda->p_cddev->cdio, p_block->p_buffer,
p_cdda->i_sector, i_blocks) != 0 )
p_input->stream.p_selected_area->i_tell = {
(off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW msg_Err( p_access, "could not read sector %lu",
- p_input->stream.p_selected_area->i_start; (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_cdda->i_sector += i_blocks;
p_input->stream.b_seekable = 1; p_access->info.i_pos += p_block->i_buffer;
p_input->stream.b_changed = 1;
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; cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
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_cdda->i_sector = p_cdda->p_sectors[p_access->info.i_title]
p_input->stream.p_selected_area->i_tell = + i_pos / CDIO_CD_FRAMESIZE_RAW;
(off_t)p_cdda->i_sector * (off_t)CDIO_CD_FRAMESIZE_RAW p_access->info.i_pos = i_pos;
- 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), dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK),
"sector %lu, offset: %lld, i_tell: %lld", "sector %lu, offset: %lld",
(long unsigned int) p_cdda->i_sector, i_off, (long unsigned int) p_cdda->i_sector, i_pos );
p_input->stream.p_selected_area->i_tell ); return VLC_SUCCESS;
}
#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
}
}
} }
#ifdef HAVE_LIBCDDB #ifdef HAVE_LIBCDDB
#define free_and_dup(var, val) \ #define free_and_dup(var, val) \
...@@ -448,80 +262,82 @@ static void InformationCreate( input_thread_t *p_input ) ...@@ -448,80 +262,82 @@ static void InformationCreate( input_thread_t *p_input )
static void 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), "" ); 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; int i, i_matches;
cddb_conn_t *conn = cddb_new(); 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); cddb_log_set_handler (uninit_log_handler);
if (!conn) { if (!conn) {
msg_Warn( p_input, "unable to initialize libcddb" ); msg_Warn( p_access, "unable to initialize libcddb" );
goto cddb_destroy; goto cddb_destroy;
} }
cddb_set_email_address( conn, cddb_set_email_address( conn,
config_GetPsz( p_input, config_GetPsz( p_access,
MODULE_STRING "-cddb-email") ); MODULE_STRING "-cddb-email") );
cddb_set_server_name( conn, cddb_set_server_name( conn,
config_GetPsz( p_input, config_GetPsz( p_access,
MODULE_STRING "-cddb-server") ); MODULE_STRING "-cddb-server") );
cddb_set_server_port(conn, cddb_set_server_port(conn,
config_GetInt( p_input, config_GetInt( p_access,
MODULE_STRING "-cddb-port") ); MODULE_STRING "-cddb-port") );
/* Set the location of the local CDDB cache directory. /* Set the location of the local CDDB cache directory.
The default location of this directory is */ 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_disable(conn);
cddb_cache_set_dir(conn, cddb_cache_set_dir(conn,
config_GetPsz( p_input, config_GetPsz( p_access,
MODULE_STRING "-cddb-cachedir") ); MODULE_STRING "-cddb-cachedir") );
cddb_set_timeout(conn, 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); cddb_http_enable(conn);
} else } else
cddb_http_disable(conn); cddb_http_disable(conn);
p_cdda->cddb.disc = cddb_disc_new(); p_cdda->cddb.disc = cddb_disc_new();
if (!p_cdda->cddb.disc) { 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; 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(); 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); cddb_disc_add_track(p_cdda->cddb.disc, t);
} }
p_cdda->cddb.disc->length = 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; / CDIO_CD_FRAMES_PER_SEC;
if (!cddb_disc_calc_discid(p_cdda->cddb.disc)) { 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; goto cddb_destroy;
} }
i_matches = cddb_query(conn, p_cdda->cddb.disc); i_matches = cddb_query(conn, p_cdda->cddb.disc);
if (i_matches > 0) { if (i_matches > 0) {
if (i_matches > 1) 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); i_matches);
cddb_read(conn, p_cdda->cddb.disc); cddb_read(conn, p_cdda->cddb.disc);
...@@ -529,7 +345,7 @@ GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda ) ...@@ -529,7 +345,7 @@ GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
cddb_disc_print(p_cdda->cddb.disc); cddb_disc_print(p_cdda->cddb.disc);
} else { } 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: cddb_destroy:
...@@ -539,6 +355,101 @@ GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda ) ...@@ -539,6 +355,101 @@ GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
} }
#endif /*HAVE_LIBCDDB*/ #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) \ #define add_format_str_info(val) \
{ \ { \
const char *str = val; \ const char *str = val; \
...@@ -587,8 +498,8 @@ GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda ) ...@@ -587,8 +498,8 @@ GetCDDBInfo( const input_thread_t *p_input, cdda_data_t *p_cdda )
%% : a % %% : a %
*/ */
static char * static char *
CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda, CDDAFormatStr( const access_t *p_access, cdda_data_t *p_cdda,
const char format_str[], const char *mrl, int i_track) const char format_str[], const char *mrl, int i_track)
{ {
#define TEMP_STR_SIZE 256 #define TEMP_STR_SIZE 256
#define TEMP_STR_LEN (TEMP_STR_SIZE-1) #define TEMP_STR_LEN (TEMP_STR_SIZE-1)
...@@ -618,30 +529,36 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda, ...@@ -618,30 +529,36 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
#ifdef HAVE_LIBCDDB #ifdef HAVE_LIBCDDB
case 'a': case 'a':
if (!p_cdda->i_cddb_enabled) goto not_special; 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; break;
case 'A': case 'A':
if (!p_cdda->i_cddb_enabled) goto not_special; 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; break;
case 'C': case 'C':
if (!p_cdda->i_cddb_enabled) goto not_special; 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; break;
case 'G': case 'G':
if (!p_cdda->i_cddb_enabled) goto not_special; 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; break;
case 'I': case 'I':
if (!p_cdda->i_cddb_enabled) goto not_special; 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; break;
case 'Y': case 'Y':
if (!p_cdda->i_cddb_enabled) goto not_special; 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; break;
case 't': 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, cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
i_track-1); i_track-1);
if (t != NULL && t->title != NULL) if (t != NULL && t->title != NULL)
...@@ -649,7 +566,7 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda, ...@@ -649,7 +566,7 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
} else goto not_special; } else goto not_special;
break; break;
case 'p': 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, cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
i_track-1); i_track-1);
if (t != NULL && t->artist != NULL) if (t != NULL && t->artist != NULL)
...@@ -657,7 +574,7 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda, ...@@ -657,7 +574,7 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
} else goto not_special; } else goto not_special;
break; break;
case 'e': 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, cddb_track_t *t=cddb_disc_get_track(p_cdda->cddb.disc,
i_track-1); i_track-1);
if (t != NULL && t->ext_data != NULL) if (t != NULL && t->ext_data != NULL)
...@@ -670,17 +587,14 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda, ...@@ -670,17 +587,14 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
add_format_str_info(mrl); add_format_str_info(mrl);
break; break;
#if FINISHED
case 'm': case 'm':
add_format_str_info(p_cdda->mcn); add_format_str_info(p_cdda->psz_mcn);
break; break;
#endif
case 'n': case 'n':
add_format_num_info(p_cdda->i_nb_tracks, "%d"); add_format_num_info(p_cdda->i_tracks, "%d");
break; break;
#ifdef HAVE_LIBCDDB
case 's': case 's':
if (p_cdda->i_cddb_enabled) { if (p_cdda->i_cddb_enabled) {
char psz_buffer[MSTRTIME_MAX_SIZE]; char psz_buffer[MSTRTIME_MAX_SIZE];
...@@ -690,7 +604,6 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda, ...@@ -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 ) ); add_format_str_info(secstotimestr( psz_buffer, i_duration ) );
} else goto not_special; } else goto not_special;
break; break;
#endif
case 'T': case 'T':
add_format_num_info(i_track, "%02d"); add_format_num_info(i_track, "%02d");
...@@ -707,8 +620,9 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda, ...@@ -707,8 +620,9 @@ CDDAFormatStr(const input_thread_t *p_input, cdda_data_t *p_cdda,
return strdup(temp_str); return strdup(temp_str);
} }
#ifdef TRACK_META_INFORMATION_FINISHED
static void 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, playlist_t *p_playlist, unsigned int i_track,
char *psz_mrl, int psz_mrl_max, char *psz_mrl, int psz_mrl_max,
const char *psz_source, int playlist_operation, const char *psz_source, int playlist_operation,
...@@ -731,8 +645,8 @@ CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda, ...@@ -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", snprintf(psz_mrl, psz_mrl_max, "%s%s@T%u",
CDDA_MRL_PREFIX, psz_source, i_track); CDDA_MRL_PREFIX, psz_source, i_track);
p_title = CDDAFormatStr(p_input, p_cdda, p_title = CDDAFormatStr(p_access, p_cdda,
config_GetPsz( p_input, config_varname ), config_GetPsz( p_access, config_varname ),
psz_mrl, i_track); psz_mrl, i_track);
dbg_print( INPUT_DBG_META, "mrl: %s, title: %s, duration, %ld, pos %d", 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, ...@@ -751,8 +665,8 @@ CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
vlc_mutex_lock( &p_item->input.lock ); vlc_mutex_lock( &p_item->input.lock );
p_author = p_author =
CDDAFormatStr( p_input, p_cdda, CDDAFormatStr( p_access, p_cdda,
config_GetPsz( p_input, MODULE_STRING "-author-format" ), config_GetPsz( p_access, MODULE_STRING "-author-format" ),
psz_mrl, i_track ); psz_mrl, i_track );
playlist_ItemAddInfo( p_item , _("General"),_("Author"), p_author); playlist_ItemAddInfo( p_item , _("General"),_("Author"), p_author);
...@@ -797,89 +711,54 @@ CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda, ...@@ -797,89 +711,54 @@ CDDACreatePlayListItem(const input_thread_t *p_input, cdda_data_t *p_cdda,
} }
static int static int
CDDAFixupPlayList( input_thread_t *p_input, cdda_data_t *p_cdda, CDDAFixupPlayList( access_t *p_access, cdda_data_t *p_cdda,
const char *psz_source, bool play_single_track) const char *psz_source, track_t i_track)
{ {
int i; int i;
playlist_t * p_playlist;
char * psz_mrl; char * psz_mrl;
unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) + unsigned int psz_mrl_max = strlen(CDDA_MRL_PREFIX) + strlen(psz_source) +
strlen("@T") + strlen("100") + 1; 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 ); psz_mrl = malloc( psz_mrl_max );
if( psz_mrl == NULL ) if( psz_mrl == NULL )
{ {
msg_Warn( p_input, "out of memory" ); msg_Warn( p_access, "out of memory" );
return -1; return -1;
} }
p_playlist = (playlist_t *) vlc_object_find( p_input, VLC_OBJECT_PLAYLIST, CDDAMetaInfo(p_access);
FIND_ANYWHERE );
if( !p_playlist ) for( i = 1 ; i <= p_cdda->i_tracks ; i++ )
{ {
msg_Warn( p_input, "can't find playlist" ); input_title_t *t = p_cdda->p_sectors[i-1] = vlc_input_title_New();
free(psz_mrl);
return -1; 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; return 0;
} }
#endif /* TRACK_META_INFORMATION_FINISHED*/
/**************************************************************************** /****************************************************************************
* Public functions * Public functions
****************************************************************************/ ****************************************************************************/
int int
E_(DebugCB) ( vlc_object_t *p_this, const char *psz_name, E_(CDDADebugCB) ( vlc_object_t *p_this, const char *psz_name,
vlc_value_t oldval, vlc_value_t val, void *p_data ) vlc_value_t oldval, vlc_value_t val, void *p_data )
{ {
cdda_data_t *p_cdda; cdda_data_t *p_cdda;
if (NULL == p_cdda_input) return VLC_EGENERIC; 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)) { 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", 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, ...@@ -897,7 +776,7 @@ E_(CDDBEnabledCB) ( vlc_object_t *p_this, const char *psz_name,
if (NULL == p_cdda_input) return VLC_EGENERIC; 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 #ifdef HAVE_LIBCDDB
if (p_cdda->i_debug & (INPUT_DBG_CALL|INPUT_DBG_EXT)) { 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, ...@@ -910,83 +789,30 @@ E_(CDDBEnabledCB) ( vlc_object_t *p_this, const char *psz_name,
return VLC_SUCCESS; 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 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; access_t *p_access = (access_t*)p_this;
char * psz_orig;
char * psz_parser;
char * psz_source; char * psz_source;
cdda_data_t * p_cdda; cdda_data_t * p_cdda;
int i; int i;
int i_track = 1;
cddev_t *p_cddev; cddev_t *p_cddev;
vlc_value_t val;
bool play_single_track = false;
/* Set where to log errors messages from libcdio. */ /* 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 : */ if( !p_access->psz_path || !*p_access->psz_path )
psz_orig = psz_parser = psz_source = strdup( p_input->psz_name );
if( !psz_orig )
{
return( -1 );
}
while( *psz_parser && *psz_parser != '@' )
{ {
psz_parser++; /* Only when selected */
} if( !p_this->b_force ) return VLC_EGENERIC;
if( *psz_parser == '@' )
{
/* Found options */
*psz_parser = '\0';
++psz_parser;
if ('T' == *psz_parser || 't' == *psz_parser )
++psz_parser;
i_track = (int)strtol( psz_parser, NULL, 10 ); psz_source = var_CreateGetString( p_this, "cd-audio" );
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" );
if( !psz_source || 0==strlen(psz_source) ) { if( !psz_source || !*psz_source ) {
/* Scan for a CD-ROM drive with a CD-DA in it. */ /* Scan for a CD-ROM drive with a CD-DA in it. */
char **cd_drives = char **cd_drives =
cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false); cdio_get_devices_with_cap(NULL, CDIO_FS_AUDIO, false);
...@@ -999,101 +825,108 @@ E_(Open)( vlc_object_t *p_this ) ...@@ -999,101 +825,108 @@ E_(Open)( vlc_object_t *p_this )
cdio_free_device_list(cd_drives); cdio_free_device_list(cd_drives);
} }
} }
else
psz_source = strdup( p_access->psz_path );
/* Open CDDA */
cdio_log_set_handler ( cdio_log_handler ); 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 )) ) if( !(p_cddev = ioctl_Open( p_this, psz_source )) )
{ {
msg_Warn( p_input, "could not open %s", psz_source ); msg_Warn( p_access, "could not open %s", psz_source );
free( psz_source ); goto error2;
return VLC_EGENERIC;
} }
p_cdda = malloc( sizeof(cdda_data_t) ); p_cdda = malloc( sizeof(cdda_data_t) );
if( p_cdda == NULL ) if( p_cdda == NULL )
{ {
msg_Err( p_input, "out of memory" ); msg_Err( p_access, "out of memory" );
free( psz_source ); free( psz_source );
return VLC_ENOMEM; return VLC_ENOMEM;
} }
p_cdda->p_cddev = p_cddev; #ifdef HAVE_LIBCDDB
p_cdda->i_debug = config_GetInt( p_this, MODULE_STRING "-debug" ); cddb_log_set_handler ( cddb_log_handler );
p_input->p_access_data = (void *)p_cdda; 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 */ /* 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 ); p_cdda->p_cddev->cdio, &p_cdda->p_sectors );
if( p_cdda->i_nb_tracks < 0 ) if( p_cdda->i_tracks < 0 ) {
msg_Err( p_input, "unable to count tracks" ); msg_Err( p_access, "unable to count tracks" );
else if( p_cdda->i_nb_tracks <= 0 ) goto error;
msg_Err( p_input, "no audio tracks found" ); } else if( p_cdda->i_tracks <= 0 ) {
msg_Err( p_access, "no audio tracks found" );
if( p_cdda->i_nb_tracks <= 0 ) goto error;
{
ioctl_Close( p_cdda->p_cddev );
free( p_cdda );
free( psz_source );
return VLC_EGENERIC;
} }
if( i_track > p_cdda->i_nb_tracks || i_track < 1 ) /* Set up p_access */
i_track = 1; p_access->pf_read = NULL;
p_access->pf_block = CDDABlock;
/* Set stream and area data */ p_access->pf_control = CDDAControl;
vlc_mutex_lock( &p_input->stream.stream_lock ); p_access->pf_seek = CDDASeek;
/* Initialize ES structures */ p_access->info.i_update = 0;
input_InitStream( p_input, 0 ); p_access->info.i_size = 0;
p_access->info.i_pos = 0;
/* cdda input method */ p_access->info.b_eof = VLC_FALSE;
p_input->stream.i_method = INPUT_METHOD_CDDA; p_access->info.i_title = 0;
p_access->info.i_seekpoint = 0;
p_input->stream.b_pace_control = 1;
p_input->stream.b_seekable = 1; p_access->p_sys = (access_sys_t *) p_cdda;
p_input->stream.i_mux_rate = 44100 * 4 / 50;
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_tracks ; i++ )
for( i = 1 ; i <= p_cdda->i_nb_tracks ; i++ ) {
{ char * psz_title;
input_AddArea( p_input, i, 1 ); input_title_t *t = p_cdda->p_title[i-1] = vlc_input_title_New();
char *psz_mrl;
/* Absolute start offset and size */
area[i]->i_start = asprintf(&psz_mrl, "%s%s@T%u", CDDA_MRL_PREFIX, psz_source, i);
(off_t)p_cdda->p_sectors[i-1] * (off_t)CDIO_CD_FRAMESIZE_RAW;
area[i]->i_size = psz_title = CDDAFormatStr(p_access, p_cdda, psz_title_fmt,
(off_t)(p_cdda->p_sectors[i] - p_cdda->p_sectors[i-1]) psz_mrl, i);
* (off_t)CDIO_CD_FRAMESIZE_RAW;
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
/* Build a WAV header to put in front of the output data.
CDDAPlay( p_input, i_track); This gets sent back in the Block (read) routine.
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 */
memset( &p_cdda->waveheader, 0, sizeof(WAVEHEADER) ); memset( &p_cdda->waveheader, 0, sizeof(WAVEHEADER) );
SetWLE( &p_cdda->waveheader.Format, 1 ); /*WAVE_FORMAT_PCM*/ SetWLE( &p_cdda->waveheader.Format, 1 ); /*WAVE_FORMAT_PCM*/
SetWLE( &p_cdda->waveheader.BitsPerSample, 16); SetWLE( &p_cdda->waveheader.BitsPerSample, 16);
...@@ -1109,22 +942,40 @@ E_(Open)( vlc_object_t *p_this ) ...@@ -1109,22 +942,40 @@ E_(Open)( vlc_object_t *p_this )
SetDWLE( &p_cdda->waveheader.BytesPerSec, SetDWLE( &p_cdda->waveheader.BytesPerSec,
2*16/8 /*BytesPerSample*/ * 44100 /*SampleFreq*/ ); 2*16/8 /*BytesPerSample*/ * 44100 /*SampleFreq*/ );
p_cdda->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a'); p_cdda->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
p_cdda->waveheader.DataLength = 0; /* we just don't know */ p_cdda->waveheader.DataLength = 0; /* we just don't know */
p_cdda->i_header_pos = 0;
/* PTS delay */
var_Create( p_access, MODULE_STRING "-caching",
VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
return VLC_SUCCESS; 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 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; access_t *p_access = (access_t *) p_this;
cdda_data_t *p_cdda = (cdda_data_t *)p_input->p_access_data; cdda_data_t *p_cdda = (cdda_data_t *) p_access->p_sys;
track_t i;
dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT), "" ); 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 ); ioctl_Close( p_cdda->p_cddev );
cdio_log_set_handler (uninit_log_handler); cdio_log_set_handler (uninit_log_handler);
...@@ -1136,6 +987,108 @@ E_(Close)( vlc_object_t *p_this ) ...@@ -1136,6 +987,108 @@ E_(Close)( vlc_object_t *p_this )
#endif #endif
free( p_cdda->p_sectors ); free( p_cdda->p_sectors );
if (p_cdda->psz_mcn) free( p_cdda->psz_mcn );
free( p_cdda ); free( p_cdda );
p_cdda_input = NULL; 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 @@ ...@@ -32,13 +32,10 @@
/***************************************************************************** /*****************************************************************************
* prototypes * prototypes
*****************************************************************************/ *****************************************************************************/
int E_(Open) ( vlc_object_t * ); int E_(CDDAOpen) ( vlc_object_t * );
void E_(Close) ( vlc_object_t * ); void E_(CDDAClose) ( vlc_object_t * );
int E_(OpenIntf) ( vlc_object_t * ); int E_(CDDADebugCB) ( vlc_object_t *p_this, const char *psz_name,
void E_(CloseIntf) ( vlc_object_t * );
int E_(DebugCB) ( vlc_object_t *p_this, const char *psz_name,
vlc_value_t oldval, vlc_value_t val, vlc_value_t oldval, vlc_value_t val,
void *p_data ); void *p_data );
...@@ -104,15 +101,15 @@ int E_(CDDBEnabledCB)( vlc_object_t *p_this, const char *psz_name, ...@@ -104,15 +101,15 @@ int E_(CDDBEnabledCB)( vlc_object_t *p_this, const char *psz_name,
*****************************************************************************/ *****************************************************************************/
vlc_module_begin(); 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_description( _("Compact Disc Digital Audio (CD-DA) input") );
set_capability( "access", 75 /* slightly higher than cdda */ ); set_capability( "access2", 10 /* slightly higher than cdda */ );
set_callbacks( E_(Open), E_(Close) ); set_callbacks( E_(CDDAOpen), E_(CDDAClose) );
add_shortcut( "cdda" );
add_shortcut( "cddax" ); add_shortcut( "cddax" );
add_shortcut( "cd" );
/* Configuration options */ /* 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."), N_("If nonzero, this gives additional debug information."),
DEBUG_LONGTEXT, VLC_TRUE ); DEBUG_LONGTEXT, VLC_TRUE );
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* using libcdio, libvcd and libvcdinfo * using libcdio, libvcd and libvcdinfo
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * 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> * Author: Rocky Bernstein <rocky@panix.com>
* *
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
*****************************************************************************/ *****************************************************************************/
#include "../vcdx/cdrom.h" #include "../vcdx/cdrom.h"
#include "vlc_meta.h"
#ifdef HAVE_LIBCDDB #ifdef HAVE_LIBCDDB
#include <cddb/cddb.h> #include <cddb/cddb.h>
...@@ -45,7 +46,7 @@ ...@@ -45,7 +46,7 @@
#if INPUT_DEBUG #if INPUT_DEBUG
#define dbg_print(mask, s, args...) \ #define dbg_print(mask, s, args...) \
if (p_cdda->i_debug & mask) \ if (p_cdda->i_debug & mask) \
msg_Dbg(p_input, "%s: "s, __func__ , ##args) msg_Dbg(p_access, "%s: "s, __func__ , ##args)
#else #else
#define dbg_print(mask, s, args...) #define dbg_print(mask, s, args...)
#endif #endif
...@@ -55,15 +56,20 @@ ...@@ -55,15 +56,20 @@
*****************************************************************************/ *****************************************************************************/
typedef struct cdda_data_s typedef struct cdda_data_s
{ {
cddev_t *p_cddev; /* CD device descriptor */ cddev_t *p_cddev; /* CD device descriptor */
int i_nb_tracks; /* Nb of tracks (titles) */ int i_tracks; /* # of tracks (titles) */
int i_track; /* Current track */
lsn_t i_sector; /* Current Sector */ /* Current position */
lsn_t * p_sectors; /* Track sectors */ int i_track; /* Current track */
vlc_bool_t b_end_of_track; /* If the end of track was reached */ lsn_t i_sector; /* Current Sector */
lsn_t * p_sectors; /* Track sectors */
int i_debug; /* Debugging mask */ int i_debug; /* Debugging mask */
char * mcn; /* Media Catalog Number */ char * psz_mcn; /* Media Catalog Number */
intf_thread_t *p_intf; vlc_meta_t *p_meta;
input_title_t *p_title[CDIO_CD_MAX_TRACKS];
#ifdef HAVE_LIBCDDB #ifdef HAVE_LIBCDDB
int i_cddb_enabled; int i_cddb_enabled;
...@@ -76,7 +82,7 @@ typedef struct cdda_data_s ...@@ -76,7 +82,7 @@ typedef struct cdda_data_s
#endif #endif
WAVEHEADER waveheader; /* Wave header for the output data */ WAVEHEADER waveheader; /* Wave header for the output data */
int i_header_pos; vlc_bool_t b_header;
} cdda_data_t; } 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