#include "codecs.h"
#include "vcd/cdrom.h"
+#include <vlc_playlist.h>
+
/*****************************************************************************
* Module descriptior
*****************************************************************************/
add_usage_hint( N_("[cdda:][device][@[track]]") );
add_integer( "cdda-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT,
CACHING_LONGTEXT, VLC_TRUE );
+ add_bool( "cdda-separate-tracks", VLC_TRUE, NULL, NULL, NULL, VLC_TRUE );
+ add_integer( "cdda-track", -1 , NULL, NULL, NULL, VLC_TRUE );
add_shortcut( "cdda" );
add_shortcut( "cddasimple" );
vlc_module_end();
/* Wave header for the output data */
WAVEHEADER waveheader;
vlc_bool_t b_header;
+
+ vlc_bool_t b_separate_items;
+ vlc_bool_t b_single_track;
+ int i_track;
};
static block_t *Block( access_t * );
static int Seek( access_t *, int64_t );
static int Control( access_t *, int, va_list );
+static int GetTracks( access_t *p_access, vlc_bool_t b_separate,
+ playlist_t *p_playlist, playlist_item_t *p_parent );
+
/*****************************************************************************
* Open: open cdda
*****************************************************************************/
vcddev_t *vcddev;
char *psz_name;
- int i;
+
+ vlc_bool_t b_separate_requested;
+ vlc_bool_t b_play = VLC_FALSE;
+ input_thread_t *p_input;
+ playlist_item_t *p_item = NULL;
+ playlist_t *p_playlist = NULL;
+ int i_ret;
+ int i_track;
if( !p_access->psz_path || !*p_access->psz_path )
{
p_access->p_sys = p_sys = malloc( sizeof( access_sys_t ) );
memset( p_sys, 0, sizeof( access_sys_t ) );
p_sys->vcddev = vcddev;
+ p_sys->b_separate_items = VLC_FALSE;
+ p_sys->b_single_track = VLC_FALSE;
p_sys->b_header = VLC_FALSE;
- /* We read the Table Of Content information */
- p_sys->i_titles = ioctl_GetTracksMap( VLC_OBJECT(p_access),
- p_sys->vcddev, &p_sys->p_sectors );
- if( p_sys->i_titles < 0 )
+ b_separate_requested = var_CreateGetBool( p_access,
+ "cdda-separate-tracks" );
+
+ /* We only do separate items if the whole disc is requested -
+ * Dirty hack we access some private data ! */
+ p_input = (input_thread_t *)( p_access->p_parent );
+ /* Do we play a single track ? */
+ i_track = var_CreateGetInteger( p_access, "cdda-track" );
+ if( b_separate_requested && p_input->input.i_title_start == -1 &&
+ i_track <= 0 )
{
- msg_Err( p_access, "unable to count tracks" );
- goto error;
+ p_sys->b_separate_items = VLC_TRUE;
}
- else if( p_sys->i_titles <= 0 )
+ if( i_track > 0 )
{
- msg_Err( p_access, "no audio tracks found" );
- goto error;
+ p_sys->b_single_track = VLC_TRUE;
+ p_sys->i_track = i_track - 1;
}
- /* Build title table */
- for( i = 0; i < p_sys->i_titles; i++ )
+ msg_Dbg( p_access, "Separate items : %i - Single track : %i",
+ p_sys->b_separate_items, p_sys->b_single_track );
+
+ if( p_sys->b_separate_items )
{
- input_title_t *t = p_sys->title[i] = vlc_input_title_New();
+ p_playlist = (playlist_t *) vlc_object_find( p_access,
+ VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
- msg_Dbg( p_access, "title[%d] start=%d", i, p_sys->p_sectors[i] );
- msg_Dbg( p_access, "title[%d] end=%d", i, p_sys->p_sectors[i+1] );
+ if( !p_playlist ) return VLC_EGENERIC;
- asprintf( &t->psz_name, _("Track %i"), i + 1 );
- t->i_size = ( p_sys->p_sectors[i+1] - p_sys->p_sectors[i] ) *
- (int64_t)CDDA_DATA_SIZE;
+ /* Let's check if we need to play */
+ if( &p_playlist->status.p_item->input ==
+ ((input_thread_t *)p_access->p_parent)->input.p_item )
+ {
+ p_item = p_playlist->status.p_item;
+ b_play = VLC_TRUE;
+ msg_Dbg( p_access, "starting Audio CD playback");
+ }
+ else
+ {
+ input_item_t *p_current = ( (input_thread_t*)p_access->p_parent)->
+ input.p_item;
+ p_item = playlist_LockItemGetByInput( p_playlist, p_current );
+ msg_Dbg( p_access, "not starting Audio CD playback");
- t->i_length = I64C(1000000) * t->i_size / 44100 / 4;
+ if( !p_item )
+ {
+ msg_Dbg( p_playlist, "unable to find item in playlist");
+ return -1;
+ }
+ b_play = VLC_FALSE;
+ }
}
- p_sys->i_sector = p_sys->p_sectors[0];
- p_access->info.i_size = p_sys->title[0]->i_size;
+ /* We read the Table Of Content information */
+ if( !p_sys->b_single_track )
+ {
+ i_ret = GetTracks( p_access, p_sys->b_separate_items,
+ p_playlist, p_item );
+ if( i_ret < 0 )
+ {
+ goto error;
+ }
+ }
/* Build a WAV header for the output data */
memset( &p_sys->waveheader, 0, sizeof(WAVEHEADER) );
p_sys->waveheader.DataChunkID = VLC_FOURCC('d', 'a', 't', 'a');
p_sys->waveheader.DataLength = 0; /* we just don't know */
- p_access->info.i_update |= INPUT_UPDATE_META;
+ /* Only update META if we are in old mode */
+ if( !p_sys->b_separate_items && !p_sys->b_single_track )
+ {
+ p_access->info.i_update |= INPUT_UPDATE_META;
+ }
+
+ /* Position on the right sector and update size */
+ if( p_sys->b_single_track )
+ {
+ p_sys->i_sector = p_sys->p_sectors[ p_sys->i_track ];
+ p_access->info.i_size =
+ ( p_sys->p_sectors[p_sys->i_track+1] -
+ p_sys->p_sectors[p_sys->i_track] ) *
+ (int64_t)CDDA_DATA_SIZE;
+ }
/* PTS delay */
var_Create( p_access, "cdda-caching", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
+
+ if( b_play )
+ {
+ playlist_Control( p_playlist, PLAYLIST_VIEWPLAY,
+ p_playlist->status.i_view, p_playlist->status.p_item,
+ NULL );
+ }
return VLC_SUCCESS;
error:
int i_blocks = CDDA_BLOCKS_ONCE;
block_t *p_block;
+ if( p_sys->b_separate_items ) p_access->info.b_eof = VLC_TRUE;
+
/* Check end of file */
if( p_access->info.b_eof ) return NULL;
return p_block;
}
- /* Check end of title */
- while( p_sys->i_sector >= p_sys->p_sectors[p_access->info.i_title + 1] )
+ /* Check end of title - Single track */
+ if( p_sys->b_single_track )
{
- if( p_access->info.i_title + 1 >= p_sys->i_titles )
+ if( p_sys->i_sector >= p_sys->p_sectors[p_sys->i_track + 1] )
{
p_access->info.b_eof = VLC_TRUE;
return NULL;
}
-
- p_access->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SIZE |
- INPUT_UPDATE_META;
- p_access->info.i_title++;
- p_access->info.i_size = p_sys->title[p_access->info.i_title]->i_size;
- p_access->info.i_pos = 0;
+ /* Don't read too far */
+ if( p_sys->i_sector + i_blocks >=
+ p_sys->p_sectors[p_sys->i_track +1] )
+ {
+ i_blocks = p_sys->p_sectors[p_sys->i_track+1] - p_sys->i_sector;
+ }
}
-
- /* Don't read after the end of a title */
- if( p_sys->i_sector + i_blocks >=
- p_sys->p_sectors[p_access->info.i_title + 1] )
+ else
{
- i_blocks = p_sys->p_sectors[p_access->info.i_title + 1 ] -
- p_sys->i_sector;
+ /* Check end of title - Normal */
+ while( p_sys->i_sector >= p_sys->p_sectors[p_access->info.i_title + 1] )
+ {
+ if( p_access->info.i_title + 1 >= p_sys->i_titles )
+ {
+ p_access->info.b_eof = VLC_TRUE;
+ return NULL;
+ }
+
+ p_access->info.i_update |= INPUT_UPDATE_TITLE | INPUT_UPDATE_SIZE |
+ INPUT_UPDATE_META;
+ p_access->info.i_title++;
+ p_access->info.i_size =
+ p_sys->title[p_access->info.i_title]->i_size;
+ p_access->info.i_pos = 0;
+ }
+ /* Don't read too far */
+ if( p_sys->i_sector + i_blocks >= p_sys->p_sectors[p_access->info.i_title + 1] )
+ {
+ i_blocks = p_sys->p_sectors[ p_access->info.i_title + 1] -
+ p_sys->i_sector;
+ }
}
/* Do the actual reading */
access_sys_t *p_sys = p_access->p_sys;
/* Next sector to read */
- p_sys->i_sector = p_sys->p_sectors[p_access->info.i_title] +
- i_pos / CDDA_DATA_SIZE;
+ p_sys->i_sector = p_sys->p_sectors[
+ (p_sys->b_single_track ?
+ p_sys->i_track :
+ p_access->info.i_title + 1)
+ ] +
+ i_pos / CDDA_DATA_SIZE;
p_access->info.i_pos = i_pos;
return VLC_SUCCESS;
break;
case ACCESS_GET_TITLE_INFO:
+ if( p_sys->b_single_track )
+ return VLC_EGENERIC;
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 */
break;
case ACCESS_SET_TITLE:
+ if( p_sys->b_single_track ) return VLC_EGENERIC;
i = (int)va_arg( args, int );
if( i != p_access->info.i_title )
{
break;
case ACCESS_GET_META:
+ if( p_sys->b_single_track ) return VLC_EGENERIC;
psz_title = malloc( strlen( _("Audio CD - Track ") ) + 5 );
snprintf( psz_title, 100, _("Audio CD - Track %i" ),
p_access->info.i_title+1 );
}
return VLC_SUCCESS;
}
+
+static int GetTracks( access_t *p_access, vlc_bool_t b_separate,
+ playlist_t *p_playlist, playlist_item_t *p_parent )
+{
+ access_sys_t *p_sys = p_access->p_sys;
+ int i;
+ playlist_item_t *p_item;
+ p_sys->i_titles = ioctl_GetTracksMap( VLC_OBJECT(p_access),
+ p_sys->vcddev, &p_sys->p_sectors );
+ if( p_sys->i_titles < 0 )
+ {
+ msg_Err( p_access, "unable to count tracks" );
+ return VLC_EGENERIC;;
+ }
+ else if( p_sys->i_titles <= 0 )
+ {
+ msg_Err( p_access, "no audio tracks found" );
+ return VLC_EGENERIC;
+ }
+
+ if( b_separate )
+ {
+ if( p_parent->i_children == -1 )
+ {
+ playlist_LockItemToNode( p_playlist, p_parent );
+ }
+ }
+
+ /* Build title table */
+ for( i = 0; i < p_sys->i_titles; i++ )
+ {
+ msg_Dbg( p_access, "track[%d] start=%d", i, p_sys->p_sectors[i] );
+ if( !b_separate )
+ {
+ input_title_t *t = p_sys->title[i] = vlc_input_title_New();
+
+ asprintf( &t->psz_name, _("Track %i"), i + 1 );
+ t->i_size = ( p_sys->p_sectors[i+1] - p_sys->p_sectors[i] ) *
+ (int64_t)CDDA_DATA_SIZE;
+
+ t->i_length = I64C(1000000) * t->i_size / 44100 / 4;
+ }
+ else
+ {
+ char *psz_uri;
+ int i_path_len = p_access->psz_path ? strlen( p_access->psz_path )
+ : 0;
+ char *psz_name = malloc( strlen( _("Audio CD - Track ") ) + 5 );
+ char *psz_opt = (char*)malloc( 14 );
+
+ psz_uri = (char*)malloc( i_path_len + 13 );
+ snprintf( psz_uri, i_path_len + 13, "cdda://%s",
+ p_access->psz_path ? p_access->psz_path : "" );
+ snprintf( psz_name, 100, _("Audio CD - Track %i" ),
+ (i+1) );
+ snprintf( psz_opt, 14, "cdda-track=%i", i+1 );
+ /* Create playlist items */
+ p_item = playlist_ItemNewWithType( VLC_OBJECT( p_playlist ),
+ psz_uri, psz_name, ITEM_TYPE_DISC );
+ playlist_ItemAddOption( p_item, psz_opt );
+ playlist_NodeAddItem( p_playlist, p_item,
+ p_parent->pp_parents[0]->i_view,
+ p_parent, PLAYLIST_APPEND, PLAYLIST_END );
+ free( psz_uri ); free( psz_opt );
+ }
+ }
+
+ p_sys->i_sector = p_sys->p_sectors[0];
+ if( p_sys->b_separate_items )
+ {
+ p_sys->i_titles = 0;
+ }
+
+ return VLC_SUCCESS;
+}