rockbox/apps/audio_path.c
Amaury Pouly 1245c5fe61 Implement speaker enable/disable on jack (un)plug
The implementation is not very complicated but there are a few things worth
noting. There was a previous "speaker enable" setting but it was a boolean.
I decided to replace it with a choice setting that has 2 options (on, off)
if headphones cannot be detect on this target, or 3 options (on, off, auto)
if we can detect headphones. This will break the old setting on target that
cannot detect jack but it makes the code more uniform and avoid maintaining
two settings with more #ifdef. The third option (auto) uses the LANG_AUTO
text, which I think is clear enough (disable speaker on jack plug).
In order to avoid code duplication (both in apps and firmware), I decided to
keep the audiohw_enable_speaker function as-is: it takes a boolean and doesn't
care about the speaker policy. I introduced a new audio_enable_speaker that
takes directly the mode (which follows the setting encoding): 0=off, 1=on
and 2=auto. This way one calls audio_enable_speaker and it changes the speaker
once to reflect the request mode. The apps code then uses this function in the
places where it makes sense: on setting load, setting change and jack (un)plug
event.

Change-Id: I027873f698eb4bc365d7c02b515297806355d9e2
2017-02-04 17:22:08 +01:00

179 lines
5 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Audio signal path management APIs
*
* Copyright (C) 2007 by Michael Sevakis
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "system.h"
#include "cpu.h"
#include "audio.h"
#include "general.h"
#include "settings.h"
#if defined(HAVE_SPDIF_IN) || defined(HAVE_SPDIF_OUT)
#ifdef HAVE_SPDIF_POWER
#include "power.h"
#endif
#include "spdif.h"
#endif
#if CONFIG_TUNER
#include "radio.h"
#endif
#if defined(IPOD_ACCESSORY_PROTOCOL) && defined(HAVE_LINE_REC)
#include "iap.h"
#endif
/* Some audio sources may require a boosted CPU */
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
#ifdef HAVE_SPDIF_REC
#define AUDIO_CPU_BOOST
#endif
#endif
#if ((CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1))
#ifdef AUDIO_CPU_BOOST
static void audio_cpu_boost(bool state)
{
static bool cpu_boosted = false;
if (state != cpu_boosted)
{
cpu_boost(state);
cpu_boosted = state;
}
} /* audio_cpu_boost */
#endif /* AUDIO_CPU_BOOST */
/**
* Selects an audio source for recording or playback
* powers/unpowers related devices and sets up monitoring.
*/
void audio_set_input_source(int source, unsigned flags)
{
/** Do power up/down of associated device(s) **/
/** SPDIF **/
#ifdef AUDIO_CPU_BOOST
/* Always boost for SPDIF */
audio_cpu_boost(source == AUDIO_SRC_SPDIF);
#endif /* AUDIO_CPU_BOOST */
#ifdef HAVE_SPDIF_POWER
/* Check if S/PDIF output power should be switched off or on. NOTE: assumes
both optical in and out is controlled by the same power source, which is
the case on H1x0. */
spdif_power_enable((source == AUDIO_SRC_SPDIF) ||
global_settings.spdif_enable);
#endif /* HAVE_SPDIF_POWER */
/* Set the appropriate feed for spdif output */
#ifdef HAVE_SPDIF_OUT
spdif_set_output_source(source
IF_SPDIF_POWER_(, global_settings.spdif_enable));
#endif /* HAVE_SPDIF_OUT */
/** Tuner **/
#if CONFIG_TUNER
/* Switch radio off or on per source and flags. */
if (source != AUDIO_SRC_FMRADIO)
radio_stop();
else if (flags & SRCF_FMRADIO_PAUSED)
radio_pause();
else
radio_start();
#endif
#if defined(IPOD_ACCESSORY_PROTOCOL) && defined(HAVE_LINE_REC)
static bool last_rec_onoff = false;
bool onoff = (source == AUDIO_SRC_LINEIN) ? true : false;
if (last_rec_onoff != onoff)
last_rec_onoff = iap_record(onoff);
#endif
/* set hardware inputs */
audio_input_mux(source, flags);
} /* audio_set_source */
#ifdef HAVE_SPDIF_IN
/**
* Return SPDIF sample rate index in audio_master_sampr_list. Since we base
* our reading on the actual SPDIF sample rate (which might be a bit
* inaccurate), we round off to the closest sample rate that is supported by
* SPDIF.
*/
int audio_get_spdif_sample_rate(void)
{
unsigned long measured_rate = spdif_measure_frequency();
/* Find which SPDIF sample rate we're closest to. */
return round_value_to_list32(measured_rate, audio_master_sampr_list,
SAMPR_NUM_FREQ, false);
} /* audio_get_spdif_sample_rate */
#endif /* HAVE_SPDIF_IN */
#else /* PLATFORM_HOSTED */
/** Sim stubs **/
#ifdef AUDIO_CPU_BOOST
static void audio_cpu_boost(bool state)
{
(void)state;
} /* audio_cpu_boost */
#endif /* AUDIO_CPU_BOOST */
void audio_set_output_source(int source)
{
(void)source;
} /* audio_set_output_source */
void audio_set_input_source(int source, unsigned flags)
{
(void)source;
(void)flags;
#if CONFIG_TUNER
/* Switch radio off or on per source and flags. */
if (source != AUDIO_SRC_FMRADIO)
radio_stop();
else if (flags & SRCF_FMRADIO_PAUSED)
radio_pause();
else
radio_start();
#endif
} /* audio_set_input_source */
#ifdef HAVE_SPDIF_IN
int audio_get_spdif_sample_rate(void)
{
return FREQ_44;
} /* audio_get_spdif_sample_rate */
#endif /* HAVE_SPDIF_IN */
#endif /* PLATFORM_NATIVE */
#ifdef HAVE_SPEAKER
void audio_enable_speaker(int mode)
{
#ifdef HAVE_HEADPHONE_DETECTION
/* if needed, query jack state */
if(mode == 2)
mode = !headphones_inserted();
#endif
/* treat any nonzero value as enable */
audiohw_enable_speaker(mode);
}
#endif