summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cfg-mplayer.h1
-rw-r--r--input/input.c67
-rw-r--r--input/input.h1
-rw-r--r--libmpcodecs/vf_ass.c50
-rw-r--r--libmpcodecs/vf_scale.c13
-rw-r--r--libmpcodecs/vf_scale.h1
-rw-r--r--libmpcodecs/vf_vo.c37
-rw-r--r--libvo/x11_common.c28
-rw-r--r--mplayer.c5
-rw-r--r--playtree.c54
-rw-r--r--screenshot.c14
-rw-r--r--timeline/tl_matroska.c51
12 files changed, 194 insertions, 128 deletions
diff --git a/cfg-mplayer.h b/cfg-mplayer.h
index f09cd9edd3..342fbccd62 100644
--- a/cfg-mplayer.h
+++ b/cfg-mplayer.h
@@ -926,7 +926,6 @@ const m_option_t mplayer_opts[]={
OPT_FLAG_ON("list-properties", list_properties, CONF_GLOBAL),
{"identify", &mp_msg_levels[MSGT_IDENTIFY], CONF_TYPE_FLAG, CONF_GLOBAL, 0, MSGL_V, NULL},
- {"-help", (void *) help_text, CONF_TYPE_PRINT, CONF_NOCFG|CONF_GLOBAL, 0, 0, NULL},
{"help", (void *) help_text, CONF_TYPE_PRINT, CONF_NOCFG|CONF_GLOBAL, 0, 0, NULL},
{"h", (void *) help_text, CONF_TYPE_PRINT, CONF_NOCFG|CONF_GLOBAL, 0, 0, NULL},
diff --git a/input/input.c b/input/input.c
index e1c001077a..f97487c1f7 100644
--- a/input/input.c
+++ b/input/input.c
@@ -571,9 +571,6 @@ struct cmd_bind_section {
struct cmd_queue {
struct mp_cmd *first;
- struct mp_cmd *last;
- int num_cmds;
- int num_abort_cmds;
};
struct input_ctx {
@@ -693,32 +690,52 @@ static bool is_abort_cmd(int cmd_id)
return false;
}
+static int queue_count_cmds(struct cmd_queue *queue)
+{
+ int res = 0;
+ for (struct mp_cmd *cmd = queue->first; cmd; cmd = cmd->queue_next)
+ res++;
+ return res;
+}
+
+static bool queue_has_abort_cmds(struct cmd_queue *queue)
+{
+ for (struct mp_cmd *cmd = queue->first; cmd; cmd = cmd->queue_next) {
+ if (is_abort_cmd(cmd->id))
+ return true;
+ }
+ return false;
+}
+
+static void queue_remove(struct cmd_queue *queue, struct mp_cmd *cmd)
+{
+ struct mp_cmd **p_prev = &queue->first;
+ while (*p_prev != cmd) {
+ p_prev = &(*p_prev)->queue_next;
+ }
+ // if this fails, cmd was not in the queue
+ assert(*p_prev == cmd);
+ *p_prev = cmd->queue_next;
+}
+
static void queue_pop(struct cmd_queue *queue)
{
- assert(queue->num_cmds > 0);
- struct mp_cmd *cmd = queue->first;
- queue->first = cmd->queue_next;
- queue->num_cmds--;
- queue->num_abort_cmds -= is_abort_cmd(cmd->id);
+ queue_remove(queue, queue->first);
}
static void queue_add(struct cmd_queue *queue, struct mp_cmd *cmd,
bool at_head)
{
- if (!queue->num_cmds) {
- queue->first = cmd;
- queue->last = cmd;
- } else if (at_head) {
- queue->first->queue_prev = cmd;
+ if (at_head) {
cmd->queue_next = queue->first;
queue->first = cmd;
} else {
- queue->last->queue_next = cmd;
- cmd->queue_prev = queue->last;
- queue->last = cmd;
+ struct mp_cmd **p_prev = &queue->first;
+ while (*p_prev)
+ p_prev = &(*p_prev)->queue_next;
+ *p_prev = cmd;
+ cmd->queue_next = NULL;
}
- queue->num_cmds++;
- queue->num_abort_cmds += is_abort_cmd(cmd->id);
}
int mp_input_add_cmd_fd(struct input_ctx *ictx, int fd, int select,
@@ -1279,8 +1296,8 @@ void mp_input_feed_key(struct input_ctx *ictx, int code)
if (!cmd)
return;
struct cmd_queue *queue = &ictx->key_cmd_queue;
- if (queue->num_cmds >= ictx->key_fifo_size &&
- (!is_abort_cmd(cmd->id) || queue->num_abort_cmds))
+ if (queue_count_cmds(queue) >= ictx->key_fifo_size &&
+ (!is_abort_cmd(cmd->id) || queue_has_abort_cmds(queue)))
return;
queue_add(queue, cmd, false);
}
@@ -1431,14 +1448,14 @@ mp_cmd_t *mp_input_get_cmd(struct input_ctx *ictx, int time, int peek_only)
if (async_quit_request)
return mp_input_parse_cmd("quit 1");
- if (ictx->control_cmd_queue.num_cmds || ictx->key_cmd_queue.num_cmds)
+ if (ictx->control_cmd_queue.first || ictx->key_cmd_queue.first)
time = 0;
read_all_events(ictx, time);
struct mp_cmd *ret;
struct cmd_queue *queue = &ictx->control_cmd_queue;
- if (!queue->num_cmds)
+ if (!queue->first)
queue = &ictx->key_cmd_queue;
- if (!queue->num_cmds) {
+ if (!queue->first) {
ret = check_autorepeat(ictx);
if (!ret)
return NULL;
@@ -1864,8 +1881,8 @@ static int print_cmd_list(m_option_t *cfg)
int mp_input_check_interrupt(struct input_ctx *ictx, int time)
{
for (int i = 0; ; i++) {
- if (async_quit_request || ictx->key_cmd_queue.num_abort_cmds ||
- ictx->control_cmd_queue.num_abort_cmds) {
+ if (async_quit_request || queue_has_abort_cmds(&ictx->key_cmd_queue) ||
+ queue_has_abort_cmds(&ictx->control_cmd_queue)) {
mp_tmsg(MSGT_INPUT, MSGL_WARN, "Received command to move to "
"another file. Aborting current processing.\n");
return true;
diff --git a/input/input.h b/input/input.h
index 4058ce3d99..8d32a9907c 100644
--- a/input/input.h
+++ b/input/input.h
@@ -194,7 +194,6 @@ typedef struct mp_cmd {
int nargs;
struct mp_cmd_arg args[MP_CMD_MAX_ARGS];
int pausing;
- struct mp_cmd *queue_prev;
struct mp_cmd *queue_next;
} mp_cmd_t;
diff --git a/libmpcodecs/vf_ass.c b/libmpcodecs/vf_ass.c
index a062149364..ce80caa74b 100644
--- a/libmpcodecs/vf_ass.c
+++ b/libmpcodecs/vf_ass.c
@@ -61,8 +61,9 @@ static const struct vf_priv_s {
int auto_insert;
struct osd_state *osd;
- ASS_Renderer *renderer_realaspect;
- ASS_Renderer *renderer_vsfilter;
+ ASS_Renderer *renderer;
+
+ double realaspect;
unsigned char *planes[3];
struct line_limits {
@@ -93,14 +94,10 @@ static int config(struct vf_instance *vf,
vf->priv->planes[2] = malloc(vf->priv->outw * vf->priv->outh);
vf->priv->line_limits = malloc((vf->priv->outh + 1) / 2 * sizeof(*vf->priv->line_limits));
- if (vf->priv->renderer_realaspect) {
- mp_ass_configure(vf->priv->renderer_realaspect, opts,
- vf->priv->outw, vf->priv->outh, 0);
- mp_ass_configure(vf->priv->renderer_vsfilter, opts,
+ if (vf->priv->renderer) {
+ mp_ass_configure(vf->priv->renderer, opts,
vf->priv->outw, vf->priv->outh, 0);
- ass_set_aspect_ratio(vf->priv->renderer_realaspect,
- (double)width / height * d_height / d_width, 1);
- ass_set_aspect_ratio(vf->priv->renderer_vsfilter, 1, 1);
+ vf->priv->realaspect = (double)width / height * d_height / d_width;
}
return vf_next_config(vf, vf->priv->outw, vf->priv->outh, d_width,
@@ -363,17 +360,16 @@ static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts)
{
struct osd_state *osd = vf->priv->osd;
ASS_Image *images = 0;
- ASS_Renderer *renderer = osd->vsfilter_aspect
+ double scale = osd->vsfilter_aspect
&& vf->opts->ass_vsfilter_aspect_compat
- ? vf->priv->renderer_vsfilter : vf->priv->renderer_realaspect;
- if (sub_visibility && renderer && osd->ass_track
+ ? 1 : vf->priv->realaspect;
+ if (sub_visibility && vf->priv->renderer && osd->ass_track
&& (pts != MP_NOPTS_VALUE)) {
- if (osd->ass_force_reload) {
- mp_ass_reload_options(vf->priv->renderer_realaspect, vf->opts);
- mp_ass_reload_options(vf->priv->renderer_vsfilter, vf->opts);
- }
+ ass_set_aspect_ratio(vf->priv->renderer, scale, 1);
+ if (osd->ass_force_reload)
+ mp_ass_reload_options(vf->priv->renderer, vf->opts);
osd->ass_force_reload = false;
- images = ass_render_frame(renderer, osd->ass_track,
+ images = ass_render_frame(vf->priv->renderer, osd->ass_track,
(pts + sub_delay) * 1000 + .5, NULL);
}
@@ -402,19 +398,13 @@ static int control(vf_instance_t *vf, int request, void *data)
vf->priv->osd = data;
break;
case VFCTRL_INIT_EOSD:
- vf->priv->renderer_realaspect = ass_renderer_init((ASS_Library *)data);
- if (!vf->priv->renderer_realaspect)
+ vf->priv->renderer = ass_renderer_init((ASS_Library *)data);
+ if (!vf->priv->renderer)
return CONTROL_FALSE;
- vf->priv->renderer_vsfilter = ass_renderer_init((ASS_Library *)data);
- if (!vf->priv->renderer_vsfilter) {
- ass_renderer_done(vf->priv->renderer_realaspect);
- return CONTROL_FALSE;
- }
- mp_ass_configure_fonts(vf->priv->renderer_realaspect);
- mp_ass_configure_fonts(vf->priv->renderer_vsfilter);
+ mp_ass_configure_fonts(vf->priv->renderer);
return CONTROL_TRUE;
case VFCTRL_DRAW_EOSD:
- if (vf->priv->renderer_realaspect)
+ if (vf->priv->renderer)
return CONTROL_TRUE;
break;
}
@@ -423,10 +413,8 @@ static int control(vf_instance_t *vf, int request, void *data)
static void uninit(struct vf_instance *vf)
{
- if (vf->priv->renderer_realaspect) {
- ass_renderer_done(vf->priv->renderer_realaspect);
- ass_renderer_done(vf->priv->renderer_vsfilter);
- }
+ if (vf->priv->renderer)
+ ass_renderer_done(vf->priv->renderer);
free(vf->priv->planes[1]);
free(vf->priv->planes[2]);
free(vf->priv->line_limits);
diff --git a/libmpcodecs/vf_scale.c b/libmpcodecs/vf_scale.c
index 585ef4d9a1..6bb076c744 100644
--- a/libmpcodecs/vf_scale.c
+++ b/libmpcodecs/vf_scale.c
@@ -704,7 +704,7 @@ void sws_getFlagsAndFilterFromCmdLine(int *flags, SwsFilter **srcFilterParam, Sw
}
// will use sws_flags & src_filter (from cmd line)
-struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat)
+static struct SwsContext *sws_getContextFromCmdLine2(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat, int extraflags)
{
int flags;
SwsFilter *dstFilterParam, *srcFilterParam;
@@ -718,6 +718,17 @@ struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat,
return sws_getContext(srcW, srcH, sfmt, dstW, dstH, dfmt, flags | get_sws_cpuflags(), srcFilterParam, dstFilterParam, NULL);
}
+struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat)
+{
+ return sws_getContextFromCmdLine2(srcW, srcH, srcFormat, dstW, dstH, dstFormat, 0);
+}
+
+struct SwsContext *sws_getContextFromCmdLine_hq(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat)
+{
+ return sws_getContextFromCmdLine2(srcW, srcH, srcFormat, dstW, dstH, dstFormat,
+ SWS_FULL_CHR_H_INT | SWS_FULL_CHR_H_INP | SWS_ACCURATE_RND | SWS_BITEXACT);
+}
+
/// An example of presets usage
static const struct size_preset {
char* name;
diff --git a/libmpcodecs/vf_scale.h b/libmpcodecs/vf_scale.h
index a9b3b506d5..08d651ce16 100644
--- a/libmpcodecs/vf_scale.h
+++ b/libmpcodecs/vf_scale.h
@@ -21,6 +21,7 @@
int get_sws_cpuflags(void);
struct SwsContext *sws_getContextFromCmdLine(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat);
+struct SwsContext *sws_getContextFromCmdLine_hq(int srcW, int srcH, int srcFormat, int dstW, int dstH, int dstFormat);
struct mp_csp_details;
int mp_sws_set_colorspace(struct SwsContext *sws, struct mp_csp_details *csp);
diff --git a/libmpcodecs/vf_vo.c b/libmpcodecs/vf_vo.c
index b855ea86df..9c0e90bb61 100644
--- a/libmpcodecs/vf_vo.c
+++ b/libmpcodecs/vf_vo.c
@@ -40,8 +40,7 @@ extern float sub_delay;
struct vf_priv_s {
struct vo *vo;
#ifdef CONFIG_ASS
- ASS_Renderer *renderer_realaspect;
- ASS_Renderer *renderer_vsfilter;
+ ASS_Renderer *renderer;
bool prev_visibility;
double scale_ratio;
#endif
@@ -85,10 +84,8 @@ static int config(struct vf_instance *vf,
#ifdef CONFIG_ASS
vf->priv->scale_ratio = (double) d_width / d_height * height / width;
- if (vf->priv->renderer_realaspect) {
- mp_ass_configure(vf->priv->renderer_realaspect, vf->opts, width, height,
- vf->default_caps & VFCAP_EOSD_UNSCALED);
- mp_ass_configure(vf->priv->renderer_vsfilter, vf->opts, width, height,
+ if (vf->priv->renderer) {
+ mp_ass_configure(vf->priv->renderer, vf->opts, width, height,
vf->default_caps & VFCAP_EOSD_UNSCALED);
}
@@ -137,16 +134,10 @@ static int control(struct vf_instance *vf, int request, void* data)
#ifdef CONFIG_ASS
case VFCTRL_INIT_EOSD:
{
- vf->priv->renderer_realaspect = ass_renderer_init(data);
- if (!vf->priv->renderer_realaspect)
- return CONTROL_FALSE;
- vf->priv->renderer_vsfilter = ass_renderer_init(data);
- if (!vf->priv->renderer_vsfilter) {
- ass_renderer_done(vf->priv->renderer_realaspect);
+ vf->priv->renderer = ass_renderer_init(data);
+ if (!vf->priv->renderer)
return CONTROL_FALSE;
- }
- mp_ass_configure_fonts(vf->priv->renderer_realaspect);
- mp_ass_configure_fonts(vf->priv->renderer_vsfilter);
+ mp_ass_configure_fonts(vf->priv->renderer);
vf->priv->prev_visibility = false;
return CONTROL_TRUE;
}
@@ -154,13 +145,11 @@ static int control(struct vf_instance *vf, int request, void* data)
{
struct osd_state *osd = data;
mp_eosd_images_t images = {NULL, 2};
- ASS_Renderer *renderer;
+ ASS_Renderer *renderer = vf->priv->renderer;
double scale;
if (osd->vsfilter_aspect && vf->opts->ass_vsfilter_aspect_compat) {
- renderer = vf->priv->renderer_vsfilter;
scale = vf->priv->scale_ratio;
} else {
- renderer = vf->priv->renderer_realaspect;
scale = 1;
}
if (!video_out->config_ok || !renderer)
@@ -176,10 +165,8 @@ static int control(struct vf_instance *vf, int request, void* data)
ass_set_aspect_ratio(renderer, scale, 1);
}
- if (osd->ass_force_reload) {
- mp_ass_reload_options(vf->priv->renderer_realaspect, vf->opts);
- mp_ass_reload_options(vf->priv->renderer_vsfilter, vf->opts);
- }
+ if (osd->ass_force_reload)
+ mp_ass_reload_options(vf->priv->renderer, vf->opts);
images.imgs = ass_render_frame(renderer, osd->ass_track,
(osd->pts+sub_delay) * 1000 + .5,
&images.changed);
@@ -252,10 +239,8 @@ static void uninit(struct vf_instance *vf)
* to get rid of numbered-mpi references that will now be invalid. */
vo_seek_reset(video_out);
#ifdef CONFIG_ASS
- if (vf->priv->renderer_realaspect) {
- ass_renderer_done(vf->priv->renderer_realaspect);
- ass_renderer_done(vf->priv->renderer_vsfilter);
- }
+ if (vf->priv->renderer)
+ ass_renderer_done(vf->priv->renderer);
#endif
free(vf->priv);
}
diff --git a/libvo/x11_common.c b/libvo/x11_common.c
index cdbbc213b5..e33b3c7ff6 100644
--- a/libvo/x11_common.c
+++ b/libvo/x11_common.c
@@ -993,34 +993,18 @@ static int vo_x11_get_gnome_layer(struct vo_x11_state *x11, Window win)
return WIN_LAYER_NORMAL;
}
-// set a X text property that expects a STRING type
+// set a X text property that expects a STRING or COMPOUND_TEXT type
static void vo_x11_set_property_string(struct vo *vo, Atom name, const char *t)
{
struct vo_x11_state *x11 = vo->x11;
XTextProperty prop = {0};
- int success;
-
- success = Xutf8TextListToTextProperty(x11->display, (char **)&t, 1,
- XStringStyle, &prop);
-
- // The call can fail if the string uses characters not in the STRING
- // encoding (which is latin-1 as far as I can tell). Try COMPOUND_TEXT
- // instead. (It is possible that COMPOUND_TEXT always works, but since the
- // difference in the type used for the property is visible to the Window
- // manager and the ICCCM seems to specify STRING, we're trying to be careful
- // and try STRING first.)
- // GTK seems to follow about the same fallback mechanism.
- if (success != Success) {
- XFree(prop.value);
- prop.value = NULL;
- success = Xutf8TextListToTextProperty(x11->display, (char **)&t, 1,
- XCompoundTextStyle, &prop);
- }
- if (success == Success)
+ if (Xutf8TextListToTextProperty(x11->display, (char **)&t, 1,
+ XStdICCTextStyle, &prop) == Success)
+ {
XSetTextProperty(x11->display, x11->window, &prop, name);
-
- XFree(prop.value);
+ XFree(prop.value);
+ }
}
// set a X text property that expects a UTF8_STRING type
diff --git a/mplayer.c b/mplayer.c
index e9f707c016..b97263b4fa 100644
--- a/mplayer.c
+++ b/mplayer.c
@@ -2672,8 +2672,11 @@ int reinit_video_chain(struct MPContext *mpctx)
{
struct MPOpts *opts = &mpctx->opts;
sh_video_t * const sh_video = mpctx->sh_video;
- if (!sh_video)
+ if (!sh_video){
+ uninit_player(mpctx, INITIALIZED_VO);
return 0;
+ }
+
double ar = -1.0;
//================== Init VIDEO (codec & libvo) ==========================
if (!opts->fixed_vo || !(mpctx->initialized_flags & INITIALIZED_VO)) {
diff --git a/playtree.c b/playtree.c
index 22205d3bf5..0d6358406f 100644
--- a/playtree.c
+++ b/playtree.c
@@ -411,6 +411,58 @@ play_tree_iter_push_params(play_tree_iter_t* iter) {
iter->entry_pushed = 1;
}
+// Shuffle the tree if the PLAY_TREE_RND flag is set, and unset it.
+// This is done recursively, but only the siblings with the same parent are
+// shuffled with each other.
+static void shuffle_tree(play_tree_t *pt) {
+ if (!pt)
+ return;
+
+ int count = 0;
+ play_tree_t *child = pt->child;
+ while (child) {
+ // possibly shuffle children
+ shuffle_tree(child);
+ child = child->next;
+ count++;
+ }
+
+ if (pt->flags & PLAY_TREE_RND) {
+ // Move a random element to the front and go to the next, until no
+ // elements are left.
+ // prev = pointer to next-link to the first yet-unshuffled entry
+ play_tree_t** prev = &pt->child;
+ while (count > 1) {
+ int n = (int)((double)(count) * rand() / (RAND_MAX + 1.0));
+ // move = element that is moved to front (inserted after prev)
+ play_tree_t **before_move = prev;
+ play_tree_t *move = *before_move;
+ while (n > 0) {
+ before_move = &move->next;
+ move = *before_move;
+ n--;
+ }
+ // unlink from old list
+ *before_move = move->next;
+ // insert between prev and the following element
+ // note that move could be the first unshuffled element
+ move->next = (*prev == move) ? move->next : *prev;
+ *prev = move;
+ prev = &move->next;
+ count--;
+ }
+ // reconstruct prev links
+ child = pt->child;
+ play_tree_t *prev_child = NULL;
+ while (child) {
+ child->prev = prev_child;
+ prev_child = child;
+ child = child->next;
+ }
+ pt->flags = pt->flags & ~PLAY_TREE_RND;
+ }
+}
+
play_tree_iter_t*
play_tree_iter_new(play_tree_t* pt,m_config_t* config) {
play_tree_iter_t* iter;
@@ -430,6 +482,8 @@ play_tree_iter_new(play_tree_t* pt,m_config_t* config) {
iter->tree = NULL;
iter->config = config;
+ shuffle_tree(pt);
+
if(pt->parent)
iter->loop = pt->parent->loop;
diff --git a/screenshot.c b/screenshot.c
index 9b8c67a89a..5ebe2e647f 100644
--- a/screenshot.c
+++ b/screenshot.c
@@ -41,7 +41,7 @@
#include "fmt-conversion.h"
-//for sws_getContextFromCmdLine and mp_sws_set_colorspace
+//for sws_getContextFromCmdLine_hq and mp_sws_set_colorspace
#include "libmpcodecs/vf_scale.h"
#include "libvo/csputils.h"
@@ -147,12 +147,12 @@ void screenshot_save(struct MPContext *mpctx, struct mp_image *image)
screenshot_ctx *ctx = screenshot_get_ctx(mpctx);
struct mp_image *dst = alloc_mpi(image->w, image->h, IMGFMT_RGB24);
- struct SwsContext *sws = sws_getContextFromCmdLine(image->width,
- image->height,
- image->imgfmt,
- dst->width,
- dst->height,
- dst->imgfmt);
+ struct SwsContext *sws = sws_getContextFromCmdLine_hq(image->width,
+ image->height,
+ image->imgfmt,
+ dst->width,
+ dst->height,
+ dst->imgfmt);
struct mp_csp_details colorspace;
get_detected_video_colorspace(mpctx->sh_video, &colorspace);
diff --git a/timeline/tl_matroska.c b/timeline/tl_matroska.c
index d378cf3aa4..cbc10a874f 100644
--- a/timeline/tl_matroska.c
+++ b/timeline/tl_matroska.c
@@ -21,6 +21,9 @@
#include <inttypes.h>
#include <assert.h>
#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
#include <libavutil/common.h>
#include "talloc.h"
@@ -33,6 +36,25 @@
#include "mpcommon.h"
#include "stream/stream.h"
+struct find_entry {
+ char *name;
+ int matchlen;
+ blkcnt_t size;
+};
+
+static int cmp_entry(const void *pa, const void *pb)
+{
+ const struct find_entry *a = pa, *b = pb;
+ // check "similar" filenames first
+ int matchdiff = b->matchlen - a->matchlen;
+ if (matchdiff)
+ return FFSIGN(matchdiff);
+ // check small files first
+ blkcnt_t sizediff = a->size - b->size;
+ if (sizediff)
+ return FFSIGN(sizediff);
+ return 0;
+}
static char **find_files(const char *original_file, const char *suffix)
{
@@ -46,9 +68,8 @@ static char **find_files(const char *original_file, const char *suffix)
talloc_free(tmpmem);
return results;
}
+ struct find_entry *entries = NULL;
struct dirent *ep;
- char ***names_by_matchlen = talloc_zero_array(tmpmem, char **,
- strlen(basename) + 1);
int num_results = 0;
while ((ep = readdir(dp))) {
int suffix_offset = strlen(ep->d_name) - strlen(suffix);
@@ -65,22 +86,26 @@ static char **find_files(const char *original_file, const char *suffix)
int matchlen = 0;
while (*s1 && *s1++ == *s2++)
matchlen++;
- int oldcount = MP_TALLOC_ELEMS(names_by_matchlen[matchlen]);
- names_by_matchlen[matchlen] = talloc_realloc(names_by_matchlen,
- names_by_matchlen[matchlen],
- char *, oldcount + 1);
- names_by_matchlen[matchlen][oldcount] = name;
+ // be a bit more fuzzy about matching the filename
+ matchlen = (matchlen + 3) / 5;
+
+ struct stat statbuf;
+ if (stat(name, &statbuf) != 0)
+ continue;
+ blkcnt_t bsize = statbuf.st_blocks;
+
+ entries = talloc_realloc(entries, entries, struct find_entry,
+ num_results + 1);
+ entries[num_results] = (struct find_entry) { name, matchlen, bsize };
num_results++;
}
closedir(dp);
+ // NOTE: maybe should make it compare pointers instead
+ qsort(entries, num_results, sizeof(struct find_entry), cmp_entry);
results = talloc_realloc(NULL, results, char *, num_results);
- char **resptr = results;
- for (int i = strlen(basename); i >= 0; i--) {
- char **p = names_by_matchlen[i];
- for (int j = 0; j < talloc_get_size(p) / sizeof(char *); j++)
- *resptr++ = p[j];
+ for (int i = 0; i < num_results; i++) {
+ results[i] = entries[i].name;
}
- assert(resptr == results + num_results);
talloc_free(tmpmem);
return results;
}