1 /*
2  * Decode Reference Frameserver Archetype
3  * Copyright 2014-2020, Björn Ståhl
4  * License: 3-Clause BSD, see COPYING file in arcan source repository.
5  * Reference: http://arcan-fe.com
6  * Description:
7  * The decode frameserver takes some form of compressed / packed input
8  * and transforms it into a raw format that shmif can use or process.
9  * The idea is to consolidate all parsers into a single volatile process
10  * that can be killed off by the parent without risking corruption. It
11  * is also a profile for sandboxing, decode is never expected to write
12  * to disk, exec other processes etc.
13  */
14 #include <arcan_shmif.h>
15 #include "decode.h"
16 
17 int show_use(struct arcan_shmif_cont* cont, const char* msg)
18 {
19 	if (msg)
20 		fprintf(stdout, "Couldn't start decode, reason: %s\n\n", msg);
21 
22 	fprintf(stdout, "Environment variables: \nARCAN_CONNPATH=path_to_server\n"
23 	  "ARCAN_ARG=packed_args (key1=value:key2:key3=value)\n\n"
24 		"General arguments:\n"
25 		"   key   \t   value   \t   description\n"
26 		"---------\t-----------\t-----------------\n"
27 #ifdef HAVE_VLC
28 		" protocol\t media     \t set 'media' mode (audio, video)\n"
29 #endif
30 		" protocol\t 3d        \t set '3d object' mode\n"
31 		" protocol\t text      \t set 'text' mode\n"
32 #ifdef HAVE_PROBE
33 		" protocol\t probe     \t set 'probe' mode\n"
34 #endif
35 		" protocol\t image     \t set 'image' mode\n"
36 #ifdef HAVE_T2S
37 		" protocol\t t2s       \t set 'text-to-speech' mode\n"
38 #endif
39 		"---------\t-----------\t----------------\n"
40 		"\n"
41 #ifdef HAVE_T2S
42 		" Accepted t2s arguments:\n"
43 		"   key   \t   value   \t   description\n"
44 		"---------\t-----------\t-----------------\n"
45 		" channel \t l,r, >lr< \t set output channels to left, right or both\n"
46 		" list    \t           \t return a list of voices then terminate\n"
47 		" text    \t msg       \t one-shot convert 'msg' to speech then terminate\n"
48 		" voice   \t name      \t select voice by name\n"
49 		" rate    \t 80..450   \t set rate in words per minute\n"
50 		" pitch   \t 0..100    \t set base pitch, 0 low, (default=50)\n"
51 		" range   \t 0..100    \t voice range, 0 monotone, (default=50)\n"
52 		" gap     \t 0..n ms   \t gap between words in miliseconds (default=10)\n"
53 		" ssml    \t           \t interpret text as 'ssml' formatted <voice> .. \n"
54 		" phonemes\t           \t interpret text as 'phoneme' ([[]]) encoded\n"
55 		"---------\t-----------\t----------------\n"
56 		"\n"
57 #endif
58 #ifdef HAVE_PROBE
59 		" Accepted probe arguments:\n"
60 		"   key   \t   value   \t   description\n"
61 		"---------\t-----------\t-----------------\n"
62 		" file    \t path      \t one-shot open file >path< for input \n"
63 		" format  \t type      \t set output format (mime, long, >short<)\n"
64 		"---------\t-----------\t-----------------\n"
65 		"\n"
66 #endif
67 		" Image protocol does not take any arguments, it operates solely \n"
68 		" in a service mode where incoming BCHUNK hints are decoded as they \n"
69 		" come and re-rastered on density changes.\n"
70 		"\n"
71 		" Accepted text arguments:\n"
72 		"   key   \t   value   \t   description\n"
73 		"---------\t-----------\t-----------------\n"
74 		" file    \t path      \t try to open file path for playback \n"
75 		" view    \t viewmode  \t (ascii, >utf8<, hex) set default view\n"
76 		"\n"
77 		"Accepted media arguments:\n"
78 		"   key   \t   value   \t   description\n"
79 		"---------\t-----------\t-----------------\n"
80 		" file    \t path      \t try to open file path for playback source\n"
81 		" fd      \t file-no   \t use inherited descriptor for playback source\n"
82 		" pos     \t 0..1      \t set the relative starting position \n"
83 		" noaudio \t           \t disable the audio output entirely \n"
84 		" stream  \t url       \t attempt to open URL for streaming input \n"
85 		" capture \t           \t try to open a capture device\n"
86 		" device  \t number    \t find capture device with specific index\n"
87 		" fps     \t rate      \t force a specific framerate\n"
88 		" width   \t outw      \t scale output to a specific width\n"
89 		" height  \t outh      \t scale output to a specific height\n"
90 		" loop    \t           \t reset playback upon completion\n"
91 #ifdef HAVE_UVC
92 		"---------\t-----------\t----------------\n");
93 	uvc_append_help(stdout);
94 	fprintf(stdout,
95 #endif
96 		"---------\t-----------\t----------------\n"
97 	);
98 
99 	if (cont){
100 		if (msg)
101 			arcan_shmif_last_words(cont, msg);
102 
103 		arcan_shmif_drop(cont);
104 	}
105 
106 	return EXIT_FAILURE;
107 }
108 
109 int wait_for_file(
110 	struct arcan_shmif_cont* cont, const char* extstr, char** idstr)
111 {
112 	int res = -1;
113 	struct arcan_event ev;
114 
115 	if (idstr)
116 		*idstr = NULL;
117 
118 	arcan_event bchunk = {
119 		.ext.kind = ARCAN_EVENT(BCHUNKSTATE),
120 		.category = EVENT_EXTERNAL,
121 		.ext.bchunk = {.hint = true, .input = true}
122 	};
123 	snprintf((char*)bchunk.ext.bchunk.extensions,
124 		COUNT_OF(bchunk.ext.bchunk.extensions), "%s", extstr);
125 	arcan_shmif_enqueue(cont, &bchunk);
126 
127 	while (arcan_shmif_wait(cont, &ev)){
128 		if (ev.category != EVENT_TARGET)
129 			continue;
130 
131 		if (ev.tgt.kind == TARGET_COMMAND_EXIT)
132 			return 0;
133 /* dup as the next call into shmif will close */
134 		else if (ev.tgt.kind == TARGET_COMMAND_BCHUNK_IN){
135 			res = arcan_shmif_dupfd(ev.tgt.ioevs[0].iv, -1, true);
136 			if (idstr)
137 				*idstr = strdup(ev.tgt.message);
138 			break;
139 		}
140 	}
141 
142 	return res;
143 }
144 
145 int afsrv_decode(struct arcan_shmif_cont* cont, struct arg_arr* args)
146 {
147 	const char* type;
148 	if (arg_lookup(args, "protocol", 0, &type)){
149 	}
150 	else {
151 /* previously decode (vs encode, remoting, ...) used 'proto' and not protocol,
152  * as to not break applications out there, silelty support the short form */
153 		if (arg_lookup(args, "proto", 0, &type)){
154 		}
155 		else
156 			type = "media";
157 	}
158 
159 #ifdef HAVE_PROBE
160 /* there should really be an 'auto' mode to this as well so that
161  * the results from probe is then switched to decode_(av, 3d, text, ...) */
162 	if (strcasecmp(type, "probe") == 0)
163 		return decode_probe(cont, args);
164 #endif
165 
166 	if (strcasecmp(type, "media") == 0)
167 		return decode_av(cont, args);
168 
169 	if (strcasecmp(type, "3d") == 0)
170 		return decode_3d(cont, args);
171 
172 	if (strcasecmp(type, "text") == 0)
173 		return decode_text(cont, args);
174 
175 	if (strcasecmp(type, "image") == 0)
176 		return decode_image(cont, args);
177 
178 #ifdef HAVE_T2S
179 	if (strcasecmp(type, "t2s") == 0)
180 		return decode_t2s(cont, args);
181 #endif
182 
183 	char errbuf[64];
184 	snprintf(errbuf, sizeof(errbuf), "unknown type argument: %s", type);
185 	return show_use(cont, errbuf);
186 }
187