Re: [Qemu-devel] [PATCH v4 04/14] audio: -audiodev command line option basic implementation

2019-02-07 Thread Zoltán Kővágó
On 2019-01-29 16:56, Markus Armbruster wrote:
> "Kővágó, Zoltán"  writes:
> 
>> Audio drivers now get an Audiodev * as config paramters, instead of the
>> global audio_option structs.  There is some code in audio/audio_legacy.c
>> that converts the old environment variables to audiodev options (this
>> way backends do not have to worry about legacy options).  It also
>> contains a replacement of -audio-help, which prints out the equivalent
>> -audiodev based config of the currently specified environment variables.
>>
>> Note that backends are not updated and still rely on environment
>> variables.
>>
>> Also note that (due to moving try-poll from global to backend specific
>> option) currently ALSA and OSS will always try poll mode, regardless of
>> environment variables or -audiodev options.
>>
>> Signed-off-by: Kővágó, Zoltán 
>> ---
> [...]
>> diff --git a/audio/audio.c b/audio/audio.c
>> index ce8e6ea8c2..b37c245a8a 100644
>> --- a/audio/audio.c
>> +++ b/audio/audio.c
> [...]
>> @@ -2129,3 +1866,145 @@ void AUD_set_volume_in (SWVoiceIn *sw, int mute, 
>> uint8_t lvol, uint8_t rvol)
>>  }
>>  }
>>  }
>> +
>> +static void audio_validate_per_direction_opts(
>> +AudiodevPerDirectionOptions **pdo, bool *has_pdo, Error **errp)
>> +{
>> +if (!*has_pdo) {
>> +*pdo = g_malloc0(sizeof(AudiodevPerDirectionOptions));
>> +*has_pdo = true;
>> +}
>> +
>> +if (!(*pdo)->has_fixed_settings) {
>> +(*pdo)->has_fixed_settings = true;
>> +(*pdo)->fixed_settings = true;
>> +}
>> +if (!(*pdo)->fixed_settings &&
>> +((*pdo)->has_frequency || (*pdo)->has_channels || 
>> (*pdo)->has_format)) {
>> +error_setg(errp,
>> +   "You can't use frequency, channels or format with 
>> fixed-settings=off");
>> +return;
>> +}
>> +
>> +if (!(*pdo)->has_frequency) {
>> +(*pdo)->has_frequency = true;
>> +(*pdo)->frequency = 44100;
>> +}
>> +if (!(*pdo)->has_channels) {
>> +(*pdo)->has_channels = true;
>> +(*pdo)->channels = 2;
>> +}
>> +if (!(*pdo)->has_voices) {
>> +(*pdo)->has_voices = true;
>> +(*pdo)->voices = 1;
>> +}
>> +if (!(*pdo)->has_format) {
>> +(*pdo)->has_format = true;
>> +(*pdo)->format = AUDIO_FORMAT_S16;
>> +}
>> +}
>> +
>> +static void audio_validate_opts(Audiodev *dev, Error **errp)
>> +{
>> +Error *err = NULL;
>> +
>> +audio_validate_per_direction_opts(>in, >has_in, );
>> +if (err) {
>> +error_propagate(errp, err);
>> +return;
>> +}
>> +
>> +audio_validate_per_direction_opts(>out, >has_out, );
>> +if (err) {
>> +error_propagate(errp, err);
>> +return;
>> +}
>> +
>> +if (!dev->has_timer_period) {
>> +dev->has_timer_period = true;
>> +dev->timer_period = 1; /* 100Hz -> 10ms */
>> +}
>> +}
> 
> Drive-by question: this validates just the generic part of Audiodev gets
> validated, not the driver-specific part.  Is there nothing to validate?
> Does it happen somewhere else?

Driver specific validation/initialization happens in each driver's init
function (they're added in the upcoming patches).

>> +
>> +void audio_parse_option(const char *opt)
>> +{
>> +AudiodevListEntry *e;
>> +Audiodev *dev = NULL;
>> +
>> +Visitor *v = qobject_input_visitor_new_str(opt, "driver", _fatal);
>> +visit_type_Audiodev(v, NULL, , _fatal);
>> +visit_free(v);
>> +
>> +audio_validate_opts(dev, _fatal);
>> +
>> +e = g_malloc0(sizeof(AudiodevListEntry));
>> +e->dev = dev;
>> +QSIMPLEQ_INSERT_TAIL(, e, next);
>> +}
>> +
>> +void audio_init_audiodevs(void)
>> +{
>> +AudiodevListEntry *e;
>> +
>> +QSIMPLEQ_FOREACH(e, , next) {
>> +audio_init(e->dev);
>> +}
>> +}
> 
> Your use of QAPI here looks good to me.
> 
> [...]
> 




Re: [Qemu-devel] [PATCH v4 04/14] audio: -audiodev command line option basic implementation

2019-01-29 Thread Markus Armbruster
"Kővágó, Zoltán"  writes:

> Audio drivers now get an Audiodev * as config paramters, instead of the
> global audio_option structs.  There is some code in audio/audio_legacy.c
> that converts the old environment variables to audiodev options (this
> way backends do not have to worry about legacy options).  It also
> contains a replacement of -audio-help, which prints out the equivalent
> -audiodev based config of the currently specified environment variables.
>
> Note that backends are not updated and still rely on environment
> variables.
>
> Also note that (due to moving try-poll from global to backend specific
> option) currently ALSA and OSS will always try poll mode, regardless of
> environment variables or -audiodev options.
>
> Signed-off-by: Kővágó, Zoltán 
> ---
[...]
> diff --git a/audio/audio.c b/audio/audio.c
> index ce8e6ea8c2..b37c245a8a 100644
> --- a/audio/audio.c
> +++ b/audio/audio.c
[...]
> @@ -2129,3 +1866,145 @@ void AUD_set_volume_in (SWVoiceIn *sw, int mute, 
> uint8_t lvol, uint8_t rvol)
>  }
>  }
>  }
> +
> +static void audio_validate_per_direction_opts(
> +AudiodevPerDirectionOptions **pdo, bool *has_pdo, Error **errp)
> +{
> +if (!*has_pdo) {
> +*pdo = g_malloc0(sizeof(AudiodevPerDirectionOptions));
> +*has_pdo = true;
> +}
> +
> +if (!(*pdo)->has_fixed_settings) {
> +(*pdo)->has_fixed_settings = true;
> +(*pdo)->fixed_settings = true;
> +}
> +if (!(*pdo)->fixed_settings &&
> +((*pdo)->has_frequency || (*pdo)->has_channels || 
> (*pdo)->has_format)) {
> +error_setg(errp,
> +   "You can't use frequency, channels or format with 
> fixed-settings=off");
> +return;
> +}
> +
> +if (!(*pdo)->has_frequency) {
> +(*pdo)->has_frequency = true;
> +(*pdo)->frequency = 44100;
> +}
> +if (!(*pdo)->has_channels) {
> +(*pdo)->has_channels = true;
> +(*pdo)->channels = 2;
> +}
> +if (!(*pdo)->has_voices) {
> +(*pdo)->has_voices = true;
> +(*pdo)->voices = 1;
> +}
> +if (!(*pdo)->has_format) {
> +(*pdo)->has_format = true;
> +(*pdo)->format = AUDIO_FORMAT_S16;
> +}
> +}
> +
> +static void audio_validate_opts(Audiodev *dev, Error **errp)
> +{
> +Error *err = NULL;
> +
> +audio_validate_per_direction_opts(>in, >has_in, );
> +if (err) {
> +error_propagate(errp, err);
> +return;
> +}
> +
> +audio_validate_per_direction_opts(>out, >has_out, );
> +if (err) {
> +error_propagate(errp, err);
> +return;
> +}
> +
> +if (!dev->has_timer_period) {
> +dev->has_timer_period = true;
> +dev->timer_period = 1; /* 100Hz -> 10ms */
> +}
> +}

Drive-by question: this validates just the generic part of Audiodev gets
validated, not the driver-specific part.  Is there nothing to validate?
Does it happen somewhere else?

> +
> +void audio_parse_option(const char *opt)
> +{
> +AudiodevListEntry *e;
> +Audiodev *dev = NULL;
> +
> +Visitor *v = qobject_input_visitor_new_str(opt, "driver", _fatal);
> +visit_type_Audiodev(v, NULL, , _fatal);
> +visit_free(v);
> +
> +audio_validate_opts(dev, _fatal);
> +
> +e = g_malloc0(sizeof(AudiodevListEntry));
> +e->dev = dev;
> +QSIMPLEQ_INSERT_TAIL(, e, next);
> +}
> +
> +void audio_init_audiodevs(void)
> +{
> +AudiodevListEntry *e;
> +
> +QSIMPLEQ_FOREACH(e, , next) {
> +audio_init(e->dev);
> +}
> +}

Your use of QAPI here looks good to me.

[...]



[Qemu-devel] [PATCH v4 04/14] audio: -audiodev command line option basic implementation

2019-01-28 Thread Kővágó, Zoltán
Audio drivers now get an Audiodev * as config paramters, instead of the
global audio_option structs.  There is some code in audio/audio_legacy.c
that converts the old environment variables to audiodev options (this
way backends do not have to worry about legacy options).  It also
contains a replacement of -audio-help, which prints out the equivalent
-audiodev based config of the currently specified environment variables.

Note that backends are not updated and still rely on environment
variables.

Also note that (due to moving try-poll from global to backend specific
option) currently ALSA and OSS will always try poll mode, regardless of
environment variables or -audiodev options.

Signed-off-by: Kővágó, Zoltán 
---

Notes:
Changes from v2:

* MAJOR: use qobject_input_visitor instead of QemuOpts
* almost completely rewrote legacy options handling
* added missing license comment to audio_legacy.c0

 audio/audio.h  |  18 +-
 audio/audio_int.h  |  16 +-
 audio/audio_template.h |  13 +-
 audio/alsaaudio.c  |   2 +-
 audio/audio.c  | 601 -
 audio/audio_legacy.c   | 295 
 audio/coreaudio.c  |   2 +-
 audio/dsoundaudio.c|   2 +-
 audio/noaudio.c|   2 +-
 audio/ossaudio.c   |   2 +-
 audio/paaudio.c|   2 +-
 audio/sdlaudio.c   |   2 +-
 audio/spiceaudio.c |   2 +-
 audio/wavaudio.c   |   2 +-
 vl.c   |   7 +-
 audio/Makefile.objs|   2 +-
 16 files changed, 590 insertions(+), 380 deletions(-)
 create mode 100644 audio/audio_legacy.c

diff --git a/audio/audio.h b/audio/audio.h
index 02f29a3b3e..64b0f761bc 100644
--- a/audio/audio.h
+++ b/audio/audio.h
@@ -36,12 +36,21 @@ typedef void (*audio_callback_fn) (void *opaque, int avail);
 #define AUDIO_HOST_ENDIANNESS 0
 #endif
 
-struct audsettings {
+typedef struct audsettings {
 int freq;
 int nchannels;
 AudioFormat fmt;
 int endianness;
-};
+} audsettings;
+
+audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo);
+int audioformat_bytes_per_sample(AudioFormat fmt);
+int audio_buffer_frames(AudiodevPerDirectionOptions *pdo,
+audsettings *as, int def_usecs);
+int audio_buffer_samples(AudiodevPerDirectionOptions *pdo,
+ audsettings *as, int def_usecs);
+int audio_buffer_bytes(AudiodevPerDirectionOptions *pdo,
+   audsettings *as, int def_usecs);
 
 typedef enum {
 AUD_CNOTIFY_ENABLE,
@@ -81,7 +90,6 @@ typedef struct QEMUAudioTimeStamp {
 void AUD_vlog (const char *cap, const char *fmt, va_list ap) GCC_FMT_ATTR(2, 
0);
 void AUD_log (const char *cap, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
 
-void AUD_help (void);
 void AUD_register_card (const char *name, QEMUSoundCard *card);
 void AUD_remove_card (QEMUSoundCard *card);
 CaptureVoiceOut *AUD_add_capture (
@@ -163,4 +171,8 @@ void audio_sample_to_uint64(void *samples, int pos,
 void audio_sample_from_uint64(void *samples, int pos,
 uint64_t left, uint64_t right);
 
+void audio_parse_option(const char *opt);
+void audio_init_audiodevs(void);
+void audio_legacy_help(void);
+
 #endif /* QEMU_AUDIO_H */
diff --git a/audio/audio_int.h b/audio/audio_int.h
index 6c451b995c..cee46c4809 100644
--- a/audio/audio_int.h
+++ b/audio/audio_int.h
@@ -146,7 +146,7 @@ struct audio_driver {
 const char *name;
 const char *descr;
 struct audio_option *options;
-void *(*init) (void);
+void *(*init) (Audiodev *);
 void (*fini) (void *);
 struct audio_pcm_ops *pcm_ops;
 int can_be_default;
@@ -193,6 +193,7 @@ struct SWVoiceCap {
 
 typedef struct AudioState {
 struct audio_driver *drv;
+Audiodev *dev;
 void *drv_opaque;
 
 QEMUTimer *ts;
@@ -203,10 +204,13 @@ typedef struct AudioState {
 int nb_hw_voices_out;
 int nb_hw_voices_in;
 int vm_running;
+int64_t period_ticks;
 } AudioState;
 
 extern const struct mixeng_volume nominal_volume;
 
+extern const char *audio_prio_list[];
+
 void audio_driver_register(audio_driver *drv);
 audio_driver *audio_driver_lookup(const char *name);
 
@@ -248,4 +252,14 @@ static inline int audio_ring_dist (int dst, int src, int 
len)
 #define AUDIO_STRINGIFY_(n) #n
 #define AUDIO_STRINGIFY(n) AUDIO_STRINGIFY_(n)
 
+typedef struct AudiodevListEntry {
+Audiodev *dev;
+QSIMPLEQ_ENTRY(AudiodevListEntry) next;
+} AudiodevListEntry;
+
+typedef QSIMPLEQ_HEAD(, AudiodevListEntry) AudiodevListHead;
+AudiodevListHead audio_handle_legacy_opts(void);
+
+void audio_free_audiodev_list(AudiodevListHead *head);
+
 #endif /* QEMU_AUDIO_INT_H */
diff --git a/audio/audio_template.h b/audio/audio_template.h
index 7de227d2d1..c1d7207abd 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -302,8 +302,10 @@ static HW *glue (audio_pcm_hw_add_new_, TYPE) (struct 
audsettings *as)
 static HW *glue (audio_pcm_hw_add_, TYPE) (struct audsettings *as)
 {
 HW