1 /* seek.c: functions to navigate through DVD.
2 *****************************************************************************
3 * Copyright (C) 1998-2001 VideoLAN
4 * $Id: seek.c,v 1.1 2002/08/04 17:23:41 sam Exp $
6 * Author: Stéphane Borel <stef@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
21 *****************************************************************************/
23 /*****************************************************************************
25 *****************************************************************************/
31 #include <vlc/input.h>
38 #include <sys/types.h>
43 #ifdef STRNCASECMP_IN_STRINGS_H
50 # include <dvdcss/dvdcss.h>
58 p_dvd->p_ifo->vts.title_unit.p_title[p_dvd->i_title_id-1].title
59 #define cell p_dvd->p_ifo->vts.cell_inf
61 int CellIsInterleaved( thread_dvd_data_t * p_dvd )
63 return title.p_cell_play[p_dvd->i_prg_cell].i_category & 0xf000;
66 int CellPrg2Map( thread_dvd_data_t * p_dvd )
70 i_cell = p_dvd->i_map_cell;
72 if( i_cell >= cell.i_cell_nb )
77 while( ( i_cell < cell.i_cell_nb ) &&
78 ( ( title.p_cell_pos[p_dvd->i_prg_cell].i_vob_id !=
79 cell.p_cell_map[i_cell].i_vob_id ) ||
80 ( title.p_cell_pos[p_dvd->i_prg_cell].i_cell_id !=
81 cell.p_cell_map[i_cell].i_cell_id ) ) )
86 if( i_cell >= cell.i_cell_nb )
94 int CellAngleOffset( thread_dvd_data_t * p_dvd, int i_prg_cell )
98 if( i_prg_cell >= title.i_cell_nb )
103 /* basic handling of angles */
104 switch( ( ( title.p_cell_play[i_prg_cell].i_category & 0xf000 )
107 /* we enter a muli-angle section */
109 i_cell_off = p_dvd->i_angle - 1;
110 p_dvd->i_angle_cell = 0;
112 /* we exit a multi-angle section */
115 i_cell_off = p_dvd->i_angle_nb - p_dvd->i_angle;
124 int CellFirstSector( thread_dvd_data_t * p_dvd )
126 return __MAX( cell.p_cell_map[p_dvd->i_map_cell].i_first_sector,
127 title.p_cell_play[p_dvd->i_prg_cell].i_first_sector );
130 int CellLastSector( thread_dvd_data_t * p_dvd )
132 return __MIN( cell.p_cell_map[p_dvd->i_map_cell].i_last_sector,
133 title.p_cell_play[p_dvd->i_prg_cell].i_last_sector );
136 int NextCellPrg( thread_dvd_data_t * p_dvd )
138 int i_cell = p_dvd->i_prg_cell;
140 if( p_dvd->i_vts_lb > title.p_cell_play[i_cell].i_last_sector )
143 i_cell += CellAngleOffset( p_dvd, i_cell );
145 if( i_cell >= title.i_cell_nb )
154 int Lb2CellPrg( thread_dvd_data_t * p_dvd )
158 while( p_dvd->i_vts_lb > title.p_cell_play[i_cell].i_last_sector )
161 i_cell += CellAngleOffset( p_dvd, i_cell );
163 if( i_cell >= title.i_cell_nb )
172 int Lb2CellMap( thread_dvd_data_t * p_dvd )
176 while( p_dvd->i_vts_lb > cell.p_cell_map[i_cell].i_last_sector )
180 if( i_cell >= cell.i_cell_nb )
189 int LbMaxOnce( thread_dvd_data_t * p_dvd )
191 int i_block_once = p_dvd->i_last_lb + 1 - p_dvd->i_vts_lb;
193 /* Get the position of the next cell if we're at cell end */
194 if( i_block_once <= 0 )
197 p_dvd->i_angle_cell++;
199 p_dvd->i_prg_cell = NextCellPrg( p_dvd );
200 if( p_dvd->i_prg_cell < 0 )
206 p_dvd->i_map_cell = CellPrg2Map( p_dvd );
207 if( p_dvd->i_map_cell < 0 )
212 p_dvd->i_vts_lb = CellFirstSector( p_dvd );
213 p_dvd->i_last_lb = CellLastSector( p_dvd );
215 p_dvd->i_chapter = NextChapter( p_dvd );
216 if( p_dvd->i_chapter < 0 )
221 /* Position the fd pointer on the right address */
222 if( dvdcss_seek( p_dvd->dvdhandle,
223 p_dvd->i_vts_start + p_dvd->i_vts_lb,
224 DVDCSS_SEEK_MPEG ) < 0 )
226 //X intf_ErrMsg( "dvd error: %s",
227 //X dvdcss_error( p_dvd->dvdhandle ) );
231 i_block_once = p_dvd->i_last_lb + 1 - p_dvd->i_vts_lb;
238 int CellPrg2Chapter( thread_dvd_data_t * p_dvd )
241 int i_cell = p_dvd->i_prg_cell;
243 if( CellIsInterleaved( p_dvd ) )
245 i_cell -= (p_dvd->i_angle - 1);
248 while( title.chapter_map.pi_start_cell[i_chapter] <= i_cell+1 )
251 if( i_chapter >= p_dvd->i_chapter_nb )
253 return p_dvd->i_chapter_nb;
260 int NextChapter( thread_dvd_data_t * p_dvd )
262 int i_cell = p_dvd->i_prg_cell;
264 if( CellIsInterleaved( p_dvd ) )
266 i_cell -= (p_dvd->i_angle - 1);
269 if( title.chapter_map.pi_start_cell[p_dvd->i_chapter] <= i_cell+1 )
272 if( p_dvd->i_chapter > p_dvd->i_chapter_nb )
276 p_dvd->b_new_chapter = 1;
278 return p_dvd->i_chapter;
281 return p_dvd->i_chapter;
286 int DVDSetChapter( thread_dvd_data_t * p_dvd, int i_chapter )
288 if( i_chapter <= 0 || i_chapter > p_dvd->i_chapter_nb )
293 if( p_dvd->i_chapter != i_chapter )
295 /* Find cell index in Program chain for current chapter */
296 p_dvd->i_prg_cell = title.chapter_map.pi_start_cell[i_chapter-1] - 1;
297 p_dvd->i_prg_cell += CellAngleOffset( p_dvd, p_dvd->i_prg_cell );
298 if( i_chapter < p_dvd->i_chapter )
300 p_dvd->i_map_cell = 0;
302 p_dvd->i_map_cell = CellPrg2Map( p_dvd );
303 p_dvd->i_vts_lb = CellFirstSector( p_dvd );
304 p_dvd->i_last_lb = CellLastSector( p_dvd );
306 /* Position the fd pointer on the right address */
307 if( dvdcss_seek( p_dvd->dvdhandle,
308 p_dvd->i_vts_start + p_dvd->i_vts_lb,
309 DVDCSS_SEEK_MPEG ) < 0 )
311 //X intf_ErrMsg( "dvd error: %s", dvdcss_error( p_dvd->dvdhandle ) );
315 //X intf_WarnMsg( 4, "dvd info: chapter %d prg_cell %d map_cell %d",
316 //X i_chapter, p_dvd->i_prg_cell, p_dvd->i_map_cell );