}
void activity_monitor_signify_activity(int active) {
- pthread_mutex_lock(&activity_monitor_mutex);
+ // this could be pthread_cancelled and they is likely to be cancellation points in the
+ // hooked-on procedures
+ pthread_cleanup_debug_mutex_lock(&activity_monitor_mutex, 10000, 1);
player_state = active == 0 ? ps_inactive : ps_active;
// Now, although we could simply let the state machine in the activity monitor thread
// look after eveything, we will change state here in two situations:
//
// The reason for all this is that we might want to perform the attached scripts
// and wait for them to complete before continuing. If they were perfomed in the
- // activity monitor thread, then we coldn't wait for them to complete.
+ // activity monitor thread, then we couldn't wait for them to complete.
// Thus, the only time the thread will execute a going_... function is when a non-zero
// timeout actually matures.
}
pthread_cond_signal(&activity_monitor_cv);
- pthread_mutex_unlock(&activity_monitor_mutex);
+ pthread_cleanup_pop(1); // release the mutex
}
void activity_thread_cleanup_handler(__attribute__((unused)) void *arg) {
snd_strerror(ret));
return ret;
}
- snd_pcm_format_t sf;
- switch (sample_format) {
- case SPS_FORMAT_S8:
- sf = SND_PCM_FORMAT_S8;
- frame_size = 2;
- break;
- case SPS_FORMAT_U8:
- sf = SND_PCM_FORMAT_U8;
- frame_size = 2;
- break;
- case SPS_FORMAT_S16:
- sf = SND_PCM_FORMAT_S16;
- frame_size = 4;
- break;
- case SPS_FORMAT_S24:
- sf = SND_PCM_FORMAT_S24;
- frame_size = 8;
- break;
- case SPS_FORMAT_S24_3LE:
- sf = SND_PCM_FORMAT_S24_3LE;
- frame_size = 6;
- break;
- case SPS_FORMAT_S24_3BE:
- sf = SND_PCM_FORMAT_S24_3BE;
- frame_size = 6;
- break;
- case SPS_FORMAT_S32:
- sf = SND_PCM_FORMAT_S32;
- frame_size = 8;
- break;
- default:
- sf = SND_PCM_FORMAT_S16; // this is just to quieten a compiler warning
- frame_size = 4;
- debug(1, "Unsupported output format at audio_alsa.c");
- return -EINVAL;
- }
- ret = snd_pcm_hw_params_set_format(alsa_handle, alsa_params, sf);
- if (ret < 0) {
- warn("audio_alsa: Sample format %d not available for device \"%s\": %s", sample_format,
- alsa_out_dev, snd_strerror(ret));
- return ret;
- }
+
ret = snd_pcm_hw_params_set_channels(alsa_handle, alsa_params, 2);
if (ret < 0) {
snd_strerror(ret));
return ret;
}
+
+
+ if (sample_format == SPS_FORMAT_AUTO) {
+
+ struct alsa_formats {
+ snd_pcm_format_t alsa_sound_format;
+ enum sps_format_t sps_sound_format;
+ int frame_size;
+ char * description;
+ };
+
+ struct alsa_formats formats[] = {{SND_PCM_FORMAT_S32,SPS_FORMAT_S32,8,"S32"},
+ {SND_PCM_FORMAT_S24,SPS_FORMAT_S24,8,"S24"},
+ {SND_PCM_FORMAT_S24_3LE,SPS_FORMAT_S24_3LE,6,"S24_LE"},
+ {SND_PCM_FORMAT_S24_3BE,SPS_FORMAT_S24_3BE,6,"S24_BE"},
+ {SND_PCM_FORMAT_S16,SPS_FORMAT_S16,4,"S16"}};
+
+ int acceptable_format_found = 0;
+ unsigned int i = 0;
+ while((!acceptable_format_found) && (i < sizeof(formats) / sizeof(formats[0]))) {
+ if (snd_pcm_hw_params_set_format(alsa_handle, alsa_params, formats[i].alsa_sound_format) == 0) {
+ acceptable_format_found = 1;
+ frame_size = formats[i].frame_size;
+ config.output_format = formats[i].sps_sound_format;
+ debug(1,"alsa: output format automatically chosen to be \"%s\".",formats[i].description);
+ } else {
+ i++;
+ }
+ }
+ if (!acceptable_format_found) {
+ die("Can't find a suitable automatic output format setting.");
+ }
+ } else {
+ snd_pcm_format_t sf;
+ switch (sample_format) {
+ case SPS_FORMAT_S8:
+ sf = SND_PCM_FORMAT_S8;
+ frame_size = 2;
+ break;
+ case SPS_FORMAT_U8:
+ sf = SND_PCM_FORMAT_U8;
+ frame_size = 2;
+ break;
+ case SPS_FORMAT_S16:
+ sf = SND_PCM_FORMAT_S16;
+ frame_size = 4;
+ break;
+ case SPS_FORMAT_S24:
+ sf = SND_PCM_FORMAT_S24;
+ frame_size = 8;
+ break;
+ case SPS_FORMAT_S24_3LE:
+ sf = SND_PCM_FORMAT_S24_3LE;
+ frame_size = 6;
+ break;
+ case SPS_FORMAT_S24_3BE:
+ sf = SND_PCM_FORMAT_S24_3BE;
+ frame_size = 6;
+ break;
+ case SPS_FORMAT_S32:
+ sf = SND_PCM_FORMAT_S32;
+ frame_size = 8;
+ break;
+ default:
+ sf = SND_PCM_FORMAT_S16; // this is just to quieten a compiler warning
+ frame_size = 4;
+ debug(1, "Unsupported output format at audio_alsa.c");
+ return -EINVAL;
+ }
+
+ ret = snd_pcm_hw_params_set_format(alsa_handle, alsa_params, sf);
+ if (ret < 0) {
+ warn("audio_alsa: Sample format %d not available for device \"%s\": %s", sample_format,
+ alsa_out_dev, snd_strerror(ret));
+ return ret;
+ }
+ }
if (set_period_size_request != 0) {
debug(1, "Attempting to set the period size");
config.output_format = SPS_FORMAT_U8;
else if (strcasecmp(str, "S8") == 0)
config.output_format = SPS_FORMAT_S8;
+ else if (strcasecmp(str, "AUTOMATIC") == 0)
+ config.output_format = SPS_FORMAT_AUTO;
else {
- warn("Invalid output format \"%s\". It should be \"U8\", \"S8\", "
+ warn("Invalid output format \"%s\". It should be \"Automatic\", \"U8\", \"S8\", "
"\"S16\", \"S24\", "
"\"S24_3LE\", \"S24_3BE\" or "
"\"S32\". It is set to \"S16\".",
static struct sndio_formats formats[] = {{"S8", SPS_FORMAT_S8, 8, 1, 1, SIO_LE_NATIVE},
{"U8", SPS_FORMAT_U8, 8, 1, 0, SIO_LE_NATIVE},
{"S16", SPS_FORMAT_S16, 16, 2, 1, SIO_LE_NATIVE},
+ {"AUTOMATIC", SPS_FORMAT_S16, 16, 2, 1, SIO_LE_NATIVE}, // TODO: make this really automatic?
{"S24", SPS_FORMAT_S24, 24, 4, 1, SIO_LE_NATIVE},
{"S24_3LE", SPS_FORMAT_S24_3LE, 24, 3, 1, 1},
{"S24_3BE", SPS_FORMAT_S24_3BE, 24, 3, 1, 0},
}
if (!found)
die("Invalid output format \"%s\". Should be one of: S8, U8, S16, S24, "
- "S24_3LE, S24_3BE, S32",
+ "S24_3LE, S24_3BE, S32, Automatic",
tmp);
}
}
break;
case SPS_FORMAT_UNKNOWN:
die("Unexpected SPS_FORMAT_UNKNOWN while calculating dither mask.");
+ break;
+ case SPS_FORMAT_AUTO:
+ die("Unexpected SPS_FORMAT_AUTO while calculating dither mask.");
}
dither_mask -= 1;
// int64_t r = r64i();
SPS_FORMAT_S24_3LE,
SPS_FORMAT_S24_3BE,
SPS_FORMAT_S32,
+ SPS_FORMAT_AUTO,
} sps_format_t;
typedef struct {
break;
case SPS_FORMAT_UNKNOWN:
die("Unexpected SPS_FORMAT_UNKNOWN while calculating dither mask.");
+ break;
+ case SPS_FORMAT_AUTO:
+ die("Unexpected SPS_FORMAT_AUTO while calculating dither mask.");
+ break;
}
dither_mask -= 1;
// int64_t r = r64i();
break;
case SPS_FORMAT_UNKNOWN:
die("Unexpected SPS_FORMAT_UNKNOWN while outputting samples");
+ break;
+ case SPS_FORMAT_AUTO:
+ die("Unexpected SPS_FORMAT_AUTO while outputting samples");
+ break;
}
*outp += result;
break;
case SPS_FORMAT_UNKNOWN:
die("Unknown format choosing output bit depth");
+ break;
+ case SPS_FORMAT_AUTO:
+ die("Unexpected SPS_FORMAT_AUTO while outputting samples");
+ break;
}
debug(3, "Output bit depth is %d.", output_bit_depth);
int rc;
if (the_queue) {
if (block == 0) {
- rc = pthread_mutex_trylock(&the_queue->pc_queue_lock);
+ rc = debug_mutex_lock(&the_queue->pc_queue_lock, 10000, 2);
if (rc == EBUSY)
return EBUSY;
} else
}
if (have_the_player) {
- debug(3, "RTSP conversation thread %d has acquired play lock.", conn->connection_number);
+ debug(3, "Connection %d: ANNOUNCE has acquired play lock.", conn->connection_number);
// now, if this new session did not break in, then it's okay to reset the next UDP ports
// to the start of the range
resp->respcode = 200;
} else {
resp->respcode = 453;
- debug(1, "Connection %d: DACP-ID \"%s\" on %s failed because a connection is already playing.",
- conn->connection_number,
- conn->dacp_id,
- conn->client_ip_string);
+ debug(1, "Connection %d: ANNOUNCE failed because another connection is already playing.",
+ conn->connection_number);
}
out:
debug(1, "use_mmap_if_available is %d.", config.no_mmap ? 0 : 1);
debug(1, "output_rate is %d.", config.output_rate);
debug(1,
- "output_format is %d (0-unknown, 1-S8, 2-U8, 3-S16, 4-S24, 5-S24_3LE, 6-S24_3BE, 7-S32).",
+ "output_format is %d (0-unknown, 1-S8, 2-U8, 3-S16, 4-S24, 5-S24_3LE, 6-S24_3BE, 7-S32, 8-Automatic).",
config.output_format);
debug(1, "audio backend desired buffer length is %f seconds.",
config.audio_backend_buffer_desired_length);