static char *alsa_out_dev = "default";
static char *alsa_mix_dev = NULL;
-static char *alsa_mix_ctrl = "Master";
+static char *alsa_mix_ctrl = NULL;
static int alsa_mix_index = 0;
-static int hardware_mixer = 0;
static int has_softvol = 0;
int64_t dither_random_number_store = 0;
} else {
pthread_cleanup_push(malloc_cleanup, silence);
int use_dither = 0;
- if ((hardware_mixer == 0) && (config.ignore_volume_control == 0) &&
+ if ((alsa_mix_ctrl == NULL) && (config.ignore_volume_control == 0) &&
(config.airplay_volume != 0.0))
use_dither = 1;
dither_random_number_store =
// assuming pthread cancellation is disabled
int open_mixer() {
int response = 0;
- if (hardware_mixer) {
+ if (alsa_mix_ctrl != NULL) {
debug(3, "Open Mixer");
int ret = 0;
snd_mixer_selem_id_alloca(&alsa_mix_sid);
return result;
}
-int do_alsa_device_init_if_needed() {
+int prepare_mixer() {
int response = 0;
- // do any alsa device initialisation (general case) if needed
+ // do any alsa device initialisation (general case)
// at present, this is only needed if a hardware mixer is being used
- // if there's a hardware mixer, it needs to be initialised before first use
- if (alsa_device_initialised == 0) {
- alsa_device_initialised = 1;
- if (hardware_mixer) {
- debug(2, "alsa: hardware mixer init");
+ // if there's a hardware mixer, it needs to be initialised before use
+ if (alsa_mix_ctrl == NULL) {
+ audio_alsa.volume = NULL;
+ audio_alsa.parameters = NULL;
+ audio_alsa.mute = NULL;
+ } else {
+ debug(2, "alsa: hardware mixer prepare");
int oldState;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); // make this un-cancellable
pthread_cleanup_pop(0);
pthread_setcancelstate(oldState, NULL);
}
- }
return response;
}
+int alsa_device_init() {
+ return prepare_mixer();
+}
+
+
static int init(int argc, char **argv) {
// for debugging
snd_output_stdio_attach(&output, stdout, 0);
/* Get the Mixer Control Name. */
if (config_lookup_string(config.cfg, "alsa.mixer_control_name", &str)) {
alsa_mix_ctrl = (char *)str;
- hardware_mixer = 1;
}
/* Get the disable_synchronization setting. */
break;
case 'c':
alsa_mix_ctrl = optarg;
- hardware_mixer = 1;
break;
case 'i':
alsa_mix_index = strtol(optarg, NULL, 10);
stall_monitor_start_time = 0;
stall_monitor_frame_count = 0;
if (alsa_device_initialised == 0) {
- debug(2, "alsa: start() calling do_alsa_device_init_if_needed.");
- do_alsa_device_init_if_needed();
+ debug(1, "alsa: start() calling alsa_device_init.");
+ alsa_device_init();
+ alsa_device_initialised = 1;
}
}
pthread_cleanup_debug_mutex_lock(&alsa_mutex, 50000, 0);
if (alsa_backend_state == abm_disconnected) {
+ if (alsa_device_initialised == 0) {
+ debug(1, "alsa: prepare() calling alsa_device_init.");
+ alsa_device_init();
+ alsa_device_initialised = 1;
+ }
ret = do_open(1); // do auto setup
if (ret == 0)
debug(2, "alsa: prepare() -- opened output device");
static void linear_volume(double vol) {
debug(2, "Setting linear volume to %f.", vol);
set_volume = vol;
- if (hardware_mixer && alsa_mix_handle) {
+ if ((alsa_mix_ctrl == NULL) && alsa_mix_handle) {
double linear_volume = pow(10, vol);
// debug(1,"Linear volume is %f.",linear_volume);
long int_vol = alsa_mix_minv + (alsa_mix_maxv - alsa_mix_minv) *
}
if ((config.keep_dac_busy != 0) && (alsa_device_initialised == 0)) {
debug(2, "alsa: alsa_buffer_monitor_thread_code() calling "
- "do_alsa_device_init_if_needed.");
- do_alsa_device_init_if_needed();
+ "alsa_device_init.");
+ alsa_device_init();
+ alsa_device_initialised = 1;
}
int sleep_time_ms = (int)(config.disable_standby_mode_silence_scan_interval * 1000);
pthread_cleanup_debug_mutex_lock(&alsa_mutex, 200000, 0);
int ret;
pthread_cleanup_push(malloc_cleanup, silence);
int use_dither = 0;
- if ((hardware_mixer == 0) && (config.ignore_volume_control == 0) &&
+ if ((alsa_mix_ctrl == NULL) && (config.ignore_volume_control == 0) &&
(config.airplay_volume != 0.0))
use_dither = 1;
dither_random_number_store =
void player_volume_without_notification(double airplay_volume, rtsp_conn_info *conn) {
debug_mutex_lock(&conn->volume_control_mutex, 5000, 1);
- debug(2, "player_volume_without_notification %f", airplay_volume);
// first, see if we are hw only, sw only, both with hw attenuation on the top or both with sw
// attenuation on top
int32_t hw_max_db = 0, hw_min_db = 0; // zeroed to quieten an incorrect uninitialised warning
int32_t sw_max_db = 0, sw_min_db = -9630;
+
if (config.output->parameters) {
volume_mode = vol_hw_only;
audio_parameters audio_information;
char *dv = malloc(128); // will be freed in the metadata thread
if (dv) {
memset(dv, 0, 128);
- snprintf(dv, 127, "%.2f,%.2f,%.2f,%.2f", airplay_volume, scaled_attenuation / 100.0,
+ if (volume_mode == vol_both) {
+ // normalise the maximum output to the hardware device's max output
+ snprintf(dv, 127, "%.2f,%.2f,%.2f,%.2f", airplay_volume, (scaled_attenuation - max_db + hw_max_db) / 100.0,
+ (min_db - max_db + hw_max_db) / 100.0, (max_db - max_db + hw_max_db) / 100.0);
+ } else {
+ snprintf(dv, 127, "%.2f,%.2f,%.2f,%.2f", airplay_volume, scaled_attenuation / 100.0,
min_db / 100.0, max_db / 100.0);
+ }
send_ssnc_metadata('pvol', dv, strlen(dv), 1);
}
#endif
#ifdef CONFIG_METADATA
else {
// here, send the 'pvol' metadata message when the airplay volume information
- // is not being used by shairport sync to control the output volume
+ // is being used by shairport sync to control the output volume
char *dv = malloc(128); // will be freed in the metadata thread
if (dv) {
memset(dv, 0, 128);