Add homepage link.
[paraslash.git] / prebuffer_filter.c
1 /* Copyright (C) 2009 Andre Noll <maan@tuebingen.mpg.de>, see file COPYING. */
2
3 /** \file prebuffer_filter.c Paraslash's prebuffering filter. */
4
5 #include <regex.h>
6 #include <lopsub.h>
7
8 #include "para.h"
9 #include "filter_cmd.lsg.h"
10 #include "list.h"
11 #include "sched.h"
12 #include "buffer_tree.h"
13 #include "filter.h"
14 #include "string.h"
15 #include "error.h"
16
17 /** Data specific to the prebuffer filter. */
18 struct private_prebuffer_data {
19 /** Number of bytes prebuffered or -1 if no longer prebuffering. */
20 int prebuffered;
21 /** End of prebuffering period. */
22 struct timeval barrier;
23 };
24
25 static void prebuffer_pre_select(struct sched *s, void *context)
26 {
27 struct filter_node *fn = context;
28 struct btr_node *btrn = fn->btrn;
29 size_t iqs = btr_get_input_queue_size(btrn);
30 struct private_prebuffer_data *ppd = fn->private_data;
31 struct timeval diff;
32
33 if (iqs == 0)
34 return;
35 if (ppd->barrier.tv_sec == 0) {
36 uint32_t duration = FILTER_CMD_OPT_UINT32_VAL(PREBUFFER,
37 DURATION, fn->lpr);
38 struct timeval tv;
39 PARA_INFO_LOG("prebuffer period %" PRIu32 "ms\n", duration);
40 ms2tv(duration, &tv);
41 tv_add(&tv, now, &ppd->barrier);
42 }
43 if (tv_diff(&ppd->barrier, now, &diff) < 0)
44 return sched_min_delay(s);
45 sched_request_timeout(&diff, s);
46 }
47
48 static void prebuffer_close(struct filter_node *fn)
49 {
50 free(fn->private_data);
51 }
52
53 static int prebuffer_post_select(__a_unused struct sched *s, void *context)
54 {
55 struct filter_node *fn = context;
56 struct btr_node *btrn = fn->btrn;
57 size_t iqs = btr_get_input_queue_size(btrn);
58 struct private_prebuffer_data *ppd = fn->private_data;
59 uint32_t size = FILTER_CMD_OPT_UINT32_VAL(PREBUFFER, SIZE, fn->lpr);
60
61 if (ppd->barrier.tv_sec == 0)
62 return 0;
63 if (tv_diff(now, &ppd->barrier, NULL) < 0)
64 return 0;
65 if (iqs < size)
66 return 0;
67 btr_splice_out_node(&fn->btrn);
68 return -E_PREBUFFER_SUCCESS;
69 }
70
71 static void prebuffer_open(struct filter_node *fn)
72 {
73 struct private_prebuffer_data *ppd = para_calloc(sizeof(*ppd));
74 fn->private_data = ppd;
75 }
76
77 const struct filter lsg_filter_cmd_com_prebuffer_user_data = {
78 .open = prebuffer_open,
79 .close = prebuffer_close,
80 .pre_select = prebuffer_pre_select,
81 .post_select = prebuffer_post_select,
82 };