Mercurial > libdvdnav.hg
comparison remap.c @ 96:2fcb4f228308 src
Adding "Personalizing DVD Viewing" files from <kevin_smathers@hp.com>
Not yet enabled. Will be enabled soon.
author | jcdutton |
---|---|
date | Tue, 17 Sep 2002 10:47:02 +0000 |
parents | |
children | b6834e6359cf |
comparison
equal
deleted
inserted
replaced
95:e7ebabe059b9 | 96:2fcb4f228308 |
---|---|
1 #include <stdlib.h> | |
2 #include <string.h> | |
3 #include <stdio.h> | |
4 #include <sys/param.h> | |
5 #include <sys/fcntl.h> | |
6 #include <assert.h> | |
7 #include "remap.h" | |
8 | |
9 struct block_s { | |
10 int domain; | |
11 int title; | |
12 int program; | |
13 unsigned long start_block; | |
14 unsigned long end_block; | |
15 }; | |
16 | |
17 struct remap_s { | |
18 char *title; | |
19 int maxblocks; | |
20 int nblocks; | |
21 int debug; | |
22 struct block_s *blocks; | |
23 }; | |
24 | |
25 remap_t* remap_new( char *title) { | |
26 remap_t *map = malloc( sizeof(remap_t)); | |
27 map->title = strdup(title); | |
28 map->maxblocks = 0; | |
29 map->nblocks = 0; | |
30 map->blocks = NULL; | |
31 map->debug = 0; | |
32 return map; | |
33 } | |
34 | |
35 static int compare_block( block_t *a, block_t *b) { | |
36 /* returns -1 if a precedes b, 1 if a follows b, and 0 if a and b overlap */ | |
37 if (a->domain < b->domain) { | |
38 return -1; | |
39 } else if (a->domain > b->domain) { | |
40 return 1; | |
41 } | |
42 | |
43 if (a->title < b->title) { | |
44 return -1; | |
45 } else if (a->title > b->title) { | |
46 return 1; | |
47 } | |
48 | |
49 if (a->program < b->program) { | |
50 return -1; | |
51 } else if (a->program > b->program) { | |
52 return 1; | |
53 } | |
54 | |
55 if (a->end_block < b->start_block) { | |
56 return -1; | |
57 } else if (a->start_block > b->end_block) { | |
58 /* | |
59 * if a->start_block == b->end_block then the two regions | |
60 * aren't strictly overlapping, but they should be merged | |
61 * anyway since there are zero blocks between them | |
62 */ | |
63 return 1; | |
64 } | |
65 | |
66 return 0; | |
67 } | |
68 | |
69 static block_t *findblock( remap_t *map, block_t *key) { | |
70 int lb = 0; | |
71 int ub = map->nblocks - 1; | |
72 int mid; | |
73 int res; | |
74 | |
75 while (lb <= ub) { | |
76 mid = lb + (ub - lb)/2; | |
77 res = compare_block( key, &map->blocks[mid]); | |
78 if (res < 0) { | |
79 ub = mid-1; | |
80 } else if (res > 0) { | |
81 lb = mid+1; | |
82 } else { | |
83 return &map->blocks[mid]; | |
84 } | |
85 } | |
86 return NULL; | |
87 } | |
88 | |
89 static void mergeblock( block_t *b, block_t tmp) { | |
90 if (tmp.start_block < b->start_block) b->start_block = tmp.start_block; | |
91 if (tmp.end_block > b->end_block) b->end_block = tmp.end_block; | |
92 } | |
93 | |
94 static void remap_add_node( remap_t *map, block_t block) { | |
95 block_t *b; | |
96 int n; | |
97 b = findblock( map, &block); | |
98 if (b) { | |
99 /* overlaps an existing block */ | |
100 mergeblock( b, block); | |
101 } else { | |
102 /* new block */ | |
103 if (map->nblocks >= map->maxblocks) { | |
104 map->maxblocks += 20; | |
105 map->blocks = realloc( map->blocks, sizeof( block_t)*map->maxblocks); | |
106 } | |
107 n = map->nblocks++; | |
108 while (n > 0 && compare_block( &block, &map->blocks[ n-1]) < 0) { | |
109 map->blocks[ n] = map->blocks[ n-1]; | |
110 n--; | |
111 } | |
112 map->blocks[ n] = block; | |
113 } | |
114 } | |
115 | |
116 int parseblock( | |
117 char *buf, int *dom, int *tt, int *pg, | |
118 unsigned long *start, unsigned long *end) | |
119 { | |
120 long tmp; | |
121 char *tok; | |
122 char *epos; | |
123 char *marker[]={"domain", "title", "program", "start", "end"}; | |
124 int st = 0; | |
125 tok = strtok( buf, " "); | |
126 while (st < 5) { | |
127 if (strcmp(tok, marker[st])) return -st-1000; | |
128 tok = strtok( NULL, " "); | |
129 if (!tok) return -st-2000; | |
130 tmp = strtol( tok, &epos, 0); | |
131 if (*epos != 0 && *epos != ',') return -st-3000; | |
132 switch (st) { | |
133 case 0: | |
134 *dom = (int)tmp; | |
135 break; | |
136 case 1: | |
137 *tt = (int)tmp; | |
138 break; | |
139 case 2: | |
140 *pg = (int)tmp; | |
141 break; | |
142 case 3: | |
143 *start = tmp; | |
144 break; | |
145 case 4: | |
146 *end = tmp; | |
147 break; | |
148 } | |
149 st++; | |
150 tok = strtok( NULL, " "); | |
151 } | |
152 return st; | |
153 } | |
154 | |
155 remap_t* remap_loadmap( char *title) { | |
156 char buf[160]; | |
157 char fname[MAXPATHLEN]; | |
158 char *home; | |
159 int res; | |
160 FILE *fp; | |
161 block_t tmp; | |
162 remap_t *map; | |
163 | |
164 /* Build the map filename */ | |
165 home = getenv("HOME"); assert(home); | |
166 strncpy(fname, home, sizeof(fname)); | |
167 strncat(fname, "/.xine/", sizeof(fname)); | |
168 strncat(fname, title, sizeof(fname)); | |
169 strncat(fname, ".map", sizeof(fname)); | |
170 | |
171 printf("Loading %s.\n", fname); | |
172 /* Open the map file */ | |
173 fp = fopen( fname, "r"); | |
174 if (!fp) { | |
175 printf("Unable to find map file '%s'\n", fname); | |
176 return NULL; | |
177 } | |
178 | |
179 /* Load the map file */ | |
180 map = remap_new( title); | |
181 while (fgets( buf, sizeof(buf), fp) != NULL) { | |
182 if (buf[0] == '\n' || buf[0] == '#' || buf[0] == 0) continue; | |
183 if (strncasecmp( buf, "debug", 5) == 0) { | |
184 map->debug = 1; | |
185 } else { | |
186 res = parseblock( buf, | |
187 &tmp.domain, &tmp.title, &tmp.program, &tmp.start_block, &tmp.end_block); | |
188 if (res != 5) { | |
189 printf("Ignoring map line (%d): %s\n", res, buf); | |
190 continue; | |
191 } | |
192 remap_add_node( map, tmp); | |
193 } | |
194 } | |
195 | |
196 if (map->nblocks == 0 && map->debug == 0) return NULL; | |
197 return map; | |
198 } | |
199 | |
200 unsigned long remap_block( | |
201 remap_t *map, int domain, int title, int program, | |
202 unsigned long cblock, unsigned long offset) | |
203 { | |
204 block_t key; | |
205 block_t *b; | |
206 | |
207 if (map->debug) { | |
208 printf("%s: domain %d, title %d, program %d, start %lx, next %lx\n", | |
209 map->title, domain, title, program, cblock, cblock+offset); | |
210 } | |
211 | |
212 key.domain = domain; | |
213 key.title = title; | |
214 key.program = program; | |
215 key.start_block = key.end_block = cblock + offset; | |
216 b = findblock( map, &key); | |
217 | |
218 if (b) { | |
219 if (map->debug) { | |
220 printf("Redirected to %lx\n", b->end_block); | |
221 } | |
222 return b->end_block - cblock; | |
223 } | |
224 return offset; | |
225 } |