1 /*
2  * Copyright (C) 2015-2019 Alibaba Group Holding Limited
3  */
4 
5 #include <string.h>
6 #include <stdarg.h>
7 
8 #include "amp_config.h"
9 #include "aos_system.h"
10 #include "amp_defines.h"
11 #include "amp_task.h"
12 #include "aos_fs.h"
13 #include "board_mgr.h"
14 #include "aos/vfs.h"
15 
16 #include "uvoice_types.h"
17 #include "uvoice_event.h"
18 #include "uvoice_player.h"
19 #include "uvoice_comb.h"
20 #include "aos_pcm.h"
21 #include "aos_tts.h"
22 
23 #include "quickjs.h"
24 #include "quickjs_addon_common.h"
25 
26 
27 #define MOD_STR        "audioplayer"
28 
29 
30 typedef struct {
31     uvoice_player_t *player;
32     JSValue js_cb_ref;
33     int list_playing;
34     int state;
35 } audio_player_t;
36 
37 typedef struct {
38     void *userdata;
39     JSValue js_cb_ref;
40     int event;
41     unsigned long timestamp;
42 } audio_player_param_t;
43 
44 enum {
45     AUDIOPLAYER_STAT_STOP = 0,
46     AUDIOPLAYER_STAT_PAUSED = 1,
47     AUDIOPLAYER_STAT_PLAYING = 2,
48     AUDIOPLAYER_STAT_LIST_PLAY_BEGIN = 3,
49     AUDIOPLAYER_STAT_LIST_PLAY_END = 4,
50     AUDIOPLAYER_STAT_ERROR = 5,
51 };
52 
53 enum {
54     JS_ATOM_NULL,
55 #define DEF(name, str) JS_ATOM_##name,
56 #include "quickjs-atom.h"
57 #undef DEF
58     JS_ATOM_END,
59 };
60 
61 static audio_player_t *g_audioplayer;
62 static JSClassID js_audio_class_id;
63 
js_get_length32(JSContext * ctx,uint32_t * pres,JSValueConst obj)64 static int js_get_length32(JSContext* ctx, uint32_t* pres,
65                                        JSValueConst obj)
66 {
67     JSValue len_val;
68     len_val = JS_GetProperty(ctx, obj, JS_ATOM_length);
69     if (JS_IsException(len_val)) {
70         *pres = 0;
71         return -1;
72     }
73     return JS_ToInt32(ctx, pres, len_val);
74 }
75 
audioplayer_state_notify(void * arg)76 static void audioplayer_state_notify(void *arg)
77 {
78     audio_player_t *audioplayer = (audio_player_t *)arg;
79     JSValue state;
80 
81     JSContext *ctx = js_get_context();
82     state = JS_NewInt32(ctx, audioplayer->state);
83 
84     JSValue val = JS_Call(ctx, audioplayer->js_cb_ref, JS_UNDEFINED, 1, &state);
85     JS_FreeValue(ctx, val);
86     JS_FreeValue(ctx, state);
87 }
88 
audioplayer_state_cb(uvoice_event_t * event,void * data)89 static void audioplayer_state_cb(uvoice_event_t *event, void *data)
90 {
91     audio_player_t *audioplayer = (audio_player_t *)data;
92     player_state_t state;
93     int audioplayer_state = PLAYER_STAT_IDLE;
94     int ret;
95 
96     if (!audioplayer)
97         return;
98 
99     if (event->type != UVOICE_EV_PLAYER)
100         return;
101 
102     if (event->code == UVOICE_CODE_PLAYER_STATE) {
103         state = event->value;
104         switch (state) {
105         case PLAYER_STAT_RUNNING:
106         case PLAYER_STAT_COMPLETE:
107         case PLAYER_STAT_RESUME:
108             audioplayer_state = AUDIOPLAYER_STAT_PLAYING;
109             break;
110         case PLAYER_STAT_PAUSED:
111             audioplayer_state = AUDIOPLAYER_STAT_PAUSED;
112             break;
113         case PLAYER_STAT_STOP:
114         case PLAYER_STAT_IDLE:
115         case PLAYER_STAT_READY:
116             audioplayer_state = AUDIOPLAYER_STAT_STOP;
117             break;
118         case PLAYER_STAT_ERROR:
119             audioplayer_state = AUDIOPLAYER_STAT_ERROR;
120             break;
121         case PLAYER_STAT_LIST_PLAY_START:
122             audioplayer_state = AUDIOPLAYER_STAT_LIST_PLAY_BEGIN;
123             audioplayer->list_playing = 1;
124             break;
125         case PLAYER_STAT_LIST_PLAY_STOP:
126             audioplayer_state = AUDIOPLAYER_STAT_LIST_PLAY_END;
127             audioplayer->list_playing = 0;
128             break;
129         default:
130             return;
131         }
132     }
133 
134     if (audioplayer->state == audioplayer_state) {
135         return;
136     }
137     audioplayer->state = audioplayer_state;
138 
139     amp_task_schedule_call(audioplayer_state_notify, audioplayer);
140 }
141 
audioplayer_play_cplt_notify(void * arg)142 static void audioplayer_play_cplt_notify(void *arg)
143 {
144     audio_player_param_t *param = (audio_player_param_t *)arg;
145     JSContext *ctx = js_get_context();
146 
147     if (param == NULL) {
148         return;
149     }
150     JSValue val = JS_Call(ctx, param->js_cb_ref, JS_UNDEFINED, 0, NULL);
151     JS_FreeValue(ctx, val);
152     JS_FreeValue(ctx, param->js_cb_ref);
153 
154     aos_free(param);
155 }
156 
audioplayer_play_cplt_cb(uvoice_event_t * event,void * data)157 static void audioplayer_play_cplt_cb(uvoice_event_t *event, void *data)
158 {
159     audio_player_param_t *param = (audio_player_param_t *)data;
160 
161     if (!param)
162         return;
163 
164     if (event->type != UVOICE_EV_PLAYER)
165         return;
166 
167     if (event->code == UVOICE_CODE_PLAYER_STATE &&
168         (event->value == PLAYER_STAT_COMPLETE ||
169         event->value == PLAYER_STAT_STOP) &&
170         (unsigned long)aos_now_ms() >= param->timestamp) {
171 
172         uvoice_event_unregister(UVOICE_EV_PLAYER, audioplayer_play_cplt_cb, param);
173         amp_task_schedule_call(audioplayer_play_cplt_notify, param);
174     }
175 }
176 
audioplayer_listplay_cplt_cb(void * data,int event)177 static void audioplayer_listplay_cplt_cb(void *data, int event)
178 {
179     audio_player_param_t *param = (audio_player_param_t *)data;
180     param->event = event;
181     amp_task_schedule_call(audioplayer_play_cplt_notify, param);
182 }
183 
native_audioplayer_play(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)184 static JSValue native_audioplayer_play(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
185 {
186     audio_player_t *audioplayer = g_audioplayer;
187     audio_player_param_t *param = NULL;
188     uvoice_player_t *player;
189     char *audiosource = NULL;
190     char *source = NULL;
191     int len;
192     int is_http = 0;
193     int ret = -1;
194 
195     if (!audioplayer)
196         goto out;
197 
198     player = audioplayer->player;
199 
200     if (!JS_IsString(argv[0]) || !JS_IsFunction(ctx, argv[1])) {
201         amp_error(MOD_STR, "parameter must be (string, function)");
202         goto out;
203     }
204 
205     param = aos_malloc(sizeof(audio_player_param_t));
206     if (!param) {
207         amp_error(MOD_STR, "alloc param fail");
208         goto out;
209     }
210 
211     audiosource = (char *)JS_ToCString(ctx, argv[0]);
212     if (!audiosource) {
213         amp_error(MOD_STR, "audio source null");
214         goto out;
215     }
216 
217     if (!strncmp(audiosource, "http", strlen("http"))) {
218         is_http = 1;
219         source = audiosource;
220     } else {
221         source = aos_malloc(strlen(audiosource) + 4);
222         if (!source) {
223             amp_error(MOD_STR, "alloc source fail");
224             goto out;
225         }
226         snprintf(source, strlen(audiosource) + 4, "fs:%s", audiosource);
227     }
228 
229     if (!JS_IsFunction(ctx, argv[1])) {
230         JS_ThrowTypeError(ctx, "not a function");
231         goto out;
232     }
233 
234     param->js_cb_ref = JS_DupValue(ctx, argv[1]);
235     param->timestamp = (unsigned long)aos_now_ms();
236 
237     if (comb_add_http_source(source, 0)) {
238         amp_error(MOD_STR, "add source fail");
239         JS_FreeValue(ctx, param->js_cb_ref);
240         goto out;
241     }
242 
243     if (uvoice_event_register(UVOICE_EV_PLAYER,
244         audioplayer_play_cplt_cb, param)) {
245         amp_error(MOD_STR, "register event fail");
246         JS_FreeValue(ctx, param->js_cb_ref);
247         aos_free(param);
248         goto out;
249     }
250 
251     ret = 0;
252 
253 out:
254     if (!is_http && source) {
255         aos_free(source);
256     }
257 
258     if(audiosource != NULL) {
259         JS_FreeCString(ctx, audiosource);
260     }
261 
262     return JS_NewInt32(ctx, ret);
263 }
264 
native_audioplayer_stop(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)265 static JSValue native_audioplayer_stop(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
266 {
267     audio_player_t *audioplayer = g_audioplayer;
268     uvoice_player_t *player;
269     int ret = -1;
270 
271     if (!audioplayer)
272         goto out;
273     player = audioplayer->player;
274 
275     if (player->stop()) {
276         comb_clr_http_source();
277         goto out;
278     }
279 
280     player->clr_source();
281     comb_clr_http_source();
282     ret = 0;
283 out:
284     return JS_NewInt32(ctx, ret);
285 }
286 
native_audioplayer_pause(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)287 static JSValue native_audioplayer_pause(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
288 {
289     audio_player_t *audioplayer = g_audioplayer;
290     uvoice_player_t *player;
291     int ret = -1;
292 
293     if (!audioplayer)
294         goto out;
295     player = audioplayer->player;
296 
297     if (player->pause()) {
298         amp_error(MOD_STR, "play pause fail");
299         goto out;
300     }
301 
302     ret = 0;
303 out:
304     return JS_NewInt32(ctx, ret);
305 }
306 
native_audioplayer_resume(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)307 static JSValue native_audioplayer_resume(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
308 {
309     audio_player_t *audioplayer = g_audioplayer;
310     uvoice_player_t *player;
311     int ret = -1;
312 
313     if (!audioplayer)
314         goto out;
315     player = audioplayer->player;
316 
317     if (player->resume()) {
318         amp_error(MOD_STR, "play resume fail");
319         goto out;
320     }
321     ret = 0;
322 out:
323     return JS_NewInt32(ctx, ret);
324 }
325 
native_audioplayer_seekto(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)326 static JSValue native_audioplayer_seekto(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
327 {
328     audio_player_t *audioplayer = g_audioplayer;
329     uvoice_player_t *player;
330     int ret = -1;
331     int seconds;
332 
333     if (!audioplayer)
334         goto out;
335     player = audioplayer->player;
336 
337     if (!JS_IsNumber(argv[0])) {
338         amp_error(MOD_STR, "parameter must be (number)");
339         goto out;
340     }
341 
342     JS_ToInt32(ctx, &seconds, argv[0]);
343     if (seconds < 0) {
344         amp_error(MOD_STR, "seconds %d invalid", seconds);
345         goto out;
346     }
347 
348     if (player->seek(seconds)) {
349         amp_error(MOD_STR, "seek to %d fail", seconds);
350         goto out;
351     }
352     ret = 0;
353 
354 out:
355     return JS_NewInt32(ctx, ret);
356 }
357 
native_audioplayer_position_get(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)358 static JSValue native_audioplayer_position_get(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
359 {
360     audio_player_t *audioplayer = g_audioplayer;
361     uvoice_player_t *player;
362     int position = 0;
363     int ret = -1;
364 
365     if (!audioplayer)
366         goto out;
367     player = audioplayer->player;
368 
369     if (player->get_position(&position)) {
370         amp_error(MOD_STR, "get position fail");
371         goto out;
372     }
373 
374     ret = position;
375 
376 out:
377     return JS_NewInt32(ctx, ret);
378 }
379 
native_audioplayer_duration_get(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)380 static JSValue native_audioplayer_duration_get(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
381 {
382     audio_player_t *audioplayer = g_audioplayer;
383     uvoice_player_t *player;
384     int duration = 0;
385     int ret = -1;
386 
387     if (!audioplayer)
388         goto out;
389     player = audioplayer->player;
390 
391     if (player->get_duration(&duration)) {
392         amp_error(MOD_STR, "get duration fail");
393         goto out;
394     }
395 
396     ret = duration;
397 
398 out:
399     return JS_NewInt32(ctx, ret);
400 }
401 
native_audioplayer_state_get(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)402 static JSValue native_audioplayer_state_get(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
403 {
404     audio_player_t *audioplayer = g_audioplayer;
405     uvoice_player_t *player;
406     player_state_t state = PLAYER_STAT_IDLE;
407     int audioplayer_state;
408     int ret = -1;
409 
410     if (!audioplayer)
411         goto out;
412     player = audioplayer->player;
413 
414     if (player->get_state(&state)) {
415         amp_error(MOD_STR, "get player state fail");
416         goto out;
417     }
418 
419     switch (state) {
420     case PLAYER_STAT_RUNNING:
421     case PLAYER_STAT_COMPLETE:
422     case PLAYER_STAT_RESUME:
423         audioplayer_state = AUDIOPLAYER_STAT_PLAYING;
424         break;
425     case PLAYER_STAT_PAUSED:
426         audioplayer_state = AUDIOPLAYER_STAT_PAUSED;
427         break;
428     case PLAYER_STAT_STOP:
429     case PLAYER_STAT_IDLE:
430     case PLAYER_STAT_READY:
431         audioplayer_state = AUDIOPLAYER_STAT_STOP;
432         break;
433     case PLAYER_STAT_ERROR:
434         audioplayer_state = AUDIOPLAYER_STAT_ERROR;
435         break;
436     case PLAYER_STAT_LIST_PLAY_START:
437         audioplayer_state = AUDIOPLAYER_STAT_LIST_PLAY_BEGIN;
438         break;
439     case PLAYER_STAT_LIST_PLAY_STOP:
440         audioplayer_state = AUDIOPLAYER_STAT_LIST_PLAY_END;
441         break;
442     default:
443         audioplayer_state = AUDIOPLAYER_STAT_STOP;
444         break;
445     }
446     ret = audioplayer_state;
447 
448 out:
449     return JS_NewInt32(ctx, ret);
450 }
451 
native_audioplayer_state_on(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)452 static JSValue native_audioplayer_state_on(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
453 {
454     audio_player_t *audioplayer = g_audioplayer;
455     int ret = -1;
456 
457     if (!JS_IsFunction(ctx, argv[0])) {
458         amp_warn(MOD_STR, "parameter must be (function)");
459         goto out;
460     }
461 
462     JSValue state_cb = argv[0];
463     if (!JS_IsFunction(ctx, state_cb)) {
464         return JS_ThrowTypeError(ctx, "not a function");
465     }
466 
467     audioplayer->js_cb_ref = JS_DupValue(ctx, state_cb);
468 
469     if (uvoice_event_register(UVOICE_EV_PLAYER,
470         audioplayer_state_cb, audioplayer)) {
471         amp_error(MOD_STR, "register event fail");
472         goto out;
473     }
474 
475     ret = 0;
476 out:
477     return JS_NewInt32(ctx, ret);
478 }
479 
native_audioplayer_volume_set(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)480 static JSValue native_audioplayer_volume_set(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
481 {
482     audio_player_t *audioplayer = g_audioplayer;
483     uvoice_player_t *player;
484     int ret = -1;
485     int volume;
486 
487     if (!audioplayer)
488         goto out;
489     player = audioplayer->player;
490 
491     if (!JS_IsNumber(argv[0])) {
492         amp_error(MOD_STR, "parameter must be (number)");
493         goto out;
494     }
495 
496     JS_ToInt32(ctx, &volume, argv[0]);
497     if (volume < 0) {
498         amp_error(MOD_STR, "volume %d invalid", volume);
499         goto out;
500     }
501 
502     if (player->set_volume(volume)) {
503         amp_error(MOD_STR, "set volume fail");
504         goto out;
505     }
506     ret = 0;
507 
508 out:
509     return JS_NewInt32(ctx, ret);
510 }
511 
native_audioplayer_volume_get(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)512 static JSValue native_audioplayer_volume_get(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
513 {
514     audio_player_t *audioplayer = g_audioplayer;
515     uvoice_player_t *player;
516     int ret = -1;
517     int volume = -1;
518 
519     if (!audioplayer)
520         goto out;
521     player = audioplayer->player;
522 
523     if (player->get_volume(&volume)) {
524         amp_error(MOD_STR, "get volume fail");
525         goto out;
526     }
527 
528     ret = volume;
529 out:
530     return JS_NewInt32(ctx, ret);
531 }
532 
native_audioplayer_play_list(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)533 static JSValue native_audioplayer_play_list(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
534 {
535     audio_player_param_t *param;
536     char *source;
537     int arr_idx;
538     int arr_cnt;
539     int i, ret = -1;
540     int error = 0;
541     struct aos_stat stat;
542     comb_source_info_t *info;
543 
544     if (!JS_IsArray(ctx, argv[0]) || !JS_IsFunction(ctx, argv[1])) {
545         amp_error(MOD_STR, "parameter must be (array, function)");
546         goto out;
547     }
548 
549     param = aos_malloc(sizeof(audio_player_param_t));
550     if (!param) {
551         amp_error(MOD_STR, "alloc param fail");
552         goto out;
553     }
554 
555     info = aos_malloc(sizeof(comb_source_info_t));
556     if (!info) {
557         amp_error(MOD_STR, "alloc info fail");
558         aos_free(param);
559         goto out;
560     }
561     memset(info, 0, sizeof(comb_source_info_t));
562 
563     js_get_length32(ctx, &arr_cnt, argv[0]);
564 
565     if (arr_cnt > COMB_SOURCE_LIST_MAX) {
566         amp_error(MOD_STR, "list count out of limit");
567         aos_free(param);
568         aos_free(info);
569         goto out;
570     }
571 
572     JSValue play_cb = argv[1];
573     if (!JS_IsFunction(ctx, play_cb)) {
574         return JS_ThrowTypeError(ctx, "not a function");
575     }
576     param->js_cb_ref = JS_DupValue(ctx, play_cb);
577 
578     for (i = 0; i < arr_cnt; i++) {
579         JSValue str_val = JS_GetPropertyUint32(ctx, argv[0], i);
580         if (!JS_IsString(str_val)) {
581             amp_error(MOD_STR, "array element %d is not string", i);
582             JS_FreeValue(ctx, param->js_cb_ref);
583             aos_free(param);
584             aos_free(info);
585             goto out;
586         }
587         source = JS_ToCString(ctx, str_val);
588 
589         if (strlen(source) >= COMB_SOURCE_PATH_LEN) {
590             amp_error(MOD_STR, "source %s path too long", source);
591             JS_FreeValue(ctx, param->js_cb_ref);
592             aos_free(param);
593             aos_free(info);
594             JS_FreeCString(ctx, source);
595             goto out;
596         }
597 
598         memset(&stat, 0, sizeof(aos_stat));
599         ret = aos_stat(source, &stat);
600         if (ret < 0 || !S_ISREG(stat.st_mode)) {
601             amp_error(MOD_STR, "source %s not exist", source);
602             JS_FreeValue(ctx, param->js_cb_ref);
603             aos_free(param);
604             aos_free(info);
605             ret = -1;
606             JS_FreeCString(ctx, source);
607             goto out;
608         }
609 
610         info->count++;
611         snprintf(info->sources[i], COMB_SOURCE_PATH_LEN, "%s", source);
612         JS_FreeCString(ctx, source);
613     }
614 
615     info->callback = audioplayer_listplay_cplt_cb;
616     info->userdata = param;
617     if (comb_add_file_source_list(info)) {
618         error = -1;
619     }
620     aos_free(info);
621     ret = error;
622 out:
623 
624     return JS_NewInt32(ctx, ret);
625 }
626 
native_audioplayer_play_list_stop(JSContext * ctx,JSValueConst this_val,int argc,JSValueConst * argv)627 static JSValue native_audioplayer_play_list_stop(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
628 {
629     comb_play_stop();
630     comb_clr_http_source();
631 
632     return JS_NewInt32(ctx, 0);
633 }
634 
native_audioplayer_config_parse(uvoice_player_t * player)635 static int native_audioplayer_config_parse(uvoice_player_t *player)
636 {
637     item_handle_t item_handle;
638     item_handle.handle = NULL;
639     aos_audio_dev_t *audio_dev;
640     audio_extpa_info_t pa_info;
641 
642     if (board_attach_item(MODULE_AUDIO, "audio", &item_handle)) {
643         player->set_out_device(AOS_SND_DEVICE_OUT_HEADPHONE);
644 #ifdef JSE_ADVANCED_ADDON_TTS
645         aos_tts_set_out_device(AOS_SND_DEVICE_OUT_HEADPHONE);
646 #endif
647     } else {
648         audio_dev = board_get_node_by_handle(MODULE_AUDIO, &item_handle);
649         if (!audio_dev) {
650             amp_warn(MOD_STR, "get audio module fail");
651             return -1;
652         } else {
653             amp_info(MOD_STR, "out device %d, ext pa %s, pin %d, delay %d, active %d",
654                 audio_dev->out_device, audio_dev->external_pa ? "enable" : "disable",
655                 audio_dev->external_pa_pin, audio_dev->external_pa_delay_ms,
656                 audio_dev->external_pa_active_high);
657         }
658 
659         if (audio_dev->out_device >= AOS_SND_DEVICE_OUT_SPEAKER &&
660             audio_dev->out_device < AOS_SND_DEVICE_MAX) {
661             player->set_out_device(audio_dev->out_device);
662 #ifdef JSE_ADVANCED_ADDON_TTS
663             aos_tts_set_out_device(audio_dev->out_device);
664 #endif
665         } else {
666             player->set_out_device(AOS_SND_DEVICE_OUT_HEADPHONE);
667 #ifdef JSE_ADVANCED_ADDON_TTS
668             aos_tts_set_out_device(AOS_SND_DEVICE_OUT_HEADPHONE);
669 #endif
670         }
671 
672         if (audio_dev->external_pa) {
673             pa_info.used = audio_dev->external_pa;
674             pa_info.active_high = audio_dev->external_pa_active_high;
675             pa_info.pin = audio_dev->external_pa_pin;
676             pa_info.delay_ms = audio_dev->external_pa_delay_ms;
677             player->set_external_pa(&pa_info);
678         }
679     }
680 
681     return 0;
682 }
683 
module_audioplayer_source_clean(void)684 static void module_audioplayer_source_clean(void)
685 {
686     audio_player_t *audioplayer = g_audioplayer;
687     uvoice_player_t *player;
688 
689     if (!audioplayer)
690         return;
691 
692     player = audioplayer->player;
693     if (!player) {
694         return;
695     }
696 
697     comb_play_stop();
698     comb_clr_http_source();
699     player->stop();
700     player->clr_source();
701 
702     uvoice_player_release(player);
703     aos_free(audioplayer);
704     g_audioplayer = NULL;
705     comb_deinit();
706     uvoice_free();
707 }
708 
709 static JSClassDef js_audio_class = {
710     "audio",
711 };
712 
713 static const JSCFunctionListEntry js_audio_funcs[] = {
714     JS_CFUNC_DEF("listPlay",    2, native_audioplayer_play_list),
715     JS_CFUNC_DEF("listPlayStop",0, native_audioplayer_play_list_stop),
716     JS_CFUNC_DEF("play",        2, native_audioplayer_play),
717     JS_CFUNC_DEF("stop",        0, native_audioplayer_stop),
718     JS_CFUNC_DEF("pause",       0, native_audioplayer_pause),
719     JS_CFUNC_DEF("resume",      0, native_audioplayer_resume),
720     JS_CFUNC_DEF("seekto",      1, native_audioplayer_seekto),
721     JS_CFUNC_DEF("getPosition", 0, native_audioplayer_position_get),
722     JS_CFUNC_DEF("getDuration", 0, native_audioplayer_duration_get),
723     JS_CFUNC_DEF("getState",    0, native_audioplayer_state_get),
724     JS_CFUNC_DEF("onState",     1, native_audioplayer_state_on),
725     JS_CFUNC_DEF("setVolume",   1, native_audioplayer_volume_set),
726     JS_CFUNC_DEF("getVolume",   0, native_audioplayer_volume_get)
727 };
728 
js_audio_init(JSContext * ctx,JSModuleDef * m)729 static int js_audio_init(JSContext *ctx, JSModuleDef *m)
730 {
731     JSValue proto;
732 
733     JS_NewClassID(&js_audio_class_id);
734 
735     JS_NewClass(JS_GetRuntime(ctx), js_audio_class_id, &js_audio_class);
736     proto = JS_NewObject(ctx);
737     JS_SetPropertyFunctionList(ctx, proto, js_audio_funcs, countof(js_audio_funcs));
738     JS_SetClassProto(ctx, js_audio_class_id, proto);
739     return JS_SetModuleExportList(ctx, m, js_audio_funcs, countof(js_audio_funcs));
740 }
741 
js_init_module_audio(JSContext * ctx,const char * module_name)742 JSModuleDef *js_init_module_audio(JSContext *ctx, const char *module_name)
743 {
744     JSModuleDef *m;
745     m = JS_NewCModule(ctx, module_name, js_audio_init);
746     if (!m)
747         return NULL;
748     JS_AddModuleExportList(ctx, m, js_audio_funcs, countof(js_audio_funcs));
749     return m;
750 }
751 
752 
module_audio_register(void)753 void module_audio_register(void)
754 {
755     audio_player_t *audioplayer;
756 
757     uvoice_init();
758     // init audio codec
759     extern int audio_install_codec_driver();
760     audio_install_codec_driver();
761 
762     comb_init();
763 
764     audioplayer = aos_malloc(sizeof(audio_player_t));
765     if (!audioplayer) {
766         amp_error(MOD_STR, "alloc audio player fail");
767         return;
768     }
769     audioplayer->player = uvoice_player_create();
770     if (!audioplayer->player) {
771         amp_error(MOD_STR, "create uvoice player fail");
772         aos_free(audioplayer);
773         return;
774     }
775     native_audioplayer_config_parse(audioplayer->player);
776     audioplayer->state = -1;
777     g_audioplayer = audioplayer;
778 
779     amp_module_free_register(module_audioplayer_source_clean);
780 
781     amp_debug(MOD_STR, "module_audio_register");
782     JSContext *ctx = js_get_context();
783     js_init_module_audio(ctx, "AUDIOPLAYER");
784 }
785 
786