/* Handle STREAM_PAUSE */
static void stream_on_pause(void)
{
    int status = stream_mgr.status;

    stream_mgr_lock();

    /* Reply with previous state */
    stream_mgr_reply_msg(status);

    if (status == STREAM_PLAYING)
    {
        /* Pause the clock */
        pcm_output_play_pause(false);

        /* Pause each active stream */
        actl_stream_broadcast(STREAM_PAUSE, 0);

        /* Pause the disk buffer - buffer may continue filling */
        disk_buf_send_msg(STREAM_PAUSE, false);

        /* Unboost the CPU */
        cancel_cpu_boost();

        /* Offically paused */
        stream_mgr.status = STREAM_PAUSED;
    }

    stream_mgr_unlock();
}
/* Handle STREAM_OPEN */
void stream_on_open(const char *filename)
{
    int err = STREAM_ERROR;

    stream_mgr_lock();

    trigger_cpu_boost();

    /* Open the video file */
    if (disk_buf_open(filename) >= 0)
    {
        /* Initialize the parser */
        err = parser_init_stream();

        if (err >= STREAM_OK)
        {
            /* File ok - save the opened filename */
            stream_mgr.filename = filename;
        }
    }

    /* If error - cleanup */
    if (err < STREAM_OK)
        stream_on_close();

    cancel_cpu_boost();

    stream_mgr_unlock();

    stream_mgr_reply_msg(err);
}
Exemplo n.º 3
0
bool create_playlist(void)
{
    char filename[MAX_PATH];

    snprintf(filename, sizeof filename, "%s.m3u8",
             tc.currdir[1] ? tc.currdir : "/root");
    splashf(0, "%s %s", str(LANG_CREATING), filename);

    trigger_cpu_boost();
    catalog_add_to_a_playlist(tc.currdir, ATTR_DIRECTORY, true, filename);
    cancel_cpu_boost();

    return true;
}
Exemplo n.º 4
0
static void codec_pcmbuf_insert_callback(
    const void *ch1, const void *ch2, int count)
{
    const char *src[2] = { ch1, ch2 };

    while (count > 0)
    {
        int out_count = dsp_output_count(ci.dsp, count);
        int inp_count;
        char *dest;

        while (1)
        {
            if ((dest = pcmbuf_request_buffer(&out_count)) != NULL)
                break;

            cancel_cpu_boost();

            /* It will be awhile before space is available but we want
               "instant" response to any message */
            queue_wait_w_tmo(&codec_queue, NULL, HZ/20);

            if (!queue_empty(&codec_queue) &&
                    codec_check_queue__have_msg() < 0)
                return;
        }

        /* Get the real input_size for output_size bytes, guarding
         * against resampling buffer overflows. */
        inp_count = dsp_input_count(ci.dsp, out_count);

        if (inp_count <= 0)
            return;

        /* Input size has grown, no error, just don't write more than length */
        if (inp_count > count)
            inp_count = count;

        out_count = dsp_process(ci.dsp, dest, src, inp_count);

        if (out_count <= 0)
            return;

        pcmbuf_write_complete(out_count);

        count -= inp_count;
    }
}
Exemplo n.º 5
0
/* Codec thread function */
static void NORETURN_ATTR codec_thread(void)
{
    struct queue_event ev;

    while (1)
    {
        cancel_cpu_boost();

        queue_wait(&codec_queue, &ev);

        switch (ev.id)
        {
        case Q_CODEC_LOAD:
            LOGFQUEUE("codec < Q_CODEC_LOAD");
            load_codec((const struct codec_load_info *)ev.data);
            break;

        case Q_CODEC_RUN:
            LOGFQUEUE("codec < Q_CODEC_RUN");
            run_codec();
            break;

        case Q_CODEC_PAUSE:
            LOGFQUEUE("codec < Q_CODEC_PAUSE");
            break;

        case Q_CODEC_SEEK:
            LOGFQUEUE("codec < Q_CODEC_SEEK: %lu", (unsigned long)ev.data);
            seek_codec(ev.data);
            break;

        case Q_CODEC_UNLOAD:
            LOGFQUEUE("codec < Q_CODEC_UNLOAD");
            unload_codec();
            break;

        case Q_CODEC_DO_CALLBACK:
            LOGFQUEUE("codec < Q_CODEC_DO_CALLBACK");
            do_callback((void (*)(void))ev.data);
            break;

        default:
            LOGFQUEUE("codec < default : %ld", ev.id);
        }
    }
}
Exemplo n.º 6
0
static void codec_pcmbuf_insert_callback(
        const void *ch1, const void *ch2, int count)
{
    const char *src[2] = { ch1, ch2 };

    while (count > 0)
    {
        int out_count = dsp_output_count(ci.dsp, count);
        int inp_count;
        char *dest;

        /* Prevent audio from a previous track from playing */
        if (ci.new_track || ci.stop_codec)
            return;

        while ((dest = pcmbuf_request_buffer(&out_count)) == NULL)
        {
            cancel_cpu_boost();
            sleep(1);
            if (ci.seek_time || ci.new_track || ci.stop_codec)
                return;
        }

        /* Get the real input_size for output_size bytes, guarding
         * against resampling buffer overflows. */
        inp_count = dsp_input_count(ci.dsp, out_count);

        if (inp_count <= 0)
            return;

        /* Input size has grown, no error, just don't write more than length */
        if (inp_count > count)
            inp_count = count;

        out_count = dsp_process(ci.dsp, dest, src, inp_count);

        if (out_count <= 0)
            return;

        pcmbuf_write_complete(out_count);

        count -= inp_count;
    }
} /* codec_pcmbuf_insert_callback */
Exemplo n.º 7
0
bool create_playlist(void)
{
    char filename[MAX_PATH];

    if (tc.currdir[1])
        snprintf(filename, sizeof filename, "%s.m3u8", tc.currdir);
    else
        snprintf(filename, sizeof filename, "%s/all.m3u8",
                catalog_get_directory());
        
    
    if (kbd_input(filename, MAX_PATH))
        return false;
    splashf(0, "%s %s", str(LANG_CREATING), filename);

    trigger_cpu_boost();
    catalog_add_to_a_playlist(tc.currdir, ATTR_DIRECTORY, true, filename);
    cancel_cpu_boost();

    return true;
}
/* Handle STREAM_STOP */
static void stream_on_stop(bool reply)
{
    int status = stream_mgr.status;

    stream_mgr_lock();

    if (reply)
        stream_mgr_reply_msg(status);

    if (status != STREAM_STOPPED)
    {
        /* Pause the clock */
        pcm_output_play_pause(false);

        /* Update the resume time info */
        stream_remember_resume_time();

        /* Not stopped = paused or playing */
        stream_mgr.seeked = false;

        /* Stop buffering */
        disk_buf_send_msg(STREAM_STOP, 0);

        /* Clear any still-active streams and remove from actl */
        actl_stream_broadcast(STREAM_STOP, 1);

        /* Stop PCM output (and clock) */
        pcm_output_stop();

        /* Cancel our processor boost */
        cancel_cpu_boost();

        stream_mgr.status = STREAM_STOPPED;
    }

    stream_mgr_unlock();
}
Exemplo n.º 9
0
/* inline since branch is chosen at compile time */
static inline void usb_slave_mode(bool on)
{
#ifdef USE_ROCKBOX_USB
    int rc;

    if (on)
    {
        trigger_cpu_boost();
#ifdef HAVE_PRIORITY_SCHEDULING
        thread_set_priority(THREAD_ID_CURRENT, PRIORITY_REALTIME);
#endif
        usb_attach();
    }
    else /* usb_state == USB_INSERTED (only!) */
    {
#ifndef USB_DETECT_BY_DRV
        usb_enable(false);
#endif
#ifdef HAVE_PRIORITY_SCHEDULING
        thread_set_priority(THREAD_ID_CURRENT, PRIORITY_SYSTEM);
#endif
        /* Entered exclusive mode */
        rc = disk_mount_all();
        if (rc <= 0) /* no partition */
            panicf("mount: %d",rc);

        cancel_cpu_boost();
    }
#else /* !USE_ROCKBOX_USB */
    if (on)
    {
        /* until we have native mass-storage mode, we want to reboot on
           usb host connect */
        try_reboot();
    }
#endif /* USE_ROCKBOX_USB */
}
Exemplo n.º 10
0
void radio_screen(void)
{
    bool done = false;
    int button;
    bool stereo = false, last_stereo = false;
    int update_type = 0;
    bool screen_freeze = false;
    bool keep_playing = false;
    bool talk = false;
#ifdef FM_RECORD_DBLPRE
    int lastbutton = BUTTON_NONE;
    unsigned long rec_lastclick = 0;
#endif
#if CONFIG_CODEC != SWCODEC
    int timeout = current_tick + HZ/10;
#if !defined(SIMULATOR)
    unsigned int last_seconds = 0;
    unsigned int seconds = 0;
    struct audio_recording_options rec_options;
#endif /* SIMULATOR */
#endif /* CONFIG_CODEC != SWCODEC */
#ifndef HAVE_NOISY_IDLE_MODE
    int button_timeout = current_tick + (2*HZ);
#endif

    /* change status to "in screen" */
    push_current_activity(ACTIVITY_FM);
    in_screen = true;

    if(radio_preset_count() <= 0)
    {
        radio_load_presets(global_settings.fmr_file);
    }
    skin_get_global_state()->id3 = NULL;
#ifdef HAVE_ALBUMART
    radioart_init(true);
#endif    

    if(radio_status == FMRADIO_OFF)
        audio_stop();

    fms_fix_displays(FMS_ENTER);

#ifndef SIMULATOR

#if CONFIG_CODEC != SWCODEC
    rec_create_directory();
    audio_init_recording();

    sound_settings_apply();
    /* Yes, we use the D/A for monitoring */
    peak_meter_playback(true);

    peak_meter_enable(true);

    rec_init_recording_options(&rec_options);
    rec_options.rec_source = AUDIO_SRC_LINEIN;
    rec_set_recording_options(&rec_options);

    audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
            sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);

#endif /* CONFIG_CODEC != SWCODEC */
#endif /* ndef SIMULATOR */
    /* turn on radio */
#if CONFIG_CODEC == SWCODEC
    /* This should be done before touching audio settings */
    while (!pcm_is_initialized())
       sleep(0);

    audio_set_input_source(AUDIO_SRC_FMRADIO,
                           (radio_status == FMRADIO_PAUSED) ?
                               SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING);
#else
    if (radio_status == FMRADIO_OFF)
        radio_start();
#endif

    if(radio_preset_count() < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN)))
        presets_scan(NULL);

    preset_set_current(preset_find(curr_freq));
    if(radio_current_preset() != -1)
         radio_mode = RADIO_PRESET_MODE;

    /* Load/update the skin at last, when fully initialzed, so that it can
     * display the right content from the beginning */
    FOR_NB_SCREENS(i)
        skin_update(FM_SCREEN, i, SKIN_REFRESH_ALL);

#ifndef HAVE_NOISY_IDLE_MODE
    cpu_idle_mode(true);
#endif

    while(!done)
    {
        if(search_dir != 0)
        {
            curr_freq = step_freq(curr_freq, search_dir);
            update_type = SKIN_REFRESH_ALL;

            if(tuner_set(RADIO_SCAN_FREQUENCY, curr_freq))
            {
                preset_set_current(preset_find(curr_freq));
                remember_frequency();
                end_search();
                talk = true;
            }
            trigger_cpu_boost();
        }

        if (!update_type)
        {
            cancel_cpu_boost();
        }

        button = fms_do_button_loop(update_type>0);

#ifndef HAVE_NOISY_IDLE_MODE
        if (button != ACTION_NONE)
        {
            cpu_idle_mode(false);
            button_timeout = current_tick + (2*HZ);
        }
#endif
        switch(button)
        {
             case ACTION_FM_STOP:
#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
                if(audio_status() == AUDIO_STATUS_RECORD)
                {
                    audio_stop();
                }
                else
#endif
                {
                    done = true;
                    if(presets_have_changed())
                    {
                        if(yesno_pop(ID2P(LANG_SAVE_CHANGES)))
                        {
                            presets_save();
                        }
                    }
                }
                update_type = SKIN_REFRESH_NON_STATIC;
                break;

#ifdef FM_RECORD
            case ACTION_FM_RECORD:
#ifdef FM_RECORD_DBLPRE
                if (lastbutton != ACTION_FM_RECORD_DBLPRE)
                {
                    rec_lastclick = 0;
                    break;
                }
                if (current_tick - rec_lastclick > HZ/2)
                {
                    rec_lastclick = current_tick;
                    break;
                }
#endif /* FM_RECORD_DBLPRE */
#ifndef SIMULATOR
                if(audio_status() == AUDIO_STATUS_RECORD)
                {
                    rec_command(RECORDING_CMD_START_NEWFILE);
                    update_type = SKIN_REFRESH_ALL;
                }
                else
                {
                    rec_command(RECORDING_CMD_START);
                    update_type = SKIN_REFRESH_ALL;
                }
#if CONFIG_CODEC != SWCODEC
                last_seconds = 0;
#endif
#endif /* SIMULATOR */
                break;
#endif /* #ifdef FM_RECORD */

            case ACTION_FM_EXIT:
#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
                if(audio_status() == AUDIO_STATUS_RECORD)
                    audio_stop();
#endif
                keep_playing = true;
                done = true;
                if(presets_have_changed())
                {
                    if(yesno_pop(ID2P(LANG_SAVE_CHANGES)))
                    {
                        presets_save();
                    }
                }

                break;

            case ACTION_STD_PREV:
            case ACTION_STD_NEXT:
                next_station(button == ACTION_STD_PREV ? -1 : 1);
                end_search();
                update_type = SKIN_REFRESH_ALL;
                talk = true;
                break;

            case ACTION_STD_PREVREPEAT:
            case ACTION_STD_NEXTREPEAT:
            {
                int dir = search_dir;
                search_dir = button == ACTION_STD_PREVREPEAT ? -1 : 1;
                if (radio_mode != RADIO_SCAN_MODE)
                {
                    preset_next(search_dir);
                    end_search();
                    talk = true;
                }
                else if (dir == 0)
                {
                    /* Starting auto scan */
                    tuner_set(RADIO_MUTE, 1);
                }
                update_type = SKIN_REFRESH_ALL;
                break;
            }

            case ACTION_SETTINGS_INC:
            case ACTION_SETTINGS_INCREPEAT:
                global_settings.volume++;
                setvol();
                update_type = SKIN_REFRESH_NON_STATIC;
                break;

            case ACTION_SETTINGS_DEC:
            case ACTION_SETTINGS_DECREPEAT:
                global_settings.volume--;
                setvol();
                update_type = SKIN_REFRESH_NON_STATIC;
                break;

            case ACTION_FM_PLAY:
                if (radio_status == FMRADIO_PLAYING)
                    radio_pause();
                else
                    radio_start();

                update_type = SKIN_REFRESH_NON_STATIC;
                talk = false;
                talk_shutup();
                break;

            case ACTION_FM_MENU:
                fms_fix_displays(FMS_EXIT);
                do_menu(&radio_settings_menu, NULL, NULL, false);
                preset_set_current(preset_find(curr_freq));
                fms_fix_displays(FMS_ENTER);
                update_type = SKIN_REFRESH_ALL;
                break;

#ifdef FM_PRESET
            case ACTION_FM_PRESET:
                if(radio_preset_count() < 1)
                {
                    splash(HZ, ID2P(LANG_FM_NO_PRESETS));
                    update_type = SKIN_REFRESH_ALL;
                    break;
                }
                fms_fix_displays(FMS_EXIT);
                handle_radio_presets();
                fms_fix_displays(FMS_ENTER);
                update_type = SKIN_REFRESH_ALL;
                break;
#endif /* FM_PRESET */

#ifdef FM_FREEZE
            case ACTION_FM_FREEZE:
                if(!screen_freeze)
                {
                    splash(HZ, str(LANG_FM_FREEZE));
                    screen_freeze = true;
                }
                else
                {
                    update_type = SKIN_REFRESH_ALL;
                    screen_freeze = false;
                }
                break;
#endif /* FM_FREEZE */

            case SYS_USB_CONNECTED:
#if CONFIG_CODEC != SWCODEC
                /* Only accept USB connection when not recording */
                if(audio_status() != AUDIO_STATUS_RECORD)
#endif
                {
                    default_event_handler(SYS_USB_CONNECTED);
                    screen_freeze = true; /* Cosmetic: makes sure the
                                             radio screen doesn't redraw */
                    done = true;
                }
                break;

#ifdef FM_MODE
           case ACTION_FM_MODE:
                if(radio_mode == RADIO_SCAN_MODE)
                {
                    /* Force scan mode if there are no presets. */
                    if(radio_preset_count() > 0)
                        radio_mode = RADIO_PRESET_MODE;
                }
                else
                    radio_mode = RADIO_SCAN_MODE;
                update_type = SKIN_REFRESH_ALL;
                cond_talk_ids_fq(radio_mode ?
                                 LANG_PRESET : LANG_RADIO_SCAN_MODE);
                talk = true;
                break;
#endif /* FM_MODE */

#ifdef FM_NEXT_PRESET
            case ACTION_FM_NEXT_PRESET:
                preset_next(1);
                end_search();
                update_type = SKIN_REFRESH_ALL;
                talk = true;
                break;
#endif

#ifdef FM_PREV_PRESET
            case ACTION_FM_PREV_PRESET:
                preset_next(-1);
                end_search();
                update_type = SKIN_REFRESH_ALL;
                talk = true;
                break;
#endif
            case ACTION_NONE:
                update_type = SKIN_REFRESH_NON_STATIC;
                break;
             /* this case is used by the softlock feature
              * it requests a full update here */
            case ACTION_REDRAW:
                skin_request_full_update(FM_SCREEN);
                break;

            default:
                default_event_handler(button);
#ifdef HAVE_RDS_CAP
                if (tuner_get(RADIO_EVENT))
                    update_type = SKIN_REFRESH_ALL;
#endif
                if (!tuner_get(RADIO_PRESENT))
                {
#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
                    if(audio_status() == AUDIO_STATUS_RECORD)
                        audio_stop();
#endif
                    keep_playing = false;
                    done = true;
                    if(presets_have_changed())
                    {
                        if(yesno_pop(ID2P(LANG_SAVE_CHANGES)))
                        {
                            radio_save_presets();
                        }
                    }

                    /* Clear the preset list on exit. */
                    preset_list_clear();
                }
                break;
        } /*switch(button)*/

#ifdef FM_RECORD_DBLPRE
        if (button != ACTION_NONE)
            lastbutton = button;
#endif

#if CONFIG_CODEC != SWCODEC
        peak_meter_peek();
#endif

        if(!screen_freeze)
        {
            /* Only display the peak meter when not recording */
#if CONFIG_CODEC != SWCODEC
            if(TIME_AFTER(current_tick, timeout))
            {
                timeout = current_tick + HZ;
#else  /* SWCODEC */
            {
#endif /* CONFIG_CODEC == SWCODEC */

                /* keep "mono" from always being displayed when paused */
                if (radio_status != FMRADIO_PAUSED)
                {
                    stereo = tuner_get(RADIO_STEREO) &&
                        !global_settings.fm_force_mono;

                    if(stereo != last_stereo)
                    {
                        update_type = SKIN_REFRESH_ALL;
                        last_stereo = stereo;
                    }
                }
            }

#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
            seconds = audio_recorded_time() / HZ;
            if (update_type || seconds > last_seconds)
            {
                last_seconds = seconds;
#else
            if (update_type)
            {
#endif
                FOR_NB_SCREENS(i)
                    skin_update(FM_SCREEN, i, update_type);
                if (update_type == (int)SKIN_REFRESH_ALL)
                    skin_request_full_update(CUSTOM_STATUSBAR);
            }
        }
        update_type = 0;

        if (global_settings.talk_file && talk
            && radio_status == FMRADIO_PAUSED)
        {
            talk = false;
            bool enqueue = false;
            if (radio_mode == RADIO_SCAN_MODE)
            {
                talk_value_decimal(curr_freq, UNIT_INT, 6, enqueue);
                enqueue = true;
            }
            if (radio_current_preset() >= 0)
                preset_talk(radio_current_preset(), radio_mode == RADIO_PRESET_MODE,
                            enqueue);
        }

#if CONFIG_CODEC != SWCODEC
        if(audio_status() & AUDIO_STATUS_ERROR)
        {
            done = true;
        }
#endif

#ifndef HAVE_NOISY_IDLE_MODE
        if (TIME_AFTER(current_tick, button_timeout))
        {
            cpu_idle_mode(true);
        }
#endif
    } /*while(!done)*/

#ifndef SIMULATOR
#if CONFIG_CODEC != SWCODEC
    if(audio_status() & AUDIO_STATUS_ERROR)
    {
        splash(0, str(LANG_DISK_FULL));
        audio_error_clear();

        while(1)
        {
            button = get_action(CONTEXT_FM|ALLOW_SOFTLOCK, TIMEOUT_BLOCK);
            if(button == ACTION_FM_STOP)
                break;
        }
    }

    audio_init_playback();
#endif /* CONFIG_CODEC != SWCODEC */

    sound_settings_apply();
#endif /* SIMULATOR */

    if(keep_playing)
    {
/* Catch FMRADIO_PLAYING status for the sim. */
#ifndef SIMULATOR
#if CONFIG_CODEC != SWCODEC
        /* Enable the Left and right A/D Converter */
        audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
                                 sound_default(SOUND_RIGHT_GAIN),
                                 AUDIO_GAIN_LINEIN);
        mas_codec_writereg(6, 0x4000);
#endif
        end_search();
#endif /* SIMULATOR */
    }
    else
    {
#if CONFIG_CODEC == SWCODEC
        audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
#else
        radio_stop();
#endif
    }

#ifndef HAVE_NOISY_IDLE_MODE
    cpu_idle_mode(false);
#endif
    fms_fix_displays(FMS_EXIT);
    pop_current_activity();
    in_screen = false;
} /* radio_screen */

void toggle_mono_mode(bool mono)
{
    tuner_set(RADIO_FORCE_MONO, mono);
}

void set_radio_region(int region)
{
#ifdef HAVE_RADIO_REGION
    tuner_set(RADIO_REGION, region);
#endif
    next_station(0);
    remember_frequency();
    (void)region;
}
/* Voice thread message processing */
static enum voice_state voice_message(struct voice_thread_data *td)
{
    if (quiet_counter > 0)
        queue_wait_w_tmo(&voice_queue, &td->ev, HZ/10);
    else
        queue_wait(&voice_queue, &td->ev);

    switch (td->ev.id)
    {
    case Q_VOICE_PLAY:
        LOGFQUEUE("voice < Q_VOICE_PLAY");
        if (quiet_counter == 0)
        {
            /* Boost CPU now */
            trigger_cpu_boost();
        }
        else
        {
            /* Stop any clip still playing */
            voice_stop_playback();
        }

        quiet_counter = QUIET_COUNT;

        /* Copy the clip info */
        td->vi = *(struct voice_info *)td->ev.data;

        /* Be sure audio buffer is initialized */
        audio_restore_playback(AUDIO_WANT_VOICE);

        /* We need nothing more from the sending thread - let it run */
        queue_reply(&voice_queue, 1);

        /* Make audio play more softly and set delay to return to normal
           playback level */
        pcmbuf_soft_mode(true);

        /* Clean-start the decoder */
        td->st = speex_decoder_init(&speex_wb_mode);

        /* Make bit buffer use our own buffer */
        speex_bits_set_bit_buffer(&td->bits, td->vi.start, td->vi.size);
        speex_decoder_ctl(td->st, SPEEX_GET_LOOKAHEAD, &td->lookahead);

        return VOICE_STATE_DECODE;

    case SYS_TIMEOUT:
        if (voice_unplayed_frames())
        {
            /* Waiting for PCM to finish */
            break;
        }

        /* Drop through and stop the first time after clip runs out */
        if (quiet_counter-- != QUIET_COUNT)
        {
            if (quiet_counter <= 0)
                pcmbuf_soft_mode(false);

            break;
        }

        /* Fall-through */
    case Q_VOICE_STOP:
        LOGFQUEUE("voice < Q_VOICE_STOP");
        cancel_cpu_boost();
        voice_stop_playback();
        break;

    /* No default: no other message ids are sent */
    }

    return VOICE_STATE_MESSAGE;
}
Exemplo n.º 12
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 */
    }
}
Exemplo n.º 13
0
void buffering_thread(void)
{
    bool filling = false;
    struct queue_event ev;

    while (true)
    {
        if (!filling) {
            cancel_cpu_boost();
        }

        queue_wait_w_tmo(&buffering_queue, &ev, filling ? 5 : HZ/2);

        switch (ev.id)
        {
            case Q_START_FILL:
                LOGFQUEUE("buffering < Q_START_FILL %d", (int)ev.data);
                /* Call buffer callbacks here because this is one of two ways
                 * to begin a full buffer fill */
                send_event(BUFFER_EVENT_BUFFER_LOW, 0);
                shrink_buffer();
                queue_reply(&buffering_queue, 1);
                filling |= buffer_handle((int)ev.data);
                break;

            case Q_BUFFER_HANDLE:
                LOGFQUEUE("buffering < Q_BUFFER_HANDLE %d", (int)ev.data);
                queue_reply(&buffering_queue, 1);
                buffer_handle((int)ev.data);
                break;

            case Q_RESET_HANDLE:
                LOGFQUEUE("buffering < Q_RESET_HANDLE %d", (int)ev.data);
                queue_reply(&buffering_queue, 1);
                reset_handle((int)ev.data);
                break;

            case Q_CLOSE_HANDLE:
                LOGFQUEUE("buffering < Q_CLOSE_HANDLE %d", (int)ev.data);
                queue_reply(&buffering_queue, close_handle((int)ev.data));
                break;

            case Q_HANDLE_ADDED:
                LOGFQUEUE("buffering < Q_HANDLE_ADDED %d", (int)ev.data);
                /* A handle was added: the disk is spinning, so we can fill */
                filling = true;
                break;

            case Q_BASE_HANDLE:
                LOGFQUEUE("buffering < Q_BASE_HANDLE %d", (int)ev.data);
                base_handle_id = (int)ev.data;
                break;

#ifndef SIMULATOR
            case SYS_USB_CONNECTED:
                LOGFQUEUE("buffering < SYS_USB_CONNECTED");
                usb_acknowledge(SYS_USB_CONNECTED_ACK);
                usb_wait_for_disconnect(&buffering_queue);
                break;
#endif

            case SYS_TIMEOUT:
                LOGFQUEUE_SYS_TIMEOUT("buffering < SYS_TIMEOUT");
                break;
        }

        update_data_counters();

        /* If the buffer is low, call the callbacks to get new data */
        if (num_handles > 0 && data_counters.useful <= conf_watermark)
            send_event(BUFFER_EVENT_BUFFER_LOW, 0);

#if 0
        /* TODO: This needs to be fixed to use the idle callback, disable it
         * for simplicity until its done right */
#if MEM > 8
        /* If the disk is spinning, take advantage by filling the buffer */
        else if (storage_disk_is_active() && queue_empty(&buffering_queue))
        {
            if (num_handles > 0 && data_counters.useful <= high_watermark)
                send_event(BUFFER_EVENT_BUFFER_LOW, 0);

            if (data_counters.remaining > 0 && BUF_USED <= high_watermark)
            {
                /* This is a new fill, shrink the buffer up first */
                if (!filling)
                    shrink_buffer();
                filling = fill_buffer();
                update_data_counters();
            }
        }
#endif
#endif

        if (queue_empty(&buffering_queue)) {
            if (filling) {
                if (data_counters.remaining > 0 && BUF_USED < buffer_len)
                    filling = fill_buffer();
                else if (data_counters.remaining == 0)
                    filling = false;
            }
            else if (ev.id == SYS_TIMEOUT)
            {
                if (data_counters.remaining > 0 &&
                    data_counters.useful <= conf_watermark) {
                    shrink_buffer();
                    filling = fill_buffer();
                }
            }
        }
    }
}
Exemplo n.º 14
0
/* Voice thread message processing */
static void voice_message(struct voice_thread_data *td)
{
    while (1)
    {
        switch (td->ev.id)
        {
        case Q_VOICE_PLAY:
            LOGFQUEUE("voice < Q_VOICE_PLAY");
            /* Put up a block for completion signal */
            voice_done = false;

            /* Copy the clip info */
            td->vi = *(struct voice_info *)td->ev.data;

            /* Be sure audio buffer is initialized */
            audio_restore_playback(AUDIO_WANT_VOICE);

            /* We need nothing more from the sending thread - let it run */
            queue_reply(&voice_queue, 1);

            if (td->state == TSTATE_STOPPED)
            {
                /* Boost CPU now */
                trigger_cpu_boost();
            }
            else if (!playback_is_playing())
            {
                /* Just voice, stop any clip still playing */
                pcmbuf_play_stop();
            }

            /* Clean-start the decoder */
            td->st = speex_decoder_init(&speex_wb_mode);

            /* Make bit buffer use our own buffer */
            speex_bits_set_bit_buffer(&td->bits, td->vi.start, td->vi.size);
            speex_decoder_ctl(td->st, SPEEX_GET_LOOKAHEAD, &td->lookahead);

            td->state = TSTATE_DECODE;
            return;

        case Q_VOICE_STOP:
            LOGFQUEUE("voice < Q_VOICE_STOP: %ld", td->ev.data);

            if (td->ev.data != 0 && !playback_is_playing())
            {
                /* If not playing, it's just voice so stop pcm playback */
                pcmbuf_play_stop();
            }

            /* Cancel boost */
            cancel_cpu_boost();

            td->state = TSTATE_STOPPED;
            voice_done = true;
            break;

        case Q_VOICE_STATE:
            LOGFQUEUE("voice < Q_VOICE_STATE");
            queue_reply(&voice_queue, td->state);

            if (td->state == TSTATE_STOPPED)
                break; /* Not in a playback state */

            return;

        default:
            /* Default messages get a reply and thread continues with no
             * state transition */
            LOGFQUEUE("voice < default");

            if (td->state == TSTATE_STOPPED)
                break;  /* Not in playback state */

            queue_reply(&voice_queue, 0);
            return;
        }

        queue_wait(&voice_queue, &td->ev);
    }
}