mirror of
https://github.com/mpv-player/mpv.git
synced 2025-12-28 05:33:14 +00:00
ao: rework audio output driver probing
Make the code a bit more uniform. Always build a "dummy" audio output list before probing, which means that opening preferred devices and pure auto-probing is done with the same code. We can drop the second ao_init() call. This also makes the next commit easier, which wants to selectively fallback to ao_null. This could have been implemented by passing a different requested audio output list (instead of reading it from MPOptions), but I think it's better if this rather special feature is handled internally in the AO code. This also makes sure the AO code can handle its own options (such as the audio output list) in a self-contained way.
This commit is contained in:
@@ -248,58 +248,62 @@ struct ao *ao_init_best(struct mpv_global *global,
|
||||
void *tmp = talloc_new(NULL);
|
||||
struct mp_log *log = mp_log_new(tmp, global->log, "ao");
|
||||
struct ao *ao = NULL;
|
||||
struct m_obj_settings *ao_list = opts->audio_driver_list;
|
||||
struct m_obj_settings *ao_list = NULL;
|
||||
int ao_num = 0;
|
||||
|
||||
for (int n = 0; opts->audio_driver_list && opts->audio_driver_list[n].name; n++)
|
||||
MP_TARRAY_APPEND(tmp, ao_list, ao_num, opts->audio_driver_list[n]);
|
||||
|
||||
bool forced_dev = false;
|
||||
char *pref_ao, *pref_dev;
|
||||
split_ao_device(tmp, opts->audio_device, &pref_ao, &pref_dev);
|
||||
if (!(ao_list && ao_list[0].name) && pref_ao) {
|
||||
if (!ao_num && pref_ao) {
|
||||
// Reuse the autoselection code
|
||||
ao_list = talloc_zero_array(tmp, struct m_obj_settings, 2);
|
||||
ao_list[0].name = pref_ao;
|
||||
MP_TARRAY_APPEND(tmp, ao_list, ao_num,
|
||||
(struct m_obj_settings){.name = pref_ao});
|
||||
forced_dev = true;
|
||||
}
|
||||
|
||||
if (ao_list && ao_list[0].name) {
|
||||
for (int n = 0; ao_list[n].name; n++) {
|
||||
if (strlen(ao_list[n].name) == 0)
|
||||
goto autoprobe;
|
||||
mp_verbose(log, "Trying preferred audio driver '%s'\n",
|
||||
ao_list[n].name);
|
||||
char *dev = NULL;
|
||||
if (pref_ao && strcmp(ao_list[n].name, pref_ao) == 0)
|
||||
dev = pref_dev;
|
||||
if (dev)
|
||||
mp_verbose(log, "Using preferred device '%s'\n", dev);
|
||||
ao = ao_init(false, global, input_ctx, encode_lavc_ctx,
|
||||
samplerate, format, channels, dev,
|
||||
ao_list[n].name, ao_list[n].attribs);
|
||||
if (ao)
|
||||
goto done;
|
||||
mp_err(log, "Failed to initialize audio driver '%s'\n",
|
||||
ao_list[n].name);
|
||||
if (forced_dev) {
|
||||
mp_err(log, "This audio driver/device was forced with the "
|
||||
"--audio-device option.\n"
|
||||
"Try unsetting it.\n");
|
||||
}
|
||||
bool autoprobe = ao_num == 0;
|
||||
|
||||
// Something like "--ao=a,b," means do autoprobing after a and b fail.
|
||||
if (ao_num && strlen(ao_list[ao_num - 1].name) == 0) {
|
||||
ao_num -= 1;
|
||||
autoprobe = true;
|
||||
}
|
||||
|
||||
if (autoprobe) {
|
||||
for (int n = 0; audio_out_drivers[n]; n++) {
|
||||
const struct ao_driver *driver = audio_out_drivers[n];
|
||||
if (driver == &audio_out_null)
|
||||
break;
|
||||
MP_TARRAY_APPEND(tmp, ao_list, ao_num,
|
||||
(struct m_obj_settings){.name = (char *)driver->name});
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
autoprobe: ;
|
||||
// now try the rest...
|
||||
for (int i = 0; audio_out_drivers[i]; i++) {
|
||||
const struct ao_driver *driver = audio_out_drivers[i];
|
||||
if (driver == &audio_out_null)
|
||||
break;
|
||||
ao = ao_init(true, global, input_ctx, encode_lavc_ctx, samplerate,
|
||||
format, channels, NULL, (char *)driver->name, NULL);
|
||||
for (int n = 0; n < ao_num; n++) {
|
||||
struct m_obj_settings *entry = &ao_list[n];
|
||||
bool probing = n + 1 != ao_num;
|
||||
mp_verbose(log, "Trying audio driver '%s'\n", entry->name);
|
||||
char *dev = NULL;
|
||||
if (pref_ao && pref_dev && strcmp(entry->name, pref_ao) == 0) {
|
||||
dev = pref_dev;
|
||||
mp_verbose(log, "Using preferred device '%s'\n", dev);
|
||||
}
|
||||
ao = ao_init(probing, global, input_ctx, encode_lavc_ctx,
|
||||
samplerate, format, channels, dev,
|
||||
entry->name, entry->attribs);
|
||||
if (ao)
|
||||
goto done;
|
||||
break;
|
||||
if (!probing)
|
||||
mp_err(log, "Failed to initialize audio driver '%s'\n", entry->name);
|
||||
if (dev && forced_dev) {
|
||||
mp_err(log, "This audio driver/device was forced with the "
|
||||
"--audio-device option.\nTry unsetting it.\n");
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
talloc_free(tmp);
|
||||
return ao;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user