1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * lws-minimal-secure-streams-alexa
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * This file is made available under the Creative Commons CC0 1.0
5*1c60b9acSAndroid Build Coastguard Worker * Universal Public Domain Dedication.
6*1c60b9acSAndroid Build Coastguard Worker */
7*1c60b9acSAndroid Build Coastguard Worker
8*1c60b9acSAndroid Build Coastguard Worker #include <libwebsockets.h>
9*1c60b9acSAndroid Build Coastguard Worker #include <string.h>
10*1c60b9acSAndroid Build Coastguard Worker #include <sys/types.h>
11*1c60b9acSAndroid Build Coastguard Worker #include <sys/stat.h>
12*1c60b9acSAndroid Build Coastguard Worker #include <unistd.h>
13*1c60b9acSAndroid Build Coastguard Worker #include <fcntl.h>
14*1c60b9acSAndroid Build Coastguard Worker
15*1c60b9acSAndroid Build Coastguard Worker #include <mpg123.h>
16*1c60b9acSAndroid Build Coastguard Worker
17*1c60b9acSAndroid Build Coastguard Worker #include "private.h"
18*1c60b9acSAndroid Build Coastguard Worker
19*1c60b9acSAndroid Build Coastguard Worker struct lws_ss_handle *hss_avs_event, *hss_avs_sync;
20*1c60b9acSAndroid Build Coastguard Worker
21*1c60b9acSAndroid Build Coastguard Worker /* this is the type for the long poll event channel */
22*1c60b9acSAndroid Build Coastguard Worker
23*1c60b9acSAndroid Build Coastguard Worker typedef struct ss_avs_event {
24*1c60b9acSAndroid Build Coastguard Worker struct lws_ss_handle *ss;
25*1c60b9acSAndroid Build Coastguard Worker void *opaque_data;
26*1c60b9acSAndroid Build Coastguard Worker /* ... application specific state ... */
27*1c60b9acSAndroid Build Coastguard Worker
28*1c60b9acSAndroid Build Coastguard Worker struct lejp_ctx jctx;
29*1c60b9acSAndroid Build Coastguard Worker } ss_avs_event_t;
30*1c60b9acSAndroid Build Coastguard Worker
31*1c60b9acSAndroid Build Coastguard Worker enum {
32*1c60b9acSAndroid Build Coastguard Worker LAMP3STATE_IDLE,
33*1c60b9acSAndroid Build Coastguard Worker LAMP3STATE_SPOOLING,
34*1c60b9acSAndroid Build Coastguard Worker LAMP3STATE_DRAINING,
35*1c60b9acSAndroid Build Coastguard Worker };
36*1c60b9acSAndroid Build Coastguard Worker
37*1c60b9acSAndroid Build Coastguard Worker /* this is the type for the utterance metadata (and audio rideshares) */
38*1c60b9acSAndroid Build Coastguard Worker
39*1c60b9acSAndroid Build Coastguard Worker typedef struct ss_avs_metadata {
40*1c60b9acSAndroid Build Coastguard Worker struct lws_ss_handle *ss;
41*1c60b9acSAndroid Build Coastguard Worker void *opaque_data;
42*1c60b9acSAndroid Build Coastguard Worker /* ... application specific state ... */
43*1c60b9acSAndroid Build Coastguard Worker
44*1c60b9acSAndroid Build Coastguard Worker struct lws_buflist *dribble; /* next mp3 data while draining last */
45*1c60b9acSAndroid Build Coastguard Worker
46*1c60b9acSAndroid Build Coastguard Worker struct lejp_ctx jctx;
47*1c60b9acSAndroid Build Coastguard Worker size_t pos;
48*1c60b9acSAndroid Build Coastguard Worker size_t mp3_in;
49*1c60b9acSAndroid Build Coastguard Worker mpg123_handle *mh;
50*1c60b9acSAndroid Build Coastguard Worker
51*1c60b9acSAndroid Build Coastguard Worker lws_sorted_usec_list_t sul;
52*1c60b9acSAndroid Build Coastguard Worker
53*1c60b9acSAndroid Build Coastguard Worker uint8_t stash_eom[16];
54*1c60b9acSAndroid Build Coastguard Worker
55*1c60b9acSAndroid Build Coastguard Worker uint8_t se_head;
56*1c60b9acSAndroid Build Coastguard Worker uint8_t se_tail;
57*1c60b9acSAndroid Build Coastguard Worker
58*1c60b9acSAndroid Build Coastguard Worker char mp3_state;
59*1c60b9acSAndroid Build Coastguard Worker char first_mp3;
60*1c60b9acSAndroid Build Coastguard Worker uint8_t mp3_mime_match;
61*1c60b9acSAndroid Build Coastguard Worker uint8_t seen;
62*1c60b9acSAndroid Build Coastguard Worker uint8_t inside_mp3;
63*1c60b9acSAndroid Build Coastguard Worker
64*1c60b9acSAndroid Build Coastguard Worker } ss_avs_metadata_t;
65*1c60b9acSAndroid Build Coastguard Worker
66*1c60b9acSAndroid Build Coastguard Worker /*
67*1c60b9acSAndroid Build Coastguard Worker * The remote server only seems to give us a budget of 10s to consume the
68*1c60b9acSAndroid Build Coastguard Worker * results, after that it doesn't drop the stream, but doesn't send us anything
69*1c60b9acSAndroid Build Coastguard Worker * further on it.
70*1c60b9acSAndroid Build Coastguard Worker *
71*1c60b9acSAndroid Build Coastguard Worker * This makes it impossible to optimize buffering for incoming mp3 since we
72*1c60b9acSAndroid Build Coastguard Worker * have to go ahead and take it before the 10s is up.
73*1c60b9acSAndroid Build Coastguard Worker */
74*1c60b9acSAndroid Build Coastguard Worker
75*1c60b9acSAndroid Build Coastguard Worker #define MAX_MP3_IN_BUFFERING_BYTES 32768
76*1c60b9acSAndroid Build Coastguard Worker
77*1c60b9acSAndroid Build Coastguard Worker /*
78*1c60b9acSAndroid Build Coastguard Worker * Structure of JSON metadata for utterance handling
79*1c60b9acSAndroid Build Coastguard Worker */
80*1c60b9acSAndroid Build Coastguard Worker
81*1c60b9acSAndroid Build Coastguard Worker static const char *metadata = "{"
82*1c60b9acSAndroid Build Coastguard Worker "\"event\": {"
83*1c60b9acSAndroid Build Coastguard Worker "\"header\": {"
84*1c60b9acSAndroid Build Coastguard Worker "\"namespace\": \"SpeechRecognizer\","
85*1c60b9acSAndroid Build Coastguard Worker "\"name\": \"Recognize\","
86*1c60b9acSAndroid Build Coastguard Worker "\"messageId\": \"message-123\","
87*1c60b9acSAndroid Build Coastguard Worker "\"dialogRequestId\": \"dialog-request-321\""
88*1c60b9acSAndroid Build Coastguard Worker "},"
89*1c60b9acSAndroid Build Coastguard Worker "\"payload\": {"
90*1c60b9acSAndroid Build Coastguard Worker "\"profile\":" "\"CLOSE_TALK\","
91*1c60b9acSAndroid Build Coastguard Worker "\"format\":" "\"AUDIO_L16_RATE_16000_CHANNELS_1\""
92*1c60b9acSAndroid Build Coastguard Worker "}"
93*1c60b9acSAndroid Build Coastguard Worker "}"
94*1c60b9acSAndroid Build Coastguard Worker "}";
95*1c60b9acSAndroid Build Coastguard Worker
96*1c60b9acSAndroid Build Coastguard Worker /*
97*1c60b9acSAndroid Build Coastguard Worker * avs metadata
98*1c60b9acSAndroid Build Coastguard Worker */
99*1c60b9acSAndroid Build Coastguard Worker
100*1c60b9acSAndroid Build Coastguard Worker static void
use_buffer_250ms(lws_sorted_usec_list_t * sul)101*1c60b9acSAndroid Build Coastguard Worker use_buffer_250ms(lws_sorted_usec_list_t *sul)
102*1c60b9acSAndroid Build Coastguard Worker {
103*1c60b9acSAndroid Build Coastguard Worker ss_avs_metadata_t *m = lws_container_of(sul, ss_avs_metadata_t, sul);
104*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = (struct lws_context *)m->opaque_data;
105*1c60b9acSAndroid Build Coastguard Worker int est = lws_ss_get_est_peer_tx_credit(m->ss);
106*1c60b9acSAndroid Build Coastguard Worker
107*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: est txcr %d\n", __func__, est);
108*1c60b9acSAndroid Build Coastguard Worker
109*1c60b9acSAndroid Build Coastguard Worker if (est < MAX_MP3_IN_BUFFERING_BYTES - (MAX_MP3_IN_BUFFERING_BYTES / 4)) {
110*1c60b9acSAndroid Build Coastguard Worker lwsl_notice(" adding %d\n", MAX_MP3_IN_BUFFERING_BYTES / 4);
111*1c60b9acSAndroid Build Coastguard Worker lws_ss_add_peer_tx_credit(m->ss, MAX_MP3_IN_BUFFERING_BYTES / 4);
112*1c60b9acSAndroid Build Coastguard Worker }
113*1c60b9acSAndroid Build Coastguard Worker
114*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(context, 0, &m->sul, use_buffer_250ms,
115*1c60b9acSAndroid Build Coastguard Worker 250 * LWS_US_PER_MS);
116*1c60b9acSAndroid Build Coastguard Worker }
117*1c60b9acSAndroid Build Coastguard Worker
118*1c60b9acSAndroid Build Coastguard Worker static const char *mp3_mimetype = "application/octet-stream",
119*1c60b9acSAndroid Build Coastguard Worker *match2 = "\x0d\x0a\x0d\x0a";
120*1c60b9acSAndroid Build Coastguard Worker
121*1c60b9acSAndroid Build Coastguard Worker static int
ss_avs_mp3_open(ss_avs_metadata_t * m)122*1c60b9acSAndroid Build Coastguard Worker ss_avs_mp3_open(ss_avs_metadata_t *m)
123*1c60b9acSAndroid Build Coastguard Worker {
124*1c60b9acSAndroid Build Coastguard Worker int r;
125*1c60b9acSAndroid Build Coastguard Worker
126*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s\n", __func__);
127*1c60b9acSAndroid Build Coastguard Worker
128*1c60b9acSAndroid Build Coastguard Worker m->first_mp3 = 1;
129*1c60b9acSAndroid Build Coastguard Worker m->mh = mpg123_new(NULL, NULL);
130*1c60b9acSAndroid Build Coastguard Worker if (!m->mh) {
131*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: unable to make new mp3\n",
132*1c60b9acSAndroid Build Coastguard Worker __func__);
133*1c60b9acSAndroid Build Coastguard Worker goto bail;
134*1c60b9acSAndroid Build Coastguard Worker }
135*1c60b9acSAndroid Build Coastguard Worker mpg123_format_none(m->mh);
136*1c60b9acSAndroid Build Coastguard Worker r = mpg123_format(m->mh, 16000, MPG123_M_MONO,
137*1c60b9acSAndroid Build Coastguard Worker MPG123_ENC_SIGNED_16);
138*1c60b9acSAndroid Build Coastguard Worker if (r) {
139*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: mpg123 format failed %d\n",
140*1c60b9acSAndroid Build Coastguard Worker __func__, r);
141*1c60b9acSAndroid Build Coastguard Worker goto bail1;
142*1c60b9acSAndroid Build Coastguard Worker }
143*1c60b9acSAndroid Build Coastguard Worker r = mpg123_open_feed(m->mh);
144*1c60b9acSAndroid Build Coastguard Worker if (r) {
145*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: mpg123 open feed failed %d\n",
146*1c60b9acSAndroid Build Coastguard Worker __func__, r);
147*1c60b9acSAndroid Build Coastguard Worker goto bail1;
148*1c60b9acSAndroid Build Coastguard Worker }
149*1c60b9acSAndroid Build Coastguard Worker
150*1c60b9acSAndroid Build Coastguard Worker return 0;
151*1c60b9acSAndroid Build Coastguard Worker
152*1c60b9acSAndroid Build Coastguard Worker bail1:
153*1c60b9acSAndroid Build Coastguard Worker mpg123_delete(m->mh);
154*1c60b9acSAndroid Build Coastguard Worker m->mh = NULL;
155*1c60b9acSAndroid Build Coastguard Worker
156*1c60b9acSAndroid Build Coastguard Worker bail:
157*1c60b9acSAndroid Build Coastguard Worker return 1;
158*1c60b9acSAndroid Build Coastguard Worker }
159*1c60b9acSAndroid Build Coastguard Worker
160*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
161*1c60b9acSAndroid Build Coastguard Worker ss_avs_metadata_rx(void *userobj, const uint8_t *buf, size_t len, int flags);
162*1c60b9acSAndroid Build Coastguard Worker
163*1c60b9acSAndroid Build Coastguard Worker /*
164*1c60b9acSAndroid Build Coastguard Worker * This is called when the mp3 has drained it's input buffer and destroyed
165*1c60b9acSAndroid Build Coastguard Worker * itself.
166*1c60b9acSAndroid Build Coastguard Worker */
167*1c60b9acSAndroid Build Coastguard Worker
168*1c60b9acSAndroid Build Coastguard Worker static int
drain_end_cb(void * v)169*1c60b9acSAndroid Build Coastguard Worker drain_end_cb(void *v)
170*1c60b9acSAndroid Build Coastguard Worker {
171*1c60b9acSAndroid Build Coastguard Worker ss_avs_metadata_t *m = (ss_avs_metadata_t *)v;
172*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = (struct lws_context *)m->opaque_data;
173*1c60b9acSAndroid Build Coastguard Worker int tot = 0;
174*1c60b9acSAndroid Build Coastguard Worker
175*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s\n", __func__);
176*1c60b9acSAndroid Build Coastguard Worker
177*1c60b9acSAndroid Build Coastguard Worker /*
178*1c60b9acSAndroid Build Coastguard Worker * We have drained and destroyed the existing mp3 session. Is there
179*1c60b9acSAndroid Build Coastguard Worker * a new one pending?
180*1c60b9acSAndroid Build Coastguard Worker */
181*1c60b9acSAndroid Build Coastguard Worker
182*1c60b9acSAndroid Build Coastguard Worker m->first_mp3 = 1;
183*1c60b9acSAndroid Build Coastguard Worker m->mp3_state = LAMP3STATE_IDLE;
184*1c60b9acSAndroid Build Coastguard Worker
185*1c60b9acSAndroid Build Coastguard Worker if (lws_buflist_total_len(&m->dribble)) {
186*1c60b9acSAndroid Build Coastguard Worker /* we started another one */
187*1c60b9acSAndroid Build Coastguard Worker
188*1c60b9acSAndroid Build Coastguard Worker /* resume tx credit top up */
189*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(context, 0, &m->sul, use_buffer_250ms, 1);
190*1c60b9acSAndroid Build Coastguard Worker
191*1c60b9acSAndroid Build Coastguard Worker if (ss_avs_mp3_open(m))
192*1c60b9acSAndroid Build Coastguard Worker return 1;
193*1c60b9acSAndroid Build Coastguard Worker
194*1c60b9acSAndroid Build Coastguard Worker m->mp3_state = LAMP3STATE_SPOOLING;
195*1c60b9acSAndroid Build Coastguard Worker
196*1c60b9acSAndroid Build Coastguard Worker /*
197*1c60b9acSAndroid Build Coastguard Worker * Dump what we stashed from draining into the new mp3
198*1c60b9acSAndroid Build Coastguard Worker */
199*1c60b9acSAndroid Build Coastguard Worker
200*1c60b9acSAndroid Build Coastguard Worker while (lws_buflist_total_len(&m->dribble)) {
201*1c60b9acSAndroid Build Coastguard Worker size_t s;
202*1c60b9acSAndroid Build Coastguard Worker uint8_t *u, t;
203*1c60b9acSAndroid Build Coastguard Worker
204*1c60b9acSAndroid Build Coastguard Worker s = lws_buflist_next_segment_len(&m->dribble, &u);
205*1c60b9acSAndroid Build Coastguard Worker t = m->stash_eom[m->se_tail];
206*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: preload %d: %d\n", __func__, (int)s, t);
207*1c60b9acSAndroid Build Coastguard Worker
208*1c60b9acSAndroid Build Coastguard Worker mpg123_feed(m->mh, u, s);
209*1c60b9acSAndroid Build Coastguard Worker lws_buflist_use_segment(&m->dribble, s);
210*1c60b9acSAndroid Build Coastguard Worker if (m->first_mp3) {
211*1c60b9acSAndroid Build Coastguard Worker play_mp3(m->mh, NULL, NULL);
212*1c60b9acSAndroid Build Coastguard Worker m->first_mp3 = 0;
213*1c60b9acSAndroid Build Coastguard Worker }
214*1c60b9acSAndroid Build Coastguard Worker
215*1c60b9acSAndroid Build Coastguard Worker tot += s;
216*1c60b9acSAndroid Build Coastguard Worker
217*1c60b9acSAndroid Build Coastguard Worker m->se_tail = (m->se_tail + 1) % sizeof(m->stash_eom);
218*1c60b9acSAndroid Build Coastguard Worker if (t) {
219*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: preloaded EOM\n", __func__);
220*1c60b9acSAndroid Build Coastguard Worker
221*1c60b9acSAndroid Build Coastguard Worker /*
222*1c60b9acSAndroid Build Coastguard Worker * We stashed the whole of the message, we need
223*1c60b9acSAndroid Build Coastguard Worker * to also do the EOM processing. We will come
224*1c60b9acSAndroid Build Coastguard Worker * back here if there's another message in the
225*1c60b9acSAndroid Build Coastguard Worker * stash.
226*1c60b9acSAndroid Build Coastguard Worker */
227*1c60b9acSAndroid Build Coastguard Worker
228*1c60b9acSAndroid Build Coastguard Worker m->mp3_state = LAMP3STATE_DRAINING;
229*1c60b9acSAndroid Build Coastguard Worker if (m->mh)
230*1c60b9acSAndroid Build Coastguard Worker play_mp3(NULL, drain_end_cb, m);
231*1c60b9acSAndroid Build Coastguard Worker
232*1c60b9acSAndroid Build Coastguard Worker lws_ss_add_peer_tx_credit(m->ss, tot);
233*1c60b9acSAndroid Build Coastguard Worker #if 0
234*1c60b9acSAndroid Build Coastguard Worker /*
235*1c60b9acSAndroid Build Coastguard Worker * Put a hold on bringing in any more data
236*1c60b9acSAndroid Build Coastguard Worker */
237*1c60b9acSAndroid Build Coastguard Worker lws_sul_cancel(&m->sul);
238*1c60b9acSAndroid Build Coastguard Worker #endif
239*1c60b9acSAndroid Build Coastguard Worker /* destroy our copy of the handle */
240*1c60b9acSAndroid Build Coastguard Worker m->mh = NULL;
241*1c60b9acSAndroid Build Coastguard Worker
242*1c60b9acSAndroid Build Coastguard Worker break;
243*1c60b9acSAndroid Build Coastguard Worker }
244*1c60b9acSAndroid Build Coastguard Worker }
245*1c60b9acSAndroid Build Coastguard Worker
246*1c60b9acSAndroid Build Coastguard Worker lws_ss_add_peer_tx_credit(m->ss, tot);
247*1c60b9acSAndroid Build Coastguard Worker }
248*1c60b9acSAndroid Build Coastguard Worker
249*1c60b9acSAndroid Build Coastguard Worker return 0;
250*1c60b9acSAndroid Build Coastguard Worker }
251*1c60b9acSAndroid Build Coastguard Worker
252*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
ss_avs_metadata_rx(void * userobj,const uint8_t * buf,size_t len,int flags)253*1c60b9acSAndroid Build Coastguard Worker ss_avs_metadata_rx(void *userobj, const uint8_t *buf, size_t len, int flags)
254*1c60b9acSAndroid Build Coastguard Worker {
255*1c60b9acSAndroid Build Coastguard Worker ss_avs_metadata_t *m = (ss_avs_metadata_t *)userobj;
256*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = (struct lws_context *)m->opaque_data;
257*1c60b9acSAndroid Build Coastguard Worker int n = 0, hit = 0;
258*1c60b9acSAndroid Build Coastguard Worker
259*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: len %d, flags %d (est peer txcr %d)\n", __func__,
260*1c60b9acSAndroid Build Coastguard Worker (int)len, flags, lws_ss_get_est_peer_tx_credit(m->ss));
261*1c60b9acSAndroid Build Coastguard Worker
262*1c60b9acSAndroid Build Coastguard Worker // lwsl_hexdump_warn(buf, len);
263*1c60b9acSAndroid Build Coastguard Worker
264*1c60b9acSAndroid Build Coastguard Worker if ((flags & LWSSS_FLAG_SOM) && !m->mh && !m->seen) {
265*1c60b9acSAndroid Build Coastguard Worker m->mp3_mime_match = 0;
266*1c60b9acSAndroid Build Coastguard Worker m->seen = 0;
267*1c60b9acSAndroid Build Coastguard Worker m->inside_mp3 = 0;
268*1c60b9acSAndroid Build Coastguard Worker }
269*1c60b9acSAndroid Build Coastguard Worker
270*1c60b9acSAndroid Build Coastguard Worker if (!m->inside_mp3) {
271*1c60b9acSAndroid Build Coastguard Worker /*
272*1c60b9acSAndroid Build Coastguard Worker * Identify the part with the mp3 in, if any
273*1c60b9acSAndroid Build Coastguard Worker */
274*1c60b9acSAndroid Build Coastguard Worker
275*1c60b9acSAndroid Build Coastguard Worker while (n < (int)len - 24) {
276*1c60b9acSAndroid Build Coastguard Worker if (!m->seen) {
277*1c60b9acSAndroid Build Coastguard Worker if (buf[n] == mp3_mimetype[m->mp3_mime_match]) {
278*1c60b9acSAndroid Build Coastguard Worker m->mp3_mime_match++;
279*1c60b9acSAndroid Build Coastguard Worker if (m->mp3_mime_match == 24) {
280*1c60b9acSAndroid Build Coastguard Worker m->mp3_mime_match = 0;
281*1c60b9acSAndroid Build Coastguard Worker m->seen = 1;
282*1c60b9acSAndroid Build Coastguard Worker n++;
283*1c60b9acSAndroid Build Coastguard Worker continue;
284*1c60b9acSAndroid Build Coastguard Worker }
285*1c60b9acSAndroid Build Coastguard Worker } else
286*1c60b9acSAndroid Build Coastguard Worker m->mp3_mime_match = 0;
287*1c60b9acSAndroid Build Coastguard Worker } else {
288*1c60b9acSAndroid Build Coastguard Worker if (buf[n] == match2[m->mp3_mime_match]) {
289*1c60b9acSAndroid Build Coastguard Worker m->mp3_mime_match++;
290*1c60b9acSAndroid Build Coastguard Worker if (m->mp3_mime_match == 4) {
291*1c60b9acSAndroid Build Coastguard Worker m->seen = 0;
292*1c60b9acSAndroid Build Coastguard Worker m->mp3_mime_match = 0;
293*1c60b9acSAndroid Build Coastguard Worker hit = 1;
294*1c60b9acSAndroid Build Coastguard Worker n++;
295*1c60b9acSAndroid Build Coastguard Worker buf += n;
296*1c60b9acSAndroid Build Coastguard Worker len -= n;
297*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("identified reply...\n");
298*1c60b9acSAndroid Build Coastguard Worker m->inside_mp3 = 1;
299*1c60b9acSAndroid Build Coastguard Worker break;
300*1c60b9acSAndroid Build Coastguard Worker }
301*1c60b9acSAndroid Build Coastguard Worker } else
302*1c60b9acSAndroid Build Coastguard Worker m->mp3_mime_match = 0;
303*1c60b9acSAndroid Build Coastguard Worker }
304*1c60b9acSAndroid Build Coastguard Worker
305*1c60b9acSAndroid Build Coastguard Worker n++;
306*1c60b9acSAndroid Build Coastguard Worker }
307*1c60b9acSAndroid Build Coastguard Worker
308*1c60b9acSAndroid Build Coastguard Worker if (!hit) {
309*1c60b9acSAndroid Build Coastguard Worker lws_ss_add_peer_tx_credit(m->ss, len);
310*1c60b9acSAndroid Build Coastguard Worker return 0;
311*1c60b9acSAndroid Build Coastguard Worker }
312*1c60b9acSAndroid Build Coastguard Worker }
313*1c60b9acSAndroid Build Coastguard Worker
314*1c60b9acSAndroid Build Coastguard Worker // lwsl_notice("%s: state %d\n", __func__, m->mp3_state);
315*1c60b9acSAndroid Build Coastguard Worker
316*1c60b9acSAndroid Build Coastguard Worker switch (m->mp3_state) {
317*1c60b9acSAndroid Build Coastguard Worker case LAMP3STATE_IDLE:
318*1c60b9acSAndroid Build Coastguard Worker
319*1c60b9acSAndroid Build Coastguard Worker if (hit) {
320*1c60b9acSAndroid Build Coastguard Worker
321*1c60b9acSAndroid Build Coastguard Worker lws_ss_add_peer_tx_credit(m->ss, n);
322*1c60b9acSAndroid Build Coastguard Worker
323*1c60b9acSAndroid Build Coastguard Worker if (ss_avs_mp3_open(m))
324*1c60b9acSAndroid Build Coastguard Worker goto bail;
325*1c60b9acSAndroid Build Coastguard Worker
326*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(context, 0, &m->sul, use_buffer_250ms, 1);
327*1c60b9acSAndroid Build Coastguard Worker m->mp3_state = LAMP3STATE_SPOOLING;
328*1c60b9acSAndroid Build Coastguard Worker break;
329*1c60b9acSAndroid Build Coastguard Worker }
330*1c60b9acSAndroid Build Coastguard Worker
331*1c60b9acSAndroid Build Coastguard Worker lws_ss_add_peer_tx_credit(m->ss, len);
332*1c60b9acSAndroid Build Coastguard Worker
333*1c60b9acSAndroid Build Coastguard Worker if (!m->inside_mp3)
334*1c60b9acSAndroid Build Coastguard Worker break;
335*1c60b9acSAndroid Build Coastguard Worker
336*1c60b9acSAndroid Build Coastguard Worker /* fallthru */
337*1c60b9acSAndroid Build Coastguard Worker
338*1c60b9acSAndroid Build Coastguard Worker case LAMP3STATE_SPOOLING:
339*1c60b9acSAndroid Build Coastguard Worker
340*1c60b9acSAndroid Build Coastguard Worker if (m->dribble)
341*1c60b9acSAndroid Build Coastguard Worker goto draining;
342*1c60b9acSAndroid Build Coastguard Worker
343*1c60b9acSAndroid Build Coastguard Worker if (len) {
344*1c60b9acSAndroid Build Coastguard Worker /*
345*1c60b9acSAndroid Build Coastguard Worker * We are shoving encoded mp3 into mpg123-allocated heap
346*1c60b9acSAndroid Build Coastguard Worker * buffers... unfortunately mpg123 doesn't seem to
347*1c60b9acSAndroid Build Coastguard Worker * expose where it is in its allocated input so we can
348*1c60b9acSAndroid Build Coastguard Worker * track how much is stashed. Instead while in playback
349*1c60b9acSAndroid Build Coastguard Worker * mode, we assume 64kbps mp3 encoding, ie, 8KB/s, and
350*1c60b9acSAndroid Build Coastguard Worker * run a sul that allows an additional 2KB tx credit
351*1c60b9acSAndroid Build Coastguard Worker * every 250ms, with 4KB initial credit.
352*1c60b9acSAndroid Build Coastguard Worker */
353*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: SPOOL %d\n", __func__, (int)len);
354*1c60b9acSAndroid Build Coastguard Worker mpg123_feed(m->mh, buf, len);
355*1c60b9acSAndroid Build Coastguard Worker
356*1c60b9acSAndroid Build Coastguard Worker if (m->first_mp3) {
357*1c60b9acSAndroid Build Coastguard Worker lws_sul_schedule(context, 0, &m->sul,
358*1c60b9acSAndroid Build Coastguard Worker use_buffer_250ms, 1);
359*1c60b9acSAndroid Build Coastguard Worker // lws_ss_add_peer_tx_credit(m->ss,
360*1c60b9acSAndroid Build Coastguard Worker // len + (MAX_MP3_IN_BUFFERING_BYTES / 2));
361*1c60b9acSAndroid Build Coastguard Worker play_mp3(m->mh, NULL, NULL);
362*1c60b9acSAndroid Build Coastguard Worker } //else
363*1c60b9acSAndroid Build Coastguard Worker // lws_ss_add_peer_tx_credit(m->ss, len);
364*1c60b9acSAndroid Build Coastguard Worker m->first_mp3 = 0;
365*1c60b9acSAndroid Build Coastguard Worker }
366*1c60b9acSAndroid Build Coastguard Worker
367*1c60b9acSAndroid Build Coastguard Worker if (flags & LWSSS_FLAG_EOM) {
368*1c60b9acSAndroid Build Coastguard Worker /*
369*1c60b9acSAndroid Build Coastguard Worker * This means one "message" / mime part with mp3 data
370*1c60b9acSAndroid Build Coastguard Worker * has finished coming in. But there may be whole other
371*1c60b9acSAndroid Build Coastguard Worker * parts with other mp3s following, with potentially
372*1c60b9acSAndroid Build Coastguard Worker * different mp3 parameters. So we want to tell this
373*1c60b9acSAndroid Build Coastguard Worker * one to drain and finish and destroy the current mp3
374*1c60b9acSAndroid Build Coastguard Worker * object before we go on.
375*1c60b9acSAndroid Build Coastguard Worker *
376*1c60b9acSAndroid Build Coastguard Worker * But not knowing the length of the current one, there
377*1c60b9acSAndroid Build Coastguard Worker * will already be outstanding tx credit at the server,
378*1c60b9acSAndroid Build Coastguard Worker * so it's going to spam us with the next part before we
379*1c60b9acSAndroid Build Coastguard Worker * have the new mp3 sink for it.
380*1c60b9acSAndroid Build Coastguard Worker */
381*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: EOM\n", __func__);
382*1c60b9acSAndroid Build Coastguard Worker m->mp3_mime_match = 0;
383*1c60b9acSAndroid Build Coastguard Worker m->seen = 0;
384*1c60b9acSAndroid Build Coastguard Worker m->mp3_state = LAMP3STATE_DRAINING;
385*1c60b9acSAndroid Build Coastguard Worker /* from input POV, we're no longer inside an mp3 */
386*1c60b9acSAndroid Build Coastguard Worker m->inside_mp3 = 0;
387*1c60b9acSAndroid Build Coastguard Worker if (m->mh)
388*1c60b9acSAndroid Build Coastguard Worker play_mp3(NULL, drain_end_cb, m);
389*1c60b9acSAndroid Build Coastguard Worker #if 0
390*1c60b9acSAndroid Build Coastguard Worker /*
391*1c60b9acSAndroid Build Coastguard Worker * Put a hold on bringing in any more data
392*1c60b9acSAndroid Build Coastguard Worker */
393*1c60b9acSAndroid Build Coastguard Worker lws_sul_cancel(&m->sul);
394*1c60b9acSAndroid Build Coastguard Worker #endif
395*1c60b9acSAndroid Build Coastguard Worker /* destroy our copy of the handle */
396*1c60b9acSAndroid Build Coastguard Worker m->mh = NULL;
397*1c60b9acSAndroid Build Coastguard Worker }
398*1c60b9acSAndroid Build Coastguard Worker break;
399*1c60b9acSAndroid Build Coastguard Worker
400*1c60b9acSAndroid Build Coastguard Worker case LAMP3STATE_DRAINING:
401*1c60b9acSAndroid Build Coastguard Worker
402*1c60b9acSAndroid Build Coastguard Worker draining:
403*1c60b9acSAndroid Build Coastguard Worker if (buf && len && m->inside_mp3) {
404*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: DRAINING: stashing %d: %d %d %d\n",
405*1c60b9acSAndroid Build Coastguard Worker __func__, (int)len, !!(flags & LWSSS_FLAG_EOM),
406*1c60b9acSAndroid Build Coastguard Worker m->se_head, m->se_tail);
407*1c60b9acSAndroid Build Coastguard Worker lwsl_hexdump_notice(buf, len);
408*1c60b9acSAndroid Build Coastguard Worker if (lws_buflist_append_segment(&m->dribble, buf, len) < 0)
409*1c60b9acSAndroid Build Coastguard Worker goto bail;
410*1c60b9acSAndroid Build Coastguard Worker
411*1c60b9acSAndroid Build Coastguard Worker m->stash_eom[m->se_head] = !!(flags & LWSSS_FLAG_EOM);
412*1c60b9acSAndroid Build Coastguard Worker m->se_head = (m->se_head + 1) % sizeof(m->stash_eom);
413*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: next head %d\n", __func__, m->se_head);
414*1c60b9acSAndroid Build Coastguard Worker
415*1c60b9acSAndroid Build Coastguard Worker lws_ss_add_peer_tx_credit(m->ss, len);
416*1c60b9acSAndroid Build Coastguard Worker }
417*1c60b9acSAndroid Build Coastguard Worker
418*1c60b9acSAndroid Build Coastguard Worker if (flags & LWSSS_FLAG_EOM) {
419*1c60b9acSAndroid Build Coastguard Worker if (!len && m->se_head != m->se_tail) {
420*1c60b9acSAndroid Build Coastguard Worker /* 0-len EOM... retrospectively mark last stash */
421*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: retro EOM\n", __func__);
422*1c60b9acSAndroid Build Coastguard Worker m->stash_eom[(m->se_head - 1) % sizeof(m->stash_eom)] = 1;
423*1c60b9acSAndroid Build Coastguard Worker }
424*1c60b9acSAndroid Build Coastguard Worker
425*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: Draining EOM\n", __func__);
426*1c60b9acSAndroid Build Coastguard Worker m->inside_mp3 = 0;
427*1c60b9acSAndroid Build Coastguard Worker }
428*1c60b9acSAndroid Build Coastguard Worker /*
429*1c60b9acSAndroid Build Coastguard Worker * Don't provide any additional tx credit... we're just
430*1c60b9acSAndroid Build Coastguard Worker * mopping up the overspill from the previous mp3 credit
431*1c60b9acSAndroid Build Coastguard Worker */
432*1c60b9acSAndroid Build Coastguard Worker break;
433*1c60b9acSAndroid Build Coastguard Worker }
434*1c60b9acSAndroid Build Coastguard Worker
435*1c60b9acSAndroid Build Coastguard Worker return 0;
436*1c60b9acSAndroid Build Coastguard Worker
437*1c60b9acSAndroid Build Coastguard Worker bail:
438*1c60b9acSAndroid Build Coastguard Worker return -1;
439*1c60b9acSAndroid Build Coastguard Worker }
440*1c60b9acSAndroid Build Coastguard Worker
441*1c60b9acSAndroid Build Coastguard Worker /*
442*1c60b9acSAndroid Build Coastguard Worker * Because this is multipart mime in h2 currently, use a "rideshare" to handle
443*1c60b9acSAndroid Build Coastguard Worker * first the native metadata on this secure stream, then the "rideshare" audio
444*1c60b9acSAndroid Build Coastguard Worker * stream mentioned in the policy.
445*1c60b9acSAndroid Build Coastguard Worker *
446*1c60b9acSAndroid Build Coastguard Worker * Lws takes care of interleaving the multipart mime pieces since the policy
447*1c60b9acSAndroid Build Coastguard Worker * calls for it.
448*1c60b9acSAndroid Build Coastguard Worker */
449*1c60b9acSAndroid Build Coastguard Worker
450*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
ss_avs_metadata_tx(void * userobj,lws_ss_tx_ordinal_t ord,uint8_t * buf,size_t * len,int * flags)451*1c60b9acSAndroid Build Coastguard Worker ss_avs_metadata_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf,
452*1c60b9acSAndroid Build Coastguard Worker size_t *len, int *flags)
453*1c60b9acSAndroid Build Coastguard Worker {
454*1c60b9acSAndroid Build Coastguard Worker ss_avs_metadata_t *m = (ss_avs_metadata_t *)userobj;
455*1c60b9acSAndroid Build Coastguard Worker size_t tot;
456*1c60b9acSAndroid Build Coastguard Worker int n;
457*1c60b9acSAndroid Build Coastguard Worker
458*1c60b9acSAndroid Build Coastguard Worker // lwsl_notice("%s %d\n", __func__, (int)m->pos);
459*1c60b9acSAndroid Build Coastguard Worker
460*1c60b9acSAndroid Build Coastguard Worker if ((long)m->pos < 0) {
461*1c60b9acSAndroid Build Coastguard Worker *len = 0;
462*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: skip\n", __func__);
463*1c60b9acSAndroid Build Coastguard Worker return 1;
464*1c60b9acSAndroid Build Coastguard Worker }
465*1c60b9acSAndroid Build Coastguard Worker
466*1c60b9acSAndroid Build Coastguard Worker if (!strcmp(lws_ss_rideshare(m->ss), "avs_audio")) {
467*1c60b9acSAndroid Build Coastguard Worker
468*1c60b9acSAndroid Build Coastguard Worker /* audio rideshare part */
469*1c60b9acSAndroid Build Coastguard Worker
470*1c60b9acSAndroid Build Coastguard Worker if (!m->pos)
471*1c60b9acSAndroid Build Coastguard Worker *flags |= LWSSS_FLAG_SOM;
472*1c60b9acSAndroid Build Coastguard Worker
473*1c60b9acSAndroid Build Coastguard Worker n = spool_capture(buf, *len);
474*1c60b9acSAndroid Build Coastguard Worker if (n > 0)
475*1c60b9acSAndroid Build Coastguard Worker *len = n;
476*1c60b9acSAndroid Build Coastguard Worker else
477*1c60b9acSAndroid Build Coastguard Worker *len = 0;
478*1c60b9acSAndroid Build Coastguard Worker if (!n) {
479*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: trying to skip tx\n", __func__);
480*1c60b9acSAndroid Build Coastguard Worker return 1;
481*1c60b9acSAndroid Build Coastguard Worker }
482*1c60b9acSAndroid Build Coastguard Worker
483*1c60b9acSAndroid Build Coastguard Worker m->pos += *len;
484*1c60b9acSAndroid Build Coastguard Worker
485*1c60b9acSAndroid Build Coastguard Worker if (n < 0) {
486*1c60b9acSAndroid Build Coastguard Worker *flags |= LWSSS_FLAG_EOM;
487*1c60b9acSAndroid Build Coastguard Worker m->pos = (long)-1l; /* ban subsequent until new stream */
488*1c60b9acSAndroid Build Coastguard Worker }
489*1c60b9acSAndroid Build Coastguard Worker
490*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: tx audio %d\n", __func__, (int)*len);
491*1c60b9acSAndroid Build Coastguard Worker
492*1c60b9acSAndroid Build Coastguard Worker #if 0
493*1c60b9acSAndroid Build Coastguard Worker {
494*1c60b9acSAndroid Build Coastguard Worker int ff = open("/tmp/z1", O_RDWR | O_CREAT | O_APPEND, 0666);
495*1c60b9acSAndroid Build Coastguard Worker if (ff == -1)
496*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: errno %d\n", __func__, errno);
497*1c60b9acSAndroid Build Coastguard Worker write(ff, buf, *len);
498*1c60b9acSAndroid Build Coastguard Worker close(ff);
499*1c60b9acSAndroid Build Coastguard Worker }
500*1c60b9acSAndroid Build Coastguard Worker #endif
501*1c60b9acSAndroid Build Coastguard Worker
502*1c60b9acSAndroid Build Coastguard Worker return 0;
503*1c60b9acSAndroid Build Coastguard Worker }
504*1c60b9acSAndroid Build Coastguard Worker
505*1c60b9acSAndroid Build Coastguard Worker /* metadata part */
506*1c60b9acSAndroid Build Coastguard Worker
507*1c60b9acSAndroid Build Coastguard Worker tot = strlen(metadata);
508*1c60b9acSAndroid Build Coastguard Worker
509*1c60b9acSAndroid Build Coastguard Worker if (!m->pos)
510*1c60b9acSAndroid Build Coastguard Worker *flags |= LWSSS_FLAG_SOM;
511*1c60b9acSAndroid Build Coastguard Worker
512*1c60b9acSAndroid Build Coastguard Worker if (*len > tot - m->pos)
513*1c60b9acSAndroid Build Coastguard Worker *len = tot - m->pos;
514*1c60b9acSAndroid Build Coastguard Worker
515*1c60b9acSAndroid Build Coastguard Worker memcpy(buf, metadata + m->pos, *len);
516*1c60b9acSAndroid Build Coastguard Worker
517*1c60b9acSAndroid Build Coastguard Worker m->pos += *len;
518*1c60b9acSAndroid Build Coastguard Worker
519*1c60b9acSAndroid Build Coastguard Worker if (m->pos == tot) {
520*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("metadata done\n");
521*1c60b9acSAndroid Build Coastguard Worker *flags |= LWSSS_FLAG_EOM;
522*1c60b9acSAndroid Build Coastguard Worker m->pos = 0; /* for next time */
523*1c60b9acSAndroid Build Coastguard Worker }
524*1c60b9acSAndroid Build Coastguard Worker
525*1c60b9acSAndroid Build Coastguard Worker return 0;
526*1c60b9acSAndroid Build Coastguard Worker }
527*1c60b9acSAndroid Build Coastguard Worker
528*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
ss_avs_metadata_state(void * userobj,void * sh,lws_ss_constate_t state,lws_ss_tx_ordinal_t ack)529*1c60b9acSAndroid Build Coastguard Worker ss_avs_metadata_state(void *userobj, void *sh,
530*1c60b9acSAndroid Build Coastguard Worker lws_ss_constate_t state, lws_ss_tx_ordinal_t ack)
531*1c60b9acSAndroid Build Coastguard Worker {
532*1c60b9acSAndroid Build Coastguard Worker ss_avs_metadata_t *m = (ss_avs_metadata_t *)userobj;
533*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = (struct lws_context *)m->opaque_data;
534*1c60b9acSAndroid Build Coastguard Worker
535*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: %p: %s, ord 0x%x\n", __func__, m->ss,
536*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_name(state), (unsigned int)ack);
537*1c60b9acSAndroid Build Coastguard Worker
538*1c60b9acSAndroid Build Coastguard Worker switch (state) {
539*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_CREATING:
540*1c60b9acSAndroid Build Coastguard Worker return lws_ss_client_connect(m->ss);
541*1c60b9acSAndroid Build Coastguard Worker
542*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_CONNECTING:
543*1c60b9acSAndroid Build Coastguard Worker m->pos = 0;
544*1c60b9acSAndroid Build Coastguard Worker break;
545*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_CONNECTED:
546*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: CONNECTED\n", __func__);
547*1c60b9acSAndroid Build Coastguard Worker return lws_ss_request_tx(m->ss);
548*1c60b9acSAndroid Build Coastguard Worker
549*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_DISCONNECTED:
550*1c60b9acSAndroid Build Coastguard Worker lws_sul_cancel(&m->sul);
551*1c60b9acSAndroid Build Coastguard Worker //if (m->mh) {
552*1c60b9acSAndroid Build Coastguard Worker play_mp3(NULL, NULL, NULL);
553*1c60b9acSAndroid Build Coastguard Worker m->mh = NULL;
554*1c60b9acSAndroid Build Coastguard Worker //}
555*1c60b9acSAndroid Build Coastguard Worker /*
556*1c60b9acSAndroid Build Coastguard Worker * For this stream encapsulating an alexa exchange, dropping
557*1c60b9acSAndroid Build Coastguard Worker * is the end of its life
558*1c60b9acSAndroid Build Coastguard Worker */
559*1c60b9acSAndroid Build Coastguard Worker return 1;
560*1c60b9acSAndroid Build Coastguard Worker
561*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_DESTROYING:
562*1c60b9acSAndroid Build Coastguard Worker lws_buflist_destroy_all_segments(&m->dribble);
563*1c60b9acSAndroid Build Coastguard Worker break;
564*1c60b9acSAndroid Build Coastguard Worker default:
565*1c60b9acSAndroid Build Coastguard Worker break;
566*1c60b9acSAndroid Build Coastguard Worker }
567*1c60b9acSAndroid Build Coastguard Worker
568*1c60b9acSAndroid Build Coastguard Worker return 0;
569*1c60b9acSAndroid Build Coastguard Worker }
570*1c60b9acSAndroid Build Coastguard Worker
571*1c60b9acSAndroid Build Coastguard Worker /*
572*1c60b9acSAndroid Build Coastguard Worker * avs event
573*1c60b9acSAndroid Build Coastguard Worker */
574*1c60b9acSAndroid Build Coastguard Worker
575*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
ss_avs_event_rx(void * userobj,const uint8_t * buf,size_t len,int flags)576*1c60b9acSAndroid Build Coastguard Worker ss_avs_event_rx(void *userobj, const uint8_t *buf, size_t len, int flags)
577*1c60b9acSAndroid Build Coastguard Worker {
578*1c60b9acSAndroid Build Coastguard Worker return 0;
579*1c60b9acSAndroid Build Coastguard Worker }
580*1c60b9acSAndroid Build Coastguard Worker
581*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
ss_avs_event_tx(void * userobj,lws_ss_tx_ordinal_t ord,uint8_t * buf,size_t * len,int * flags)582*1c60b9acSAndroid Build Coastguard Worker ss_avs_event_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf,
583*1c60b9acSAndroid Build Coastguard Worker size_t *len, int *flags)
584*1c60b9acSAndroid Build Coastguard Worker {
585*1c60b9acSAndroid Build Coastguard Worker return 1; /* don't transmit anything */
586*1c60b9acSAndroid Build Coastguard Worker }
587*1c60b9acSAndroid Build Coastguard Worker
588*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
ss_avs_event_state(void * userobj,void * sh,lws_ss_constate_t state,lws_ss_tx_ordinal_t ack)589*1c60b9acSAndroid Build Coastguard Worker ss_avs_event_state(void *userobj, void *sh,
590*1c60b9acSAndroid Build Coastguard Worker lws_ss_constate_t state, lws_ss_tx_ordinal_t ack)
591*1c60b9acSAndroid Build Coastguard Worker {
592*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: %s, ord 0x%x\n", __func__, lws_ss_state_name(state),
593*1c60b9acSAndroid Build Coastguard Worker (unsigned int)ack);
594*1c60b9acSAndroid Build Coastguard Worker
595*1c60b9acSAndroid Build Coastguard Worker switch (state) {
596*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_CREATING:
597*1c60b9acSAndroid Build Coastguard Worker mpg123_init();
598*1c60b9acSAndroid Build Coastguard Worker break;
599*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_CONNECTING:
600*1c60b9acSAndroid Build Coastguard Worker break;
601*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_CONNECTED:
602*1c60b9acSAndroid Build Coastguard Worker lwsl_user("Connected to Alexa... speak \"Alexa, ...\"\n");
603*1c60b9acSAndroid Build Coastguard Worker break;
604*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_DISCONNECTED:
605*1c60b9acSAndroid Build Coastguard Worker lwsl_user("Disconnected from Alexa\n");
606*1c60b9acSAndroid Build Coastguard Worker break;
607*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_DESTROYING:
608*1c60b9acSAndroid Build Coastguard Worker mpg123_exit();
609*1c60b9acSAndroid Build Coastguard Worker break;
610*1c60b9acSAndroid Build Coastguard Worker default:
611*1c60b9acSAndroid Build Coastguard Worker break;
612*1c60b9acSAndroid Build Coastguard Worker }
613*1c60b9acSAndroid Build Coastguard Worker
614*1c60b9acSAndroid Build Coastguard Worker return 0;
615*1c60b9acSAndroid Build Coastguard Worker }
616*1c60b9acSAndroid Build Coastguard Worker
617*1c60b9acSAndroid Build Coastguard Worker int
avs_query_start(struct lws_context * context)618*1c60b9acSAndroid Build Coastguard Worker avs_query_start(struct lws_context *context)
619*1c60b9acSAndroid Build Coastguard Worker {
620*1c60b9acSAndroid Build Coastguard Worker lws_ss_info_t ssi;
621*1c60b9acSAndroid Build Coastguard Worker
622*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s:\n", __func__);
623*1c60b9acSAndroid Build Coastguard Worker
624*1c60b9acSAndroid Build Coastguard Worker memset(&ssi, 0, sizeof(ssi));
625*1c60b9acSAndroid Build Coastguard Worker ssi.handle_offset = offsetof(ss_avs_metadata_t, ss);
626*1c60b9acSAndroid Build Coastguard Worker ssi.opaque_user_data_offset = offsetof(ss_avs_metadata_t, opaque_data);
627*1c60b9acSAndroid Build Coastguard Worker ssi.rx = ss_avs_metadata_rx;
628*1c60b9acSAndroid Build Coastguard Worker ssi.tx = ss_avs_metadata_tx;
629*1c60b9acSAndroid Build Coastguard Worker ssi.state = ss_avs_metadata_state;
630*1c60b9acSAndroid Build Coastguard Worker ssi.user_alloc = sizeof(ss_avs_metadata_t);
631*1c60b9acSAndroid Build Coastguard Worker ssi.streamtype = "avs_metadata";
632*1c60b9acSAndroid Build Coastguard Worker
633*1c60b9acSAndroid Build Coastguard Worker ssi.manual_initial_tx_credit = 8192;
634*1c60b9acSAndroid Build Coastguard Worker
635*1c60b9acSAndroid Build Coastguard Worker if (lws_ss_create(context, 0, &ssi, context, &hss_avs_sync, NULL, NULL)) {
636*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: failed to create avs metadata secstream\n",
637*1c60b9acSAndroid Build Coastguard Worker __func__);
638*1c60b9acSAndroid Build Coastguard Worker
639*1c60b9acSAndroid Build Coastguard Worker return 1;
640*1c60b9acSAndroid Build Coastguard Worker }
641*1c60b9acSAndroid Build Coastguard Worker
642*1c60b9acSAndroid Build Coastguard Worker lwsl_user("%s: created query stream %p\n", __func__, hss_avs_sync);
643*1c60b9acSAndroid Build Coastguard Worker
644*1c60b9acSAndroid Build Coastguard Worker return 0;
645*1c60b9acSAndroid Build Coastguard Worker }
646*1c60b9acSAndroid Build Coastguard Worker
647*1c60b9acSAndroid Build Coastguard Worker int
avs_example_start(struct lws_context * context)648*1c60b9acSAndroid Build Coastguard Worker avs_example_start(struct lws_context *context)
649*1c60b9acSAndroid Build Coastguard Worker {
650*1c60b9acSAndroid Build Coastguard Worker lws_ss_info_t ssi;
651*1c60b9acSAndroid Build Coastguard Worker
652*1c60b9acSAndroid Build Coastguard Worker if (hss_avs_event)
653*1c60b9acSAndroid Build Coastguard Worker return 0;
654*1c60b9acSAndroid Build Coastguard Worker
655*1c60b9acSAndroid Build Coastguard Worker lwsl_info("%s: Starting AVS stream\n", __func__);
656*1c60b9acSAndroid Build Coastguard Worker
657*1c60b9acSAndroid Build Coastguard Worker /* AVS wants us to establish the long poll event stream first */
658*1c60b9acSAndroid Build Coastguard Worker
659*1c60b9acSAndroid Build Coastguard Worker memset(&ssi, 0, sizeof(ssi));
660*1c60b9acSAndroid Build Coastguard Worker ssi.handle_offset = offsetof(ss_avs_event_t, ss);
661*1c60b9acSAndroid Build Coastguard Worker ssi.opaque_user_data_offset = offsetof(ss_avs_event_t, opaque_data);
662*1c60b9acSAndroid Build Coastguard Worker ssi.rx = ss_avs_event_rx;
663*1c60b9acSAndroid Build Coastguard Worker ssi.tx = ss_avs_event_tx;
664*1c60b9acSAndroid Build Coastguard Worker ssi.state = ss_avs_event_state;
665*1c60b9acSAndroid Build Coastguard Worker ssi.user_alloc = sizeof(ss_avs_event_t);
666*1c60b9acSAndroid Build Coastguard Worker ssi.streamtype = "avs_event";
667*1c60b9acSAndroid Build Coastguard Worker
668*1c60b9acSAndroid Build Coastguard Worker if (lws_ss_create(context, 0, &ssi, context, &hss_avs_event, NULL, NULL)) {
669*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s: failed to create avs event secure stream\n",
670*1c60b9acSAndroid Build Coastguard Worker __func__);
671*1c60b9acSAndroid Build Coastguard Worker return 1;
672*1c60b9acSAndroid Build Coastguard Worker }
673*1c60b9acSAndroid Build Coastguard Worker
674*1c60b9acSAndroid Build Coastguard Worker return 0;
675*1c60b9acSAndroid Build Coastguard Worker }
676