* access.c: access capabilities for dvdplay plugin.
*****************************************************************************
* Copyright (C) 2001 VideoLAN
- * $Id: access.c,v 1.2 2002/08/07 00:29:36 sam Exp $
+ * $Id: access.c,v 1.19 2003/08/13 01:45:13 gbazin Exp $
*
* Author: Stéphane Borel <stef@via.ecp.fr>
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# include <strings.h>
#endif
-#if defined( WIN32 )
-# include <io.h> /* read() */
-#else
-# include <sys/uio.h> /* struct iovec */
-#endif
-
-#if defined( WIN32 )
-# include "input_iovec.h"
-#endif
-
#include "dvd.h"
#include "es.h"
#include "tools.h"
* Local prototypes
*****************************************************************************/
/* called from outside */
-static int dvdplay_SetArea ( input_thread_t *, input_area_t * );
-static int dvdplay_SetProgram ( input_thread_t *, pgrm_descriptor_t * );
-static int dvdplay_Read ( input_thread_t *, byte_t *, size_t );
-static void dvdplay_Seek ( input_thread_t *, off_t );
+static int dvdplay_SetArea ( input_thread_t *, input_area_t * );
+static int dvdplay_SetProgram ( input_thread_t *, pgrm_descriptor_t * );
+static ssize_t dvdplay_Read ( input_thread_t *, byte_t *, size_t );
+static void dvdplay_Seek ( input_thread_t *, off_t );
-static void pf_vmg_callback ( void*, dvdplay_event_t );
+static void pf_vmg_callback ( void*, dvdplay_event_t );
/* only from inside */
static int dvdNewArea( input_thread_t *, input_area_t * );
static int dvdNewPGC ( input_thread_t * );
+
+static int MenusCallback( vlc_object_t *, char const *,
+ vlc_value_t, vlc_value_t, void * );
+
/*****************************************************************************
* OpenDVD: open libdvdplay
*****************************************************************************/
char * psz_source;
dvd_data_t * p_dvd;
input_area_t * p_area;
- int i_title_nr;
- int i_title;
- int i_chapter;
- int i_angle;
- int i;
-
+ unsigned int i_title_nr;
+ unsigned int i_title;
+ unsigned int i_chapter;
+ unsigned int i_angle;
+ unsigned int i;
+ vlc_value_t val, text;
+
p_dvd = malloc( sizeof(dvd_data_t) );
if( p_dvd == NULL )
{
- msg_Err( p_input, "dvdplay error: out of memory" );
+ msg_Err( p_input, "out of memory" );
return -1;
}
p_input->pf_set_program = dvdplay_SetProgram;
/* command line */
- if( ( psz_source = dvdplay_ParseCL( p_input,
+ if( ( psz_source = dvdplay_ParseCL( p_input,
&i_title, &i_chapter, &i_angle ) ) == NULL )
{
free( p_dvd );
/* Open libdvdplay */
p_dvd->vmg = dvdplay_open( psz_source, pf_vmg_callback, (void*)p_input );
- /* free allocated strings */
- free( psz_source );
-
if( p_dvd->vmg == NULL )
{
- msg_Err( p_input, "dvdplay error: can't open source" );
+ msg_Warn( p_input, "cannot open %s", psz_source );
+ free( psz_source );
free( p_dvd );
return -1;
}
+ /* free allocated strings */
+ free( psz_source );
+
p_dvd->p_intf = NULL;
p_dvd->i_still_time = 0;
-
+
/* set up input */
p_input->i_mtu = 0;
p_input->stream.b_pace_control = 1;
/* seek is only allowed when we have size info */
p_input->stream.b_seekable = 0;
-
+
/* Initialize ES structures */
input_InitStream( p_input, sizeof( stream_ps_data_t ) );
/* Area 0 for menu */
area[0]->i_plugin_data = 0;
-
+ input_DelArea( p_input, p_input->stream.pp_areas[0] );
+ input_AddArea( p_input, 0, 1 );
+
for( i = 1 ; i <= i_title_nr ; i++ )
{
- input_AddArea( p_input );
-
- /* Titles id */
- area[i]->i_id = i;
-
- /* Number of chapters */
- area[i]->i_part_nb = dvdplay_chapter_nr( p_dvd->vmg, i );
-
+ input_AddArea( p_input, i, dvdplay_chapter_nr( p_dvd->vmg, i ) );
area[i]->i_plugin_data = 0;
}
#undef area
vlc_mutex_unlock( &p_input->stream.stream_lock );
return -1;
}
-
+
if( i_angle <= p_input->stream.i_pgrm_number )
{
dvdplay_SetProgram( p_input,
vlc_mutex_unlock( &p_input->stream.stream_lock );
- p_input->psz_demux = "dvdplay";
+ if( !p_input->psz_demux || !*p_input->psz_demux )
+ {
+ p_input->psz_demux = "dvdplay";
+ }
+
+ /* FIXME: we might lose variables here */
+ var_Create( p_input, "x-start", VLC_VAR_INTEGER );
+ var_Create( p_input, "y-start", VLC_VAR_INTEGER );
+ var_Create( p_input, "x-end", VLC_VAR_INTEGER );
+ var_Create( p_input, "y-end", VLC_VAR_INTEGER );
+
+ var_Create( p_input, "color", VLC_VAR_ADDRESS );
+ var_Create( p_input, "contrast", VLC_VAR_ADDRESS );
+
+ var_Create( p_input, "highlight", VLC_VAR_BOOL );
+ var_Create( p_input, "highlight-mutex", VLC_VAR_MUTEX );
+
+ /* Create a few object variables used for navigation in the interfaces */
+ var_Create( p_input, "dvd_menus",
+ VLC_VAR_INTEGER | VLC_VAR_HASCHOICE | VLC_VAR_ISCOMMAND );
+ text.psz_string = _("DVD menus");
+ var_Change( p_input, "dvd_menus", VLC_VAR_SETTEXT, &text, NULL );
+ var_AddCallback( p_input, "dvd_menus", MenusCallback, NULL );
+ val.i_int = ROOT_MENU; text.psz_string = _("Root");
+ var_Change( p_input, "dvd_menus", VLC_VAR_ADDCHOICE, &val, &text );
+ val.i_int = TITLE_MENU; text.psz_string = _("Title");
+ var_Change( p_input, "dvd_menus", VLC_VAR_ADDCHOICE, &val, &text );
+ val.i_int = PART_MENU; text.psz_string = _("Chapter");
+ var_Change( p_input, "dvd_menus", VLC_VAR_ADDCHOICE, &val, &text );
+ val.i_int = SUBPICTURE_MENU; text.psz_string = _("Subtitle");
+ var_Change( p_input, "dvd_menus", VLC_VAR_ADDCHOICE, &val, &text );
+ val.i_int = AUDIO_MENU; text.psz_string = _("Audio");
+ var_Change( p_input, "dvd_menus", VLC_VAR_ADDCHOICE, &val, &text );
+ val.i_int = ANGLE_MENU; text.psz_string = _("Angle");
+ var_Change( p_input, "dvd_menus", VLC_VAR_ADDCHOICE, &val, &text );
+ val.i_int = 99; text.psz_string = _("Resume");
+ var_Change( p_input, "dvd_menus", VLC_VAR_ADDCHOICE, &val, &text );
return 0;
}
input_thread_t * p_input = (input_thread_t *)p_this;
dvd_data_t * p_dvd = (dvd_data_t *)p_input->p_access_data;
+ var_Destroy( p_input, "highlight-mutex" );
+ var_Destroy( p_input, "highlight" );
+
+ var_Destroy( p_input, "x-start" );
+ var_Destroy( p_input, "x-end" );
+ var_Destroy( p_input, "y-start" );
+ var_Destroy( p_input, "y-end" );
+
+ var_Destroy( p_input, "color" );
+ var_Destroy( p_input, "contrast" );
+
/* close libdvdplay */
dvdplay_close( p_dvd->vmg );
{
dvd_data_t * p_dvd;
int i_angle;
-
+ vlc_value_t val;
+
p_dvd = (dvd_data_t*)(p_input->p_access_data);
i_angle = p_program->i_number;
msg_Dbg( p_input, "angle %d selected", i_angle );
}
+
+ /* Update the navigation variables without triggering a callback */
+ val.i_int = p_program->i_number;
+ var_Change( p_input, "program", VLC_VAR_SETVALUE, &val, NULL );
}
return 0;
static int dvdplay_SetArea( input_thread_t * p_input, input_area_t * p_area )
{
dvd_data_t * p_dvd;
+ vlc_value_t val;
p_dvd = (dvd_data_t*)p_input->p_access_data;
if( p_area != p_input->stream.p_selected_area )
{
int i_chapter;
-
+
/* prevent intf to try to seek */
p_input->stream.b_seekable = 0;
-
+
/* Store selected chapter */
i_chapter = p_area->i_part;
dvdNewArea( p_input, p_area );
-
+
+ dvdNewPGC( p_input );
+
dvdplay_start( p_dvd->vmg, p_area->i_id );
-
+
p_area->i_part = i_chapter;
+
} /* i_title >= 0 */
else
{
* Chapter selection
*/
- if( p_area->i_part != dvdplay_chapter_cur( p_dvd->vmg ) )
+ if( (int)p_area->i_part != dvdplay_chapter_cur( p_dvd->vmg ) )
{
if( ( p_area->i_part > 0 ) &&
( p_area->i_part <= p_area->i_part_nb ))
LB2OFF( dvdplay_position( p_dvd->vmg ) ) - p_area->i_start;
p_input->stream.b_changed = 1;
+ /* Update the navigation variables without triggering a callback */
+ val.i_int = p_area->i_part;
+ var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &val, NULL );
+
return 0;
}
* Returns -1 in case of error, the number of bytes read if everything went
* well.
*****************************************************************************/
-static int dvdplay_Read( input_thread_t * p_input,
+static ssize_t dvdplay_Read( input_thread_t * p_input,
byte_t * p_buffer, size_t i_count )
{
dvd_data_t * p_dvd;
off_t i_read;
-
+
p_dvd = (dvd_data_t *)p_input->p_access_data;
vlc_mutex_lock( &p_input->stream.stream_lock );
-
i_read = LB2OFF( dvdplay_read( p_dvd->vmg, p_buffer, OFF2LB( i_count ) ) );
-
- p_input->stream.p_selected_area->i_tell =
- LB2OFF( dvdplay_position( p_dvd->vmg ) ) -
- p_input->stream.p_selected_area->i_start;
-
vlc_mutex_unlock( &p_input->stream.stream_lock );
return i_read;
static void dvdplay_Seek( input_thread_t * p_input, off_t i_off )
{
dvd_data_t * p_dvd;
-
+
p_dvd = (dvd_data_t *)p_input->p_access_data;
vlc_mutex_lock( &p_input->stream.stream_lock );
-
+
dvdplay_seek( p_dvd->vmg, OFF2LB( i_off ) );
+ p_input->stream.p_selected_area->i_tell =
+ LB2OFF( dvdplay_position( p_dvd->vmg ) ) -
+ p_input->stream.p_selected_area->i_start;
+
vlc_mutex_unlock( &p_input->stream.stream_lock );
return;
{
input_thread_t * p_input;
dvd_data_t * p_dvd;
- int i;
+ vlc_value_t val;
+ unsigned int i;
p_input = (input_thread_t*)p_args;
p_dvd = (dvd_data_t*)p_input->p_access_data;
-
+
switch( event )
{
case NEW_DOMAIN:
case NEW_VTS:
break;
case NEW_FILE:
-
break;
case NEW_PGC:
/* prevent intf to try to seek by default */
p_input->stream.b_seekable = 0;
- if( ( i = dvdplay_title_cur( p_dvd->vmg ) ) !=
- p_input->stream.p_selected_area->i_id )
+ i = dvdplay_title_cur( p_dvd->vmg );
+ if( i != p_input->stream.p_selected_area->i_id )
{
/* the title number has changed: update area */
msg_Warn( p_input, "new title %d (%d)", i,
}
/* new pgc in same title: reinit ES */
+ dvdplay_ES( p_input );
dvdNewPGC( p_input );
-
+
p_input->stream.b_changed = 1;
break;
+ case JUMP:
+ dvdplay_ES( p_input );
+ dvdNewPGC( p_input );
case NEW_PG:
/* update current chapter */
p_input->stream.p_selected_area->i_part =
dvdplay_chapter_cur( p_dvd->vmg );
+
+ p_input->stream.p_selected_area->i_tell =
+ LB2OFF( dvdplay_position( p_dvd->vmg ) ) -
+ p_input->stream.p_selected_area->i_start;
+
+ /* warn interface that something has changed */
+ p_input->stream.b_changed = 1;
+
+ /* Update the navigation variables without triggering a callback */
+ val.i_int = p_input->stream.p_selected_area->i_part;
+ var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &val, NULL );
break;
case NEW_CELL:
p_dvd->b_end_of_cell = 0;
case END_OF_CELL:
p_dvd->b_end_of_cell = 1;
break;
- case JUMP:
- dvdplay_ES( p_input );
- break;
case STILL_TIME:
/* we must pause only from demux
* when the data in cache has been decoded */
case COMPLETE_VIDEO:
break;
case NEW_HIGHLIGHT:
-
+ if( var_Get( p_input, "highlight-mutex", &val ) == VLC_SUCCESS )
+ {
+ vlc_mutex_t *p_mutex = val.p_address;
+ vlc_mutex_lock( p_mutex );
+
+ /* Retrieve the highlight from dvdplay */
+ dvdplay_highlight( p_dvd->vmg, &p_dvd->hli );
+
+ if( p_dvd->hli.i_x_start || p_dvd->hli.i_y_start ||
+ p_dvd->hli.i_x_end || p_dvd->hli.i_y_end )
+ {
+ /* Fill our internal variables with this data */
+ val.i_int = p_dvd->hli.i_x_start;
+ var_Set( p_input, "x-start", val );
+ val.i_int = p_dvd->hli.i_y_start;
+ var_Set( p_input, "y-start", val );
+ val.i_int = p_dvd->hli.i_x_end;
+ var_Set( p_input, "x-end", val );
+ val.i_int = p_dvd->hli.i_y_end;
+ var_Set( p_input, "y-end", val );
+
+ val.p_address = (void *)p_dvd->hli.pi_color;
+ var_Set( p_input, "color", val );
+ val.p_address = (void *)p_dvd->hli.pi_contrast;
+ var_Set( p_input, "contrast", val );
+
+ /* Tell the SPU decoder that there's a new highlight */
+ val.b_bool = VLC_TRUE;
+ }
+ else
+ {
+ /* Turn off the highlight */
+ val.b_bool = VLC_FALSE;
+ }
+ var_Set( p_input, "highlight", val );
+
+ vlc_mutex_unlock( p_mutex );
+ }
break;
default:
- msg_Err( p_input, "unknown event from libdvdplay (%d)",
- event );
+ msg_Err( p_input, "unknown event from libdvdplay (%d)", event );
}
return;
{
dvd_data_t * p_dvd;
int i_angle_nb, i_angle;
+ vlc_value_t val;
int i;
p_dvd = (dvd_data_t*)p_input->p_access_data;
{
input_AddProgram( p_input, i+1, 0 );
}
-
- dvdplay_SetProgram( p_input,
- p_input->stream.pp_programs[i_angle-1] );
-// dvdNewPGC( p_input );
+ if( i_angle )
+ dvdplay_SetProgram( p_input,
+ p_input->stream.pp_programs[i_angle-1] );
+ else
+ dvdplay_SetProgram( p_input,
+ p_input->stream.pp_programs[0] );
/* No PSM to read in DVD mode, we already have all information */
p_input->stream.p_selected_program->b_is_ok = 1;
+ /* Reinit ES */
+ dvdplay_ES( p_input );
+
+ /* 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 );
+ var_Change( p_input, "chapter", VLC_VAR_CLEARCHOICES, NULL, NULL );
+ for( i = 1; (unsigned int)i <= p_area->i_part_nb; i++ )
+ {
+ val.i_int = i;
+ var_Change( p_input, "chapter", VLC_VAR_ADDCHOICE, &val, NULL );
+ }
+
+ /* Update the navigation variables without triggering a callback */
+ val.i_int = p_area->i_part;
+ var_Change( p_input, "chapter", VLC_VAR_SETVALUE, &val, NULL );
+
return 0;
}
static int dvdNewPGC( input_thread_t * p_input )
{
- dvd_data_t * p_dvd;
-// int i_audio_nr = -1;
-// int i_audio = -1;
-// int i_subp_nr = -1;
-// int i_subp = -1;
-// int i_sec;
-
- p_dvd = (dvd_data_t*)p_input->p_access_data;
-
-// dvdplay_audio_info( p_dvd->vmg, &i_audio_nr, &i_audio );
-// dvdplay_subp_info( p_dvd->vmg, &i_subp_nr, &i_subp );
+ dvd_data_t * p_dvd = (dvd_data_t*)p_input->p_access_data;
- dvdplay_ES( p_input );
p_input->stream.p_selected_area->i_start =
LB2OFF( dvdplay_title_first( p_dvd->vmg ) );
p_input->stream.p_selected_area->i_size =
LB2OFF( dvdplay_title_end ( p_dvd->vmg ) ) -
p_input->stream.p_selected_area->i_start;
+ p_input->stream.p_selected_area->i_tell = 0;
if( p_input->stream.p_selected_area->i_size > 0 )
{
{
p_input->stream.b_seekable = 0;
}
-
-#if 0
- i_sec = dvdplay_title_time( p_dvd->vmg );
- msg_Dbg( p_input, "title time: %d:%02d:%02d (%d)",
- i_sec/3600, (i_sec%3600)/60, i_sec%60, i_sec );
-#endif
return 0;
}
+
+static int MenusCallback( vlc_object_t *p_this, char const *psz_name,
+ vlc_value_t oldval, vlc_value_t newval, void *p_arg )
+{
+ input_thread_t * p_input;
+ dvd_data_t * p_dvd;
+
+ p_input = (input_thread_t*)p_this;
+ p_dvd = (dvd_data_t*)p_input->p_access_data;
+
+ vlc_mutex_lock( &p_input->stream.stream_lock );
+ if( newval.i_int < 99 )
+ dvdplay_menu( p_dvd->vmg, newval.i_int, 0 );
+ else
+ dvdplay_resume( p_dvd->vmg );
+ vlc_mutex_unlock( &p_input->stream.stream_lock );
+
+ if( p_dvd->p_intf ) dvdIntfResetStillTime( p_dvd->p_intf );
+
+ return VLC_SUCCESS;
+}