diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-17 00:32:19 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-17 00:32:19 +0000 |
commit | 0d382a262c0638d0f572fc37193ccc5ed3dc895f (patch) | |
tree | 8578dcddfce4191f3f7a142a37769df7add48475 /libdvdnav/remap.c | |
download | k9copy-0d382a262c0638d0f572fc37193ccc5ed3dc895f.tar.gz k9copy-0d382a262c0638d0f572fc37193ccc5ed3dc895f.zip |
Added old abandoned version of k9copy
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/k9copy@1091546 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'libdvdnav/remap.c')
-rw-r--r-- | libdvdnav/remap.c | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/libdvdnav/remap.c b/libdvdnav/remap.c new file mode 100644 index 0000000..1788b15 --- /dev/null +++ b/libdvdnav/remap.c @@ -0,0 +1,257 @@ +/* + * This file is part of libdvdnav, a DVD navigation library. + * + * libdvdnav is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * libdvdnav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + * + * $Id: remap.c,v 1.4 2003/08/25 21:51:40 f1rmb Exp $ + */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#ifndef _MSC_VER +#include <sys/param.h> +#include <sys/fcntl.h> +#else +#ifndef MAXPATHLEN +#define MAXPATHLEN 255 +#endif +#endif /* _MSC_VER */ + +#include <assert.h> +#include "remap.h" +#include "dvdnav_internal.h" + +struct block_s { + int domain; + int title; + int program; + unsigned long start_block; + unsigned long end_block; +}; + +struct remap_s { + char *title; + int maxblocks; + int nblocks; + int debug; + struct block_s *blocks; +}; + +static remap_t* remap_new( char *title) { + remap_t *map = malloc( sizeof(remap_t)); + map->title = strdup(title); + map->maxblocks = 0; + map->nblocks = 0; + map->blocks = NULL; + map->debug = 0; + return map; +} + +static int compare_block( block_t *a, block_t *b) { + /* returns -1 if a precedes b, 1 if a follows b, and 0 if a and b overlap */ + if (a->domain < b->domain) { + return -1; + } else if (a->domain > b->domain) { + return 1; + } + + if (a->title < b->title) { + return -1; + } else if (a->title > b->title) { + return 1; + } + + if (a->program < b->program) { + return -1; + } else if (a->program > b->program) { + return 1; + } + + if (a->end_block < b->start_block) { + return -1; + } else if (a->start_block > b->end_block) { + /* + * if a->start_block == b->end_block then the two regions + * aren't strictly overlapping, but they should be merged + * anyway since there are zero blocks between them + */ + return 1; + } + + return 0; +} + +static block_t *findblock( remap_t *map, block_t *key) { + int lb = 0; + int ub = map->nblocks - 1; + int mid; + int res; + + while (lb <= ub) { + mid = lb + (ub - lb)/2; + res = compare_block( key, &map->blocks[mid]); + if (res < 0) { + ub = mid-1; + } else if (res > 0) { + lb = mid+1; + } else { + return &map->blocks[mid]; + } + } + return NULL; +} + +static void mergeblock( block_t *b, block_t tmp) { + if (tmp.start_block < b->start_block) b->start_block = tmp.start_block; + if (tmp.end_block > b->end_block) b->end_block = tmp.end_block; +} + +static void remap_add_node( remap_t *map, block_t block) { + block_t *b; + int n; + b = findblock( map, &block); + if (b) { + /* overlaps an existing block */ + mergeblock( b, block); + } else { + /* new block */ + if (map->nblocks >= map->maxblocks) { + map->maxblocks += 20; + map->blocks = realloc( map->blocks, sizeof( block_t)*map->maxblocks); + } + n = map->nblocks++; + while (n > 0 && compare_block( &block, &map->blocks[ n-1]) < 0) { + map->blocks[ n] = map->blocks[ n-1]; + n--; + } + map->blocks[ n] = block; + } +} + +static int parseblock(char *buf, int *dom, int *tt, int *pg, + unsigned long *start, unsigned long *end) { + long tmp; + char *tok; + char *epos; + char *marker[]={"domain", "title", "program", "start", "end"}; + int st = 0; + tok = strtok( buf, " "); + while (st < 5) { + if (strcmp(tok, marker[st])) return -st-1000; + tok = strtok( NULL, " "); + if (!tok) return -st-2000; + tmp = strtol( tok, &epos, 0); + if (*epos != 0 && *epos != ',') return -st-3000; + switch (st) { + case 0: + *dom = (int)tmp; + break; + case 1: + *tt = (int)tmp; + break; + case 2: + *pg = (int)tmp; + break; + case 3: + *start = tmp; + break; + case 4: + *end = tmp; + break; + } + st++; + tok = strtok( NULL, " "); + } + return st; +} + +remap_t* remap_loadmap( char *title) { + char buf[160]; + char *fname; + char *home; + int res; + int fname_len=0; + FILE *fp; + block_t tmp; + remap_t *map; + + /* Build the map filename */ + home = getenv("HOME"); assert(home); + /*strncpy(fname, home, sizeof(fname)); + strncat(fname, "/.dvdnav/", sizeof(fname)); + strncat(fname, title, sizeof(fname)); + strncat(fname, ".map", sizeof(fname)); + */ + fname_len = strlen(home)+strlen("/.dvdnav/")+strlen(title)+strlen(".map")+1; + fname = calloc(fname_len, sizeof(char)); + snprintf(fname, fname_len, "%s%s%s%s", home, "/.dvdnav/", title, ".map"); + + /* Open the map file */ + fp = fopen( fname, "r"); + if (!fp) { + fprintf(MSG_OUT, "libdvdnav: Unable to find map file '%s'\n", fname); + return NULL; + } + + /* Load the map file */ + map = remap_new( title); + while (fgets( buf, sizeof(buf), fp) != NULL) { + if (buf[0] == '\n' || buf[0] == '#' || buf[0] == 0) continue; + if (strncasecmp( buf, "debug", 5) == 0) { + map->debug = 1; + } else { + res = parseblock( buf, + &tmp.domain, &tmp.title, &tmp.program, &tmp.start_block, &tmp.end_block); + if (res != 5) { + fprintf(MSG_OUT, "libdvdnav: Ignoring map line (%d): %s\n", res, buf); + continue; + } + remap_add_node( map, tmp); + } + } + + free(fname); + if (map->nblocks == 0 && map->debug == 0) return NULL; + return map; +} + +unsigned long remap_block( + remap_t *map, int domain, int title, int program, + unsigned long cblock, unsigned long offset) +{ + block_t key; + block_t *b; + + if (map->debug) { + fprintf(MSG_OUT, "libdvdnav: %s: domain %d, title %d, program %d, start %lx, next %lx\n", + map->title, domain, title, program, cblock, cblock+offset); + } + + key.domain = domain; + key.title = title; + key.program = program; + key.start_block = key.end_block = cblock + offset; + b = findblock( map, &key); + + if (b) { + if (map->debug) { + fprintf(MSG_OUT, "libdvdnav: Redirected to %lx\n", b->end_block); + } + return b->end_block - cblock; + } + return offset; +} |