Пример #1
0
/* Handle Q_CODEC_LOAD */
static void load_codec(const struct codec_load_info *ev_data)
{
    int status = CODEC_ERROR;
    /* Save a local copy so we can let the audio thread go ASAP */
    struct codec_load_info data = *ev_data;
    bool const encoder = type_is_encoder(data.afmt);

    if (codec_type != AFMT_UNKNOWN)
    {
        /* Must have unloaded it first */
        logf("a codec is already loaded");
        if (data.hid >= 0)
            bufclose(data.hid);
        return;
    }

    trigger_cpu_boost();

    if (!encoder)
    {
        /* Do this now because codec may set some things up at load time */
        dsp_configure(ci.dsp, DSP_RESET, 0);
    }

    if (data.hid >= 0)
    {
        /* First try buffer load */
        status = codec_load_buf(data.hid, &ci);
        bufclose(data.hid);
    }

    if (status < 0)
    {
        /* Either not a valid handle or the buffer method failed */
        const char *codec_fn = get_codec_filename(data.afmt);
        if (codec_fn)
        {
#ifdef HAVE_IO_PRIORITY
            buf_back_off_storage(true);
#endif
            status = codec_load_file(codec_fn, &ci);
#ifdef HAVE_IO_PRIORITY
            buf_back_off_storage(false);
#endif
        }
    }

    if (status >= 0)
    {
        codec_type = data.afmt;
        codec_queue_ack(Q_CODEC_LOAD);
        return;
    }

    /* Failed - get rid of it */
    unload_codec();
}
Пример #2
0
/** CODEC THREAD */
static void codec_thread(void)
{
    struct queue_event ev;
    int status;

    while (1) {
        status = 0;
        
#ifdef HAVE_CROSSFADE
        if (!pcmbuf_is_crossfade_active())
#endif
        {
            cancel_cpu_boost();
        }
            
        queue_wait(&codec_queue, &ev);
        codec_requested_stop = false;

        switch (ev.id) {
            case Q_CODEC_LOAD_DISK:
                LOGFQUEUE("codec < Q_CODEC_LOAD_DISK");
                queue_reply(&codec_queue, 1);
                audio_codec_loaded = true;
                ci.stop_codec = false;
                status = codec_load_file((const char *)ev.data, &ci);
                LOGFQUEUE("codec_load_file %s %d\n", (const char *)ev.data, status);
                break;

            case Q_CODEC_LOAD:
                LOGFQUEUE("codec < Q_CODEC_LOAD");
                if (*get_codec_hid() < 0) {
                    logf("Codec slot is empty!");
                    /* Wait for the pcm buffer to go empty */
                    while (pcm_is_playing())
                        yield();
                    /* This must be set to prevent an infinite loop */
                    ci.stop_codec = true;
                    LOGFQUEUE("codec > codec Q_AUDIO_PLAY");
                    queue_post(&codec_queue, Q_AUDIO_PLAY, 0);
                    break;
                }

                audio_codec_loaded = true;
                ci.stop_codec = false;
                status = codec_load_buf(*get_codec_hid(), &ci);
                LOGFQUEUE("codec_load_buf %d\n", status);
                break;

            case Q_CODEC_DO_CALLBACK:
                LOGFQUEUE("codec < Q_CODEC_DO_CALLBACK");
                queue_reply(&codec_queue, 1);
                if ((void*)ev.data != NULL)
                {
                    cpucache_invalidate();
                    ((void (*)(void))ev.data)();
                    cpucache_flush();
                }
                break;

#ifdef AUDIO_HAVE_RECORDING
            case Q_ENCODER_LOAD_DISK:
                LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");
                audio_codec_loaded = false; /* Not audio codec! */
                logf("loading encoder");
                ci.stop_encoder = false;
                status = codec_load_file((const char *)ev.data, &ci);
                logf("encoder stopped");
                break;
#endif /* AUDIO_HAVE_RECORDING */

            default:
                LOGFQUEUE("codec < default");
        }

        if (audio_codec_loaded)
        {
            if (ci.stop_codec)
            {
                status = CODEC_OK;
                if (!(audio_status() & AUDIO_STATUS_PLAY))
                    pcmbuf_play_stop();

            }
            audio_codec_loaded = false;
        }

        switch (ev.id) {
            case Q_CODEC_LOAD_DISK:
            case Q_CODEC_LOAD:
                LOGFQUEUE("codec < Q_CODEC_LOAD");
                if (audio_status() & AUDIO_STATUS_PLAY)
                {
                    if (ci.new_track || status != CODEC_OK)
                    {
                        if (!ci.new_track)
                        {
                            logf("Codec failure, %d %d", ci.new_track, status);
                            splash(HZ*2, "Codec failure");
                        }

                        if (!codec_load_next_track())
                        {
                            LOGFQUEUE("codec > audio Q_AUDIO_STOP");
                            /* End of playlist */
                            queue_post(&audio_queue, Q_AUDIO_STOP, 0);
                            break;
                        }
                    }
                    else
                    {
                        logf("Codec finished");
                        if (ci.stop_codec)
                        {
                            /* Wait for the audio to stop playing before
                             * triggering the WPS exit */
                            while(pcm_is_playing())
                            {
                                /* There has been one too many struct pointer swaps by now
                                 * so even though it says othertrack_id3, its the correct one! */
                                othertrack_id3->elapsed =
                                    othertrack_id3->length - pcmbuf_get_latency();
                                sleep(1);
                            }

                            if (codec_requested_stop)
                            {
                                LOGFQUEUE("codec > audio Q_AUDIO_STOP");
                                queue_post(&audio_queue, Q_AUDIO_STOP, 0);
                            }
                            break;
                        }
                    }

                    if (*get_codec_hid() >= 0)
                    {
                        LOGFQUEUE("codec > codec Q_CODEC_LOAD");
                        queue_post(&codec_queue, Q_CODEC_LOAD, 0);
                    }
                    else
                    {
                        const char *codec_fn =
                            get_codec_filename(thistrack_id3->codectype);
                        if (codec_fn)
                        {
                            LOGFQUEUE("codec > codec Q_CODEC_LOAD_DISK");
                            queue_post(&codec_queue, Q_CODEC_LOAD_DISK,
                                       (intptr_t)codec_fn);
                        }
                    }
                }
                break;

#ifdef AUDIO_HAVE_RECORDING
            case Q_ENCODER_LOAD_DISK:
                LOGFQUEUE("codec < Q_ENCODER_LOAD_DISK");

                if (status == CODEC_OK)
                    break;

                logf("Encoder failure");
                splash(HZ*2, "Encoder failure");

                if (ci.enc_codec_loaded < 0)
                    break;

                logf("Encoder failed to load");
                ci.enc_codec_loaded = -1;
                break;
#endif /* AUDIO_HAVE_RECORDING */

            default:
                LOGFQUEUE("codec < default");

        } /* end switch */
    }
}