summaryrefslogtreecommitdiff
path: root/src/modules/rtv/rtv.c
blob: da6ae52065c147864e44b9fd457815ce013067cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <stdlib.h>
#include <time.h>

#include "fb.h"
#include "rototiller.h"
#include "util.h"

/* Copyright (C) 2019 - Vito Caputo <vcaputo@pengaru.com> */

/* This implements an MTV-inspired random slideshow of rototiller modules.
 *
 * Eventually it'd be nice to have it show a caption every time a new
 * module starts overlaying the name, author, license, etc.
 *
 * Some TODO items:
 * - show captions (need text rendering)
 * - optionally persist module contexts so they resume rather than restart
 * - runtime-configurable duration
 * - randomize runtime settings of shown modules
 * - redo the next module selection from random to
 *   walking the list and randomizing the list every
 *   time it completes a cycle.   The current dumb
 *   random technique will happily keep showing you the
 *   same thing over and over.
 */

#define RTV_DURATION_SECS	15

typedef struct rtv_context_t {
	const rototiller_module_t	**modules;
	size_t				n_modules;

	time_t				last_switch;
	const rototiller_module_t	*module;
	void				*module_ctxt;
} rtv_context_t;

static void setup_next_module(rtv_context_t *ctxt);
static void * rtv_create_context(void);
static void rtv_destroy_context(void *context);
static void rtv_prepare_frame(void *context, unsigned n_cpus, fb_fragment_t *fragment, rototiller_fragmenter_t *res_fragmenter);
static void rtv_finish_frame(void *context, fb_fragment_t *fragment);


rototiller_module_t	rtv_module = {
	.create_context = rtv_create_context,
	.destroy_context = rtv_destroy_context,
	.prepare_frame = rtv_prepare_frame,
	.finish_frame = rtv_finish_frame,
	.name = "rtv",
	.description = "Rototiller TV",
	.author = "Vito Caputo <vcaputo@pengaru.com>",
	.license = "GPLv2",
};


static void setup_next_module(rtv_context_t *ctxt)
{
	int	i;

	/* TODO: most of this module stuff should probably be
	 * in rototiller.c helpers, but it's harmless for now.
	 */
	if (ctxt->module) {
		if (ctxt->module->destroy_context)
			ctxt->module->destroy_context(ctxt->module_ctxt);

		ctxt->module_ctxt = NULL;
	}

	do {
		i = rand() % ctxt->n_modules;
	} while (ctxt->modules[i] == &rtv_module || ctxt->modules[i] == ctxt->module);

	ctxt->module = ctxt->modules[i];
	if (ctxt->module->create_context)
		ctxt->module_ctxt = ctxt->module->create_context();

	ctxt->last_switch = time(NULL);
}


static void * rtv_create_context(void)
{
	rtv_context_t	*ctxt = calloc(1, sizeof(rtv_context_t));

	rototiller_get_modules(&ctxt->modules, &ctxt->n_modules);
	setup_next_module(ctxt);

	return ctxt;
}


static void rtv_destroy_context(void *context)
{
	free(context);
}


static void rtv_prepare_frame(void *context, unsigned n_cpus, fb_fragment_t *fragment, rototiller_fragmenter_t *res_fragmenter)
{
	rtv_context_t	*ctxt = context;

	if (!ctxt->last_switch || time(NULL) - ctxt->last_switch > RTV_DURATION_SECS)
		setup_next_module(ctxt);

	rototiller_module_render(ctxt->module, ctxt->module_ctxt, fragment);
}


static void rtv_finish_frame(void *context, fb_fragment_t *fragment)
{
	/* TODO: this is stubbed here for drawing the caption overlay */
}
© All Rights Reserved