2
* This file is part of libdvdnav, a DVD navigation library.
4
* libdvdnav is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* libdvdnav is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License along
15
* with libdvdnav; if not, write to the Free Software Foundation, Inc.,
16
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28
#include <sys/param.h>
29
#include <sys/fcntl.h>
32
#define MAXPATHLEN 255
39
#include "dvdnav/dvdnav.h"
40
#include <dvdread/nav_types.h>
41
#include <dvdread/ifo_types.h>
43
#include "vm/decoder.h"
45
#include "dvdnav_internal.h"
51
unsigned long start_block;
52
unsigned long end_block;
60
struct block_s *blocks;
63
static remap_t* remap_new( char *title) {
64
remap_t *map = malloc( sizeof(remap_t));
65
map->title = strdup(title);
73
static int compare_block( block_t *a, block_t *b) {
74
/* returns -1 if a precedes b, 1 if a follows b, and 0 if a and b overlap */
75
if (a->domain < b->domain) {
77
} else if (a->domain > b->domain) {
81
if (a->title < b->title) {
83
} else if (a->title > b->title) {
87
if (a->program < b->program) {
89
} else if (a->program > b->program) {
93
if (a->end_block < b->start_block) {
95
} else if (a->start_block > b->end_block) {
97
* if a->start_block == b->end_block then the two regions
98
* aren't strictly overlapping, but they should be merged
99
* anyway since there are zero blocks between them
107
static block_t *findblock( remap_t *map, block_t *key) {
109
int ub = map->nblocks - 1;
114
mid = lb + (ub - lb)/2;
115
res = compare_block( key, &map->blocks[mid]);
118
} else if (res > 0) {
121
return &map->blocks[mid];
127
static void mergeblock( block_t *b, block_t tmp) {
128
if (tmp.start_block < b->start_block) b->start_block = tmp.start_block;
129
if (tmp.end_block > b->end_block) b->end_block = tmp.end_block;
132
static void remap_add_node( remap_t *map, block_t block) {
135
b = findblock( map, &block);
137
/* overlaps an existing block */
138
mergeblock( b, block);
141
if (map->nblocks >= map->maxblocks) {
142
map->maxblocks += 20;
143
map->blocks = realloc( map->blocks, sizeof( block_t)*map->maxblocks);
146
while (n > 0 && compare_block( &block, &map->blocks[ n-1]) < 0) {
147
map->blocks[ n] = map->blocks[ n-1];
150
map->blocks[ n] = block;
154
static int parseblock(char *buf, int *dom, int *tt, int *pg,
155
unsigned long *start, unsigned long *end) {
159
char *marker[]={"domain", "title", "program", "start", "end"};
161
tok = strtok( buf, " ");
163
if (strcmp(tok, marker[st])) return -st-1000;
164
tok = strtok( NULL, " ");
165
if (!tok) return -st-2000;
166
tmp = strtol( tok, &epos, 0);
167
if (*epos != 0 && *epos != ',') return -st-3000;
186
tok = strtok( NULL, " ");
191
remap_t* remap_loadmap( char *title) {
193
char fname[MAXPATHLEN];
200
memset(&tmp, 0, sizeof(tmp));
201
/* Build the map filename */
202
home = getenv("HOME");
204
fprintf(MSG_OUT, "libdvdnav: Unable to find home directory" );
207
snprintf(fname, sizeof(fname), "%s/.dvdnav/%s.map", home, title);
209
/* Open the map file */
210
fp = fopen( fname, "r");
212
fprintf(MSG_OUT, "libdvdnav: Unable to find map file '%s'\n", fname);
216
/* Load the map file */
217
map = remap_new( title);
218
while (fgets( buf, sizeof(buf), fp) != NULL) {
219
if (buf[0] == '\n' || buf[0] == '#' || buf[0] == 0) continue;
220
if (strncasecmp( buf, "debug", 5) == 0) {
223
res = parseblock( buf,
224
&tmp.domain, &tmp.title, &tmp.program, &tmp.start_block, &tmp.end_block);
226
fprintf(MSG_OUT, "libdvdnav: Ignoring map line (%d): %s\n", res, buf);
229
remap_add_node( map, tmp);
234
if (map->nblocks == 0 && map->debug == 0) {
241
unsigned long remap_block(
242
remap_t *map, int domain, int title, int program,
243
unsigned long cblock, unsigned long offset)
249
fprintf(MSG_OUT, "libdvdnav: %s: domain %d, title %d, program %d, start %lx, next %lx\n",
250
map->title, domain, title, program, cblock, cblock+offset);
255
key.program = program;
256
key.start_block = key.end_block = cblock + offset;
257
b = findblock( map, &key);
261
fprintf(MSG_OUT, "libdvdnav: Redirected to %lx\n", b->end_block);
263
return b->end_block - cblock;