|  | /* | 
|  | * QEMU Audio subsystem header | 
|  | * | 
|  | * Copyright (c) 2003-2005 Vassili Karpov (malc) | 
|  | * | 
|  | * Permission is hereby granted, free of charge, to any person obtaining a copy | 
|  | * of this software and associated documentation files (the "Software"), to deal | 
|  | * in the Software without restriction, including without limitation the rights | 
|  | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | 
|  | * copies of the Software, and to permit persons to whom the Software is | 
|  | * furnished to do so, subject to the following conditions: | 
|  | * | 
|  | * The above copyright notice and this permission notice shall be included in | 
|  | * all copies or substantial portions of the Software. | 
|  | * | 
|  | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | 
|  | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | 
|  | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | 
|  | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | 
|  | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 
|  | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | 
|  | * THE SOFTWARE. | 
|  | */ | 
|  |  | 
|  | #ifndef QEMU_AUDIO_INT_H | 
|  | #define QEMU_AUDIO_INT_H | 
|  |  | 
|  | #ifdef CONFIG_AUDIO_COREAUDIO | 
|  | #define FLOAT_MIXENG | 
|  | /* #define RECIPROCAL */ | 
|  | #endif | 
|  | #include "mixeng.h" | 
|  |  | 
|  | #ifdef CONFIG_GIO | 
|  | #include <gio/gio.h> | 
|  | #endif | 
|  |  | 
|  | struct audio_pcm_ops; | 
|  |  | 
|  | struct audio_callback { | 
|  | void *opaque; | 
|  | audio_callback_fn fn; | 
|  | }; | 
|  |  | 
|  | struct audio_pcm_info { | 
|  | int bits; | 
|  | bool is_signed; | 
|  | bool is_float; | 
|  | int freq; | 
|  | int nchannels; | 
|  | int bytes_per_frame; | 
|  | int bytes_per_second; | 
|  | int swap_endianness; | 
|  | }; | 
|  |  | 
|  | typedef struct AudioState AudioState; | 
|  | typedef struct SWVoiceCap SWVoiceCap; | 
|  |  | 
|  | typedef struct STSampleBuffer { | 
|  | size_t pos, size; | 
|  | st_sample *buffer; | 
|  | } STSampleBuffer; | 
|  |  | 
|  | typedef struct HWVoiceOut { | 
|  | AudioState *s; | 
|  | int enabled; | 
|  | int poll_mode; | 
|  | int pending_disable; | 
|  | struct audio_pcm_info info; | 
|  |  | 
|  | f_sample *clip; | 
|  | uint64_t ts_helper; | 
|  |  | 
|  | STSampleBuffer mix_buf; | 
|  | void *buf_emul; | 
|  | size_t pos_emul, pending_emul, size_emul; | 
|  |  | 
|  | size_t samples; | 
|  | QLIST_HEAD (sw_out_listhead, SWVoiceOut) sw_head; | 
|  | QLIST_HEAD (sw_cap_listhead, SWVoiceCap) cap_head; | 
|  | struct audio_pcm_ops *pcm_ops; | 
|  | QLIST_ENTRY (HWVoiceOut) entries; | 
|  | } HWVoiceOut; | 
|  |  | 
|  | typedef struct HWVoiceIn { | 
|  | AudioState *s; | 
|  | int enabled; | 
|  | int poll_mode; | 
|  | struct audio_pcm_info info; | 
|  |  | 
|  | t_sample *conv; | 
|  |  | 
|  | size_t total_samples_captured; | 
|  | uint64_t ts_helper; | 
|  |  | 
|  | STSampleBuffer conv_buf; | 
|  | void *buf_emul; | 
|  | size_t pos_emul, pending_emul, size_emul; | 
|  |  | 
|  | size_t samples; | 
|  | QLIST_HEAD (sw_in_listhead, SWVoiceIn) sw_head; | 
|  | struct audio_pcm_ops *pcm_ops; | 
|  | QLIST_ENTRY (HWVoiceIn) entries; | 
|  | } HWVoiceIn; | 
|  |  | 
|  | struct SWVoiceOut { | 
|  | QEMUSoundCard *card; | 
|  | AudioState *s; | 
|  | struct audio_pcm_info info; | 
|  | t_sample *conv; | 
|  | STSampleBuffer resample_buf; | 
|  | void *rate; | 
|  | size_t total_hw_samples_mixed; | 
|  | int active; | 
|  | int empty; | 
|  | HWVoiceOut *hw; | 
|  | char *name; | 
|  | struct mixeng_volume vol; | 
|  | struct audio_callback callback; | 
|  | QLIST_ENTRY (SWVoiceOut) entries; | 
|  | }; | 
|  |  | 
|  | struct SWVoiceIn { | 
|  | QEMUSoundCard *card; | 
|  | AudioState *s; | 
|  | int active; | 
|  | struct audio_pcm_info info; | 
|  | void *rate; | 
|  | size_t total_hw_samples_acquired; | 
|  | STSampleBuffer resample_buf; | 
|  | f_sample *clip; | 
|  | HWVoiceIn *hw; | 
|  | char *name; | 
|  | struct mixeng_volume vol; | 
|  | struct audio_callback callback; | 
|  | QLIST_ENTRY (SWVoiceIn) entries; | 
|  | }; | 
|  |  | 
|  | typedef struct audio_driver audio_driver; | 
|  | struct audio_driver { | 
|  | const char *name; | 
|  | const char *descr; | 
|  | void *(*init) (Audiodev *, Error **); | 
|  | void (*fini) (void *); | 
|  | #ifdef CONFIG_GIO | 
|  | void (*set_dbus_server) (AudioState *s, GDBusObjectManagerServer *manager, bool p2p); | 
|  | #endif | 
|  | struct audio_pcm_ops *pcm_ops; | 
|  | int max_voices_out; | 
|  | int max_voices_in; | 
|  | size_t voice_size_out; | 
|  | size_t voice_size_in; | 
|  | QLIST_ENTRY(audio_driver) next; | 
|  | }; | 
|  |  | 
|  | struct audio_pcm_ops { | 
|  | int    (*init_out)(HWVoiceOut *hw, audsettings *as, void *drv_opaque); | 
|  | void   (*fini_out)(HWVoiceOut *hw); | 
|  | size_t (*write)   (HWVoiceOut *hw, void *buf, size_t size); | 
|  | void   (*run_buffer_out)(HWVoiceOut *hw); | 
|  | /* | 
|  | * Get the free output buffer size. This is an upper limit. The size | 
|  | * returned by function get_buffer_out may be smaller. | 
|  | */ | 
|  | size_t (*buffer_get_free)(HWVoiceOut *hw); | 
|  | /* | 
|  | * get a buffer that after later can be passed to put_buffer_out; optional | 
|  | * returns the buffer, and writes it's size to size (in bytes) | 
|  | */ | 
|  | void  *(*get_buffer_out)(HWVoiceOut *hw, size_t *size); | 
|  | /* | 
|  | * put back the buffer returned by get_buffer_out; optional | 
|  | * buf must be equal the pointer returned by get_buffer_out, | 
|  | * size may be smaller | 
|  | */ | 
|  | size_t (*put_buffer_out)(HWVoiceOut *hw, void *buf, size_t size); | 
|  | void   (*enable_out)(HWVoiceOut *hw, bool enable); | 
|  | void   (*volume_out)(HWVoiceOut *hw, Volume *vol); | 
|  |  | 
|  | int    (*init_in) (HWVoiceIn *hw, audsettings *as, void *drv_opaque); | 
|  | void   (*fini_in) (HWVoiceIn *hw); | 
|  | size_t (*read)    (HWVoiceIn *hw, void *buf, size_t size); | 
|  | void   (*run_buffer_in)(HWVoiceIn *hw); | 
|  | void  *(*get_buffer_in)(HWVoiceIn *hw, size_t *size); | 
|  | void   (*put_buffer_in)(HWVoiceIn *hw, void *buf, size_t size); | 
|  | void   (*enable_in)(HWVoiceIn *hw, bool enable); | 
|  | void   (*volume_in)(HWVoiceIn *hw, Volume *vol); | 
|  | }; | 
|  |  | 
|  | void audio_generic_run_buffer_in(HWVoiceIn *hw); | 
|  | void *audio_generic_get_buffer_in(HWVoiceIn *hw, size_t *size); | 
|  | void audio_generic_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size); | 
|  | void audio_generic_run_buffer_out(HWVoiceOut *hw); | 
|  | size_t audio_generic_buffer_get_free(HWVoiceOut *hw); | 
|  | void *audio_generic_get_buffer_out(HWVoiceOut *hw, size_t *size); | 
|  | size_t audio_generic_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size); | 
|  | size_t audio_generic_write(HWVoiceOut *hw, void *buf, size_t size); | 
|  | size_t audio_generic_read(HWVoiceIn *hw, void *buf, size_t size); | 
|  |  | 
|  | struct capture_callback { | 
|  | struct audio_capture_ops ops; | 
|  | void *opaque; | 
|  | QLIST_ENTRY (capture_callback) entries; | 
|  | }; | 
|  |  | 
|  | struct CaptureVoiceOut { | 
|  | HWVoiceOut hw; | 
|  | void *buf; | 
|  | QLIST_HEAD (cb_listhead, capture_callback) cb_head; | 
|  | QLIST_ENTRY (CaptureVoiceOut) entries; | 
|  | }; | 
|  |  | 
|  | struct SWVoiceCap { | 
|  | SWVoiceOut sw; | 
|  | CaptureVoiceOut *cap; | 
|  | QLIST_ENTRY (SWVoiceCap) entries; | 
|  | }; | 
|  |  | 
|  | typedef struct AudioState { | 
|  | struct audio_driver *drv; | 
|  | Audiodev *dev; | 
|  | void *drv_opaque; | 
|  |  | 
|  | QEMUTimer *ts; | 
|  | QLIST_HEAD (card_listhead, QEMUSoundCard) card_head; | 
|  | QLIST_HEAD (hw_in_listhead, HWVoiceIn) hw_head_in; | 
|  | QLIST_HEAD (hw_out_listhead, HWVoiceOut) hw_head_out; | 
|  | QLIST_HEAD (cap_listhead, CaptureVoiceOut) cap_head; | 
|  | int nb_hw_voices_out; | 
|  | int nb_hw_voices_in; | 
|  | int vm_running; | 
|  | int64_t period_ticks; | 
|  |  | 
|  | bool timer_running; | 
|  | uint64_t timer_last; | 
|  |  | 
|  | QTAILQ_ENTRY(AudioState) list; | 
|  | } AudioState; | 
|  |  | 
|  | extern const struct mixeng_volume nominal_volume; | 
|  |  | 
|  | extern const char *audio_prio_list[]; | 
|  |  | 
|  | void audio_driver_register(audio_driver *drv); | 
|  |  | 
|  | void audio_pcm_init_info (struct audio_pcm_info *info, struct audsettings *as); | 
|  | void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len); | 
|  |  | 
|  | int audio_bug (const char *funcname, int cond); | 
|  |  | 
|  | void audio_run(AudioState *s, const char *msg); | 
|  |  | 
|  | const char *audio_application_name(void); | 
|  |  | 
|  | typedef struct RateCtl { | 
|  | int64_t start_ticks; | 
|  | int64_t bytes_sent; | 
|  | } RateCtl; | 
|  |  | 
|  | void audio_rate_start(RateCtl *rate); | 
|  | size_t audio_rate_peek_bytes(RateCtl *rate, struct audio_pcm_info *info); | 
|  | void audio_rate_add_bytes(RateCtl *rate, size_t bytes_used); | 
|  | size_t audio_rate_get_bytes(RateCtl *rate, struct audio_pcm_info *info, | 
|  | size_t bytes_avail); | 
|  |  | 
|  | static inline size_t audio_ring_dist(size_t dst, size_t src, size_t len) | 
|  | { | 
|  | return (dst >= src) ? (dst - src) : (len - src + dst); | 
|  | } | 
|  |  | 
|  | /** | 
|  | * audio_ring_posb() - returns new position in ringbuffer in backward | 
|  | * direction at given distance | 
|  | * | 
|  | * @pos: current position in ringbuffer | 
|  | * @dist: distance in ringbuffer to walk in reverse direction | 
|  | * @len: size of ringbuffer | 
|  | */ | 
|  | static inline size_t audio_ring_posb(size_t pos, size_t dist, size_t len) | 
|  | { | 
|  | return pos >= dist ? pos - dist : len - dist + pos; | 
|  | } | 
|  |  | 
|  | #define dolog(fmt, ...) AUD_log(AUDIO_CAP, fmt, ## __VA_ARGS__) | 
|  |  | 
|  | #ifdef DEBUG | 
|  | #define ldebug(fmt, ...) AUD_log(AUDIO_CAP, fmt, ## __VA_ARGS__) | 
|  | #else | 
|  | #define ldebug(fmt, ...) (void)0 | 
|  | #endif | 
|  |  | 
|  | typedef struct AudiodevListEntry { | 
|  | Audiodev *dev; | 
|  | QSIMPLEQ_ENTRY(AudiodevListEntry) next; | 
|  | } AudiodevListEntry; | 
|  |  | 
|  | typedef QSIMPLEQ_HEAD(, AudiodevListEntry) AudiodevListHead; | 
|  |  | 
|  | void audio_create_pdos(Audiodev *dev); | 
|  | AudiodevPerDirectionOptions *audio_get_pdo_in(Audiodev *dev); | 
|  | AudiodevPerDirectionOptions *audio_get_pdo_out(Audiodev *dev); | 
|  |  | 
|  | #endif /* QEMU_AUDIO_INT_H */ |