You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
155 lines
3.2 KiB
155 lines
3.2 KiB
/* |
|
index.c - compact version of famous library mpg123 |
|
Copyright (C) 2017 Uncle Mike |
|
|
|
This program 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 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program 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. |
|
*/ |
|
|
|
#include "mpg123.h" |
|
#include "index.h" |
|
|
|
// the next expected frame offset, one step ahead. |
|
static mpg_off_t fi_next( frame_index_t *fi ) |
|
{ |
|
return (mpg_off_t)fi->fill*fi->step; |
|
} |
|
|
|
// shrink down the used index to the half. |
|
// be careful with size = 1 ... there's no shrinking possible there. |
|
static void fi_shrink( frame_index_t *fi ) |
|
{ |
|
if( fi->fill < 2 ) |
|
{ |
|
return; // won't shrink below 1. |
|
} |
|
else |
|
{ |
|
size_t c; |
|
|
|
// double the step, half the fill. Should work as well for fill%2 = 1 |
|
fi->step *= 2; |
|
fi->fill /= 2; |
|
|
|
// move the data down. |
|
for( c = 0; c < fi->fill; ++c ) |
|
fi->data[c] = fi->data[2*c]; |
|
} |
|
|
|
fi->next = fi_next( fi ); |
|
} |
|
|
|
void fi_init( frame_index_t *fi ) |
|
{ |
|
fi->data = NULL; |
|
fi->step = 1; |
|
fi->fill = 0; |
|
fi->size = 0; |
|
fi->grow_size = 0; |
|
fi->next = fi_next( fi ); |
|
} |
|
|
|
void fi_exit( frame_index_t *fi ) |
|
{ |
|
if( fi->size && fi->data != NULL ) |
|
free( fi->data ); |
|
|
|
fi_init( fi ); // be prepared for further fun, still. |
|
} |
|
|
|
int fi_resize( frame_index_t *fi, size_t newsize ) |
|
{ |
|
mpg_off_t *newdata = NULL; |
|
|
|
if( newsize == fi->size ) |
|
return 0; |
|
|
|
if( newsize > 0 && newsize < fi->size ) |
|
{ |
|
// when we reduce buffer size a bit, shrink stuff. |
|
while( fi->fill > newsize ) |
|
fi_shrink( fi ); |
|
} |
|
|
|
newdata = realloc( fi->data, newsize * sizeof( mpg_off_t )); |
|
if( newsize == 0 || newdata != NULL ) |
|
{ |
|
fi->data = newdata; |
|
fi->size = newsize; |
|
|
|
if( fi->fill > fi->size ) |
|
fi->fill = fi->size; |
|
|
|
fi->next = fi_next( fi ); |
|
|
|
return 0; |
|
} |
|
else |
|
{ |
|
return -1; |
|
} |
|
} |
|
|
|
void fi_add( frame_index_t *fi, mpg_off_t pos ) |
|
{ |
|
if( fi->fill == fi->size ) |
|
{ |
|
mpg_off_t framenum = fi->fill*fi->step; |
|
|
|
// index is full, we need to shrink... or grow. |
|
// store the current frame number to check later if we still want it. |
|
|
|
// if we want not / cannot grow, we shrink. |
|
if( !( fi->grow_size && fi_resize( fi, fi->size+fi->grow_size ) == 0 )) |
|
fi_shrink( fi ); |
|
|
|
// now check if we still want to add this frame (could be that not, because of changed step). |
|
if( fi->next != framenum ) |
|
return; |
|
} |
|
|
|
// when we are here, we want that frame. |
|
if( fi->fill < fi->size ) // safeguard for size = 1, or just generally |
|
{ |
|
fi->data[fi->fill] = pos; |
|
fi->fill++; |
|
fi->next = fi_next( fi ); |
|
} |
|
} |
|
|
|
int fi_set( frame_index_t *fi, mpg_off_t *offsets, mpg_off_t step, size_t fill ) |
|
{ |
|
if( fi_resize( fi, fill ) == -1 ) |
|
return -1; |
|
|
|
fi->step = step; |
|
|
|
if( offsets != NULL ) |
|
{ |
|
memcpy( fi->data, offsets, fill * sizeof( mpg_off_t )); |
|
fi->fill = fill; |
|
} |
|
else |
|
{ |
|
// allocation only, no entries in index yet |
|
fi->fill = 0; |
|
} |
|
|
|
fi->next = fi_next( fi ); |
|
|
|
return 0; |
|
} |
|
|
|
void fi_reset( frame_index_t *fi ) |
|
{ |
|
fi->fill = 0; |
|
fi->step = 1; |
|
fi->next = fi_next( fi ); |
|
} |