1 #include <stdlib.h>
2 #include <stdint.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <stdbool.h>
6 #include <pthread.h>
7 #include <time.h>
8 #include <math.h>
9 
10 #include <arcan_shmif.h>
11 
12 static shmif_pixel palette[] = {
13 	SHMIF_RGBA(0xff, 0x00, 0x00, 0xff),
14 	SHMIF_RGBA(0x00, 0xff, 0x00, 0xff),
15 	SHMIF_RGBA(0x00, 0x00, 0xff, 0xff),
16 	SHMIF_RGBA(0xff, 0xff, 0x00, 0xff),
17 	SHMIF_RGBA(0xff, 0x00, 0xff, 0xff),
18 	SHMIF_RGBA(0x00, 0xff, 0xff, 0xff),
19 	SHMIF_RGBA(0xff, 0xff, 0xff, 0xff)
20 };
21 
22 static float tones[] = {
23 	16.35, 18.35, 20.60, 21.83, 24.50, 27.50, 30.87, 32.70,
24 	30.87, 27.50, 24.50, 21.83, 20.60, 18.35
25 };
26 
27 static int pi = 0;
28 static int ti = 0;
29 static float pos = 0;
30 
time_ms()31 static long long time_ms()
32 {
33 	struct timespec tp;
34 	clock_gettime(CLOCK_MONOTONIC_RAW, &tp);
35 	return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000);
36 }
37 
aprod(void * data)38 static void* aprod(void* data)
39 {
40 	struct arcan_shmif_cont* cont = data;
41 	size_t bps = ARCAN_SHMIF_ACHANNELS * sizeof(shmif_asample);
42 
43 	while (1){
44 		size_t nsamp = (cont->abufsize - cont->abufused) / (bps * 2);
45 		float stepv = 2.0 * 3.14 * ((5 * tones[ti]) / (float)cont->samplerate);
46 		for (size_t b = 0; b < cont->abuf_cnt; b++){
47 			for (size_t i = 0; i < nsamp; i++){
48 				cont->audp[i*2+0] = 32767.0 * sinf(pos);
49 				cont->audp[i*2+1] = 32767.0 * sinf(pos);
50 				pos += stepv;
51 			}
52 			cont->abufused = nsamp * bps;
53 			arcan_shmif_signal(cont, SHMIF_SIGAUD);
54 		}
55 	}
56 
57 	return NULL;
58 }
59 
step(struct arcan_shmif_cont * cont)60 static void step(struct arcan_shmif_cont* cont)
61 {
62 	printf("pre;%lld;%d;%d\n", time_ms(), pi, ti);
63 	pi = (pi + 1) % (sizeof(palette) / sizeof(palette[0]));
64 	ti = (ti + 1) % (sizeof(tones) / sizeof(tones[0]));
65 	size_t count = cont->pitch * cont->h;
66 	for (size_t i = 0; i < count; i++)
67 		cont->vidp[i] = palette[pi];
68 
69 /* will create pop:ing as any queued buffers are dropped */
70 	arcan_shmif_enqueue(cont, &(arcan_event){
71 		.tgt.kind = ARCAN_EVENT(FLUSHAUD)
72 	});
73 	arcan_shmif_signal(cont, SHMIF_SIGVID);
74 	printf("post;%lld;%d;%d\n", time_ms(), pi, ti);
75 }
76 
main(int argc,char ** argv)77 int main(int argc, char** argv)
78 {
79 	struct arg_arr* aarr;
80 	if (argc != 7){
81 		printf("usage: \n\tavlat w h vbuf_count abuf_count abuf_sz samplerate\n");
82 			return EXIT_FAILURE;
83 	}
84 
85 	int w = strtoul(argv[1], NULL, 10);
86 	int h = strtoul(argv[2], NULL, 10);
87 
88 	struct shmif_resize_ext ext_sz = {
89 		.vbuf_cnt = strtoul(argv[3], NULL, 10),
90 		.abuf_cnt = strtoul(argv[4], NULL, 10),
91 		.abuf_sz = strtoul(argv[5], NULL, 10),
92 		.samplerate = strtoul(argv[6], NULL, 10)
93 	};
94 
95 	struct arcan_shmif_cont cont = arcan_shmif_open(
96 		SEGID_APPLICATION, SHMIF_ACQUIRE_FATALFAIL, &aarr);
97 
98 	if (!arcan_shmif_resize_ext(&cont, w, h, ext_sz)){
99 		printf("failed to set buffer properties\n");
100 		return EXIT_FAILURE;
101 	}
102 
103 	printf("context: %d * %d, %d bytes @ %d Hz",
104 		(int)cont.w, (int)cont.h, (int)cont.abufsize, (int)cont.samplerate);
105 
106 	step(&cont);
107 	ti = 0;
108 
109 	pthread_t athread;
110 	pthread_create(&athread, NULL, aprod, (void*) &cont);
111 
112 	arcan_event ev;
113 	while (arcan_shmif_wait(&cont, &ev)){
114 		if (ev.category == EVENT_TARGET)
115 		switch (ev.tgt.kind){
116 		case TARGET_COMMAND_EXIT:
117 			return EXIT_SUCCESS;
118 		break;
119 		default:
120 		break;
121 		}
122 		else if (ev.category == EVENT_IO){
123 			switch (ev.io.datatype){
124 				case EVENT_IDATATYPE_TRANSLATED:
125 					if (ev.io.input.translated.active)
126 						step(&cont);
127 				break;
128 				case EVENT_IDATATYPE_DIGITAL:
129 					if (ev.io.input.digital.active)
130 						step(&cont);
131 				break;
132 				default:
133 				break;
134 			}
135 		}
136 	}
137 
138 	return EXIT_SUCCESS;
139 }
140