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
;