Mercurial > libdvdnav.hg
annotate searching.c @ 266:21ba13a7b77a src
Implement:
uint16_t dvdnav_audio_stream_to_format(dvdnav_t *self, uint8_t stream);
author | jcdutton |
---|---|
date | Thu, 14 Dec 2006 13:28:07 +0000 |
parents | 99d33725395d |
children | 77e472cef5f8 |
rev | line source |
---|---|
131 | 1 /* |
0 | 2 * Copyright (C) 2000 Rich Wareham <richwareham@users.sourceforge.net> |
3 * | |
4 * This file is part of libdvdnav, a DVD navigation library. | |
5 * | |
6 * libdvdnav is free software; you can redistribute it and/or modify | |
7 * it under the terms of the GNU General Public License as published by | |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
11 * libdvdnav is distributed in the hope that it will be useful, | |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program; if not, write to the Free Software | |
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | |
19 * | |
20 * $Id$ | |
21 * | |
22 */ | |
23 | |
24 #ifdef HAVE_CONFIG_H | |
25 #include "config.h" | |
26 #endif | |
27 | |
114 | 28 #include <assert.h> |
0 | 29 #include "dvdnav_internal.h" |
30 | |
114 | 31 /* |
32 #define LOG_DEBUG | |
33 */ | |
34 | |
0 | 35 /* Searching API calls */ |
36 | |
24 | 37 /* Scan the ADMAP for a particular block number. */ |
38 /* Return placed in vobu. */ | |
39 /* Returns error status */ | |
114 | 40 /* FIXME: Maybe need to handle seeking outside current cell. */ |
195 | 41 static dvdnav_status_t dvdnav_scan_admap(dvdnav_t *this, int32_t domain, uint32_t seekto_block, uint32_t *vobu) { |
24 | 42 vobu_admap_t *admap = NULL; |
114 | 43 |
44 #ifdef LOG_DEBUG | |
45 fprintf(MSG_OUT, "libdvdnav: Seeking to target %u ...\n", seekto_block); | |
46 #endif | |
24 | 47 *vobu = -1; |
48 | |
49 /* Search through the VOBU_ADMAP for the nearest VOBU | |
50 * to the target block */ | |
51 switch(domain) { | |
114 | 52 case FP_DOMAIN: |
53 case VMGM_DOMAIN: | |
54 admap = this->vm->vmgi->menu_vobu_admap; | |
55 break; | |
56 case VTSM_DOMAIN: | |
57 admap = this->vm->vtsi->menu_vobu_admap; | |
58 break; | |
59 case VTS_DOMAIN: | |
60 admap = this->vm->vtsi->vts_vobu_admap; | |
61 break; | |
62 default: | |
63 fprintf(MSG_OUT, "libdvdnav: Error: Unknown domain for seeking.\n"); | |
24 | 64 } |
65 if(admap) { | |
166 | 66 uint32_t address = 0; |
67 uint32_t vobu_start, next_vobu; | |
195 | 68 int32_t found = 0; |
24 | 69 |
70 /* Search through ADMAP for best sector */ | |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
71 vobu_start = SRI_END_OF_CELL; |
24 | 72 /* FIXME: Implement a faster search algorithm */ |
73 while((!found) && ((address<<2) < admap->last_byte)) { | |
74 next_vobu = admap->vobu_start_sectors[address]; | |
75 | |
76 | 76 /* fprintf(MSG_OUT, "libdvdnav: Found block %u\n", next_vobu); */ |
24 | 77 |
78 if(vobu_start <= seekto_block && | |
79 next_vobu > seekto_block) { | |
80 found = 1; | |
81 } else { | |
82 vobu_start = next_vobu; | |
83 } | |
84 address ++; | |
85 } | |
86 if(found) { | |
87 *vobu = vobu_start; | |
193 | 88 return DVDNAV_STATUS_OK; |
24 | 89 } else { |
76 | 90 fprintf(MSG_OUT, "libdvdnav: Could not locate block\n"); |
193 | 91 return DVDNAV_STATUS_ERR; |
24 | 92 } |
93 } | |
76 | 94 fprintf(MSG_OUT, "libdvdnav: admap not located\n"); |
193 | 95 return DVDNAV_STATUS_ERR; |
24 | 96 } |
97 | |
265 | 98 /* FIXME: right now, this function does not use the time tables but interpolates |
99 only the cell times */ | |
100 dvdnav_status_t dvdnav_time_search(dvdnav_t *this, | |
101 uint64_t time) { | |
102 | |
103 uint64_t target = time; | |
104 uint64_t length = 0; | |
105 uint32_t first_cell_nr, last_cell_nr, cell_nr; | |
106 int32_t found; | |
107 cell_playback_t *cell; | |
108 dvd_state_t *state; | |
109 dvdnav_status_t result; | |
110 | |
111 if(this->position_current.still != 0) { | |
112 printerr("Cannot seek in a still frame."); | |
113 return DVDNAV_STATUS_ERR; | |
114 } | |
115 | |
116 pthread_mutex_lock(&this->vm_lock); | |
117 state = &(this->vm->state); | |
118 if(!state->pgc) { | |
119 printerr("No current PGC."); | |
120 pthread_mutex_unlock(&this->vm_lock); | |
121 return DVDNAV_STATUS_ERR; | |
122 } | |
123 | |
124 | |
125 if (this->pgc_based) { | |
126 first_cell_nr = 1; | |
127 last_cell_nr = state->pgc->nr_of_cells; | |
128 } else { | |
129 /* Find start cell of program. */ | |
130 first_cell_nr = state->pgc->program_map[state->pgN-1]; | |
131 /* Find end cell of program */ | |
132 if(state->pgN < state->pgc->nr_of_programs) | |
133 last_cell_nr = state->pgc->program_map[state->pgN] - 1; | |
134 else | |
135 last_cell_nr = state->pgc->nr_of_cells; | |
136 } | |
137 | |
138 found = 0; | |
139 for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) { | |
140 cell = &(state->pgc->cell_playback[cell_nr-1]); | |
141 length = dvdnav_convert_time(&cell->playback_time); | |
142 if (target >= length) { | |
143 target -= length; | |
144 } else { | |
145 /* FIXME: there must be a better way than interpolation */ | |
146 target = target * (cell->last_sector - cell->first_sector + 1) / length; | |
147 target += cell->first_sector; | |
148 | |
149 found = 1; | |
150 break; | |
151 } | |
152 } | |
153 | |
154 if(found) { | |
155 int32_t vobu; | |
156 #ifdef LOG_DEBUG | |
157 fprintf(MSG_OUT, "libdvdnav: Seeking to cell %i from choice of %i to %i\n", | |
158 cell_nr, first_cell_nr, last_cell_nr); | |
159 #endif | |
160 if (dvdnav_scan_admap(this, state->domain, target, &vobu) == DVDNAV_STATUS_OK) { | |
161 int32_t start = state->pgc->cell_playback[cell_nr-1].first_sector; | |
162 | |
163 if (vm_jump_cell_block(this->vm, cell_nr, vobu - start)) { | |
164 #ifdef LOG_DEBUG | |
165 fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" , | |
166 state->cellN, state->blockN, target, vobu, start); | |
167 #endif | |
168 this->vm->hop_channel += HOP_SEEK; | |
169 pthread_mutex_unlock(&this->vm_lock); | |
170 return DVDNAV_STATUS_OK; | |
171 } | |
172 } | |
173 } | |
174 | |
175 fprintf(MSG_OUT, "libdvdnav: Error when seeking\n"); | |
176 printerr("Error when seeking."); | |
177 pthread_mutex_unlock(&this->vm_lock); | |
178 return DVDNAV_STATUS_ERR; | |
179 } | |
180 | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
181 dvdnav_status_t dvdnav_sector_search(dvdnav_t *this, |
195 | 182 uint64_t offset, int32_t origin) { |
0 | 183 uint32_t target = 0; |
184 uint32_t length = 0; | |
114 | 185 uint32_t first_cell_nr, last_cell_nr, cell_nr; |
195 | 186 int32_t found; |
114 | 187 cell_playback_t *cell; |
0 | 188 dvd_state_t *state; |
189 dvdnav_status_t result; | |
190 | |
114 | 191 if(this->position_current.still != 0) { |
192 printerr("Cannot seek in a still frame."); | |
193 | 193 return DVDNAV_STATUS_ERR; |
114 | 194 } |
0 | 195 |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
196 result = dvdnav_get_position(this, &target, &length); |
0 | 197 if(!result) { |
193 | 198 return DVDNAV_STATUS_ERR; |
0 | 199 } |
200 | |
114 | 201 pthread_mutex_lock(&this->vm_lock); |
202 state = &(this->vm->state); | |
203 if(!state->pgc) { | |
204 printerr("No current PGC."); | |
205 pthread_mutex_unlock(&this->vm_lock); | |
193 | 206 return DVDNAV_STATUS_ERR; |
114 | 207 } |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
208 #ifdef LOG_DEBUG |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
209 fprintf(MSG_OUT, "libdvdnav: seeking to offset=%lu pos=%u length=%u\n", offset, target, length); |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
210 fprintf(MSG_OUT, "libdvdnav: Before cellN=%u blockN=%u\n", state->cellN, state->blockN); |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
211 #endif |
114 | 212 |
0 | 213 switch(origin) { |
214 case SEEK_SET: | |
215 if(offset > length) { | |
114 | 216 printerr("Request to seek behind end."); |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
217 pthread_mutex_unlock(&this->vm_lock); |
193 | 218 return DVDNAV_STATUS_ERR; |
0 | 219 } |
220 target = offset; | |
221 break; | |
222 case SEEK_CUR: | |
223 if(target + offset > length) { | |
114 | 224 printerr("Request to seek behind end."); |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
225 pthread_mutex_unlock(&this->vm_lock); |
193 | 226 return DVDNAV_STATUS_ERR; |
0 | 227 } |
228 target += offset; | |
229 break; | |
230 case SEEK_END: | |
231 if(length - offset < 0) { | |
114 | 232 printerr("Request to seek before start."); |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
233 pthread_mutex_unlock(&this->vm_lock); |
193 | 234 return DVDNAV_STATUS_ERR; |
0 | 235 } |
236 target = length - offset; | |
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
237 break; |
0 | 238 default: |
239 /* Error occured */ | |
114 | 240 printerr("Illegal seek mode."); |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
241 pthread_mutex_unlock(&this->vm_lock); |
193 | 242 return DVDNAV_STATUS_ERR; |
0 | 243 } |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
244 |
132 | 245 if (this->pgc_based) { |
246 first_cell_nr = 1; | |
247 last_cell_nr = state->pgc->nr_of_cells; | |
0 | 248 } else { |
132 | 249 /* Find start cell of program. */ |
250 first_cell_nr = state->pgc->program_map[state->pgN-1]; | |
251 /* Find end cell of program */ | |
252 if(state->pgN < state->pgc->nr_of_programs) | |
253 last_cell_nr = state->pgc->program_map[state->pgN] - 1; | |
254 else | |
255 last_cell_nr = state->pgc->nr_of_cells; | |
0 | 256 } |
132 | 257 |
114 | 258 found = 0; |
0 | 259 for(cell_nr = first_cell_nr; (cell_nr <= last_cell_nr) && !found; cell_nr ++) { |
260 cell = &(state->pgc->cell_playback[cell_nr-1]); | |
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
261 length = cell->last_sector - cell->first_sector + 1; |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
262 if (target >= length) { |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
263 target -= length; |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
264 } else { |
131 | 265 /* convert the target sector from Cell-relative to absolute physical sector */ |
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
266 target += cell->first_sector; |
114 | 267 found = 1; |
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
268 break; |
0 | 269 } |
270 } | |
271 | |
114 | 272 if(found) { |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
273 int32_t vobu; |
114 | 274 #ifdef LOG_DEBUG |
76 | 275 fprintf(MSG_OUT, "libdvdnav: Seeking to cell %i from choice of %i to %i\n", |
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
276 cell_nr, first_cell_nr, last_cell_nr); |
114 | 277 #endif |
193 | 278 if (dvdnav_scan_admap(this, state->domain, target, &vobu) == DVDNAV_STATUS_OK) { |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
279 int32_t start = state->pgc->cell_playback[cell_nr-1].first_sector; |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
280 |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
281 if (vm_jump_cell_block(this->vm, cell_nr, vobu - start)) { |
114 | 282 #ifdef LOG_DEBUG |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
283 fprintf(MSG_OUT, "libdvdnav: After cellN=%u blockN=%u target=%x vobu=%x start=%x\n" , |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
284 state->cellN, state->blockN, target, vobu, start); |
114 | 285 #endif |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
286 this->vm->hop_channel += HOP_SEEK; |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
287 pthread_mutex_unlock(&this->vm_lock); |
193 | 288 return DVDNAV_STATUS_OK; |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
289 } |
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
290 } |
0 | 291 } |
114 | 292 |
133
d09a81cf65ce
determine correct PG and PTT numbers when seeking across PG boundaries
mroi
parents:
132
diff
changeset
|
293 fprintf(MSG_OUT, "libdvdnav: Error when seeking\n"); |
76 | 294 fprintf(MSG_OUT, "libdvdnav: FIXME: Implement seeking to location %u\n", target); |
114 | 295 printerr("Error when seeking."); |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
296 pthread_mutex_unlock(&this->vm_lock); |
193 | 297 return DVDNAV_STATUS_ERR; |
0 | 298 } |
299 | |
195 | 300 dvdnav_status_t dvdnav_part_search(dvdnav_t *this, int32_t part) { |
301 int32_t title, old_part; | |
114 | 302 |
193 | 303 if (dvdnav_current_title_info(this, &title, &old_part) == DVDNAV_STATUS_OK) |
114 | 304 return dvdnav_part_play(this, title, part); |
193 | 305 return DVDNAV_STATUS_ERR; |
0 | 306 } |
307 | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
308 dvdnav_status_t dvdnav_prev_pg_search(dvdnav_t *this) { |
68
3b45c78f061e
Some NULL-pointer check from aschultz@cs.uni-magdeburg.de
richwareham
parents:
63
diff
changeset
|
309 |
114 | 310 if(!this) { |
311 printerr("Passed a NULL pointer."); | |
193 | 312 return DVDNAV_STATUS_ERR; |
114 | 313 } |
314 | |
315 pthread_mutex_lock(&this->vm_lock); | |
316 if(!this->vm->state.pgc) { | |
317 printerr("No current PGC."); | |
318 pthread_mutex_unlock(&this->vm_lock); | |
193 | 319 return DVDNAV_STATUS_ERR; |
114 | 320 } |
68
3b45c78f061e
Some NULL-pointer check from aschultz@cs.uni-magdeburg.de
richwareham
parents:
63
diff
changeset
|
321 |
114 | 322 #ifdef LOG_DEBUG |
113 | 323 fprintf(MSG_OUT, "libdvdnav: previous chapter\n"); |
114 | 324 #endif |
325 if (!vm_jump_prev_pg(this->vm)) { | |
326 fprintf(MSG_OUT, "libdvdnav: previous chapter failed.\n"); | |
327 printerr("Skip to previous chapter failed."); | |
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
328 pthread_mutex_unlock(&this->vm_lock); |
193 | 329 return DVDNAV_STATUS_ERR; |
0 | 330 } |
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
331 this->position_current.still = 0; |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
332 this->vm->hop_channel++; |
114 | 333 #ifdef LOG_DEBUG |
76 | 334 fprintf(MSG_OUT, "libdvdnav: previous chapter done\n"); |
114 | 335 #endif |
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
336 pthread_mutex_unlock(&this->vm_lock); |
0 | 337 |
193 | 338 return DVDNAV_STATUS_OK; |
0 | 339 } |
340 | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
341 dvdnav_status_t dvdnav_top_pg_search(dvdnav_t *this) { |
0 | 342 |
114 | 343 if(!this) { |
344 printerr("Passed a NULL pointer."); | |
193 | 345 return DVDNAV_STATUS_ERR; |
114 | 346 } |
68
3b45c78f061e
Some NULL-pointer check from aschultz@cs.uni-magdeburg.de
richwareham
parents:
63
diff
changeset
|
347 |
114 | 348 pthread_mutex_lock(&this->vm_lock); |
349 if(!this->vm->state.pgc) { | |
350 printerr("No current PGC."); | |
351 pthread_mutex_unlock(&this->vm_lock); | |
193 | 352 return DVDNAV_STATUS_ERR; |
114 | 353 } |
68
3b45c78f061e
Some NULL-pointer check from aschultz@cs.uni-magdeburg.de
richwareham
parents:
63
diff
changeset
|
354 |
114 | 355 #ifdef LOG_DEBUG |
356 fprintf(MSG_OUT, "libdvdnav: top chapter\n"); | |
357 #endif | |
358 if (!vm_jump_top_pg(this->vm)) { | |
359 fprintf(MSG_OUT, "libdvdnav: top chapter failed.\n"); | |
360 printerr("Skip to top chapter failed."); | |
113 | 361 pthread_mutex_unlock(&this->vm_lock); |
193 | 362 return DVDNAV_STATUS_ERR; |
0 | 363 } |
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
364 this->position_current.still = 0; |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
365 this->vm->hop_channel++; |
114 | 366 #ifdef LOG_DEBUG |
367 fprintf(MSG_OUT, "libdvdnav: top chapter done\n"); | |
368 #endif | |
369 pthread_mutex_unlock(&this->vm_lock); | |
370 | |
193 | 371 return DVDNAV_STATUS_OK; |
114 | 372 } |
373 | |
374 dvdnav_status_t dvdnav_next_pg_search(dvdnav_t *this) { | |
122
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
375 vm_t *try_vm; |
114 | 376 |
377 if(!this) { | |
378 printerr("Passed a NULL pointer."); | |
193 | 379 return DVDNAV_STATUS_ERR; |
114 | 380 } |
381 | |
382 pthread_mutex_lock(&this->vm_lock); | |
383 if(!this->vm->state.pgc) { | |
384 printerr("No current PGC."); | |
385 pthread_mutex_unlock(&this->vm_lock); | |
193 | 386 return DVDNAV_STATUS_ERR; |
114 | 387 } |
388 | |
389 #ifdef LOG_DEBUG | |
390 fprintf(MSG_OUT, "libdvdnav: next chapter\n"); | |
391 #endif | |
122
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
392 /* make a copy of current VM and try to navigate the copy to the next PG */ |
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
393 try_vm = vm_new_copy(this->vm); |
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
394 if (!vm_jump_next_pg(try_vm) || try_vm->stopped) { |
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
395 vm_free_copy(try_vm); |
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
396 /* next_pg failed, try to jump at least to the next cell */ |
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
397 try_vm = vm_new_copy(this->vm); |
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
398 vm_get_next_cell(try_vm); |
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
399 if (try_vm->stopped) { |
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
400 vm_free_copy(try_vm); |
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
401 fprintf(MSG_OUT, "libdvdnav: next chapter failed.\n"); |
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
402 printerr("Skip to next chapter failed."); |
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
403 pthread_mutex_unlock(&this->vm_lock); |
193 | 404 return DVDNAV_STATUS_ERR; |
122
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
405 } |
114 | 406 } |
122
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
407 /* merge changes on success */ |
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
408 vm_merge(this->vm, try_vm); |
29b046894eac
use the new VM copy mechanism to try-run program skipping and report failure in case
mroi
parents:
119
diff
changeset
|
409 vm_free_copy(try_vm); |
114 | 410 this->position_current.still = 0; |
411 this->vm->hop_channel++; | |
412 #ifdef LOG_DEBUG | |
76 | 413 fprintf(MSG_OUT, "libdvdnav: next chapter done\n"); |
114 | 414 #endif |
102
3e6970dbe8d6
- allow seeking to offset 0 (pressing '0' in xine won't work otherwise)
mroi
parents:
90
diff
changeset
|
415 pthread_mutex_unlock(&this->vm_lock); |
0 | 416 |
193 | 417 return DVDNAV_STATUS_OK; |
0 | 418 } |
419 | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
420 dvdnav_status_t dvdnav_menu_call(dvdnav_t *this, DVDMenuID_t menu) { |
125 | 421 vm_t *try_vm; |
114 | 422 |
423 if(!this) { | |
424 printerr("Passed a NULL pointer."); | |
193 | 425 return DVDNAV_STATUS_ERR; |
0 | 426 } |
427 | |
114 | 428 pthread_mutex_lock(&this->vm_lock); |
429 if(!this->vm->state.pgc) { | |
430 printerr("No current PGC."); | |
431 pthread_mutex_unlock(&this->vm_lock); | |
193 | 432 return DVDNAV_STATUS_ERR; |
114 | 433 } |
434 | |
125 | 435 /* make a copy of current VM and try to navigate the copy to the menu */ |
436 try_vm = vm_new_copy(this->vm); | |
162
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
437 if ( (menu == DVD_MENU_Escape) && (this->vm->state.domain != VTS_DOMAIN)) { |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
438 /* Try resume */ |
167 | 439 if (vm_jump_resume(try_vm) && !try_vm->stopped) { |
162
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
440 /* merge changes on success */ |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
441 vm_merge(this->vm, try_vm); |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
442 vm_free_copy(try_vm); |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
443 this->position_current.still = 0; |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
444 this->vm->hop_channel++; |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
445 pthread_mutex_unlock(&this->vm_lock); |
193 | 446 return DVDNAV_STATUS_OK; |
162
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
447 } |
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
448 } |
166 | 449 if (menu == DVD_MENU_Escape) menu = DVD_MENU_Root; |
162
0fd70a257b44
Implement ESCAPE key jumping from TITLE to MENU and back again.
jcdutton
parents:
136
diff
changeset
|
450 |
125 | 451 if (vm_jump_menu(try_vm, menu) && !try_vm->stopped) { |
452 /* merge changes on success */ | |
453 vm_merge(this->vm, try_vm); | |
454 vm_free_copy(try_vm); | |
129 | 455 this->position_current.still = 0; |
114 | 456 this->vm->hop_channel++; |
457 pthread_mutex_unlock(&this->vm_lock); | |
193 | 458 return DVDNAV_STATUS_OK; |
114 | 459 } else { |
125 | 460 vm_free_copy(try_vm); |
461 printerr("No such menu or menu not reachable."); | |
114 | 462 pthread_mutex_unlock(&this->vm_lock); |
193 | 463 return DVDNAV_STATUS_ERR; |
114 | 464 } |
0 | 465 } |
466 | |
195 | 467 dvdnav_status_t dvdnav_get_position(dvdnav_t *this, uint32_t *pos, |
468 uint32_t *len) { | |
0 | 469 uint32_t cur_sector; |
195 | 470 int32_t cell_nr, first_cell_nr, last_cell_nr; |
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
471 cell_playback_t *cell; |
0 | 472 dvd_state_t *state; |
114 | 473 |
474 if(!this || !pos || !len) { | |
475 printerr("Passed a NULL pointer."); | |
193 | 476 return DVDNAV_STATUS_ERR; |
114 | 477 } |
478 if(!this->started) { | |
479 printerr("Virtual DVD machine not started."); | |
193 | 480 return DVDNAV_STATUS_ERR; |
114 | 481 } |
482 | |
483 pthread_mutex_lock(&this->vm_lock); | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
484 state = &(this->vm->state); |
224
f19fce15577b
fix assertion failure when someone asks for the position between an Exit
mroi
parents:
195
diff
changeset
|
485 if(!state->pgc || this->vm->stopped) { |
114 | 486 printerr("No current PGC."); |
487 pthread_mutex_unlock(&this->vm_lock); | |
193 | 488 return DVDNAV_STATUS_ERR; |
0 | 489 } |
181
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
490 if (this->position_current.hop_channel != this->vm->hop_channel || |
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
491 this->position_current.domain != state->domain || |
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
492 this->position_current.vts != state->vtsN || |
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
493 this->position_current.cell_restart != state->cell_restart) { |
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
494 printerr("New position not yet determined."); |
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
495 pthread_mutex_unlock(&this->vm_lock); |
193 | 496 return DVDNAV_STATUS_ERR; |
181
5d9770cb2961
fix some conditions where the following assertion would fail
mroi
parents:
167
diff
changeset
|
497 } |
114 | 498 |
0 | 499 /* Get current sector */ |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
500 cur_sector = this->vobu.vobu_start + this->vobu.blockN; |
0 | 501 |
132 | 502 if (this->pgc_based) { |
503 first_cell_nr = 1; | |
504 last_cell_nr = state->pgc->nr_of_cells; | |
0 | 505 } else { |
132 | 506 /* Find start cell of program. */ |
507 first_cell_nr = state->pgc->program_map[state->pgN-1]; | |
508 /* Find end cell of program */ | |
509 if(state->pgN < state->pgc->nr_of_programs) | |
510 last_cell_nr = state->pgc->program_map[state->pgN] - 1; | |
511 else | |
512 last_cell_nr = state->pgc->nr_of_cells; | |
0 | 513 } |
132 | 514 |
130
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
515 *pos = -1; |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
516 *len = 0; |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
517 for (cell_nr = first_cell_nr; cell_nr <= last_cell_nr; cell_nr++) { |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
518 cell = &(state->pgc->cell_playback[cell_nr-1]); |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
519 if (cell_nr == state->cellN) { |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
520 /* the current sector is in this cell, |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
521 * pos is length of PG up to here + sector's offset in this cell */ |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
522 *pos = *len + cur_sector - cell->first_sector; |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
523 } |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
524 *len += cell->last_sector - cell->first_sector + 1; |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
525 } |
f47065513ad8
do not assume PGs to be physically layed out in sequence on the disc
mroi
parents:
129
diff
changeset
|
526 |
166 | 527 assert((signed)*pos != -1); |
0 | 528 |
114 | 529 pthread_mutex_unlock(&this->vm_lock); |
0 | 530 |
193 | 531 return DVDNAV_STATUS_OK; |
0 | 532 } |
533 | |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
534 dvdnav_status_t dvdnav_get_position_in_title(dvdnav_t *this, |
195 | 535 uint32_t *pos, |
536 uint32_t *len) { | |
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
537 uint32_t cur_sector; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
538 uint32_t first_cell_nr; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
539 uint32_t last_cell_nr; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
540 cell_playback_t *first_cell; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
541 cell_playback_t *last_cell; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
542 dvd_state_t *state; |
114 | 543 |
544 if(!this || !pos || !len) { | |
545 printerr("Passed a NULL pointer."); | |
193 | 546 return DVDNAV_STATUS_ERR; |
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
547 } |
114 | 548 |
549 state = &(this->vm->state); | |
550 if(!state->pgc) { | |
551 printerr("No current PGC."); | |
193 | 552 return DVDNAV_STATUS_ERR; |
114 | 553 } |
554 | |
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
555 /* Get current sector */ |
22
3c1df0cb3aee
Start of rewrite of libdvdnav. Still need to re-implement seeking.
jcdutton
parents:
8
diff
changeset
|
556 cur_sector = this->vobu.vobu_start + this->vobu.blockN; |
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
557 |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
558 /* Now find first and last cells in title. */ |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
559 first_cell_nr = state->pgc->program_map[0]; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
560 first_cell = &(state->pgc->cell_playback[first_cell_nr-1]); |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
561 last_cell_nr = state->pgc->nr_of_cells; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
562 last_cell = &(state->pgc->cell_playback[last_cell_nr-1]); |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
563 |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
564 *pos = cur_sector - first_cell->first_sector; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
565 *len = last_cell->last_sector - first_cell->first_sector; |
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
566 |
193 | 567 return DVDNAV_STATUS_OK; |
8
66708b4a1b5e
Stop C++ bitching about some things and extend the menus example
richwareham
parents:
3
diff
changeset
|
568 } |