1 /*  RetroArch - A frontend for libretro.
2  *  Copyright (C) 2011-2017 - Daniel De Matteis
3  *
4  *  RetroArch is free software: you can redistribute it and/or modify it under the terms
5  *  of the GNU General Public License as published by the Free Software Found-
6  *  ation, either version 3 of the License, or (at your option) any later version.
7  *
8  *  RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9  *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10  *  PURPOSE.  See the GNU General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License along with RetroArch.
13  *  If not, see <http://www.gnu.org/licenses/>.
14  */
15 
16 #include "tasks_internal.h"
17 
18 #include <stdint.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <errno.h>
22 
23 #include <file/nbio.h>
24 #include <file/file_path.h>
25 #include <audio/audio_mixer.h>
26 #include <compat/strl.h>
27 #include <string/stdstring.h>
28 #include <retro_miscellaneous.h>
29 #include <queues/task_queue.h>
30 
31 #include "../file_path_special.h"
32 #include "../retroarch.h"
33 #include "../verbosity.h"
34 
35 #include "task_file_transfer.h"
36 #include "tasks_internal.h"
37 
38 struct audio_mixer_userdata
39 {
40    unsigned slot_selection_idx;
41    enum audio_mixer_stream_type stream_type;
42    enum audio_mixer_slot_selection_type slot_selection_type;
43 };
44 
45 struct audio_mixer_handle
46 {
47    nbio_buf_t *buffer;
48    retro_task_callback_t cb;
49    enum audio_mixer_type type;
50    char path[4095];
51    bool copy_data_over;
52    bool is_finished;
53 };
54 
task_audio_mixer_load_free(retro_task_t * task)55 static void task_audio_mixer_load_free(retro_task_t *task)
56 {
57    nbio_handle_t       *nbio        = (nbio_handle_t*)task->state;
58    struct audio_mixer_handle *mixer = (struct audio_mixer_handle*)nbio->data;
59 
60    if (mixer)
61    {
62       if (mixer->buffer)
63       {
64          if (mixer->buffer->path)
65             free(mixer->buffer->path);
66          free(mixer->buffer);
67       }
68 
69       if (mixer->cb)
70          mixer->cb(task, NULL, NULL, NULL);
71    }
72 
73    if (!string_is_empty(nbio->path))
74       free(nbio->path);
75    if (nbio->data)
76       free(nbio->data);
77    nbio_free(nbio->handle);
78    free(nbio);
79 }
80 
cb_nbio_audio_mixer_load(void * data,size_t len)81 static int cb_nbio_audio_mixer_load(void *data, size_t len)
82 {
83    nbio_handle_t *nbio             = (nbio_handle_t*)data;
84    struct audio_mixer_handle *mixer= (struct audio_mixer_handle*)nbio->data;
85    void *ptr                       = nbio_get_ptr(nbio->handle, &len);
86    nbio_buf_t *buffer              = (nbio_buf_t*)calloc(1, sizeof(*mixer->buffer));
87 
88    if (!buffer)
89       return -1;
90 
91    mixer->buffer                   = buffer;
92    mixer->buffer->buf              = ptr;
93    mixer->buffer->bufsize          = (unsigned)len;
94    mixer->copy_data_over           = true;
95    nbio->is_finished               = true;
96 
97    return 0;
98 }
99 
task_audio_mixer_handle_upload_ogg(retro_task_t * task,void * task_data,void * user_data,const char * err)100 static void task_audio_mixer_handle_upload_ogg(retro_task_t *task,
101       void *task_data,
102       void *user_data, const char *err)
103 {
104    audio_mixer_stream_params_t params;
105    nbio_buf_t             *img = (nbio_buf_t*)task_data;
106    struct audio_mixer_userdata *user = (struct audio_mixer_userdata*)user_data;
107    if (!img || !user)
108       return;
109 
110    params.volume               = 1.0f;
111    params.slot_selection_type  = user->slot_selection_type;
112    params.slot_selection_idx   = user->slot_selection_idx;
113    params.stream_type          = user->stream_type;
114    params.type                 = AUDIO_MIXER_TYPE_OGG;
115    params.state                = AUDIO_STREAM_STATE_STOPPED;
116    params.buf                  = img->buf;
117    params.bufsize              = img->bufsize;
118    params.cb                   = NULL;
119    params.basename             = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL;
120 
121    audio_driver_mixer_add_stream(&params);
122 
123    if (img->path)
124       free(img->path);
125    if (params.basename != NULL)
126       free(params.basename);
127    free(img);
128    free(user_data);
129 }
130 
task_audio_mixer_handle_upload_ogg_and_play(retro_task_t * task,void * task_data,void * user_data,const char * err)131 static void task_audio_mixer_handle_upload_ogg_and_play(retro_task_t *task,
132       void *task_data,
133       void *user_data, const char *err)
134 {
135    audio_mixer_stream_params_t params;
136    nbio_buf_t             *img = (nbio_buf_t*)task_data;
137    struct audio_mixer_userdata *user = (struct audio_mixer_userdata*)user_data;
138 
139    if (!img || !user)
140       return;
141 
142    params.volume               = 1.0f;
143    params.slot_selection_type  = user->slot_selection_type;
144    params.slot_selection_idx   = user->slot_selection_idx;
145    params.stream_type          = user->stream_type;
146    params.type                 = AUDIO_MIXER_TYPE_OGG;
147    params.state                = AUDIO_STREAM_STATE_PLAYING;
148    params.buf                  = img->buf;
149    params.bufsize              = img->bufsize;
150    params.cb                   = NULL;
151    params.basename             = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL;
152 
153    audio_driver_mixer_add_stream(&params);
154 
155    if (img->path)
156       free(img->path);
157    if (params.basename != NULL)
158       free(params.basename);
159    free(img);
160    free(user_data);
161 }
162 
task_audio_mixer_handle_upload_flac(retro_task_t * task,void * task_data,void * user_data,const char * err)163 static void task_audio_mixer_handle_upload_flac(retro_task_t *task,
164       void *task_data,
165       void *user_data, const char *err)
166 {
167    audio_mixer_stream_params_t params;
168    nbio_buf_t             *img = (nbio_buf_t*)task_data;
169    struct audio_mixer_userdata *user = (struct audio_mixer_userdata*)user_data;
170 
171    if (!img || !user)
172       return;
173 
174    params.volume               = 1.0f;
175    params.slot_selection_type  = user->slot_selection_type;
176    params.slot_selection_idx   = user->slot_selection_idx;
177    params.stream_type          = user->stream_type;
178    params.type                 = AUDIO_MIXER_TYPE_FLAC;
179    params.state                = AUDIO_STREAM_STATE_STOPPED;
180    params.buf                  = img->buf;
181    params.bufsize              = img->bufsize;
182    params.cb                   = NULL;
183    params.basename             = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL;
184 
185    audio_driver_mixer_add_stream(&params);
186 
187    if (img->path)
188       free(img->path);
189    if (params.basename != NULL)
190       free(params.basename);
191    free(img);
192    free(user_data);
193 }
194 
task_audio_mixer_handle_upload_flac_and_play(retro_task_t * task,void * task_data,void * user_data,const char * err)195 static void task_audio_mixer_handle_upload_flac_and_play(retro_task_t *task,
196       void *task_data,
197       void *user_data, const char *err)
198 {
199    audio_mixer_stream_params_t params;
200    nbio_buf_t             *img = (nbio_buf_t*)task_data;
201    struct audio_mixer_userdata *user = (struct audio_mixer_userdata*)user_data;
202 
203    if (!img || !user)
204       return;
205 
206    params.volume               = 1.0f;
207    params.slot_selection_type  = user->slot_selection_type;
208    params.slot_selection_idx   = user->slot_selection_idx;
209    params.stream_type          = user->stream_type;
210    params.type                 = AUDIO_MIXER_TYPE_FLAC;
211    params.state                = AUDIO_STREAM_STATE_PLAYING;
212    params.buf                  = img->buf;
213    params.bufsize              = img->bufsize;
214    params.cb                   = NULL;
215    params.basename             = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL;
216 
217    audio_driver_mixer_add_stream(&params);
218 
219    if (img->path)
220       free(img->path);
221    if (params.basename != NULL)
222       free(params.basename);
223    free(img);
224    free(user_data);
225 }
226 
task_audio_mixer_handle_upload_mp3(retro_task_t * task,void * task_data,void * user_data,const char * err)227 static void task_audio_mixer_handle_upload_mp3(retro_task_t *task,
228       void *task_data,
229       void *user_data, const char *err)
230 {
231    audio_mixer_stream_params_t params;
232    nbio_buf_t             *img = (nbio_buf_t*)task_data;
233    struct audio_mixer_userdata *user = (struct audio_mixer_userdata*)user_data;
234 
235    if (!img || !user)
236       return;
237 
238    params.volume               = 1.0f;
239    params.slot_selection_type  = user->slot_selection_type;
240    params.slot_selection_idx   = user->slot_selection_idx;
241    params.stream_type          = user->stream_type;
242    params.type                 = AUDIO_MIXER_TYPE_MP3;
243    params.state                = AUDIO_STREAM_STATE_STOPPED;
244    params.buf                  = img->buf;
245    params.bufsize              = img->bufsize;
246    params.cb                   = NULL;
247    params.basename             = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL;
248 
249    audio_driver_mixer_add_stream(&params);
250 
251    if (img->path)
252       free(img->path);
253    if (params.basename != NULL)
254       free(params.basename);
255    free(img);
256    free(user_data);
257 }
258 
task_audio_mixer_handle_upload_mp3_and_play(retro_task_t * task,void * task_data,void * user_data,const char * err)259 static void task_audio_mixer_handle_upload_mp3_and_play(retro_task_t *task,
260       void *task_data,
261       void *user_data, const char *err)
262 {
263    audio_mixer_stream_params_t params;
264    nbio_buf_t             *img = (nbio_buf_t*)task_data;
265    struct audio_mixer_userdata *user = (struct audio_mixer_userdata*)user_data;
266 
267    if (!img || !user)
268       return;
269 
270    params.volume               = 1.0f;
271    params.slot_selection_type  = user->slot_selection_type;
272    params.slot_selection_idx   = user->slot_selection_idx;
273    params.stream_type          = user->stream_type;
274    params.type                 = AUDIO_MIXER_TYPE_MP3;
275    params.state                = AUDIO_STREAM_STATE_PLAYING;
276    params.buf                  = img->buf;
277    params.bufsize              = img->bufsize;
278    params.cb                   = NULL;
279    params.basename             = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL;
280 
281    audio_driver_mixer_add_stream(&params);
282 
283    if (img->path)
284       free(img->path);
285    if (params.basename != NULL)
286       free(params.basename);
287    free(img);
288    free(user_data);
289 }
290 
task_audio_mixer_handle_upload_mod(retro_task_t * task,void * task_data,void * user_data,const char * err)291 static void task_audio_mixer_handle_upload_mod(retro_task_t *task,
292       void *task_data,
293       void *user_data, const char *err)
294 {
295    audio_mixer_stream_params_t params;
296    nbio_buf_t             *img = (nbio_buf_t*)task_data;
297    struct audio_mixer_userdata *user = (struct audio_mixer_userdata*)user_data;
298 
299    if (!img || !user)
300       return;
301 
302    params.volume               = 1.0f;
303    params.slot_selection_type  = user->slot_selection_type;
304    params.slot_selection_idx   = user->slot_selection_idx;
305    params.stream_type          = user->stream_type;
306    params.type                 = AUDIO_MIXER_TYPE_MOD;
307    params.state                = AUDIO_STREAM_STATE_STOPPED;
308    params.buf                  = img->buf;
309    params.bufsize              = img->bufsize;
310    params.cb                   = NULL;
311    params.basename             = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL;
312 
313    audio_driver_mixer_add_stream(&params);
314 
315    if (img->path)
316       free(img->path);
317    if (params.basename != NULL)
318       free(params.basename);
319    free(img);
320    free(user_data);
321 }
322 
task_audio_mixer_handle_upload_mod_and_play(retro_task_t * task,void * task_data,void * user_data,const char * err)323 static void task_audio_mixer_handle_upload_mod_and_play(retro_task_t *task,
324       void *task_data,
325       void *user_data, const char *err)
326 {
327    audio_mixer_stream_params_t params;
328    nbio_buf_t             *img = (nbio_buf_t*)task_data;
329    struct audio_mixer_userdata *user = (struct audio_mixer_userdata*)user_data;
330 
331    if (!img || !user)
332       return;
333 
334    params.volume               = 1.0f;
335    params.slot_selection_type  = user->slot_selection_type;
336    params.slot_selection_idx   = user->slot_selection_idx;
337    params.stream_type          = user->stream_type;
338    params.type                 = AUDIO_MIXER_TYPE_MOD;
339    params.state                = AUDIO_STREAM_STATE_PLAYING;
340    params.buf                  = img->buf;
341    params.bufsize              = img->bufsize;
342    params.cb                   = NULL;
343    params.basename             = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL;
344 
345    audio_driver_mixer_add_stream(&params);
346 
347    if (img->path)
348       free(img->path);
349    if (params.basename != NULL)
350       free(params.basename);
351    free(img);
352    free(user_data);
353 }
354 
355 #ifdef HAVE_RWAV
task_audio_mixer_handle_upload_wav(retro_task_t * task,void * task_data,void * user_data,const char * err)356 static void task_audio_mixer_handle_upload_wav(retro_task_t *task,
357       void *task_data,
358       void *user_data, const char *err)
359 {
360    audio_mixer_stream_params_t params;
361    nbio_buf_t *img = (nbio_buf_t*)task_data;
362    struct audio_mixer_userdata *user = (struct audio_mixer_userdata*)user_data;
363 
364    if (!img || !user)
365       return;
366 
367    params.volume               = 1.0f;
368    params.slot_selection_type  = user->slot_selection_type;
369    params.slot_selection_idx   = user->slot_selection_idx;
370    params.stream_type          = user->stream_type;
371    params.type                 = AUDIO_MIXER_TYPE_WAV;
372    params.state                = AUDIO_STREAM_STATE_STOPPED;
373    params.buf                  = img->buf;
374    params.bufsize              = img->bufsize;
375    params.cb                   = NULL;
376    params.basename             = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL;
377 
378    audio_driver_mixer_add_stream(&params);
379 
380    if (img->path)
381       free(img->path);
382    if (params.basename != NULL)
383       free(params.basename);
384    free(img);
385    free(user_data);
386 }
387 
task_audio_mixer_handle_upload_wav_and_play(retro_task_t * task,void * task_data,void * user_data,const char * err)388 static void task_audio_mixer_handle_upload_wav_and_play(retro_task_t *task,
389       void *task_data,
390       void *user_data, const char *err)
391 {
392    audio_mixer_stream_params_t params;
393    nbio_buf_t *img = (nbio_buf_t*)task_data;
394    struct audio_mixer_userdata *user = (struct audio_mixer_userdata*)user_data;
395 
396    if (!img || !user)
397       return;
398 
399    params.volume               = 1.0f;
400    params.slot_selection_type  = user->slot_selection_type;
401    params.slot_selection_idx   = user->slot_selection_idx;
402    params.stream_type          = user->stream_type;
403    params.type                 = AUDIO_MIXER_TYPE_WAV;
404    params.state                = AUDIO_STREAM_STATE_PLAYING;
405    params.buf                  = img->buf;
406    params.bufsize              = img->bufsize;
407    params.cb                   = NULL;
408    params.basename             = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL;
409 
410    audio_driver_mixer_add_stream(&params);
411 
412    if (img->path)
413       free(img->path);
414    if (params.basename != NULL)
415       free(params.basename);
416    free(img);
417    free(user_data);
418 }
419 #endif
420 
task_audio_mixer_load_handler(retro_task_t * task)421 bool task_audio_mixer_load_handler(retro_task_t *task)
422 {
423    nbio_handle_t             *nbio  = (nbio_handle_t*)task->state;
424    struct audio_mixer_handle *mixer = (struct audio_mixer_handle*)nbio->data;
425 
426    if (
427          nbio->is_finished
428          && (mixer && !mixer->is_finished)
429          && (mixer->copy_data_over)
430          && (!task_get_cancelled(task)))
431    {
432       nbio_buf_t *img = (nbio_buf_t*)malloc(sizeof(*img));
433 
434       if (img)
435       {
436          img->buf     = mixer->buffer->buf;
437          img->bufsize = mixer->buffer->bufsize;
438          img->path    = strdup(nbio->path);
439       }
440 
441       task_set_data(task, img);
442 
443       mixer->copy_data_over = false;
444       mixer->is_finished    = true;
445 
446       return false;
447    }
448 
449    return true;
450 }
451 
task_push_audio_mixer_load_and_play(const char * fullpath,retro_task_callback_t cb,void * user_data,bool system,enum audio_mixer_slot_selection_type slot_selection_type,int slot_selection_idx)452 bool task_push_audio_mixer_load_and_play(
453       const char *fullpath, retro_task_callback_t cb, void *user_data,
454       bool system,
455       enum audio_mixer_slot_selection_type slot_selection_type,
456       int slot_selection_idx)
457 {
458    nbio_handle_t             *nbio    = NULL;
459    struct audio_mixer_handle   *mixer = NULL;
460    retro_task_t                   *t  = task_init();
461    struct audio_mixer_userdata *user  = (struct audio_mixer_userdata*)calloc(1, sizeof(*user));
462    /* We are comparing against a fixed list of file
463     * extensions, the longest (jpeg) being 4 characters
464     * in length. We therefore only need to extract the first
465     * 5 characters from the extension of the input path
466     * to correctly validate a match */
467    const char *ext                    = NULL;
468    char ext_lower[6];
469 
470    ext_lower[0] = '\0';
471 
472    if (!t || !user)
473       goto error;
474 
475    nbio               = (nbio_handle_t*)calloc(1, sizeof(*nbio));
476 
477    if (!nbio)
478       goto error;
479 
480    nbio->path         = strdup(fullpath);
481 
482    mixer              = (struct audio_mixer_handle*)calloc(1, sizeof(*mixer));
483    if (!mixer)
484       goto error;
485 
486    mixer->is_finished = false;
487 
488    strlcpy(mixer->path, fullpath, sizeof(mixer->path));
489 
490    nbio->type         = NBIO_TYPE_NONE;
491    mixer->type        = AUDIO_MIXER_TYPE_NONE;
492 
493    /* Get file extension */
494    ext = strrchr(fullpath, '.');
495 
496    if (!ext || (*(++ext) == '\0'))
497       goto error;
498 
499    /* Copy and convert to lower case */
500    strlcpy(ext_lower, ext, sizeof(ext_lower));
501    string_to_lower(ext_lower);
502 
503 #ifdef HAVE_RWAV
504    if (string_is_equal(ext_lower, "wav"))
505    {
506       mixer->type     = AUDIO_MIXER_TYPE_WAV;
507       nbio->type      = NBIO_TYPE_WAV;
508       t->callback     = task_audio_mixer_handle_upload_wav_and_play;
509    }
510    else
511 #endif
512       if (string_is_equal(ext_lower, "ogg"))
513    {
514       mixer->type     = AUDIO_MIXER_TYPE_OGG;
515       nbio->type      = NBIO_TYPE_OGG;
516       t->callback     = task_audio_mixer_handle_upload_ogg_and_play;
517    }
518    else if (string_is_equal(ext_lower, "mp3"))
519    {
520       mixer->type     = AUDIO_MIXER_TYPE_MP3;
521       nbio->type      = NBIO_TYPE_MP3;
522       t->callback     = task_audio_mixer_handle_upload_mp3_and_play;
523    }
524    else if (string_is_equal(ext_lower, "flac"))
525    {
526       mixer->type     = AUDIO_MIXER_TYPE_FLAC;
527       nbio->type      = NBIO_TYPE_FLAC;
528       t->callback     = task_audio_mixer_handle_upload_flac_and_play;
529    }
530    else if (
531          string_is_equal(ext_lower, "mod") ||
532          string_is_equal(ext_lower, "s3m") ||
533          string_is_equal(ext_lower, "xm"))
534    {
535       mixer->type     = AUDIO_MIXER_TYPE_MOD;
536       nbio->type      = NBIO_TYPE_MOD;
537       t->callback     = task_audio_mixer_handle_upload_mod_and_play;
538    }
539 
540    if (system)
541       user->stream_type      = AUDIO_STREAM_TYPE_SYSTEM;
542    else
543       user->stream_type      = AUDIO_STREAM_TYPE_USER;
544 
545    user->slot_selection_type = slot_selection_type;
546    user->slot_selection_idx  = slot_selection_idx;
547 
548    nbio->data                = (struct audio_mixer_handle*)mixer;
549    nbio->is_finished         = false;
550    nbio->cb                  = &cb_nbio_audio_mixer_load;
551    nbio->status              = NBIO_STATUS_INIT;
552 
553    t->state           = nbio;
554    t->handler         = task_file_load_handler;
555    t->cleanup         = task_audio_mixer_load_free;
556    t->user_data       = user;
557 
558    task_queue_push(t);
559 
560    return true;
561 
562 error:
563    if (nbio)
564    {
565       if (!string_is_empty(nbio->path))
566          free(nbio->path);
567       if (nbio->data)
568          free(nbio->data);
569       nbio_free(nbio->handle);
570       free(nbio);
571    }
572    if (user)
573       free(user);
574    if (t)
575       free(t);
576 
577    RARCH_ERR("[audio mixer load] Failed to open '%s': %s.\n",
578          fullpath, strerror(errno));
579 
580    return false;
581 }
582 
task_push_audio_mixer_load(const char * fullpath,retro_task_callback_t cb,void * user_data,bool system,enum audio_mixer_slot_selection_type slot_selection_type,int slot_selection_idx)583 bool task_push_audio_mixer_load(
584       const char *fullpath, retro_task_callback_t cb, void *user_data,
585       bool system,
586       enum audio_mixer_slot_selection_type slot_selection_type,
587       int slot_selection_idx)
588 {
589    nbio_handle_t             *nbio    = NULL;
590    struct audio_mixer_handle   *mixer = NULL;
591    retro_task_t                   *t  = task_init();
592    struct audio_mixer_userdata *user  = (struct audio_mixer_userdata*)calloc(1, sizeof(*user));
593    /* We are comparing against a fixed list of file
594     * extensions, the longest (jpeg) being 4 characters
595     * in length. We therefore only need to extract the first
596     * 5 characters from the extension of the input path
597     * to correctly validate a match */
598    const char *ext                    = NULL;
599    char ext_lower[6];
600 
601    ext_lower[0] = '\0';
602 
603    if (!t || !user)
604       goto error;
605 
606    nbio               = (nbio_handle_t*)calloc(1, sizeof(*nbio));
607 
608    if (!nbio)
609       goto error;
610 
611    nbio->path         = strdup(fullpath);
612 
613    mixer              = (struct audio_mixer_handle*)calloc(1, sizeof(*mixer));
614    if (!mixer)
615       goto error;
616 
617    mixer->is_finished = false;
618    mixer->cb          = cb;
619 
620    strlcpy(mixer->path, fullpath, sizeof(mixer->path));
621 
622    nbio->type         = NBIO_TYPE_NONE;
623    mixer->type        = AUDIO_MIXER_TYPE_NONE;
624 
625    /* Get file extension */
626    ext                = strrchr(fullpath, '.');
627 
628    if (!ext || (*(++ext) == '\0'))
629       goto error;
630 
631    /* Copy and convert to lower case */
632    strlcpy(ext_lower, ext, sizeof(ext_lower));
633    string_to_lower(ext_lower);
634 
635 #ifdef HAVE_RWAV
636    if (string_is_equal(ext_lower, "wav"))
637    {
638       mixer->type     = AUDIO_MIXER_TYPE_WAV;
639       nbio->type      = NBIO_TYPE_WAV;
640       t->callback     = task_audio_mixer_handle_upload_wav;
641    }
642    else
643 #endif
644       if (string_is_equal(ext_lower, "ogg"))
645    {
646       mixer->type     = AUDIO_MIXER_TYPE_OGG;
647       nbio->type      = NBIO_TYPE_OGG;
648       t->callback     = task_audio_mixer_handle_upload_ogg;
649    }
650    else if (string_is_equal(ext_lower, "mp3"))
651    {
652       mixer->type     = AUDIO_MIXER_TYPE_MP3;
653       nbio->type      = NBIO_TYPE_MP3;
654       t->callback     = task_audio_mixer_handle_upload_mp3;
655    }
656    else if (string_is_equal(ext_lower, "flac"))
657    {
658       mixer->type     = AUDIO_MIXER_TYPE_FLAC;
659       nbio->type      = NBIO_TYPE_FLAC;
660       t->callback     = task_audio_mixer_handle_upload_flac;
661    }
662    else if (
663          string_is_equal(ext_lower, "mod") ||
664          string_is_equal(ext_lower, "s3m") ||
665          string_is_equal(ext_lower, "xm"))
666    {
667       mixer->type     = AUDIO_MIXER_TYPE_MOD;
668       nbio->type      = NBIO_TYPE_MOD;
669       t->callback     = task_audio_mixer_handle_upload_mod;
670    }
671 
672    nbio->data         = (struct audio_mixer_handle*)mixer;
673    nbio->is_finished  = false;
674    nbio->cb           = &cb_nbio_audio_mixer_load;
675    nbio->status       = NBIO_STATUS_INIT;
676 
677    if (system)
678       user->stream_type      = AUDIO_STREAM_TYPE_SYSTEM;
679    else
680       user->stream_type      = AUDIO_STREAM_TYPE_USER;
681 
682    user->slot_selection_type = slot_selection_type;
683    user->slot_selection_idx  = slot_selection_idx;
684 
685    t->state                  = nbio;
686    t->handler                = task_file_load_handler;
687    t->cleanup                = task_audio_mixer_load_free;
688    t->user_data              = user;
689 
690    task_queue_push(t);
691 
692    return true;
693 
694 error:
695    if (nbio)
696    {
697       if (!string_is_empty(nbio->path))
698          free(nbio->path);
699       if (nbio->data)
700          free(nbio->data);
701       nbio_free(nbio->handle);
702       free(nbio);
703    }
704    if (user)
705       free(user);
706    if (t)
707       free(t);
708 
709    RARCH_ERR("[audio mixer load] Failed to open '%s': %s.\n",
710          fullpath, strerror(errno));
711 
712    return false;
713 }
714