char *device;
};
-#include "volume.h"
+#include "audio_output/volume.h"
#define A52_FRAME_NB 1536
}
#define DumpDeviceStatus(o, p) DumpDeviceStatus(VLC_OBJECT(o), p)
-static unsigned SetupChannelsUnknown (vlc_object_t *obj,
- uint16_t *restrict mask)
-{
- uint16_t map = var_InheritInteger (obj, "alsa-audio-channels");
- uint16_t chans = *mask & map;
-
- if (unlikely(chans == 0)) /* WTH? */
- chans = AOUT_CHANS_STEREO;
-
- if (popcount (chans) < popcount (*mask))
- msg_Dbg (obj, "downmixing from %u to %u channels",
- popcount (*mask), popcount (chans));
- else
- msg_Dbg (obj, "keeping %u channels", popcount (chans));
- *mask = chans;
- return 0;
-}
-
#if (SND_LIB_VERSION >= 0x01001B)
static const uint16_t vlc_chans[] = {
[SND_CHMAP_MONO] = AOUT_CHAN_CENTER,
* Negotiate channels mapping.
*/
static unsigned SetupChannels (vlc_object_t *obj, snd_pcm_t *pcm,
- uint16_t *restrict mask, uint8_t *restrict tab)
+ uint16_t *restrict mask, uint8_t *restrict tab)
{
snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps (pcm);
if (maps == NULL)
- { /* Fallback to manual configuration */
+ { /* Fallback to default order if unknown */
msg_Dbg(obj, "channels map not provided");
- return SetupChannelsUnknown (obj, mask);
+ return 0;
}
/* Find most appropriate available channels map */
- unsigned best_offset;
- unsigned best_score = 0;
+ unsigned best_offset, best_score = 0, to_reorder = 0;
for (snd_pcm_chmap_query_t *const *p = maps; *p != NULL; p++)
{
if (chans == -1)
continue;
- unsigned score = popcount (chans & *mask);
+ unsigned score = (popcount (chans & *mask) << 8)
+ | (255 - popcount (chans));
if (score > best_score)
{
best_offset = p - maps;
if (best_score == 0)
{
msg_Err (obj, "cannot find supported channels map");
- snd_pcm_free_chmaps (maps);
- return SetupChannelsUnknown (obj, mask);
+ goto out;
}
const snd_pcm_chmap_t *map = &maps[best_offset]->map;
msg_Dbg (obj, "using channels map %u, type %u, %u channel(s)", best_offset,
- maps[best_offset]->type, best_score);
+ maps[best_offset]->type, map->channels);
/* Setup channels map */
- unsigned to_reorder = SetupChannelsFixed(map, mask, tab);
+ to_reorder = SetupChannelsFixed(map, mask, tab);
/* TODO: avoid reordering for PAIRED and VAR types */
//snd_pcm_set_chmap (pcm, ...)
-
+out:
snd_pcm_free_chmaps (maps);
return to_reorder;
}
#else /* (SND_LIB_VERSION < 0x01001B) */
-# define SetupChannels(obj, pcm, mask, tab) \
- SetupChannelsUnknown(obj, mask)
+# define SetupChannels(obj, pcm, mask, tab) (0)
#endif
static int TimeGet (audio_output_t *aout, mtime_t *);
}
const char *device = sys->device;
- char *devbuf = NULL;
+
/* Choose the IEC device for S/PDIF output */
- if (spdif && !strcmp (device, "default"))
+ char sep = '\0';
+ if (spdif)
+ {
+ const char *opt;
+
+ if (!strcmp (device, "default"))
+ device = "iec958"; /* TODO: hdmi */
+
+ if (!strncmp (device, "iec958", 6))
+ opt = device + 6;
+ if (!strncmp (device, "hdmi", 4))
+ opt = device + 4;
+
+ if (opt != NULL)
+ switch (*opt)
+ {
+ case ':': sep = ','; break;
+ case '\0': sep = ':'; break;
+ }
+ }
+
+ char *devbuf = NULL;
+ if (sep != '\0')
{
unsigned aes3;
break;
}
- if (asprintf (&devbuf,
- "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
+ if (asprintf (&devbuf, "%s%cAES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x",
+ device, sep,
IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO,
IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER,
0, aes3) == -1)
const int mode = SND_PCM_NO_AUTO_RESAMPLE;
int val = snd_pcm_open (&pcm, device, SND_PCM_STREAM_PLAYBACK, mode);
- free (devbuf);
if (val != 0)
{
- msg_Err (aout, "cannot open ALSA device \"%s\": %s", sys->device,
+ msg_Err (aout, "cannot open ALSA device \"%s\": %s", device,
snd_strerror (val));
dialog_Fatal (aout, _("Audio output failed"),
_("The audio device \"%s\" could not be used:\n%s."),
sys->device, snd_strerror (val));
+ free (devbuf);
return VLC_EGENERIC;
}
sys->pcm = pcm;
/* Print some potentially useful debug */
- msg_Dbg (aout, "using ALSA device: %s", sys->device);
+ msg_Dbg (aout, "using ALSA device: %s", device);
+ free (devbuf);
DumpDevice (VLC_OBJECT(aout), pcm);
/* Get Initial hardware parameters */
unsigned channels;
if (!spdif)
{
- sys->chans_to_reorder = SetupChannels (VLC_OBJECT(aout), pcm,
- &fmt->i_physical_channels, sys->chans_table);
- channels = popcount (fmt->i_physical_channels);
+ uint16_t map = var_InheritInteger (aout, "alsa-audio-channels");
+
+ sys->chans_to_reorder = SetupChannels (VLC_OBJECT(aout), pcm, &map,
+ sys->chans_table);
+ fmt->i_physical_channels = map;
+ fmt->i_original_channels = map;
+ channels = popcount (map);
}
else
{
sys->chans_to_reorder = 0;
channels = 2;
}
- fmt->i_original_channels = fmt->i_physical_channels;
/* By default, ALSA plug will pad missing channels with zeroes, which is
* usually fine. However, it will also discard extraneous channels, which
msg_Err (aout, "cannot set buffer duration: %s", snd_strerror (val));
goto error;
}
-#if 0
- val = snd_pcm_hw_params_get_buffer_time (hw, ¶m, NULL);
- if (val)
- {
- msg_Warn (aout, "cannot get buffer time: %s", snd_strerror(val));
- param = AOUT_MIN_PREPARE_TIME;
- }
- else
- param /= 2;
-#else /* work-around for period-long latency outputs (e.g. PulseAudio): */
+
param = AOUT_MIN_PREPARE_TIME;
-#endif
val = snd_pcm_hw_params_set_period_time_near (pcm, hw, ¶m, NULL);
if (val)
{