2 * This file has been modified for the cdrkit suite.
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
13 /* @(#)p_block.c 1.19 04/02/23 J. Schilling from cdparanoia-III-alpha9.8 */
15 * Modifications to make the code portable Copyright (c) 2002 J. Schilling
23 #include "cdda_paranoia.h"
26 linked_list *new_list(void *(*newp) (void), void (*freep) (void *));
27 linked_element *add_elem(linked_list *l, void *elem);
28 linked_element *new_elem(linked_list *list);
29 void free_elem(linked_element *e, int free_ptr);
30 void free_list(linked_list *list, int free_ptr);
31 void *get_elem(linked_element *e);
32 linked_list *copy_list(linked_list *list);
33 static c_block *i_cblock_constructor(void);
34 void i_cblock_destructor(c_block *c);
35 c_block *new_c_block(cdrom_paranoia *p);
36 void free_c_block(c_block *c);
37 static v_fragment *i_vfragment_constructor(void);
38 static void i_v_fragment_destructor(v_fragment *v);
39 v_fragment *new_v_fragment(cdrom_paranoia *p, c_block *one, long begin,
41 void free_v_fragment(v_fragment *v);
42 c_block *c_first(cdrom_paranoia *p);
43 c_block *c_last(cdrom_paranoia *p);
44 c_block *c_next(c_block *c);
45 c_block *c_prev(c_block *c);
46 v_fragment *v_first(cdrom_paranoia *p);
47 v_fragment *v_last(cdrom_paranoia *p);
48 v_fragment *v_next(v_fragment *v);
49 v_fragment *v_prev(v_fragment *v);
50 void recover_cache(cdrom_paranoia *p);
51 Int16_t *v_buffer(v_fragment *v);
52 c_block *c_alloc(Int16_t *vector, long begin, long size);
53 void c_set(c_block *v, long begin);
54 void c_remove(c_block *v, long cutpos, long cutsize);
55 void c_overwrite(c_block *v, long pos, Int16_t *b, long size);
56 void c_append(c_block *v, Int16_t *vector, long size);
57 void c_removef(c_block *v, long cut);
58 void i_paranoia_firstlast(cdrom_paranoia *p);
59 cdrom_paranoia *paranoia_init(void *d, int nsectors);
62 linked_list *new_list(void *(*newp)(void), void (*freep)(void *))
64 linked_list *ret = _pcalloc(1, sizeof (linked_list));
67 ret->free_poly = freep;
71 linked_element *add_elem(linked_list *l, void *elem)
74 linked_element *ret = _pcalloc(1, sizeof (linked_element));
76 ret->stamp = l->current++;
92 linked_element *new_elem(linked_list *list)
94 void *new = list->new_poly();
96 return (add_elem(list, new));
99 void free_elem(linked_element *e, int free_ptr)
101 linked_list *l = e->list;
104 l->free_poly(e->ptr);
112 e->prev->next = e->next;
114 e->next->prev = e->prev;
120 void free_list(linked_list *list, int free_ptr)
123 free_elem(list->head, free_ptr);
127 void *get_elem(linked_element *e)
132 linked_list *copy_list(linked_list *list)
134 linked_list *new = new_list(list->new_poly, list->free_poly);
135 linked_element *i = list->tail;
138 add_elem(new, i->ptr);
144 /**** C_block stuff ******************************************************/
146 #define vp_cblock_constructor_func ((void*(*)(void))i_cblock_constructor)
147 static c_block *i_cblock_constructor()
149 c_block *ret = _pcalloc(1, sizeof (c_block));
154 #define vp_cblock_destructor_func ((void(*)(void*))i_cblock_destructor)
155 void i_cblock_destructor(c_block *c)
167 c_block *new_c_block(cdrom_paranoia *p)
169 linked_element *e = new_elem(p->cache);
177 void free_c_block(c_block *c)
180 * also rid ourselves of v_fragments that reference this block
182 v_fragment *v = v_first(c->p);
185 v_fragment *next = v_next(v);
195 #define vp_vfragment_constructor_func ((void*(*)(void))i_vfragment_constructor)
196 static v_fragment *i_vfragment_constructor()
198 v_fragment *ret = _pcalloc(1, sizeof (v_fragment));
203 #define vp_v_fragment_destructor_func ((void(*)(void*))i_v_fragment_destructor)
204 static void i_v_fragment_destructor(v_fragment *v)
209 v_fragment *new_v_fragment(cdrom_paranoia *p, c_block *one, long begin,
212 linked_element *e = new_elem(p->fragments);
213 v_fragment *b = e->ptr;
220 b->vector = one->vector + begin - one->begin;
221 b->size = end - begin;
222 b->lastsector = last;
227 void free_v_fragment(v_fragment *v)
232 c_block *c_first(cdrom_paranoia *p)
235 return (p->cache->head->ptr);
239 c_block* c_last(cdrom_paranoia *p)
242 return (p->cache->tail->ptr);
246 c_block *c_next(c_block *c)
249 return (c->e->next->ptr);
253 c_block *c_prev(c_block *c)
256 return (c->e->prev->ptr);
260 v_fragment *v_first(cdrom_paranoia *p)
262 if (p->fragments->head) {
263 return (p->fragments->head->ptr);
268 v_fragment *v_last(cdrom_paranoia *p)
270 if (p->fragments->tail)
271 return (p->fragments->tail->ptr);
275 v_fragment *v_next(v_fragment *v)
278 return (v->e->next->ptr);
282 v_fragment *v_prev(v_fragment *v)
285 return (v->e->prev->ptr);
289 void recover_cache(cdrom_paranoia *p)
291 linked_list *l = p->cache;
294 * Are we at/over our allowed cache size?
296 while (l->active > p->cache_limit) {
298 * cull from the tail of the list
300 free_c_block(c_last(p));
305 Int16_t *v_buffer(v_fragment *v)
315 * alloc a c_block not on a cache list
317 c_block *c_alloc(Int16_t *vector, long begin, long size)
319 c_block *c = _pcalloc(1, sizeof (c_block));
327 void c_set(c_block *v, long begin)
333 * pos here is vector position from zero
335 void c_insert(c_block *v, long pos, Int16_t *b, long size)
339 if (pos < 0 || pos > vs)
343 v->vector = _prealloc(v->vector, sizeof (Int16_t) * (size + vs));
345 v->vector = _pmalloc(sizeof (Int16_t) * size);
348 memmove(v->vector + pos + size, v->vector + pos,
349 (vs - pos) * sizeof (Int16_t));
350 memcpy(v->vector + pos, b, size * sizeof (Int16_t));
355 void c_remove(c_block *v, long cutpos, long cutsize)
359 if (cutpos < 0 || cutpos > vs)
361 if (cutpos + cutsize > vs)
362 cutsize = vs - cutpos;
364 cutsize = vs - cutpos;
368 memmove(v->vector + cutpos, v->vector + cutpos + cutsize,
369 (vs - cutpos - cutsize) * sizeof (Int16_t));
374 void c_overwrite(c_block *v, long pos, Int16_t *b, long size)
383 memcpy(v->vector + pos, b, size * sizeof (Int16_t));
386 void c_append(c_block *v, Int16_t *vector, long size)
394 v->vector = _prealloc(v->vector, sizeof (Int16_t) * (size + vs));
396 v->vector = _pmalloc(sizeof (Int16_t) * size);
397 memcpy(v->vector + vs, vector, sizeof (Int16_t) * size);
402 void c_removef(c_block *v, long cut)
413 void i_paranoia_firstlast(cdrom_paranoia *p)
418 p->current_lastsector = -1;
419 for (i = cdda_sector_gettrack(d, p->cursor); i < cdda_tracks(d); i++)
420 if (!cdda_track_audiop(d, i))
421 p->current_lastsector = cdda_track_lastsector(d, i - 1);
422 if (p->current_lastsector == -1)
423 p->current_lastsector = cdda_disc_lastsector(d);
425 p->current_firstsector = -1;
426 for (i = cdda_sector_gettrack(d, p->cursor); i > 0; i--)
427 if (!cdda_track_audiop(d, i))
428 p->current_firstsector = cdda_track_firstsector(d, i + 1);
429 if (p->current_firstsector == -1)
430 p->current_firstsector = cdda_disc_firstsector(d);
434 cdrom_paranoia *paranoia_init(void *d, int nsectors)
436 cdrom_paranoia *p = _pcalloc(1, sizeof (cdrom_paranoia));
438 p->cache = new_list(vp_cblock_constructor_func,
439 vp_cblock_destructor_func);
441 p->fragments = new_list(vp_vfragment_constructor_func,
442 vp_v_fragment_destructor_func);
444 p->nsectors = nsectors;
446 p->sortcache = sort_alloc(p->readahead * CD_FRAMEWORDS);
448 p->mindynoverlap = MIN_SECTOR_EPSILON;
449 p->maxdynoverlap = MAX_SECTOR_OVERLAP * CD_FRAMEWORDS;
450 p->maxdynoverlap = (nsectors - 1) * CD_FRAMEWORDS;
451 p->dynoverlap = MAX_SECTOR_OVERLAP * CD_FRAMEWORDS;
452 p->cache_limit = JIGGLE_MODULO;
453 p->enable = PARANOIA_MODE_FULL;
454 p->cursor = cdda_disc_firstsector(d);
455 p->lastread = -1000000;
458 * One last one... in case data and audio tracks are mixed...
460 i_paranoia_firstlast(p);
465 void paranoia_dynoverlapset(cdrom_paranoia *p, int minoverlap, int maxoverlap)
468 p->mindynoverlap = minoverlap;
469 if (maxoverlap > minoverlap)
470 p->maxdynoverlap = maxoverlap;
472 if (p->maxdynoverlap < p->mindynoverlap)
473 p->maxdynoverlap = p->mindynoverlap;