audio merge (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1636 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									5e941d4b51
								
							
						
					
					
						commit
						571ec3d68d
					
				@ -31,15 +31,12 @@ typedef struct ALSAVoiceOut {
 | 
				
			|||||||
    HWVoiceOut hw;
 | 
					    HWVoiceOut hw;
 | 
				
			||||||
    void *pcm_buf;
 | 
					    void *pcm_buf;
 | 
				
			||||||
    snd_pcm_t *handle;
 | 
					    snd_pcm_t *handle;
 | 
				
			||||||
    int can_pause;
 | 
					 | 
				
			||||||
    int was_enabled;
 | 
					 | 
				
			||||||
} ALSAVoiceOut;
 | 
					} ALSAVoiceOut;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct ALSAVoiceIn {
 | 
					typedef struct ALSAVoiceIn {
 | 
				
			||||||
    HWVoiceIn hw;
 | 
					    HWVoiceIn hw;
 | 
				
			||||||
    snd_pcm_t *handle;
 | 
					    snd_pcm_t *handle;
 | 
				
			||||||
    void *pcm_buf;
 | 
					    void *pcm_buf;
 | 
				
			||||||
    int can_pause;
 | 
					 | 
				
			||||||
} ALSAVoiceIn;
 | 
					} ALSAVoiceIn;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct {
 | 
					static struct {
 | 
				
			||||||
@ -58,6 +55,7 @@ static struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    int buffer_size_out_overriden;
 | 
					    int buffer_size_out_overriden;
 | 
				
			||||||
    int period_size_out_overriden;
 | 
					    int period_size_out_overriden;
 | 
				
			||||||
 | 
					    int verbose;
 | 
				
			||||||
} conf = {
 | 
					} conf = {
 | 
				
			||||||
#ifdef HIGH_LATENCY
 | 
					#ifdef HIGH_LATENCY
 | 
				
			||||||
    .size_in_usec_in = 1,
 | 
					    .size_in_usec_in = 1,
 | 
				
			||||||
@ -73,8 +71,8 @@ static struct {
 | 
				
			|||||||
#else
 | 
					#else
 | 
				
			||||||
#define DEFAULT_BUFFER_SIZE 1024
 | 
					#define DEFAULT_BUFFER_SIZE 1024
 | 
				
			||||||
#define DEFAULT_PERIOD_SIZE 256
 | 
					#define DEFAULT_PERIOD_SIZE 256
 | 
				
			||||||
    .buffer_size_in = DEFAULT_BUFFER_SIZE,
 | 
					    .buffer_size_in = DEFAULT_BUFFER_SIZE * 4,
 | 
				
			||||||
    .period_size_in = DEFAULT_PERIOD_SIZE,
 | 
					    .period_size_in = DEFAULT_PERIOD_SIZE * 4,
 | 
				
			||||||
    .buffer_size_out = DEFAULT_BUFFER_SIZE,
 | 
					    .buffer_size_out = DEFAULT_BUFFER_SIZE,
 | 
				
			||||||
    .period_size_out = DEFAULT_PERIOD_SIZE,
 | 
					    .period_size_out = DEFAULT_PERIOD_SIZE,
 | 
				
			||||||
    .buffer_size_in_overriden = 0,
 | 
					    .buffer_size_in_overriden = 0,
 | 
				
			||||||
@ -82,7 +80,8 @@ static struct {
 | 
				
			|||||||
    .period_size_in_overriden = 0,
 | 
					    .period_size_in_overriden = 0,
 | 
				
			||||||
    .period_size_out_overriden = 0,
 | 
					    .period_size_out_overriden = 0,
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    .threshold = 0
 | 
					    .threshold = 0,
 | 
				
			||||||
 | 
					    .verbose = 0
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct alsa_params_req {
 | 
					struct alsa_params_req {
 | 
				
			||||||
@ -97,7 +96,6 @@ struct alsa_params_obt {
 | 
				
			|||||||
    int freq;
 | 
					    int freq;
 | 
				
			||||||
    audfmt_e fmt;
 | 
					    audfmt_e fmt;
 | 
				
			||||||
    int nchannels;
 | 
					    int nchannels;
 | 
				
			||||||
    int can_pause;
 | 
					 | 
				
			||||||
    snd_pcm_uframes_t samples;
 | 
					    snd_pcm_uframes_t samples;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -474,12 +472,6 @@ static int alsa_open (int in, struct alsa_params_req *req,
 | 
				
			|||||||
        goto err;
 | 
					        goto err;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    obt->can_pause = snd_pcm_hw_params_can_pause (hw_params);
 | 
					 | 
				
			||||||
    if (obt->can_pause < 0) {
 | 
					 | 
				
			||||||
        alsa_logerr (err, "Could not get pause capability for %s\n", typ);
 | 
					 | 
				
			||||||
        obt->can_pause = 0;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!in && conf.threshold) {
 | 
					    if (!in && conf.threshold) {
 | 
				
			||||||
        snd_pcm_uframes_t threshold;
 | 
					        snd_pcm_uframes_t threshold;
 | 
				
			||||||
        int bytes_per_sec;
 | 
					        int bytes_per_sec;
 | 
				
			||||||
@ -527,6 +519,28 @@ static int alsa_recover (snd_pcm_t *handle)
 | 
				
			|||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static snd_pcm_sframes_t alsa_get_avail (snd_pcm_t *handle)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    snd_pcm_sframes_t avail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    avail = snd_pcm_avail_update (handle);
 | 
				
			||||||
 | 
					    if (avail < 0) {
 | 
				
			||||||
 | 
					        if (avail == -EPIPE) {
 | 
				
			||||||
 | 
					            if (!alsa_recover (handle)) {
 | 
				
			||||||
 | 
					                avail = snd_pcm_avail_update (handle);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (avail < 0) {
 | 
				
			||||||
 | 
					            alsa_logerr (avail,
 | 
				
			||||||
 | 
					                         "Could not obtain number of available frames\n");
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return avail;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int alsa_run_out (HWVoiceOut *hw)
 | 
					static int alsa_run_out (HWVoiceOut *hw)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 | 
					    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 | 
				
			||||||
@ -541,57 +555,53 @@ static int alsa_run_out (HWVoiceOut *hw)
 | 
				
			|||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    avail = snd_pcm_avail_update (alsa->handle);
 | 
					    avail = alsa_get_avail (alsa->handle);
 | 
				
			||||||
    if (avail < 0) {
 | 
					    if (avail < 0) {
 | 
				
			||||||
        if (avail == -EPIPE) {
 | 
					        dolog ("Could not get number of available playback frames\n");
 | 
				
			||||||
            if (!alsa_recover (alsa->handle)) {
 | 
					 | 
				
			||||||
                avail = snd_pcm_avail_update (alsa->handle);
 | 
					 | 
				
			||||||
                if (avail >= 0) {
 | 
					 | 
				
			||||||
                    goto ok;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        alsa_logerr (avail, "Could not get amount free space\n");
 | 
					 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 ok:
 | 
					 | 
				
			||||||
    decr = audio_MIN (live, avail);
 | 
					    decr = audio_MIN (live, avail);
 | 
				
			||||||
    samples = decr;
 | 
					    samples = decr;
 | 
				
			||||||
    rpos = hw->rpos;
 | 
					    rpos = hw->rpos;
 | 
				
			||||||
    while (samples) {
 | 
					    while (samples) {
 | 
				
			||||||
        int left_till_end_samples = hw->samples - rpos;
 | 
					        int left_till_end_samples = hw->samples - rpos;
 | 
				
			||||||
        int convert_samples = audio_MIN (samples, left_till_end_samples);
 | 
					        int len = audio_MIN (samples, left_till_end_samples);
 | 
				
			||||||
        snd_pcm_sframes_t written;
 | 
					        snd_pcm_sframes_t written;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        src = hw->mix_buf + rpos;
 | 
					        src = hw->mix_buf + rpos;
 | 
				
			||||||
        dst = advance (alsa->pcm_buf, rpos << hw->info.shift);
 | 
					        dst = advance (alsa->pcm_buf, rpos << hw->info.shift);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        hw->clip (dst, src, convert_samples);
 | 
					        hw->clip (dst, src, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        while (convert_samples) {
 | 
					        while (len) {
 | 
				
			||||||
            written = snd_pcm_writei (alsa->handle, dst, convert_samples);
 | 
					            written = snd_pcm_writei (alsa->handle, dst, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (written < 0) {
 | 
					            if (written <= 0) {
 | 
				
			||||||
                switch (written) {
 | 
					                switch (written) {
 | 
				
			||||||
                case -EPIPE:
 | 
					                case 0:
 | 
				
			||||||
                    if (!alsa_recover (alsa->handle)) {
 | 
					                    if (conf.verbose) {
 | 
				
			||||||
                        continue;
 | 
					                        dolog ("Failed to write %d frames (wrote zero)\n", len);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    dolog ("Failed to write %d frames to %p, "
 | 
					 | 
				
			||||||
                           "handle %p not prepared\n",
 | 
					 | 
				
			||||||
                           convert_samples,
 | 
					 | 
				
			||||||
                           dst,
 | 
					 | 
				
			||||||
                           alsa->handle);
 | 
					 | 
				
			||||||
                    goto exit;
 | 
					                    goto exit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case -EAGAIN:
 | 
					                case -EPIPE:
 | 
				
			||||||
 | 
					                    if (alsa_recover (alsa->handle)) {
 | 
				
			||||||
 | 
					                        alsa_logerr (written, "Failed to write %d frames\n",
 | 
				
			||||||
 | 
					                                     len);
 | 
				
			||||||
 | 
					                        goto exit;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    if (conf.verbose) {
 | 
				
			||||||
 | 
					                        dolog ("Recovering from playback xrun\n");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case -EAGAIN:
 | 
				
			||||||
 | 
					                    goto exit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    alsa_logerr (written, "Failed to write %d frames to %p\n",
 | 
					                    alsa_logerr (written, "Failed to write %d frames to %p\n",
 | 
				
			||||||
                                 convert_samples, dst);
 | 
					                                 len, dst);
 | 
				
			||||||
                    goto exit;
 | 
					                    goto exit;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -599,7 +609,7 @@ static int alsa_run_out (HWVoiceOut *hw)
 | 
				
			|||||||
            mixeng_clear (src, written);
 | 
					            mixeng_clear (src, written);
 | 
				
			||||||
            rpos = (rpos + written) % hw->samples;
 | 
					            rpos = (rpos + written) % hw->samples;
 | 
				
			||||||
            samples -= written;
 | 
					            samples -= written;
 | 
				
			||||||
            convert_samples -= written;
 | 
					            len -= written;
 | 
				
			||||||
            dst = advance (dst, written << hw->info.shift);
 | 
					            dst = advance (dst, written << hw->info.shift);
 | 
				
			||||||
            src += written;
 | 
					            src += written;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -659,7 +669,6 @@ static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as)
 | 
				
			|||||||
        &obt_as,
 | 
					        &obt_as,
 | 
				
			||||||
        audio_need_to_swap_endian (endianness)
 | 
					        audio_need_to_swap_endian (endianness)
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    alsa->can_pause = obt.can_pause;
 | 
					 | 
				
			||||||
    hw->samples = obt.samples;
 | 
					    hw->samples = obt.samples;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << hw->info.shift);
 | 
					    alsa->pcm_buf = audio_calloc (AUDIO_FUNC, obt.samples, 1 << hw->info.shift);
 | 
				
			||||||
@ -671,46 +680,46 @@ static int alsa_init_out (HWVoiceOut *hw, audsettings_t *as)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    alsa->handle = handle;
 | 
					    alsa->handle = handle;
 | 
				
			||||||
    alsa->was_enabled = 0;
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int pause)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (pause) {
 | 
				
			||||||
 | 
					        err = snd_pcm_drop (handle);
 | 
				
			||||||
 | 
					        if (err < 0) {
 | 
				
			||||||
 | 
					            alsa_logerr (err, "Could not stop %s", typ);
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        err = snd_pcm_prepare (handle);
 | 
				
			||||||
 | 
					        if (err < 0) {
 | 
				
			||||||
 | 
					            alsa_logerr (err, "Could not prepare handle for %s", typ);
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
 | 
					static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int err;
 | 
					 | 
				
			||||||
    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 | 
					    ALSAVoiceOut *alsa = (ALSAVoiceOut *) hw;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (cmd) {
 | 
					    switch (cmd) {
 | 
				
			||||||
    case VOICE_ENABLE:
 | 
					    case VOICE_ENABLE:
 | 
				
			||||||
        ldebug ("enabling voice\n");
 | 
					        ldebug ("enabling voice\n");
 | 
				
			||||||
        audio_pcm_info_clear_buf (&hw->info, alsa->pcm_buf, hw->samples);
 | 
					        return alsa_voice_ctl (alsa->handle, "playback", 0);
 | 
				
			||||||
        if (alsa->can_pause) {
 | 
					 | 
				
			||||||
            /* Why this was_enabled madness is needed at all?? */
 | 
					 | 
				
			||||||
            if (alsa->was_enabled) {
 | 
					 | 
				
			||||||
                err = snd_pcm_pause (alsa->handle, 0);
 | 
					 | 
				
			||||||
                if (err < 0) {
 | 
					 | 
				
			||||||
                    alsa_logerr (err, "Failed to resume playing\n");
 | 
					 | 
				
			||||||
                    /* not fatal really */
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else {
 | 
					 | 
				
			||||||
                alsa->was_enabled = 1;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case VOICE_DISABLE:
 | 
					    case VOICE_DISABLE:
 | 
				
			||||||
        ldebug ("disabling voice\n");
 | 
					        ldebug ("disabling voice\n");
 | 
				
			||||||
        if (alsa->can_pause) {
 | 
					        return alsa_voice_ctl (alsa->handle, "playback", 1);
 | 
				
			||||||
            err = snd_pcm_pause (alsa->handle, 1);
 | 
					 | 
				
			||||||
            if (err < 0) {
 | 
					 | 
				
			||||||
                alsa_logerr (err, "Failed to stop playing\n");
 | 
					 | 
				
			||||||
                /* not fatal really */
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
        break;
 | 
					    return -1;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as)
 | 
					static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as)
 | 
				
			||||||
@ -749,7 +758,6 @@ static int alsa_init_in (HWVoiceIn *hw, audsettings_t *as)
 | 
				
			|||||||
        &obt_as,
 | 
					        &obt_as,
 | 
				
			||||||
        audio_need_to_swap_endian (endianness)
 | 
					        audio_need_to_swap_endian (endianness)
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
    alsa->can_pause = obt.can_pause;
 | 
					 | 
				
			||||||
    hw->samples = obt.samples;
 | 
					    hw->samples = obt.samples;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
 | 
					    alsa->pcm_buf = audio_calloc (AUDIO_FUNC, hw->samples, 1 << hw->info.shift);
 | 
				
			||||||
@ -783,6 +791,7 @@ static int alsa_run_in (HWVoiceIn *hw)
 | 
				
			|||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
    int live = audio_pcm_hw_get_live_in (hw);
 | 
					    int live = audio_pcm_hw_get_live_in (hw);
 | 
				
			||||||
    int dead = hw->samples - live;
 | 
					    int dead = hw->samples - live;
 | 
				
			||||||
 | 
					    int decr;
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
        int add;
 | 
					        int add;
 | 
				
			||||||
        int len;
 | 
					        int len;
 | 
				
			||||||
@ -790,21 +799,35 @@ static int alsa_run_in (HWVoiceIn *hw)
 | 
				
			|||||||
        { hw->wpos, 0 },
 | 
					        { hw->wpos, 0 },
 | 
				
			||||||
        { 0, 0 }
 | 
					        { 0, 0 }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					    snd_pcm_sframes_t avail;
 | 
				
			||||||
    snd_pcm_uframes_t read_samples = 0;
 | 
					    snd_pcm_uframes_t read_samples = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!dead) {
 | 
					    if (!dead) {
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (hw->wpos + dead > hw->samples) {
 | 
					    avail = alsa_get_avail (alsa->handle);
 | 
				
			||||||
        bufs[0].len = (hw->samples - hw->wpos);
 | 
					    if (avail < 0) {
 | 
				
			||||||
        bufs[1].len = (dead - (hw->samples - hw->wpos));
 | 
					        dolog ("Could not get number of captured frames\n");
 | 
				
			||||||
    }
 | 
					        return 0;
 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
        bufs[0].len = dead;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!avail && (snd_pcm_state (alsa->handle) == SND_PCM_STATE_PREPARED)) {
 | 
				
			||||||
 | 
					        avail = hw->samples;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    decr = audio_MIN (dead, avail);
 | 
				
			||||||
 | 
					    if (!decr) {
 | 
				
			||||||
 | 
					        return 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (hw->wpos + decr > hw->samples) {
 | 
				
			||||||
 | 
					        bufs[0].len = (hw->samples - hw->wpos);
 | 
				
			||||||
 | 
					        bufs[1].len = (decr - (hw->samples - hw->wpos));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else {
 | 
				
			||||||
 | 
					        bufs[0].len = decr;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < 2; ++i) {
 | 
					    for (i = 0; i < 2; ++i) {
 | 
				
			||||||
        void *src;
 | 
					        void *src;
 | 
				
			||||||
@ -820,24 +843,27 @@ static int alsa_run_in (HWVoiceIn *hw)
 | 
				
			|||||||
        while (len) {
 | 
					        while (len) {
 | 
				
			||||||
            nread = snd_pcm_readi (alsa->handle, src, len);
 | 
					            nread = snd_pcm_readi (alsa->handle, src, len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (nread < 0) {
 | 
					            if (nread <= 0) {
 | 
				
			||||||
                switch (nread) {
 | 
					                switch (nread) {
 | 
				
			||||||
                case -EPIPE:
 | 
					                case 0:
 | 
				
			||||||
                    if (!alsa_recover (alsa->handle)) {
 | 
					                    if (conf.verbose) {
 | 
				
			||||||
                        continue;
 | 
					                        dolog ("Failed to read %ld frames (read zero)\n", len);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    dolog (
 | 
					 | 
				
			||||||
                        "Failed to read %ld frames from %p, "
 | 
					 | 
				
			||||||
                        "handle %p not prepared\n",
 | 
					 | 
				
			||||||
                        len,
 | 
					 | 
				
			||||||
                        src,
 | 
					 | 
				
			||||||
                        alsa->handle
 | 
					 | 
				
			||||||
                        );
 | 
					 | 
				
			||||||
                    goto exit;
 | 
					                    goto exit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                case -EAGAIN:
 | 
					                case -EPIPE:
 | 
				
			||||||
 | 
					                    if (alsa_recover (alsa->handle)) {
 | 
				
			||||||
 | 
					                        alsa_logerr (nread, "Failed to read %ld frames\n", len);
 | 
				
			||||||
 | 
					                        goto exit;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    if (conf.verbose) {
 | 
				
			||||||
 | 
					                        dolog ("Recovering from capture xrun\n");
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                case -EAGAIN:
 | 
				
			||||||
 | 
					                    goto exit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                default:
 | 
					                default:
 | 
				
			||||||
                    alsa_logerr (
 | 
					                    alsa_logerr (
 | 
				
			||||||
                        nread,
 | 
					                        nread,
 | 
				
			||||||
@ -871,9 +897,19 @@ static int alsa_read (SWVoiceIn *sw, void *buf, int size)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
 | 
					static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    (void) hw;
 | 
					    ALSAVoiceIn *alsa = (ALSAVoiceIn *) hw;
 | 
				
			||||||
    (void) cmd;
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    switch (cmd) {
 | 
				
			||||||
 | 
					    case VOICE_ENABLE:
 | 
				
			||||||
 | 
					        ldebug ("enabling voice\n");
 | 
				
			||||||
 | 
					        return alsa_voice_ctl (alsa->handle, "capture", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case VOICE_DISABLE:
 | 
				
			||||||
 | 
					        ldebug ("disabling voice\n");
 | 
				
			||||||
 | 
					        return alsa_voice_ctl (alsa->handle, "capture", 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void *alsa_audio_init (void)
 | 
					static void *alsa_audio_init (void)
 | 
				
			||||||
@ -909,6 +945,10 @@ static struct audio_option alsa_options[] = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    {"ADC_DEV", AUD_OPT_STR, &conf.pcm_name_in,
 | 
					    {"ADC_DEV", AUD_OPT_STR, &conf.pcm_name_in,
 | 
				
			||||||
     "ADC device name", NULL, 0},
 | 
					     "ADC device name", NULL, 0},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    {"VERBOSE", AUD_OPT_BOOL, &conf.verbose,
 | 
				
			||||||
 | 
					     "Behave in a more verbose way", NULL, 0},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {NULL, 0, NULL, NULL, NULL, 0}
 | 
					    {NULL, 0, NULL, NULL, NULL, 0}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										344
									
								
								audio/audio.c
									
									
									
									
									
								
							
							
						
						
									
										344
									
								
								audio/audio.c
									
									
									
									
									
								
							@ -96,7 +96,7 @@ static struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    { 0 },                      /* period */
 | 
					    { 0 },                      /* period */
 | 
				
			||||||
    0,                          /* plive */
 | 
					    0,                          /* plive */
 | 
				
			||||||
    0
 | 
					    0                           /* log_to_monitor */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static AudioState glob_audio_state;
 | 
					static AudioState glob_audio_state;
 | 
				
			||||||
@ -623,25 +623,6 @@ void audio_pcm_info_clear_buf (struct audio_pcm_info *info, void *buf, int len)
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Hard voice (capture)
 | 
					 * Hard voice (capture)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void audio_pcm_hw_free_resources_in (HWVoiceIn *hw)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (hw->conv_buf) {
 | 
					 | 
				
			||||||
        qemu_free (hw->conv_buf);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    hw->conv_buf = NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int audio_pcm_hw_alloc_resources_in (HWVoiceIn *hw)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    hw->conv_buf = audio_calloc (AUDIO_FUNC, hw->samples, sizeof (st_sample_t));
 | 
					 | 
				
			||||||
    if (!hw->conv_buf) {
 | 
					 | 
				
			||||||
        dolog ("Could not allocate ADC conversion buffer (%d samples)\n",
 | 
					 | 
				
			||||||
               hw->samples);
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int audio_pcm_hw_find_min_in (HWVoiceIn *hw)
 | 
					static int audio_pcm_hw_find_min_in (HWVoiceIn *hw)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SWVoiceIn *sw;
 | 
					    SWVoiceIn *sw;
 | 
				
			||||||
@ -668,64 +649,6 @@ int audio_pcm_hw_get_live_in (HWVoiceIn *hw)
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Soft voice (capture)
 | 
					 * Soft voice (capture)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void audio_pcm_sw_free_resources_in (SWVoiceIn *sw)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (sw->conv_buf) {
 | 
					 | 
				
			||||||
        qemu_free (sw->conv_buf);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (sw->rate) {
 | 
					 | 
				
			||||||
        st_rate_stop (sw->rate);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sw->conv_buf = NULL;
 | 
					 | 
				
			||||||
    sw->rate = NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int audio_pcm_sw_alloc_resources_in (SWVoiceIn *sw)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int samples = ((int64_t) sw->hw->samples << 32) / sw->ratio;
 | 
					 | 
				
			||||||
    sw->conv_buf = audio_calloc (AUDIO_FUNC, samples, sizeof (st_sample_t));
 | 
					 | 
				
			||||||
    if (!sw->conv_buf) {
 | 
					 | 
				
			||||||
        dolog ("Could not allocate buffer for `%s' (%d samples)\n",
 | 
					 | 
				
			||||||
               SW_NAME (sw), samples);
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq);
 | 
					 | 
				
			||||||
    if (!sw->rate) {
 | 
					 | 
				
			||||||
        qemu_free (sw->conv_buf);
 | 
					 | 
				
			||||||
        sw->conv_buf = NULL;
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int audio_pcm_sw_init_in (
 | 
					 | 
				
			||||||
    SWVoiceIn *sw,
 | 
					 | 
				
			||||||
    HWVoiceIn *hw,
 | 
					 | 
				
			||||||
    const char *name,
 | 
					 | 
				
			||||||
    audsettings_t *as
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    /* None of the cards emulated by QEMU are big-endian
 | 
					 | 
				
			||||||
       hence following shortcut */
 | 
					 | 
				
			||||||
    audio_pcm_init_info (&sw->info, as, audio_need_to_swap_endian (0));
 | 
					 | 
				
			||||||
    sw->hw = hw;
 | 
					 | 
				
			||||||
    sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sw->clip =
 | 
					 | 
				
			||||||
        mixeng_clip
 | 
					 | 
				
			||||||
        [sw->info.nchannels == 2]
 | 
					 | 
				
			||||||
        [sw->info.sign]
 | 
					 | 
				
			||||||
        [sw->info.swap_endian]
 | 
					 | 
				
			||||||
        [sw->info.bits == 16];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sw->name = qemu_strdup (name);
 | 
					 | 
				
			||||||
    audio_pcm_sw_free_resources_in (sw);
 | 
					 | 
				
			||||||
    return audio_pcm_sw_alloc_resources_in (sw);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int audio_pcm_sw_get_rpos_in (SWVoiceIn *sw)
 | 
					static int audio_pcm_sw_get_rpos_in (SWVoiceIn *sw)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    HWVoiceIn *hw = sw->hw;
 | 
					    HWVoiceIn *hw = sw->hw;
 | 
				
			||||||
@ -750,7 +673,7 @@ int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    HWVoiceIn *hw = sw->hw;
 | 
					    HWVoiceIn *hw = sw->hw;
 | 
				
			||||||
    int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
 | 
					    int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
 | 
				
			||||||
    st_sample_t *src, *dst = sw->conv_buf;
 | 
					    st_sample_t *src, *dst = sw->buf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples;
 | 
					    rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -794,7 +717,7 @@ int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size)
 | 
				
			|||||||
        total += isamp;
 | 
					        total += isamp;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sw->clip (buf, sw->conv_buf, ret);
 | 
					    sw->clip (buf, sw->buf, ret);
 | 
				
			||||||
    sw->total_hw_samples_acquired += total;
 | 
					    sw->total_hw_samples_acquired += total;
 | 
				
			||||||
    return ret << sw->info.shift;
 | 
					    return ret << sw->info.shift;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -802,27 +725,6 @@ int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size)
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Hard voice (playback)
 | 
					 * Hard voice (playback)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void audio_pcm_hw_free_resources_out (HWVoiceOut *hw)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (hw->mix_buf) {
 | 
					 | 
				
			||||||
        qemu_free (hw->mix_buf);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    hw->mix_buf = NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int audio_pcm_hw_alloc_resources_out (HWVoiceOut *hw)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    hw->mix_buf = audio_calloc (AUDIO_FUNC, hw->samples, sizeof (st_sample_t));
 | 
					 | 
				
			||||||
    if (!hw->mix_buf) {
 | 
					 | 
				
			||||||
        dolog ("Could not allocate DAC mixing buffer (%d samples)\n",
 | 
					 | 
				
			||||||
               hw->samples);
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep)
 | 
					static int audio_pcm_hw_find_min_out (HWVoiceOut *hw, int *nb_livep)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SWVoiceOut *sw;
 | 
					    SWVoiceOut *sw;
 | 
				
			||||||
@ -876,66 +778,6 @@ int audio_pcm_hw_get_live_out (HWVoiceOut *hw)
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * Soft voice (playback)
 | 
					 * Soft voice (playback)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static void audio_pcm_sw_free_resources_out (SWVoiceOut *sw)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (sw->buf) {
 | 
					 | 
				
			||||||
        qemu_free (sw->buf);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (sw->rate) {
 | 
					 | 
				
			||||||
        st_rate_stop (sw->rate);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sw->buf = NULL;
 | 
					 | 
				
			||||||
    sw->rate = NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int audio_pcm_sw_alloc_resources_out (SWVoiceOut *sw)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    sw->buf = audio_calloc (AUDIO_FUNC, sw->hw->samples, sizeof (st_sample_t));
 | 
					 | 
				
			||||||
    if (!sw->buf) {
 | 
					 | 
				
			||||||
        dolog ("Could not allocate buffer for `%s' (%d samples)\n",
 | 
					 | 
				
			||||||
               SW_NAME (sw), sw->hw->samples);
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq);
 | 
					 | 
				
			||||||
    if (!sw->rate) {
 | 
					 | 
				
			||||||
        qemu_free (sw->buf);
 | 
					 | 
				
			||||||
        sw->buf = NULL;
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int audio_pcm_sw_init_out (
 | 
					 | 
				
			||||||
    SWVoiceOut *sw,
 | 
					 | 
				
			||||||
    HWVoiceOut *hw,
 | 
					 | 
				
			||||||
    const char *name,
 | 
					 | 
				
			||||||
    audsettings_t *as
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    /* None of the cards emulated by QEMU are big-endian
 | 
					 | 
				
			||||||
       hence following shortcut */
 | 
					 | 
				
			||||||
    audio_pcm_init_info (&sw->info, as, audio_need_to_swap_endian (0));
 | 
					 | 
				
			||||||
    sw->hw = hw;
 | 
					 | 
				
			||||||
    sw->empty = 1;
 | 
					 | 
				
			||||||
    sw->active = 0;
 | 
					 | 
				
			||||||
    sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq;
 | 
					 | 
				
			||||||
    sw->total_hw_samples_mixed = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sw->conv =
 | 
					 | 
				
			||||||
        mixeng_conv
 | 
					 | 
				
			||||||
        [sw->info.nchannels == 2]
 | 
					 | 
				
			||||||
        [sw->info.sign]
 | 
					 | 
				
			||||||
        [sw->info.swap_endian]
 | 
					 | 
				
			||||||
        [sw->info.bits == 16];
 | 
					 | 
				
			||||||
    sw->name = qemu_strdup (name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    audio_pcm_sw_free_resources_out (sw);
 | 
					 | 
				
			||||||
    return audio_pcm_sw_alloc_resources_out (sw);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size)
 | 
					int audio_pcm_sw_write (SWVoiceOut *sw, void *buf, int size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
 | 
					    int hwsamples, samples, isamp, osamp, wpos, live, dead, left, swlim, blck;
 | 
				
			||||||
@ -1316,6 +1158,16 @@ static void audio_run_in (AudioState *s)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void audio_timer (void *opaque)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    AudioState *s = opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    audio_run_out (s);
 | 
				
			||||||
 | 
					    audio_run_in (s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct audio_option audio_options[] = {
 | 
					static struct audio_option audio_options[] = {
 | 
				
			||||||
    /* DAC */
 | 
					    /* DAC */
 | 
				
			||||||
    {"DAC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_out.enabled,
 | 
					    {"DAC_FIXED_SETTINGS", AUD_OPT_BOOL, &conf.fixed_out.enabled,
 | 
				
			||||||
@ -1356,13 +1208,31 @@ static struct audio_option audio_options[] = {
 | 
				
			|||||||
    {"PLIVE", AUD_OPT_BOOL, &conf.plive,
 | 
					    {"PLIVE", AUD_OPT_BOOL, &conf.plive,
 | 
				
			||||||
     "(undocumented)", NULL, 0},
 | 
					     "(undocumented)", NULL, 0},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    {"LOG_TO_MONITOR", AUD_OPT_BOOL, &conf.log_to_monitor,
 | 
					    {"LOG_TO_MONITOR", AUD_OPT_BOOL, &conf.log_to_monitor,
 | 
				
			||||||
     "print logging messages to montior instead of stderr", NULL, 0},
 | 
					     "print logging messages to montior instead of stderr", NULL, 0},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {NULL, 0, NULL, NULL, NULL, 0}
 | 
					    {NULL, 0, NULL, NULL, NULL, 0}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void audio_pp_nb_voices (const char *typ, int nb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    switch (nb) {
 | 
				
			||||||
 | 
					    case 0:
 | 
				
			||||||
 | 
					        printf ("Does not support %s\n", typ);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case 1:
 | 
				
			||||||
 | 
					        printf ("One %s voice\n", typ);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    case INT_MAX:
 | 
				
			||||||
 | 
					        printf ("Theoretically supports many %s voices\n", typ);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        printf ("Theoretically supports upto %d %s voices\n", nb, typ);
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AUD_help (void)
 | 
					void AUD_help (void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    size_t i;
 | 
					    size_t i;
 | 
				
			||||||
@ -1387,37 +1257,8 @@ void AUD_help (void)
 | 
				
			|||||||
        printf ("Name: %s\n", d->name);
 | 
					        printf ("Name: %s\n", d->name);
 | 
				
			||||||
        printf ("Description: %s\n", d->descr);
 | 
					        printf ("Description: %s\n", d->descr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        switch (d->max_voices_out) {
 | 
					        audio_pp_nb_voices ("playback", d->max_voices_out);
 | 
				
			||||||
        case 0:
 | 
					        audio_pp_nb_voices ("capture", d->max_voices_in);
 | 
				
			||||||
            printf ("Does not support DAC\n");
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case 1:
 | 
					 | 
				
			||||||
            printf ("One DAC voice\n");
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case INT_MAX:
 | 
					 | 
				
			||||||
            printf ("Theoretically supports many DAC voices\n");
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
            printf ("Theoretically supports upto %d DAC voices\n",
 | 
					 | 
				
			||||||
                     d->max_voices_out);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        switch (d->max_voices_in) {
 | 
					 | 
				
			||||||
        case 0:
 | 
					 | 
				
			||||||
            printf ("Does not support ADC\n");
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case 1:
 | 
					 | 
				
			||||||
            printf ("One ADC voice\n");
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case INT_MAX:
 | 
					 | 
				
			||||||
            printf ("Theoretically supports many ADC voices\n");
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        default:
 | 
					 | 
				
			||||||
            printf ("Theoretically supports upto %d ADC voices\n",
 | 
					 | 
				
			||||||
                     d->max_voices_in);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (d->options) {
 | 
					        if (d->options) {
 | 
				
			||||||
            printf ("Options:\n");
 | 
					            printf ("Options:\n");
 | 
				
			||||||
@ -1434,7 +1275,7 @@ void AUD_help (void)
 | 
				
			|||||||
        "Example:\n"
 | 
					        "Example:\n"
 | 
				
			||||||
#ifdef _WIN32
 | 
					#ifdef _WIN32
 | 
				
			||||||
        "  set QEMU_AUDIO_DRV=wav\n"
 | 
					        "  set QEMU_AUDIO_DRV=wav\n"
 | 
				
			||||||
        "  set QEMU_WAV_PATH=c:/tune.wav\n"
 | 
					        "  set QEMU_WAV_PATH=c:\\tune.wav\n"
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
        "  export QEMU_AUDIO_DRV=wav\n"
 | 
					        "  export QEMU_AUDIO_DRV=wav\n"
 | 
				
			||||||
        "  export QEMU_WAV_PATH=$HOME/tune.wav\n"
 | 
					        "  export QEMU_WAV_PATH=$HOME/tune.wav\n"
 | 
				
			||||||
@ -1444,16 +1285,6 @@ void AUD_help (void)
 | 
				
			|||||||
        );
 | 
					        );
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void audio_timer (void *opaque)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    AudioState *s = opaque;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    audio_run_out (s);
 | 
					 | 
				
			||||||
    audio_run_in (s);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int audio_driver_init (AudioState *s, struct audio_driver *drv)
 | 
					static int audio_driver_init (AudioState *s, struct audio_driver *drv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (drv->options) {
 | 
					    if (drv->options) {
 | 
				
			||||||
@ -1462,62 +1293,8 @@ static int audio_driver_init (AudioState *s, struct audio_driver *drv)
 | 
				
			|||||||
    s->drv_opaque = drv->init ();
 | 
					    s->drv_opaque = drv->init ();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->drv_opaque) {
 | 
					    if (s->drv_opaque) {
 | 
				
			||||||
        if (s->nb_hw_voices_out > drv->max_voices_out) {
 | 
					        audio_init_nb_voices_out (s, drv);
 | 
				
			||||||
            if (!drv->max_voices_out) {
 | 
					        audio_init_nb_voices_in (s, drv);
 | 
				
			||||||
                dolog ("`%s' does not support DAC\n", drv->name);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else {
 | 
					 | 
				
			||||||
                dolog (
 | 
					 | 
				
			||||||
                    "`%s' does not support %d multiple DAC voicess\n"
 | 
					 | 
				
			||||||
                    "Resetting to %d\n",
 | 
					 | 
				
			||||||
                    drv->name,
 | 
					 | 
				
			||||||
                    s->nb_hw_voices_out,
 | 
					 | 
				
			||||||
                    drv->max_voices_out
 | 
					 | 
				
			||||||
                    );
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            s->nb_hw_voices_out = drv->max_voices_out;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!drv->voice_size_in && drv->max_voices_in) {
 | 
					 | 
				
			||||||
            ldebug ("warning: No ADC voice size defined for `%s'\n",
 | 
					 | 
				
			||||||
                    drv->name);
 | 
					 | 
				
			||||||
            drv->max_voices_in = 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!drv->voice_size_out && drv->max_voices_out) {
 | 
					 | 
				
			||||||
            ldebug ("warning: No DAC voice size defined for `%s'\n",
 | 
					 | 
				
			||||||
                    drv->name);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (drv->voice_size_in && !drv->max_voices_in) {
 | 
					 | 
				
			||||||
            ldebug ("warning: `%s' ADC voice size %d, zero voices \n",
 | 
					 | 
				
			||||||
                    drv->name, drv->voice_size_out);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (drv->voice_size_out && !drv->max_voices_out) {
 | 
					 | 
				
			||||||
            ldebug ("warning: `%s' DAC voice size %d, zero voices \n",
 | 
					 | 
				
			||||||
                    drv->name, drv->voice_size_in);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (s->nb_hw_voices_in > drv->max_voices_in) {
 | 
					 | 
				
			||||||
            if (!drv->max_voices_in) {
 | 
					 | 
				
			||||||
                ldebug ("`%s' does not support ADC\n", drv->name);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            else {
 | 
					 | 
				
			||||||
                dolog (
 | 
					 | 
				
			||||||
                    "`%s' does not support %d multiple ADC voices\n"
 | 
					 | 
				
			||||||
                    "Resetting to %d\n",
 | 
					 | 
				
			||||||
                    drv->name,
 | 
					 | 
				
			||||||
                    s->nb_hw_voices_in,
 | 
					 | 
				
			||||||
                    drv->max_voices_in
 | 
					 | 
				
			||||||
                    );
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            s->nb_hw_voices_in = drv->max_voices_in;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LIST_INIT (&s->hw_head_out);
 | 
					 | 
				
			||||||
        LIST_INIT (&s->hw_head_in);
 | 
					 | 
				
			||||||
        s->drv = drv;
 | 
					        s->drv = drv;
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -1549,25 +1326,13 @@ static void audio_atexit (void)
 | 
				
			|||||||
    HWVoiceOut *hwo = NULL;
 | 
					    HWVoiceOut *hwo = NULL;
 | 
				
			||||||
    HWVoiceIn *hwi = NULL;
 | 
					    HWVoiceIn *hwi = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while ((hwo = audio_pcm_hw_find_any_out (s, hwo))) {
 | 
					    while ((hwo = audio_pcm_hw_find_any_enabled_out (s, hwo))) {
 | 
				
			||||||
        if (!hwo->pcm_ops) {
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (hwo->enabled) {
 | 
					 | 
				
			||||||
        hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
 | 
					        hwo->pcm_ops->ctl_out (hwo, VOICE_DISABLE);
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        hwo->pcm_ops->fini_out (hwo);
 | 
					        hwo->pcm_ops->fini_out (hwo);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while ((hwi = audio_pcm_hw_find_any_in (s, hwi))) {
 | 
					    while ((hwi = audio_pcm_hw_find_any_enabled_in (s, hwi))) {
 | 
				
			||||||
        if (!hwi->pcm_ops) {
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (hwi->enabled) {
 | 
					 | 
				
			||||||
        hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
 | 
					        hwi->pcm_ops->ctl_in (hwi, VOICE_DISABLE);
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        hwi->pcm_ops->fini_in (hwi);
 | 
					        hwi->pcm_ops->fini_in (hwi);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1616,21 +1381,31 @@ AudioState *AUD_init (void)
 | 
				
			|||||||
    const char *drvname;
 | 
					    const char *drvname;
 | 
				
			||||||
    AudioState *s = &glob_audio_state;
 | 
					    AudioState *s = &glob_audio_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LIST_INIT (&s->hw_head_out);
 | 
				
			||||||
 | 
					    LIST_INIT (&s->hw_head_in);
 | 
				
			||||||
 | 
					    atexit (audio_atexit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s->ts = qemu_new_timer (vm_clock, audio_timer, s);
 | 
				
			||||||
 | 
					    if (!s->ts) {
 | 
				
			||||||
 | 
					        dolog ("Could not create audio timer\n");
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    audio_process_options ("AUDIO", audio_options);
 | 
					    audio_process_options ("AUDIO", audio_options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->nb_hw_voices_out = conf.fixed_out.nb_voices;
 | 
					    s->nb_hw_voices_out = conf.fixed_out.nb_voices;
 | 
				
			||||||
    s->nb_hw_voices_in = conf.fixed_in.nb_voices;
 | 
					    s->nb_hw_voices_in = conf.fixed_in.nb_voices;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->nb_hw_voices_out <= 0) {
 | 
					    if (s->nb_hw_voices_out <= 0) {
 | 
				
			||||||
        dolog ("Bogus number of DAC voices %d\n",
 | 
					        dolog ("Bogus number of playback voices %d, setting to 1\n",
 | 
				
			||||||
               s->nb_hw_voices_out);
 | 
					               s->nb_hw_voices_out);
 | 
				
			||||||
        s->nb_hw_voices_out = 1;
 | 
					        s->nb_hw_voices_out = 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->nb_hw_voices_in <= 0) {
 | 
					    if (s->nb_hw_voices_in <= 0) {
 | 
				
			||||||
        dolog ("Bogus number of ADC voices %d\n",
 | 
					        dolog ("Bogus number of capture voices %d, setting to 0\n",
 | 
				
			||||||
               s->nb_hw_voices_in);
 | 
					               s->nb_hw_voices_in);
 | 
				
			||||||
        s->nb_hw_voices_in = 1;
 | 
					        s->nb_hw_voices_in = 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@ -1638,12 +1413,6 @@ AudioState *AUD_init (void)
 | 
				
			|||||||
        drvname = audio_get_conf_str ("QEMU_AUDIO_DRV", NULL, &def);
 | 
					        drvname = audio_get_conf_str ("QEMU_AUDIO_DRV", NULL, &def);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->ts = qemu_new_timer (vm_clock, audio_timer, s);
 | 
					 | 
				
			||||||
    if (!s->ts) {
 | 
					 | 
				
			||||||
        dolog ("Could not create audio timer\n");
 | 
					 | 
				
			||||||
        return NULL;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (drvname) {
 | 
					    if (drvname) {
 | 
				
			||||||
        int found = 0;
 | 
					        int found = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1680,6 +1449,8 @@ AudioState *AUD_init (void)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (done) {
 | 
					    if (done) {
 | 
				
			||||||
 | 
					        VMChangeStateEntry *e;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (conf.period.hz <= 0) {
 | 
					        if (conf.period.hz <= 0) {
 | 
				
			||||||
            if (conf.period.hz < 0) {
 | 
					            if (conf.period.hz < 0) {
 | 
				
			||||||
                dolog ("warning: Timer period is negative - %d "
 | 
					                dolog ("warning: Timer period is negative - %d "
 | 
				
			||||||
@ -1692,7 +1463,11 @@ AudioState *AUD_init (void)
 | 
				
			|||||||
            conf.period.ticks = ticks_per_sec / conf.period.hz;
 | 
					            conf.period.ticks = ticks_per_sec / conf.period.hz;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);
 | 
					        e = qemu_add_vm_change_state_handler (audio_vm_change_state_handler, s);
 | 
				
			||||||
 | 
					        if (!e) {
 | 
				
			||||||
 | 
					            dolog ("warning: Could not register change state handler\n"
 | 
				
			||||||
 | 
					                   "(Audio can continue looping even after stopping the VM)\n");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        qemu_del_timer (s->ts);
 | 
					        qemu_del_timer (s->ts);
 | 
				
			||||||
@ -1701,7 +1476,6 @@ AudioState *AUD_init (void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    LIST_INIT (&s->card_head);
 | 
					    LIST_INIT (&s->card_head);
 | 
				
			||||||
    register_savevm ("audio", 0, 1, audio_save, audio_load, s);
 | 
					    register_savevm ("audio", 0, 1, audio_save, audio_load, s);
 | 
				
			||||||
    atexit (audio_atexit);
 | 
					 | 
				
			||||||
    qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
 | 
					    qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + conf.period.ticks);
 | 
				
			||||||
    return s;
 | 
					    return s;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -73,7 +73,8 @@ SWVoiceOut *AUD_open_out (
 | 
				
			|||||||
    const char *name,
 | 
					    const char *name,
 | 
				
			||||||
    void *callback_opaque,
 | 
					    void *callback_opaque,
 | 
				
			||||||
    audio_callback_fn_t callback_fn,
 | 
					    audio_callback_fn_t callback_fn,
 | 
				
			||||||
    audsettings_t *settings
 | 
					    audsettings_t *settings,
 | 
				
			||||||
 | 
					    int sw_endian
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AUD_close_out (QEMUSoundCard *card, SWVoiceOut *sw);
 | 
					void AUD_close_out (QEMUSoundCard *card, SWVoiceOut *sw);
 | 
				
			||||||
@ -91,7 +92,8 @@ SWVoiceIn *AUD_open_in (
 | 
				
			|||||||
    const char *name,
 | 
					    const char *name,
 | 
				
			||||||
    void *callback_opaque,
 | 
					    void *callback_opaque,
 | 
				
			||||||
    audio_callback_fn_t callback_fn,
 | 
					    audio_callback_fn_t callback_fn,
 | 
				
			||||||
    audsettings_t *settings
 | 
					    audsettings_t *settings,
 | 
				
			||||||
 | 
					    int sw_endian
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AUD_close_in (QEMUSoundCard *card, SWVoiceIn *sw);
 | 
					void AUD_close_in (QEMUSoundCard *card, SWVoiceIn *sw);
 | 
				
			||||||
 | 
				
			|||||||
@ -123,7 +123,7 @@ struct SWVoiceIn {
 | 
				
			|||||||
    int64_t ratio;
 | 
					    int64_t ratio;
 | 
				
			||||||
    void *rate;
 | 
					    void *rate;
 | 
				
			||||||
    int total_hw_samples_acquired;
 | 
					    int total_hw_samples_acquired;
 | 
				
			||||||
    st_sample_t *conv_buf;
 | 
					    st_sample_t *buf;
 | 
				
			||||||
    f_sample *clip;
 | 
					    f_sample *clip;
 | 
				
			||||||
    HWVoiceIn *hw;
 | 
					    HWVoiceIn *hw;
 | 
				
			||||||
    char *name;
 | 
					    char *name;
 | 
				
			||||||
 | 
				
			|||||||
@ -23,52 +23,159 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef DAC
 | 
					#ifdef DAC
 | 
				
			||||||
 | 
					#define NAME "playback"
 | 
				
			||||||
 | 
					#define HWBUF hw->mix_buf
 | 
				
			||||||
#define TYPE out
 | 
					#define TYPE out
 | 
				
			||||||
#define HW glue (HWVoice, Out)
 | 
					#define HW HWVoiceOut
 | 
				
			||||||
#define SW glue (SWVoice, Out)
 | 
					#define SW SWVoiceOut
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
 | 
					#define NAME "capture"
 | 
				
			||||||
#define TYPE in
 | 
					#define TYPE in
 | 
				
			||||||
#define HW glue (HWVoice, In)
 | 
					#define HW HWVoiceIn
 | 
				
			||||||
#define SW glue (SWVoice, In)
 | 
					#define SW SWVoiceIn
 | 
				
			||||||
 | 
					#define HWBUF hw->conv_buf
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int glue (audio_pcm_hw_init_, TYPE) (
 | 
					static void glue (audio_init_nb_voices_, TYPE) (
 | 
				
			||||||
    HW *hw,
 | 
					    AudioState *s,
 | 
				
			||||||
    audsettings_t *as
 | 
					    struct audio_driver *drv
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    glue (audio_pcm_hw_free_resources_, TYPE) (hw);
 | 
					    int max_voices = glue (drv->max_voices_, TYPE);
 | 
				
			||||||
 | 
					    int voice_size = glue (drv->voice_size_, TYPE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) {
 | 
					    if (glue (s->nb_hw_voices_, TYPE) > max_voices) {
 | 
				
			||||||
        return -1;
 | 
					        if (!max_voices) {
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (audio_bug (AUDIO_FUNC, hw->samples <= 0)) {
 | 
					 | 
				
			||||||
        dolog ("hw->samples=%d\n", hw->samples);
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    LIST_INIT (&hw->sw_head);
 | 
					 | 
				
			||||||
#ifdef DAC
 | 
					#ifdef DAC
 | 
				
			||||||
    hw->clip =
 | 
					            dolog ("Driver `%s' does not support " NAME "\n", drv->name);
 | 
				
			||||||
        mixeng_clip
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
    hw->conv =
 | 
					 | 
				
			||||||
        mixeng_conv
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        [hw->info.nchannels == 2]
 | 
					        }
 | 
				
			||||||
        [hw->info.sign]
 | 
					        else {
 | 
				
			||||||
        [hw->info.swap_endian]
 | 
					            dolog ("Driver `%s' does not support %d " NAME " voices, max %d\n",
 | 
				
			||||||
        [hw->info.bits == 16];
 | 
					                   drv->name,
 | 
				
			||||||
 | 
					                   glue (s->nb_hw_voices_, TYPE),
 | 
				
			||||||
 | 
					                   max_voices);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        glue (s->nb_hw_voices_, TYPE) = max_voices;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) {
 | 
					    if (audio_bug (AUDIO_FUNC, !voice_size && max_voices)) {
 | 
				
			||||||
        glue (hw->pcm_ops->fini_, TYPE) (hw);
 | 
					        dolog ("drv=`%s' voice_size=0 max_voices=%d\n",
 | 
				
			||||||
 | 
					               drv->name, max_voices);
 | 
				
			||||||
 | 
					        glue (s->nb_hw_voices_, TYPE) = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (audio_bug (AUDIO_FUNC, voice_size && !max_voices)) {
 | 
				
			||||||
 | 
					        dolog ("drv=`%s' voice_size=%d max_voices=0\n",
 | 
				
			||||||
 | 
					               drv->name, voice_size);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void glue (audio_pcm_hw_free_resources_, TYPE) (HW *hw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (HWBUF) {
 | 
				
			||||||
 | 
					        qemu_free (HWBUF);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    HWBUF = NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int glue (audio_pcm_hw_alloc_resources_, TYPE) (HW *hw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    HWBUF = audio_calloc (AUDIO_FUNC, hw->samples, sizeof (st_sample_t));
 | 
				
			||||||
 | 
					    if (!HWBUF) {
 | 
				
			||||||
 | 
					        dolog ("Could not allocate " NAME " buffer (%d samples)\n",
 | 
				
			||||||
 | 
					               hw->samples);
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void glue (audio_pcm_sw_free_resources_, TYPE) (SW *sw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (sw->buf) {
 | 
				
			||||||
 | 
					        qemu_free (sw->buf);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (sw->rate) {
 | 
				
			||||||
 | 
					        st_rate_stop (sw->rate);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sw->buf = NULL;
 | 
				
			||||||
 | 
					    sw->rate = NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int glue (audio_pcm_sw_alloc_resources_, TYPE) (SW *sw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int samples;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DAC
 | 
				
			||||||
 | 
					    samples = sw->hw->samples;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    samples = ((int64_t) sw->hw->samples << 32) / sw->ratio;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sw->buf = audio_calloc (AUDIO_FUNC, samples, sizeof (st_sample_t));
 | 
				
			||||||
 | 
					    if (!sw->buf) {
 | 
				
			||||||
 | 
					        dolog ("Could not allocate buffer for `%s' (%d samples)\n",
 | 
				
			||||||
 | 
					               SW_NAME (sw), samples);
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DAC
 | 
				
			||||||
 | 
					    sw->rate = st_rate_start (sw->info.freq, sw->hw->info.freq);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    sw->rate = st_rate_start (sw->hw->info.freq, sw->info.freq);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    if (!sw->rate) {
 | 
				
			||||||
 | 
					        qemu_free (sw->buf);
 | 
				
			||||||
 | 
					        sw->buf = NULL;
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int glue (audio_pcm_sw_init_, TYPE) (
 | 
				
			||||||
 | 
					    SW *sw,
 | 
				
			||||||
 | 
					    HW *hw,
 | 
				
			||||||
 | 
					    const char *name,
 | 
				
			||||||
 | 
					    audsettings_t *as,
 | 
				
			||||||
 | 
					    int endian
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    audio_pcm_init_info (&sw->info, as, audio_need_to_swap_endian (endian));
 | 
				
			||||||
 | 
					    sw->hw = hw;
 | 
				
			||||||
 | 
					    sw->active = 0;
 | 
				
			||||||
 | 
					#ifdef DAC
 | 
				
			||||||
 | 
					    sw->ratio = ((int64_t) sw->hw->info.freq << 32) / sw->info.freq;
 | 
				
			||||||
 | 
					    sw->total_hw_samples_mixed = 0;
 | 
				
			||||||
 | 
					    sw->empty = 1;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    sw->ratio = ((int64_t) sw->info.freq << 32) / sw->hw->info.freq;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DAC
 | 
				
			||||||
 | 
					    sw->conv = mixeng_conv
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    sw->clip = mixeng_clip
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					        [sw->info.nchannels == 2]
 | 
				
			||||||
 | 
					        [sw->info.sign]
 | 
				
			||||||
 | 
					        [sw->info.swap_endian]
 | 
				
			||||||
 | 
					        [sw->info.bits == 16];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sw->name = qemu_strdup (name);
 | 
				
			||||||
 | 
					    err = glue (audio_pcm_sw_alloc_resources_, TYPE) (sw);
 | 
				
			||||||
 | 
					    if (err) {
 | 
				
			||||||
 | 
					        qemu_free (sw->name);
 | 
				
			||||||
 | 
					        sw->name = NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void glue (audio_pcm_sw_fini_, TYPE) (SW *sw)
 | 
					static void glue (audio_pcm_sw_fini_, TYPE) (SW *sw)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    glue (audio_pcm_sw_free_resources_, TYPE) (sw);
 | 
					    glue (audio_pcm_sw_free_resources_, TYPE) (sw);
 | 
				
			||||||
@ -117,31 +224,6 @@ static HW *glue (audio_pcm_hw_find_any_enabled_, TYPE) (AudioState *s, HW *hw)
 | 
				
			|||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static HW *glue (audio_pcm_hw_find_any_passive_, TYPE) (AudioState *s)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    if (glue (s->nb_hw_voices_, TYPE)) {
 | 
					 | 
				
			||||||
        struct audio_driver *drv = s->drv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (audio_bug (AUDIO_FUNC, !drv)) {
 | 
					 | 
				
			||||||
            dolog ("No host audio driver\n");
 | 
					 | 
				
			||||||
            return NULL;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        HW *hw = audio_calloc (AUDIO_FUNC, 1, glue (drv->voice_size_, TYPE));
 | 
					 | 
				
			||||||
        if (!hw) {
 | 
					 | 
				
			||||||
            dolog ("Can not allocate voice `%s' size %d\n",
 | 
					 | 
				
			||||||
                   drv->name, glue (drv->voice_size_, TYPE));
 | 
					 | 
				
			||||||
            return NULL;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        LIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
 | 
					 | 
				
			||||||
        glue (s->nb_hw_voices_, TYPE) -= 1;
 | 
					 | 
				
			||||||
        return hw;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static HW *glue (audio_pcm_hw_find_specific_, TYPE) (
 | 
					static HW *glue (audio_pcm_hw_find_specific_, TYPE) (
 | 
				
			||||||
    AudioState *s,
 | 
					    AudioState *s,
 | 
				
			||||||
    HW *hw,
 | 
					    HW *hw,
 | 
				
			||||||
@ -159,23 +241,63 @@ static HW *glue (audio_pcm_hw_find_specific_, TYPE) (
 | 
				
			|||||||
static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s, audsettings_t *as)
 | 
					static HW *glue (audio_pcm_hw_add_new_, TYPE) (AudioState *s, audsettings_t *as)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    HW *hw;
 | 
					    HW *hw;
 | 
				
			||||||
 | 
					    struct audio_driver *drv = s->drv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    hw = glue (audio_pcm_hw_find_any_passive_, TYPE) (s);
 | 
					    if (!glue (s->nb_hw_voices_, TYPE)) {
 | 
				
			||||||
    if (hw) {
 | 
					 | 
				
			||||||
        hw->pcm_ops = s->drv->pcm_ops;
 | 
					 | 
				
			||||||
        if (!hw->pcm_ops) {
 | 
					 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (glue (audio_pcm_hw_init_, TYPE) (hw, as)) {
 | 
					    if (audio_bug (AUDIO_FUNC, !drv)) {
 | 
				
			||||||
            glue (audio_pcm_hw_gc_, TYPE) (s, &hw);
 | 
					        dolog ("No host audio driver\n");
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
        else {
 | 
					
 | 
				
			||||||
 | 
					    if (audio_bug (AUDIO_FUNC, !drv->pcm_ops)) {
 | 
				
			||||||
 | 
					        dolog ("Host audio driver without pcm_ops\n");
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    hw = audio_calloc (AUDIO_FUNC, 1, glue (drv->voice_size_, TYPE));
 | 
				
			||||||
 | 
					    if (!hw) {
 | 
				
			||||||
 | 
					        dolog ("Can not allocate voice `%s' size %d\n",
 | 
				
			||||||
 | 
					               drv->name, glue (drv->voice_size_, TYPE));
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    hw->pcm_ops = drv->pcm_ops;
 | 
				
			||||||
 | 
					    LIST_INIT (&hw->sw_head);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (glue (hw->pcm_ops->init_, TYPE) (hw, as)) {
 | 
				
			||||||
 | 
					        goto err0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (audio_bug (AUDIO_FUNC, hw->samples <= 0)) {
 | 
				
			||||||
 | 
					        dolog ("hw->samples=%d\n", hw->samples);
 | 
				
			||||||
 | 
					        goto err1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef DAC
 | 
				
			||||||
 | 
					    hw->clip = mixeng_clip
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					    hw->conv = mixeng_conv
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					        [hw->info.nchannels == 2]
 | 
				
			||||||
 | 
					        [hw->info.sign]
 | 
				
			||||||
 | 
					        [hw->info.swap_endian]
 | 
				
			||||||
 | 
					        [hw->info.bits == 16];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (glue (audio_pcm_hw_alloc_resources_, TYPE) (hw)) {
 | 
				
			||||||
 | 
					        goto err1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    LIST_INSERT_HEAD (&s->glue (hw_head_, TYPE), hw, entries);
 | 
				
			||||||
 | 
					    glue (s->nb_hw_voices_, TYPE) -= 1;
 | 
				
			||||||
    return hw;
 | 
					    return hw;
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 err1:
 | 
				
			||||||
 | 
					    glue (hw->pcm_ops->fini_, TYPE) (hw);
 | 
				
			||||||
 | 
					 err0:
 | 
				
			||||||
 | 
					    qemu_free (hw);
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -206,7 +328,8 @@ static HW *glue (audio_pcm_hw_add_, TYPE) (AudioState *s, audsettings_t *as)
 | 
				
			|||||||
static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
 | 
					static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
 | 
				
			||||||
    AudioState *s,
 | 
					    AudioState *s,
 | 
				
			||||||
    const char *sw_name,
 | 
					    const char *sw_name,
 | 
				
			||||||
    audsettings_t *as
 | 
					    audsettings_t *as,
 | 
				
			||||||
 | 
					    int sw_endian
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SW *sw;
 | 
					    SW *sw;
 | 
				
			||||||
@ -234,7 +357,7 @@ static SW *glue (audio_pcm_create_voice_pair_, TYPE) (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
 | 
					    glue (audio_pcm_hw_add_sw_, TYPE) (hw, sw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as)) {
 | 
					    if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, sw_name, as, sw_endian)) {
 | 
				
			||||||
        goto err3;
 | 
					        goto err3;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -256,6 +379,7 @@ static void glue (audio_close_, TYPE) (AudioState *s, SW *sw)
 | 
				
			|||||||
    glue (audio_pcm_hw_gc_, TYPE) (s, &sw->hw);
 | 
					    glue (audio_pcm_hw_gc_, TYPE) (s, &sw->hw);
 | 
				
			||||||
    qemu_free (sw);
 | 
					    qemu_free (sw);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw)
 | 
					void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (sw) {
 | 
					    if (sw) {
 | 
				
			||||||
@ -275,7 +399,8 @@ SW *glue (AUD_open_, TYPE) (
 | 
				
			|||||||
    const char *name,
 | 
					    const char *name,
 | 
				
			||||||
    void *callback_opaque ,
 | 
					    void *callback_opaque ,
 | 
				
			||||||
    audio_callback_fn_t callback_fn,
 | 
					    audio_callback_fn_t callback_fn,
 | 
				
			||||||
    audsettings_t *as
 | 
					    audsettings_t *as,
 | 
				
			||||||
 | 
					    int sw_endian
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    AudioState *s;
 | 
					    AudioState *s;
 | 
				
			||||||
@ -347,15 +472,16 @@ SW *glue (AUD_open_, TYPE) (
 | 
				
			|||||||
            goto fail;
 | 
					            goto fail;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as)) {
 | 
					        glue (audio_pcm_sw_fini_, TYPE) (sw);
 | 
				
			||||||
 | 
					        if (glue (audio_pcm_sw_init_, TYPE) (sw, hw, name, as, sw_endian)) {
 | 
				
			||||||
            goto fail;
 | 
					            goto fail;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as);
 | 
					        sw = glue (audio_pcm_create_voice_pair_, TYPE) (s, name, as, sw_endian);
 | 
				
			||||||
        if (!sw) {
 | 
					        if (!sw) {
 | 
				
			||||||
            dolog ("Failed to create voice `%s'\n", name);
 | 
					            dolog ("Failed to create voice `%s'\n", name);
 | 
				
			||||||
            goto fail;
 | 
					            return NULL;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -435,3 +561,5 @@ uint64_t glue (AUD_get_elapsed_usec_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
 | 
				
			|||||||
#undef TYPE
 | 
					#undef TYPE
 | 
				
			||||||
#undef HW
 | 
					#undef HW
 | 
				
			||||||
#undef SW
 | 
					#undef SW
 | 
				
			||||||
 | 
					#undef HWBUF
 | 
				
			||||||
 | 
					#undef NAME
 | 
				
			||||||
 | 
				
			|||||||
@ -75,11 +75,11 @@ static void GCC_FMT_ATTR (2, 3) oss_logerr (int err, const char *fmt, ...)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    va_list ap;
 | 
					    va_list ap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    AUD_vlog (AUDIO_CAP, fmt, ap);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    va_start (ap, fmt);
 | 
					    va_start (ap, fmt);
 | 
				
			||||||
    AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
 | 
					    AUD_vlog (AUDIO_CAP, fmt, ap);
 | 
				
			||||||
    va_end (ap);
 | 
					    va_end (ap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    AUD_log (AUDIO_CAP, "Reason: %s\n", strerror (err));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void GCC_FMT_ATTR (3, 4) oss_logerr2 (
 | 
					static void GCC_FMT_ATTR (3, 4) oss_logerr2 (
 | 
				
			||||||
@ -422,6 +422,8 @@ static int oss_init_out (HWVoiceOut *hw, audsettings_t *as)
 | 
				
			|||||||
    audfmt_e effective_fmt;
 | 
					    audfmt_e effective_fmt;
 | 
				
			||||||
    audsettings_t obt_as;
 | 
					    audsettings_t obt_as;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    oss->fd = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    req.fmt = aud_to_ossfmt (as->fmt);
 | 
					    req.fmt = aud_to_ossfmt (as->fmt);
 | 
				
			||||||
    req.freq = as->freq;
 | 
					    req.freq = as->freq;
 | 
				
			||||||
    req.nchannels = as->nchannels;
 | 
					    req.nchannels = as->nchannels;
 | 
				
			||||||
@ -565,6 +567,8 @@ static int oss_init_in (HWVoiceIn *hw, audsettings_t *as)
 | 
				
			|||||||
    audfmt_e effective_fmt;
 | 
					    audfmt_e effective_fmt;
 | 
				
			||||||
    audsettings_t obt_as;
 | 
					    audsettings_t obt_as;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    oss->fd = -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    req.fmt = aud_to_ossfmt (as->fmt);
 | 
					    req.fmt = aud_to_ossfmt (as->fmt);
 | 
				
			||||||
    req.freq = as->freq;
 | 
					    req.freq = as->freq;
 | 
				
			||||||
    req.nchannels = as->nchannels;
 | 
					    req.nchannels = as->nchannels;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user