Esempio n. 1
0
/**************************************************************************
 * 		      wodPlayer_ProcessMessages			[internal]
 */
static void wodPlayer_ProcessMessages(WINE_WAVEDEV* wwo)
{
    LPWAVEHDR           lpWaveHdr;
    enum win_wm_message	msg;
    DWORD_PTR		param;
    HANDLE		ev;
    int                 err;

    while (ALSA_RetrieveRingMessage(&wwo->msgRing, &msg, &param, &ev)) {
     TRACE("Received %s %lx\n", ALSA_getCmdString(msg), param);

	switch (msg) {
	case WINE_WM_PAUSING:
	    if ( snd_pcm_state(wwo->pcm) == SND_PCM_STATE_RUNNING )
	     {
                if ( snd_pcm_hw_params_can_pause(wwo->hw_params) )
		{
		    err = snd_pcm_pause(wwo->pcm, 1);
		    if ( err < 0 )
			ERR("pcm_pause failed: %s\n", snd_strerror(err));
		    wwo->state = WINE_WS_PAUSED;
		}
		else
		{
		    wodPlayer_Reset(wwo,FALSE);
		}
	     }
	    SetEvent(ev);
	    break;
	case WINE_WM_RESTARTING:
            if (wwo->state == WINE_WS_PAUSED)
            {
		if ( snd_pcm_state(wwo->pcm) == SND_PCM_STATE_PAUSED )
		 {
		    err = snd_pcm_pause(wwo->pcm, 0);
		    if ( err < 0 )
		        ERR("pcm_pause failed: %s\n", snd_strerror(err));
		 }
                wwo->state = WINE_WS_PLAYING;
            }
	    SetEvent(ev);
	    break;
	case WINE_WM_HEADER:
	    lpWaveHdr = (LPWAVEHDR)param;

	    /* insert buffer at the end of queue */
	    {
		LPWAVEHDR*	wh;
		for (wh = &(wwo->lpQueuePtr); *wh; wh = &((*wh)->lpNext));
		*wh = lpWaveHdr;
	    }
            if (!wwo->lpPlayPtr)
                wodPlayer_BeginWaveHdr(wwo,lpWaveHdr);
	    if (wwo->state == WINE_WS_STOPPED)
		wwo->state = WINE_WS_PLAYING;
	    break;
	case WINE_WM_RESETTING:
	    wodPlayer_Reset(wwo,TRUE);
	    SetEvent(ev);
	    break;
        case WINE_WM_BREAKLOOP:
            if (wwo->state == WINE_WS_PLAYING && wwo->lpLoopPtr != NULL) {
                /* ensure exit at end of current loop */
                wwo->dwLoops = 1;
            }
	    SetEvent(ev);
            break;
	case WINE_WM_CLOSING:
	    /* sanity check: this should not happen since the device must have been reset before */
	    if (wwo->lpQueuePtr || wwo->lpPlayPtr) ERR("out of sync\n");
	    wwo->hThread = 0;
	    wwo->state = WINE_WS_CLOSED;
	    SetEvent(ev);
	    ExitThread(0);
	    /* shouldn't go here */
	default:
	    FIXME("unknown message %d\n", msg);
	    break;
	}
    }
}
Esempio n. 2
0
/**
 * Set up the snd_pcm_t object which was opened by the caller.  Set up
 * the configured settings and the audio format.
 */
static bool
alsa_setup(struct alsa_data *ad, struct audio_format *audio_format,
	   GError **error)
{
	snd_pcm_hw_params_t *hwparams;
	snd_pcm_sw_params_t *swparams;
	unsigned int sample_rate = audio_format->sample_rate;
	unsigned int channels = audio_format->channels;
	snd_pcm_uframes_t alsa_buffer_size;
	snd_pcm_uframes_t alsa_period_size;
	int err;
	const char *cmd = NULL;
	int retry = MPD_ALSA_RETRY_NR;
	unsigned int period_time, period_time_ro;
	unsigned int buffer_time;

	period_time_ro = period_time = ad->period_time;
configure_hw:
	/* configure HW params */
	snd_pcm_hw_params_alloca(&hwparams);
	cmd = "snd_pcm_hw_params_any";
	err = snd_pcm_hw_params_any(ad->pcm, hwparams);
	if (err < 0)
		goto error;

	if (ad->use_mmap) {
		err = snd_pcm_hw_params_set_access(ad->pcm, hwparams,
						   SND_PCM_ACCESS_MMAP_INTERLEAVED);
		if (err < 0) {
			g_warning("Cannot set mmap'ed mode on ALSA device \"%s\":  %s\n",
				  alsa_device(ad), snd_strerror(-err));
			g_warning("Falling back to direct write mode\n");
			ad->use_mmap = false;
		} else
			ad->writei = snd_pcm_mmap_writei;
	}

	if (!ad->use_mmap) {
		cmd = "snd_pcm_hw_params_set_access";
		err = snd_pcm_hw_params_set_access(ad->pcm, hwparams,
						   SND_PCM_ACCESS_RW_INTERLEAVED);
		if (err < 0)
			goto error;
		ad->writei = snd_pcm_writei;
	}

	err = alsa_output_setup_format(ad->pcm, hwparams, audio_format);
	if (err < 0) {
		g_set_error(error, alsa_output_quark(), err,
			    "ALSA device \"%s\" does not support format %s: %s",
			    alsa_device(ad),
			    sample_format_to_string(audio_format->format),
			    snd_strerror(-err));
		return false;
	}

	err = snd_pcm_hw_params_set_channels_near(ad->pcm, hwparams,
						  &channels);
	if (err < 0) {
		g_set_error(error, alsa_output_quark(), err,
			    "ALSA device \"%s\" does not support %i channels: %s",
			    alsa_device(ad), (int)audio_format->channels,
			    snd_strerror(-err));
		return false;
	}
	audio_format->channels = (int8_t)channels;

	err = snd_pcm_hw_params_set_rate_near(ad->pcm, hwparams,
					      &sample_rate, NULL);
	if (err < 0 || sample_rate == 0) {
		g_set_error(error, alsa_output_quark(), err,
			    "ALSA device \"%s\" does not support %u Hz audio",
			    alsa_device(ad), audio_format->sample_rate);
		return false;
	}
	audio_format->sample_rate = sample_rate;

	snd_pcm_uframes_t buffer_size_min, buffer_size_max;
	snd_pcm_hw_params_get_buffer_size_min(hwparams, &buffer_size_min);
	snd_pcm_hw_params_get_buffer_size_max(hwparams, &buffer_size_max);
	unsigned buffer_time_min, buffer_time_max;
	snd_pcm_hw_params_get_buffer_time_min(hwparams, &buffer_time_min, 0);
	snd_pcm_hw_params_get_buffer_time_max(hwparams, &buffer_time_max, 0);
	g_debug("buffer: size=%u..%u time=%u..%u",
		(unsigned)buffer_size_min, (unsigned)buffer_size_max,
		buffer_time_min, buffer_time_max);

	snd_pcm_uframes_t period_size_min, period_size_max;
	snd_pcm_hw_params_get_period_size_min(hwparams, &period_size_min, 0);
	snd_pcm_hw_params_get_period_size_max(hwparams, &period_size_max, 0);
	unsigned period_time_min, period_time_max;
	snd_pcm_hw_params_get_period_time_min(hwparams, &period_time_min, 0);
	snd_pcm_hw_params_get_period_time_max(hwparams, &period_time_max, 0);
	g_debug("period: size=%u..%u time=%u..%u",
		(unsigned)period_size_min, (unsigned)period_size_max,
		period_time_min, period_time_max);

	if (ad->buffer_time > 0) {
		buffer_time = ad->buffer_time;
		cmd = "snd_pcm_hw_params_set_buffer_time_near";
		err = snd_pcm_hw_params_set_buffer_time_near(ad->pcm, hwparams,
							     &buffer_time, NULL);
		if (err < 0)
			goto error;
	} else {
		err = snd_pcm_hw_params_get_buffer_time(hwparams, &buffer_time,
							NULL);
		if (err < 0)
			buffer_time = 0;
	}

	if (period_time_ro == 0 && buffer_time >= 10000) {
		period_time_ro = period_time = buffer_time / 4;

		g_debug("default period_time = buffer_time/4 = %u/4 = %u",
			buffer_time, period_time);
	}

	if (period_time_ro > 0) {
		period_time = period_time_ro;
		cmd = "snd_pcm_hw_params_set_period_time_near";
		err = snd_pcm_hw_params_set_period_time_near(ad->pcm, hwparams,
							     &period_time, NULL);
		if (err < 0)
			goto error;
	}

	cmd = "snd_pcm_hw_params";
	err = snd_pcm_hw_params(ad->pcm, hwparams);
	if (err == -EPIPE && --retry > 0 && period_time_ro > 0) {
		period_time_ro = period_time_ro >> 1;
		goto configure_hw;
	} else if (err < 0)
void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
                  int encoding, float sampleRate, int sampleSizeInBits,
                  int frameSize, int channels,
                  int isSigned, int isBigEndian, int bufferSizeInBytes) {
    snd_pcm_format_mask_t* formatMask;
    snd_pcm_format_t format;
    int dir;
    int ret = 0;
    AlsaPcmInfo* info = NULL;
    /* snd_pcm_uframes_t is 64 bit on 64-bit systems */
    snd_pcm_uframes_t alsaPeriodSize = 0;
    snd_pcm_uframes_t alsaBufferSizeInFrames = 0;


    TRACE0("> DAUDIO_Open\n");
#ifdef USE_TRACE
    // for using ALSA debug dump methods
    if (ALSA_OUTPUT == NULL) {
        snd_output_stdio_attach(&ALSA_OUTPUT, stdout, 0);
    }
#endif

    info = (AlsaPcmInfo*) malloc(sizeof(AlsaPcmInfo));
    if (!info) {
        ERROR0("Out of memory\n");
        return NULL;
    }
    memset(info, 0, sizeof(AlsaPcmInfo));

    ret = openPCMfromDeviceID(deviceID, &(info->handle), isSource, FALSE /* do open device*/);
    if (ret == 0) {
        // set to blocking mode
        snd_pcm_nonblock(info->handle, 0);
        ret = snd_pcm_hw_params_malloc(&(info->hwParams));
        if (ret != 0) {
            ERROR1("  snd_pcm_hw_params_malloc returned error %d\n", ret);
        } else {
            ret = -1;
            if (getAlsaFormatFromFormat(&format, frameSize / channels, sampleSizeInBits,
                                        isSigned, isBigEndian, encoding)) {
                if (setHWParams(info,
                                sampleRate,
                                channels,
                                bufferSizeInBytes / frameSize,
                                format)) {
                    info->frameSize = frameSize;
#ifdef ALSA_PCM_NEW_HW_PARAMS_API
                    ret = snd_pcm_hw_params_get_period_size(info->hwParams, &alsaPeriodSize, &dir);
                    info->periodSize = (int) alsaPeriodSize;
                    if (ret < 0) {
                        ERROR1("ERROR: snd_pcm_hw_params_get_period: %s\n", snd_strerror(ret));
                    }
                    snd_pcm_hw_params_get_periods(info->hwParams, &(info->periods), &dir);
                    snd_pcm_hw_params_get_buffer_size(info->hwParams, &alsaBufferSizeInFrames);
                    info->bufferSizeInBytes = (int) alsaBufferSizeInFrames * frameSize;
#else
                    info->periodSize = snd_pcm_hw_params_get_period_size(info->hwParams, &dir);
                    info->periods = snd_pcm_hw_params_get_periods(info->hwParams, &dir);
                    info->bufferSizeInBytes = snd_pcm_hw_params_get_buffer_size(info->hwParams) * frameSize;
                    ret = 0;
#endif
                    TRACE3("  DAUDIO_Open: period size = %d frames, periods = %d. Buffer size: %d bytes.\n",
                           (int) info->periodSize, info->periods, info->bufferSizeInBytes);
                }
            }
        }
        if (ret == 0) {
            // set software parameters
            ret = snd_pcm_sw_params_malloc(&(info->swParams));
            if (ret != 0) {
                ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
            } else {
                if (!setSWParams(info)) {
                    ret = -1;
                }
            }
        }
        if (ret == 0) {
            // prepare device
            ret = snd_pcm_prepare(info->handle);
            if (ret < 0) {
                ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret));
            }
        }

#ifdef GET_POSITION_METHOD2
        if (ret == 0) {
            ret = snd_pcm_status_malloc(&(info->positionStatus));
            if (ret != 0) {
                ERROR1("ERROR in snd_pcm_status_malloc: %s\n", snd_strerror(ret));
            }
        }
#endif
    }
    if (ret != 0) {
        DAUDIO_Close((void*) info, isSource);
        info = NULL;
    } else {
        // set to non-blocking mode
        snd_pcm_nonblock(info->handle, 1);
        TRACE1("< DAUDIO_Open: Opened device successfully. Handle=%p\n",
               (void*) info->handle);
    }
    return (void*) info;
}
Esempio n. 4
0
File: mic.c Progetto: naeems/bkvoice
//音频采集线程
void * capture_audio_thread(void *para)
{
    int fdsound = 0;
    int readbyte = 0;


#if RECORD_CAPTURE_PCM
    FILE *fp = fopen("capture.pcm", "wb");
#endif

#if SILK_AUDIO_CODEC
    SKP_uint8 encode[MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES];
#endif

#if SILK_AUDIO_CODEC
    init_silk_encoder();//初始化silk codec
    printf("end of init silk encoder\n");
#endif














#if (SOUND_INTERFACE == SOUND_OSS)
    fdsound = open("/dev/dsp", O_RDONLY);
    if(fdsound<0)
    {
       perror("以只写方式打开音频设备");
       //return;
    }    

    printf("设置读音频设备参数 setup capture audio device parament\n");
    ioctl(fdsound, SNDCTL_DSP_SPEED, &Frequency);//采样频率
    ioctl(fdsound, SNDCTL_DSP_SETFMT, &format);//音频设备位宽
    ioctl(fdsound, SNDCTL_DSP_CHANNELS, &channels);//音频设备通道
    ioctl(fdsound, SNDCTL_DSP_SETFRAGMENT, &setting);//采样缓冲区

    while(flag_capture_audio)
    {
        if((readbyte=read(fdsound, pWriteHeader->buffer_capture, SAMPLERATE/1000*READMSFORONCE*sizeof(short))) < 0)
        {
            perror("读声卡数据");
        }
        else
        {
            //printf("readbyte=%d\n", readbyte);
#if RECORD_CAPTURE_PCM
            fwrite(pWriteHeader->buffer_capture, SAMPLERATE/1000*READMSFORONCE*sizeof(short), 1, fp);
#endif
            traceprintf("发送信号量 sem_capture\n");
            
            pWriteHeader->FrameNO = FrameNO++;

            time(&(pWriteHeader->time));
            //printf("cNO:%d, readbyte=%d,压缩后大小%d,pWriteHeader->vad=%d\n", pWriteHeader->FrameNO, readbyte, pWriteHeader->count_encode, pWriteHeader->vad);
            pthread_mutex_lock(&mutex_lock);
            n++;
            pWriteHeader->Valid = 1;
            pthread_mutex_unlock(&mutex_lock);
            pWriteHeader = pWriteHeader->pNext;
            sem_post(&sem_capture);
        }
    }
    close(fdsound);
#elif (SOUND_INTERFACE == SOUND_ALSA)
    printf("alsa xxxxxxxxxxxxxxx\n");
    struct timeval tv;
    struct timezone tz;
    /* Open PCM device for recording (capture). */
    rc = snd_pcm_open(&handle, "plughw:0,0", SND_PCM_STREAM_CAPTURE, 0);
    if (rc < 0) 
    {
        fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(rc));
        exit(1);
    }
    snd_pcm_hw_params_alloca(&params);/* Allocate a hardware parameters object. */    
    snd_pcm_hw_params_any(handle, params);/* Fill it in with default values. */

    /* Set the desired hardware parameters. */
    snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);/* Interleaved mode */
    snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);/* Signed 16-bit little-endian format */
    snd_pcm_hw_params_set_channels(handle, params, CHANNELS);/* Two channels (stereo), On for mono */
    val = SAMPLERATE;
    snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);/* SAMPLERATE bits/second sampling rate  */
    frames = SAMPLERATE/1000*READMSFORONCE;
    snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);/* Set period size to SAMPLES_FOR_EACH_TIME frames. */

    /* Write the parameters to the driver */
    rc = snd_pcm_hw_params(handle, params);
    if (rc < 0) 
    {
        fprintf(stderr, "unable to set hw parameters: %s\n",snd_strerror(rc));
        exit(1);
    }

    snd_pcm_hw_params_get_period_size(params, &frames, &dir);/* Use a buffer large enough to hold one period */
#if 0    
    size = frames * sizeof(short) * CHANNELS; /* 2 bytes/sample, 2 channels */
    buffer = (char *) malloc(size);
#endif
    snd_pcm_hw_params_get_period_time(params, &val, &dir);/* We want to loop for 5 seconds */
                                         
    while(flag_capture_audio)
    {
        rc = snd_pcm_readi(handle, pWriteHeader->buffer_capture, frames);
        printf("read rc=%d\n", rc);
        if (rc == -EPIPE) 
        {
            /* EPIPE means overrun */
            fprintf(stderr, "overrun occurred\n");
            snd_pcm_prepare(handle);
        } 
        else if (rc < 0) 
        {
            fprintf(stderr, "error from read: %s\n", snd_strerror(rc));
        } 
        else if (rc != (int)frames) 
        {
            fprintf(stderr, "short read, read %d frames\n", rc);
        }

#if RECORD_CAPTURE_PCM
            fwrite(pWriteHeader->buffer_capture, SAMPLERATE/1000*READMSFORONCE*sizeof(short), 1, fp);
#endif
#if 0
#if DEBUG_SAVE_CAPTURE_PCM
        rc = fwrite(pWriteHeader->buffer_capture, frames*sizeof(short), 1, fp);
        if(rc != 1)
        {
            fprintf(stderr, "write error %d\n", rc);
        }
#endif 
#endif
#if SILK_AUDIO_CODEC
            /* max payload size */
            int nbBytes = MAX_BYTES_PER_FRAME * MAX_INPUT_FRAMES;
            /* Silk Encoder */
            ret = SKP_Silk_SDK_Encode(psEnc, &encControl, pWriteHeader->buffer_capture, (SKP_int16)SAMPLERATE/1000*READMSFORONCE, pWriteHeader->buffer_encode, &nbBytes);
            pWriteHeader->count = nbBytes;
            printf("ret=%d, nbBytes=%d\n", ret, nbBytes);
            if(ret) 
            { 
                printf( "SKP_Silk_Encode returned %d, nbBytes=%d\n", ret, nbBytes);
                //break;
            }
#endif


#if SPEEX_AUDIO_CODEC
            speex_bits_reset(&bits);

            /*Encode the frame*/
            speex_encode_int(state, pWriteHeader->buffer_capture, &bits);

            /*Copy the bits to an array of char that can be written*/
            nbBytes = speex_bits_write(&bits, cbits, 200);

            printf("压缩后大小 %d\n", nbBytes);
#endif

        sem_post(&sem_capture); 
        sem_post(&sem_capture);                     
        gettimeofday(&tv, &tz);
        //((AUDIOBUFFER*)(pWriteHeader->buffer_capture))->FrameNO = FrameNO++;
        //((AUDIOBUFFER*)(pWriteHeader->buffer))->sec = tv.tv_sec;
        //((AUDIOBUFFER*)(pWriteHeader->buffer))->usec = tv.tv_usec;
        //printf("capture NO=%5d \n", FrameNO);
        pthread_mutex_lock(&mutex_lock);     
        //pWriteHeader = pWriteHeader->pNext;
        pWriteHeader->Valid = 1;
        n++;                
        pthread_mutex_unlock(&mutex_lock);  
        pWriteHeader = pWriteHeader->pNext;
        sem_post(&sem_capture);                     
        //traceprintf("发送信号量 sem_capture\n");
    }
                                         
    snd_pcm_drain(handle);
    snd_pcm_close(handle);
#if 0    
    free(buffer);
#endif  
#endif

#if RECORD_CAPTURE_PCM
    fclose(fp);
#endif

    printf("音频采集线程已经关闭 audio capture thread is closed\n");
    return NULL;
}
Esempio n. 5
0
int alsa_hook_hw_params(alsa_hook_t alsa_hook, snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
{
	struct alsa_hook_stream_s *stream;

	snd_pcm_format_t format;
	snd_pcm_uframes_t period_size;
	snd_pcm_access_t access;
	int dir, ret;

	alsa_hook_get_stream(alsa_hook, pcm, &stream);
	if (unlikely((ret = alsa_hook_lock_write(alsa_hook, stream))))
		return ret;

	glc_log(alsa_hook->glc, GLC_DEBUG, "alsa_hook",
		 "%p: creating/updating configuration for stream %d",
		 stream->pcm, stream->id);

	/* extract information */
	if (unlikely((ret = snd_pcm_hw_params_get_format(params, &format)) < 0))
		goto err;
	stream->flags = 0; /* zero flags */
	stream->format = pcm_fmt_to_glc_fmt(format);
	if (unlikely(!stream->format)) {
		glc_log(alsa_hook->glc, GLC_ERROR, "alsa_hook",
			"%p: unsupported audio format 0x%02x", stream->pcm, format);
		ret = ENOTSUP;
		goto err;
	}
	if (unlikely((ret = snd_pcm_hw_params_get_rate(params, &stream->rate, &dir)) < 0))
		goto err;
	if (unlikely((ret = snd_pcm_hw_params_get_channels(params, &stream->channels)) < 0))
		goto err;
	if (unlikely((ret = snd_pcm_hw_params_get_period_size(params, &period_size, NULL)) < 0))
		goto err;
	if (unlikely((ret = snd_pcm_hw_params_get_access(params, &access)) < 0))
		goto err;
	if ((access == SND_PCM_ACCESS_RW_INTERLEAVED) ||
	    (access == SND_PCM_ACCESS_MMAP_INTERLEAVED))
		stream->flags |= GLC_AUDIO_INTERLEAVED;
	else if (access == SND_PCM_ACCESS_MMAP_COMPLEX) {
		stream->flags |= GLC_AUDIO_INTERLEAVED; /* convert to interleaved */
		stream->complex = 1; /* do conversion */
	} else {
		glc_log(alsa_hook->glc, GLC_ERROR, "alsa_hook",
			 "%p: unsupported access mode 0x%02x", stream->pcm, access);
		ret = ENOTSUP;
		goto err;
	}

	glc_log(alsa_hook->glc, GLC_DEBUG, "alsa_hook",
		 "%p: %d channels, rate %d, flags 0x%02x",
		 stream->pcm, stream->channels, stream->rate, stream->flags);

	stream->fmt = 1;
	if (alsa_hook->started) {
		if (unlikely((ret = alsa_hook_stream_init(alsa_hook, stream))))
			goto err;
	}

	alsa_hook_unlock_write(alsa_hook, stream);
	return 0;

err:
	glc_log(alsa_hook->glc, GLC_ERROR, "alsa_hook",
		 "%p: can't extract hardware configuration: %s (%d)",
		 stream->pcm, snd_strerror(ret), ret);

	alsa_hook_unlock_write(alsa_hook, stream);
	return ret;
}
Esempio n. 6
0
int set_hwparams(snd_pcm_t *handle,
                        snd_pcm_hw_params_t *params,
                        snd_pcm_access_t access)
{
        unsigned int rrate;
        int err, dir;

	printf("set_hwparams\n");
        /* choose all parameters */
        err = snd_pcm_hw_params_any(handle, params);
        if (err < 0) {
                printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err));
                return err;
        }
        /* set the interleaved read/write format */
        err = snd_pcm_hw_params_set_access(handle, params, access);
        if (err < 0) {
                printf("Access type not available for playback: %s\n", snd_strerror(err));
                return err;
        }
        /* set the sample format */
        err = snd_pcm_hw_params_set_format(handle, params, format);
        if (err < 0) {
                printf("Sample format not available for playback: %s\n", snd_strerror(err));
                return err;
        }
        /* set the count of channels */
        err = snd_pcm_hw_params_set_channels(handle, params, channels);
        if (err < 0) {
                printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err));
                return err;
        }
        /* set the stream rate */
        rrate = rate;
        err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0);
        if (err < 0) {
                printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err));
                return err;
        }
        if (rrate != rate) {
                printf("Rate doesn't match (requested %iHz, get %iHz)\n", rate, err);
                return -EINVAL;
        }
	dir = 0;
        err = snd_pcm_hw_params_set_period_size_near(handle, params, &period_size, &dir);
        if (err < 0) {
                printf("Unable to set period size %i for playback: %s\n", (int)period_size, snd_strerror(err));
                return err;
        }
        err = snd_pcm_hw_params_set_periods(handle, params, periods, 0);
        if (err < 0) {
                printf("Unable to set periods %i for playback: %s\n", periods, snd_strerror(err));
                return err;
        }
        /* write the parameters to device */
        err = snd_pcm_hw_params(handle, params);
        if (err < 0) {
                printf("Unable to set hw params for playback: %s\n", snd_strerror(err));
                return err;
        }

        err = snd_pcm_hw_params_get_periods(params, &periods, &dir);
        if (err < 0) {
                printf("Unable to get periods for playback: %s\n", snd_strerror(err));
                return err;
        }
        err = snd_pcm_hw_params_get_period_size(params, &period_size, &dir);
        if (err < 0) {
                printf("Unable to get period size for playback: %s\n", snd_strerror(err));
                return err;
        }
        return 0;
}
Esempio n. 7
0
void* PORT_Open(INT32 mixerIndex) {
    char devname[16];
    snd_mixer_t* mixer_handle;
    int err;
    PortMixer* handle;

    TRACE0("> PORT_Open\n");
    sprintf(devname, ALSA_HARDWARE_CARD, (int) mixerIndex);
    if ((err = snd_mixer_open(&mixer_handle, 0)) < 0) {
	ERROR2("Mixer %s open error: %s", devname, snd_strerror(err));
	return NULL;
    }
    if ((err = snd_mixer_attach(mixer_handle, devname)) < 0) {
	ERROR2("Mixer attach %s error: %s", devname, snd_strerror(err));
	snd_mixer_close(mixer_handle);
	return NULL;
    }
    if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL)) < 0) {
	ERROR1("Mixer register error: %s", snd_strerror(err));
	snd_mixer_close(mixer_handle);
	return NULL;
    }
    err = snd_mixer_load(mixer_handle);
    if (err < 0) {
	ERROR2("Mixer %s load error: %s", devname, snd_strerror(err));
	snd_mixer_close(mixer_handle);
	return NULL;
    }
    handle = (PortMixer*) calloc(1, sizeof(PortMixer));
    if (handle == NULL) {
	ERROR0("malloc() failed.");
	snd_mixer_close(mixer_handle);
	return NULL;
    }
    handle->numElems = 0;
    handle->elems = (snd_mixer_elem_t**) calloc(MAX_ELEMS, sizeof(snd_mixer_elem_t*));
    if (handle->elems == NULL) {
	ERROR0("malloc() failed.");
	snd_mixer_close(mixer_handle);
	free(handle);
	return NULL;
    }
    handle->types = (INT32*) calloc(MAX_ELEMS, sizeof(INT32));
    if (handle->types == NULL) {
	ERROR0("malloc() failed.");
	snd_mixer_close(mixer_handle);
	free(handle->elems);
	free(handle);
	return NULL;
    }
    handle->controls = (PortControl*) calloc(MAX_CONTROLS, sizeof(PortControl));
    if (handle->controls == NULL) {
	ERROR0("malloc() failed.");
	snd_mixer_close(mixer_handle);
	free(handle->elems);
	free(handle->types);
	free(handle);
	return NULL;
    }
    handle->mixer_handle = mixer_handle;
    // necessary to initialize data structures
    PORT_GetPortCount(handle);
    TRACE0("< PORT_Open\n");
    return handle;
}
Esempio n. 8
0
/*******************************************************************************
 **
 ** Function        app_alsa_capture_loopback_open
 **
 ** Description     Open ALSA Capture channel (from loopback driver)
 **
 ** Parameters      p_open: Capture parameters
 **
 ** Returns         status
 **
 *******************************************************************************/
int app_alsa_capture_loopback_open(tAPP_ALSA_CAPTURE_OPEN *p_open)
{
    int mode = 0; /* Default is blocking */
    unsigned int nb_channels;
    int rv;
    snd_pcm_format_t format;
    snd_pcm_access_t access;

    APP_DEBUG0("Opening ALSA/Asound audio driver Capture");

    /* Sanity check if already opened */
    if (app_alsa_cb.p_capture_handle != NULL)
    {
        APP_DEBUG0("Capture was already opened");
    }

    /* check PCM Format parameter */
    format = app_alsa_get_pcm_format(p_open->format);
    if (format == SND_PCM_FORMAT_UNKNOWN)
    {
        return -1;
    }

    /* Check PCM access parameter */
    if (p_open->access == APP_ALSA_PCM_ACCESS_RW_INTERLEAVED)
    {
        access = SND_PCM_ACCESS_RW_INTERLEAVED;
    }
    else
    {
        APP_ERROR1("Unsupported PCM access:%d", p_open->access);
        return -1;
    }
    /* Check Blocking parameter */
    if (p_open->blocking == FALSE)
    {
        mode = SND_PCM_NONBLOCK;
    }

    /* check Stereo parameter */
    if (p_open->stereo)
    {
        nb_channels = 2;
    }
    else
    {
        nb_channels = 1;
    }

    /* Save the Capture open parameters */
    memcpy(&app_alsa_cb.capture_param, p_open, sizeof(app_alsa_cb.capture_param));

    /* Open ALSA driver */
    rv = snd_pcm_open(&app_alsa_cb.p_capture_handle, alsa_device_loopback,
            SND_PCM_STREAM_CAPTURE, mode);
    if (rv < 0)
    {
        APP_ERROR1("unable to open ALSA loopback device in Capture mode:%s", snd_strerror(rv));
        return rv;
    }
    APP_DEBUG0("ALSA loopback driver opened in Capture mode");

    /* Configure ALSA driver with PCM parameters */
    rv = snd_pcm_set_params(app_alsa_cb.p_capture_handle,
            format,
            access,
            nb_channels,
            p_open->sample_rate,
            1, /* SW resample */
            p_open->latency);
    if (rv)
    {
        APP_ERROR1("Unable to config ALSA device:%s", snd_strerror(rv));
        snd_pcm_close(app_alsa_cb.p_capture_handle);
        app_alsa_cb.p_capture_handle = NULL;
        return rv;
    }
    return 0;
}
Esempio n. 9
0
int main(int argc, char **argv)
{
   register int  err;
   int           cardNum;

   // Start with first card
   cardNum = -1;

   for (;;)
   {
      snd_ctl_t *cardHandle;

      // Get next sound card's card number. When "cardNum" == -1, then ALSA
      // fetches the first card
      if ((err = snd_card_next(&cardNum)) < 0)
      {
         printf("Can't get the next card number: %s\n", snd_strerror(err));
         break;
      }

      // No more cards? ALSA sets "cardNum" to -1 if so
      if (cardNum < 0) break;

      // Open this card's control interface. We specify only the card number -- not
      // any device nor sub-device too
      {
      char   str[64];

      sprintf(str, "hw:%i", cardNum);
      if ((err = snd_ctl_open(&cardHandle, str, 0)) < 0)
      {
         printf("Can't open card %i: %s\n", cardNum, snd_strerror(err));
         continue;
      }
      }

      {
      int      devNum, totalDevices;

      // No waveform devices found yet
      totalDevices = 0;

      // Start with the first wave device on this card
      devNum = -1;
		
      for (;;)
      {
         // Get the number of the next wave device on this card
         if ((err = snd_ctl_pcm_next_device(cardHandle, &devNum)) < 0)
         {
            printf("Can't get next wave device number: %s\n", snd_strerror(err));
            break;
         }

         // No more wave devices on this card? ALSA sets "devNum" to -1 if so.
         // NOTE: It's possible that this sound card may have no wave devices on it
         // at all, for example if it's only a MIDI card
         if (devNum < 0) break;

         // Another wave device found on this card, so bump the count
         ++totalDevices;
      }

      printf("Found %i digital audio devices on card %i\n", totalDevices, cardNum);
      }

      // Close the card's control interface after we're done with it
      snd_ctl_close(cardHandle);
   }

   // ALSA allocates some mem to load its config file when we call some of the
   // above functions. Now that we're done getting the info, let's tell ALSA
   // to unload the info and free up that mem
   snd_config_update_free_global();
}
Esempio n. 10
0
static int
mixer_open(void)
{
  snd_mixer_elem_t *elem;
  snd_mixer_elem_t *master;
  snd_mixer_elem_t *pcm;
  snd_mixer_elem_t *custom;
  snd_mixer_selem_id_t *sid;
  int ret;

  ret = snd_mixer_open(&mixer_hdl, 0);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Failed to open mixer: %s\n", snd_strerror(ret));

      mixer_hdl = NULL;
      return -1;
    }

  ret = snd_mixer_attach(mixer_hdl, card_name);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Failed to attach mixer: %s\n", snd_strerror(ret));

      goto out_close;
    }

  ret = snd_mixer_selem_register(mixer_hdl, NULL, NULL);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Failed to register mixer: %s\n", snd_strerror(ret));

      goto out_detach;
    }

  ret = snd_mixer_load(mixer_hdl);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Failed to load mixer: %s\n", snd_strerror(ret));

      goto out_detach;
    }

  /* Grab interesting elements */
  snd_mixer_selem_id_alloca(&sid);

  pcm = NULL;
  master = NULL;
  custom = NULL;
  for (elem = snd_mixer_first_elem(mixer_hdl); elem; elem = snd_mixer_elem_next(elem))
    {
      snd_mixer_selem_get_id(elem, sid);

      if (mixer_name && (strcmp(snd_mixer_selem_id_get_name(sid), mixer_name) == 0))
	{
	  custom = elem;
	  break;
	}
      else if (strcmp(snd_mixer_selem_id_get_name(sid), "PCM") == 0)
        pcm = elem;
      else if (strcmp(snd_mixer_selem_id_get_name(sid), "Master") == 0)
	master = elem;
    }

  if (mixer_name)
    {
      if (custom)
	vol_elem = custom;
      else
	{
	  DPRINTF(E_LOG, L_LAUDIO, "Failed to open configured mixer element '%s'\n", mixer_name);

	  goto out_detach;
	}
    }
  else if (pcm)
    vol_elem = pcm;
  else if (master)
    vol_elem = master;
  else
    {
      DPRINTF(E_LOG, L_LAUDIO, "Failed to open PCM or Master mixer element\n");

      goto out_detach;
    }

  /* Get min & max volume */
  snd_mixer_selem_get_playback_volume_range(vol_elem, &vol_min, &vol_max);

  return 0;

 out_detach:
  snd_mixer_detach(mixer_hdl, card_name);
 out_close:
  snd_mixer_close(mixer_hdl);
  mixer_hdl = NULL;
  vol_elem = NULL;

  return -1;
}
Esempio n. 11
0
static int
laudio_alsa_open(void)
{
  snd_pcm_hw_params_t *hw_params;
  snd_pcm_uframes_t bufsize;
  snd_pcm_uframes_t period_size;
  int ret;

  hw_params = NULL;

  ret = snd_pcm_open(&hdl, card_name, SND_PCM_STREAM_PLAYBACK, 0);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not open playback device: %s\n", snd_strerror(ret));

      return -1;
    }

  /* HW params */
  ret = snd_pcm_hw_params_malloc(&hw_params);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not allocate hw params: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  ret = snd_pcm_hw_params_any(hdl, hw_params);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not retrieve hw params: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  ret = snd_pcm_hw_params_set_access(hdl, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not set access method: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  ret = snd_pcm_hw_params_set_format(hdl, hw_params, SND_PCM_FORMAT_S16_LE);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not set S16LE format: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  ret = snd_pcm_hw_params_set_channels(hdl, hw_params, 2);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not set stereo output: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  ret = snd_pcm_hw_params_set_rate(hdl, hw_params, 44100, 0);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Hardware doesn't support 44.1 kHz: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  ret = snd_pcm_hw_params_get_buffer_size_max(hw_params, &bufsize);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not get max buffer size: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  DPRINTF(E_DBG, L_LAUDIO, "Max buffer size is %lu samples\n", bufsize);

  ret = snd_pcm_hw_params_set_buffer_size_max(hdl, hw_params, &bufsize);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not set buffer size to max: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  // With a small period size we seem to get underruns because the period time
  // passes before we manage to feed with samples (if the player is slightly
  // behind - especially critical during startup when the buffer is low)
  // Internet suggests period_size should be /2 bufsize, but default seems to be
  // much lower, so compromise on /4 (but not more than 65536 frames = almost 2 sec).
  period_size = bufsize / 4;
  if (period_size > 65536)
    period_size = 65536;

  ret = snd_pcm_hw_params_set_period_size_near(hdl, hw_params, &period_size, NULL);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not set period size: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  DPRINTF(E_DBG, L_LAUDIO, "Buffer size is %lu samples, period size is %lu samples\n", bufsize, period_size);

  ret = snd_pcm_hw_params(hdl, hw_params);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not set hw params: %s\n", snd_strerror(ret));

      goto out_fail;
    }

  snd_pcm_hw_params_free(hw_params);
  hw_params = NULL;

  pcm_pos = 0;
  pcm_last_error = 0;
  pcm_recovery = 0;
  pcm_buf_threshold = ((bufsize - period_size) / AIRTUNES_V2_PACKET_SAMPLES) * AIRTUNES_V2_PACKET_SAMPLES;
  pcm_period_size = period_size;

  ret = mixer_open();
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not open mixer\n");

      goto out_fail;
    }

  update_status(LAUDIO_OPEN);

  return 0;

 out_fail:
  if (hw_params)
    snd_pcm_hw_params_free(hw_params);

  snd_pcm_close(hdl);
  hdl = NULL;

  return -1;
}
Esempio n. 12
0
static int
laudio_alsa_start(uint64_t cur_pos, uint64_t next_pkt)
{
  snd_output_t *output;
  char *debug_pcm_cfg;
  int ret;

  ret = snd_pcm_prepare(hdl);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not prepare PCM device: %s\n", snd_strerror(ret));

      return -1;
    }

  DPRINTF(E_DBG, L_LAUDIO, "Start local audio curpos %" PRIu64 ", next_pkt %" PRIu64 "\n", cur_pos, next_pkt);

  /* Make pcm_pos the rtptime of the packet containing cur_pos */
  pcm_pos = next_pkt;
  while (pcm_pos > cur_pos)
    pcm_pos -= AIRTUNES_V2_PACKET_SAMPLES;

  pcm_start_pos = next_pkt + pcm_period_size;

  /* Compensate period size, otherwise get_pos won't be correct */
  pcm_pos += pcm_period_size;

  DPRINTF(E_DBG, L_LAUDIO, "PCM pos %" PRIu64 ", start pos %" PRIu64 "\n", pcm_pos, pcm_start_pos);

  pcm_pkt_head = NULL;
  pcm_pkt_tail = NULL;

  pcm_last_error = 0;
  pcm_recovery = 0;

  // alsa doesn't actually seem to wait for this threshold?
  ret = laudio_alsa_set_start_threshold(pcm_buf_threshold);
  if (ret < 0)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Could not set PCM start threshold for local audio start\n");

      return -1;
    }

  // Dump PCM config data for E_DBG logging
  ret = snd_output_buffer_open(&output);
  if (ret == 0)
    {
      if (snd_pcm_dump_setup(hdl, output) == 0)
	{
	  snd_output_buffer_string(output, &debug_pcm_cfg);
	  DPRINTF(E_DBG, L_LAUDIO, "Dump of sound device config:\n%s\n", debug_pcm_cfg);
	}

      snd_output_close(output);
    }

  update_status(LAUDIO_STARTED);

  return 0;
}
Esempio n. 13
0
static void
laudio_alsa_write(uint8_t *buf, uint64_t rtptime)
{
  struct pcm_packet *pkt;
  snd_pcm_sframes_t nsamp;
  int ret;

  pkt = (struct pcm_packet *)malloc(sizeof(struct pcm_packet));
  if (!pkt)
    {
      DPRINTF(E_LOG, L_LAUDIO, "Out of memory for PCM pkt\n");

      update_status(LAUDIO_FAILED);
      return;
    }

  memcpy(pkt->samples, buf, sizeof(pkt->samples));

  pkt->rtptime = rtptime;
  pkt->offset = 0;
  pkt->next = NULL;

  if (pcm_pkt_tail)
    {
      pcm_pkt_tail->next = pkt;
      pcm_pkt_tail = pkt;
    }
  else
    {
      pcm_pkt_head = pkt;
      pcm_pkt_tail = pkt;
    }

  if (pcm_pos < pcm_pkt_head->rtptime)
    {
      pcm_pos += AIRTUNES_V2_PACKET_SAMPLES;

      return;
    }
  else if ((pcm_status != LAUDIO_RUNNING) && (pcm_pos >= pcm_start_pos))
    {
      update_status(LAUDIO_RUNNING);
    }

  pkt = pcm_pkt_head;

  while (pkt)
    {
      if (pcm_recovery)
	{
	  ret = laudio_alsa_xrun_recover(0);
	  if ((ret == 2) && (pcm_recovery < 10))
	    return;
	  else
	    {
	      if (ret == 2)
		DPRINTF(E_LOG, L_LAUDIO, "Couldn't recover PCM device after 10 tries, aborting\n");

	      update_status(LAUDIO_FAILED);
	      return;
	    }
	}

      nsamp = snd_pcm_writei(hdl, pkt->samples + pkt->offset, BTOS(sizeof(pkt->samples) - pkt->offset));
      if ((nsamp == -EPIPE) || (nsamp == -ESTRPIPE))
	{
	  ret = laudio_alsa_xrun_recover(nsamp);
	  if ((ret < 0) || (ret == 1))
	    {
	      if (ret < 0)
		DPRINTF(E_LOG, L_LAUDIO, "PCM write error: %s\n", snd_strerror(ret));

	      update_status(LAUDIO_FAILED);
	      return;
	    }
	  else if (ret != 0)
	    return;

	  continue;
	}
      else if (nsamp < 0)
	{
	  DPRINTF(E_LOG, L_LAUDIO, "PCM write error: %s\n", snd_strerror(nsamp));

	  update_status(LAUDIO_FAILED);
	  return;
	}

      pcm_last_error = 0;
      pcm_pos += nsamp;

      pkt->offset += STOB(nsamp);
      if (pkt->offset == sizeof(pkt->samples))
	{
	  pcm_pkt_head = pkt->next;

	  if (pkt == pcm_pkt_tail)
	    pcm_pkt_tail = NULL;

	  free(pkt);

	  pkt = pcm_pkt_head;
	}

      /* Don't let ALSA fill up the buffer too much */
      if (nsamp == AIRTUNES_V2_PACKET_SAMPLES)
	return;
    }
}
Esempio n. 14
0
/**************************************************************************
 * 				wodOpen				[internal]
 */
static DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
{
    WINE_WAVEDEV*	        wwo;
    snd_pcm_t *                 pcm = NULL;
    snd_hctl_t *                hctl = NULL;
    snd_pcm_hw_params_t *       hw_params = NULL;
    snd_pcm_sw_params_t *       sw_params;
    snd_pcm_access_t            access;
    snd_pcm_format_t            format = -1;
    unsigned int                rate;
    unsigned int                buffer_time = 120000;
    unsigned int                period_time = 22000;
    snd_pcm_uframes_t           buffer_size;
    snd_pcm_uframes_t           period_size;
    int                         flags;
    int                         err=0;
    int                         dir=0;
    DWORD                       retcode = 0;

    TRACE("(%u, %p, %08X);\n", wDevID, lpDesc, dwFlags);
    if (lpDesc == NULL) {
	WARN("Invalid Parameter !\n");
	return MMSYSERR_INVALPARAM;
    }
    if (wDevID >= ALSA_WodNumDevs) {
	TRACE("Asked for device %d, but only %d known!\n", wDevID, ALSA_WodNumDevs);
	return MMSYSERR_BADDEVICEID;
    }

    /* only PCM format is supported so far... */
    if (!ALSA_supportedFormat(lpDesc->lpFormat)) {
	WARN("Bad format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
	     lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
	     lpDesc->lpFormat->nSamplesPerSec);
	return WAVERR_BADFORMAT;
    }

    if (dwFlags & WAVE_FORMAT_QUERY) {
	TRACE("Query format: tag=%04X nChannels=%d nSamplesPerSec=%d !\n",
	     lpDesc->lpFormat->wFormatTag, lpDesc->lpFormat->nChannels,
	     lpDesc->lpFormat->nSamplesPerSec);
	return MMSYSERR_NOERROR;
    }

    wwo = &WOutDev[wDevID];

    if (wwo->pcm != NULL) {
        WARN("%d already allocated\n", wDevID);
        return MMSYSERR_ALLOCATED;
    }

    if (dwFlags & WAVE_DIRECTSOUND)
        FIXME("Why are we called with DirectSound flag? It doesn't use MMSYSTEM any more\n");
        /* not supported, ignore it */
    dwFlags &= ~WAVE_DIRECTSOUND;

    flags = SND_PCM_NONBLOCK;

    if ( (err = snd_pcm_open(&pcm, wwo->pcmname, SND_PCM_STREAM_PLAYBACK, flags)) < 0)
    {
        ERR("Error open: %s\n", snd_strerror(err));
	return MMSYSERR_NOTENABLED;
    }

    if (wwo->ctlname)
    {
        err = snd_hctl_open(&hctl, wwo->ctlname, 0);
        if (err >= 0)
        {
            snd_hctl_load(hctl);
        }
        else
        {
            WARN("Could not open hctl for [%s]: %s\n", wwo->ctlname, snd_strerror(err));
            hctl = NULL;
        }
    }

    wwo->wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);

    wwo->waveDesc = *lpDesc;
    ALSA_copyFormat(lpDesc->lpFormat, &wwo->format);

    TRACE("Requested this format: %dx%dx%d %s\n",
          wwo->format.Format.nSamplesPerSec,
          wwo->format.Format.wBitsPerSample,
          wwo->format.Format.nChannels,
          ALSA_getFormat(wwo->format.Format.wFormatTag));

    if (wwo->format.Format.wBitsPerSample == 0) {
	WARN("Resetting zeroed wBitsPerSample\n");
	wwo->format.Format.wBitsPerSample = 8 *
	    (wwo->format.Format.nAvgBytesPerSec /
	     wwo->format.Format.nSamplesPerSec) /
	    wwo->format.Format.nChannels;
    }

#define EXIT_ON_ERROR(f,e,txt) do \
{ \
    int err; \
    if ( (err = (f) ) < 0) \
    { \
	WARN(txt ": %s\n", snd_strerror(err)); \
	retcode=e; \
	goto errexit; \
    } \
} while(0)

    sw_params = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, snd_pcm_sw_params_sizeof() );
    snd_pcm_hw_params_malloc(&hw_params);
    if (! hw_params)
    {
        retcode = MMSYSERR_NOMEM;
        goto errexit;
    }
    snd_pcm_hw_params_any(pcm, hw_params);

    access = SND_PCM_ACCESS_MMAP_INTERLEAVED;
    if ( ( err = snd_pcm_hw_params_set_access(pcm, hw_params, access ) ) < 0) {
        WARN("mmap not available. switching to standard write.\n");
        access = SND_PCM_ACCESS_RW_INTERLEAVED;
	EXIT_ON_ERROR( snd_pcm_hw_params_set_access(pcm, hw_params, access ), MMSYSERR_INVALPARAM, "unable to set access for playback");
	wwo->write = snd_pcm_writei;
    }
    else
	wwo->write = snd_pcm_mmap_writei;

    if ((err = snd_pcm_hw_params_set_channels(pcm, hw_params, wwo->format.Format.nChannels)) < 0) {
        WARN("unable to set required channels: %d\n", wwo->format.Format.nChannels);
        EXIT_ON_ERROR( snd_pcm_hw_params_set_channels(pcm, hw_params, wwo->format.Format.nChannels ), WAVERR_BADFORMAT, "unable to set required channels" );
    }

    if ((wwo->format.Format.wFormatTag == WAVE_FORMAT_PCM) ||
        ((wwo->format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) &&
        IsEqualGUID(&wwo->format.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))) {
        format = (wwo->format.Format.wBitsPerSample == 8) ? SND_PCM_FORMAT_U8 :
                 (wwo->format.Format.wBitsPerSample == 16) ? SND_PCM_FORMAT_S16_LE :
                 (wwo->format.Format.wBitsPerSample == 24) ? SND_PCM_FORMAT_S24_3LE :
                 (wwo->format.Format.wBitsPerSample == 32) ? SND_PCM_FORMAT_S32_LE : -1;
    } else if ((wwo->format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) &&
        IsEqualGUID(&wwo->format.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)){
        format = (wwo->format.Format.wBitsPerSample == 32) ? SND_PCM_FORMAT_FLOAT_LE : -1;
    } else {
        ERR("invalid format: %0x04x\n", wwo->format.Format.wFormatTag);
        retcode = WAVERR_BADFORMAT;
        goto errexit;
    }

    if ((err = snd_pcm_hw_params_set_format(pcm, hw_params, format)) < 0) {
        WARN("unable to set required format: %s\n", snd_pcm_format_name(format));
        EXIT_ON_ERROR( snd_pcm_hw_params_set_format(pcm, hw_params, format), WAVERR_BADFORMAT, "unable to set required format" );
    }

    rate = wwo->format.Format.nSamplesPerSec;
    dir=0;
    err = snd_pcm_hw_params_set_rate_near(pcm, hw_params, &rate, &dir);
    if (err < 0) {
	WARN("Rate %d Hz not available for playback: %s\n", wwo->format.Format.nSamplesPerSec, snd_strerror(rate));
        retcode = WAVERR_BADFORMAT;
        goto errexit;
    }
    if (!ALSA_NearMatch(rate, wwo->format.Format.nSamplesPerSec)) {
        WARN("Rate doesn't match (requested %d Hz, got %d Hz)\n", wwo->format.Format.nSamplesPerSec, rate);
        retcode = WAVERR_BADFORMAT;
        goto errexit;
    }

    TRACE("Got this format: %dx%dx%d %s\n",
          wwo->format.Format.nSamplesPerSec,
          wwo->format.Format.wBitsPerSample,
          wwo->format.Format.nChannels,
          ALSA_getFormat(wwo->format.Format.wFormatTag));

    dir=0;
    EXIT_ON_ERROR( snd_pcm_hw_params_set_buffer_time_near(pcm, hw_params, &buffer_time, &dir), MMSYSERR_INVALPARAM, "unable to set buffer time");
    dir=0;
    EXIT_ON_ERROR( snd_pcm_hw_params_set_period_time_near(pcm, hw_params, &period_time, &dir), MMSYSERR_INVALPARAM, "unable to set period time");

    EXIT_ON_ERROR( snd_pcm_hw_params(pcm, hw_params), MMSYSERR_INVALPARAM, "unable to set hw params for playback");

    err = snd_pcm_hw_params_get_period_size(hw_params, &period_size, &dir);
    err = snd_pcm_hw_params_get_buffer_size(hw_params, &buffer_size);

    snd_pcm_sw_params_current(pcm, sw_params);

    EXIT_ON_ERROR( snd_pcm_sw_params_set_start_threshold(pcm, sw_params, 1), MMSYSERR_ERROR, "unable to set start threshold");
    EXIT_ON_ERROR( snd_pcm_sw_params_set_silence_size(pcm, sw_params, 0), MMSYSERR_ERROR, "unable to set silence size");
    EXIT_ON_ERROR( snd_pcm_sw_params_set_avail_min(pcm, sw_params, period_size), MMSYSERR_ERROR, "unable to set avail min");
    EXIT_ON_ERROR( snd_pcm_sw_params_set_silence_threshold(pcm, sw_params, 0), MMSYSERR_ERROR, "unable to set silence threshold");
    EXIT_ON_ERROR( snd_pcm_sw_params(pcm, sw_params), MMSYSERR_ERROR, "unable to set sw params for playback");
#undef EXIT_ON_ERROR

    snd_pcm_prepare(pcm);

    if (TRACE_ON(wave))
	ALSA_TraceParameters(hw_params, sw_params, FALSE);

    /* now, we can save all required data for later use... */

    wwo->dwBufferSize = snd_pcm_frames_to_bytes(pcm, buffer_size);
    wwo->lpQueuePtr = wwo->lpPlayPtr = wwo->lpLoopPtr = NULL;
    wwo->dwPlayedTotal = wwo->dwWrittenTotal = 0;
    wwo->dwPartialOffset = 0;

    ALSA_InitRingMessage(&wwo->msgRing);

    wwo->hStartUpEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
    wwo->hThread = CreateThread(NULL, 0, wodPlayer, (LPVOID)(DWORD_PTR)wDevID, 0, &(wwo->dwThreadID));
    if (wwo->hThread)
        SetThreadPriority(wwo->hThread, THREAD_PRIORITY_TIME_CRITICAL);
    else
    {
        ERR("Thread creation for the wodPlayer failed!\n");
        CloseHandle(wwo->hStartUpEvent);
        retcode = MMSYSERR_NOMEM;
        goto errexit;
    }
    WaitForSingleObject(wwo->hStartUpEvent, INFINITE);
    CloseHandle(wwo->hStartUpEvent);
    wwo->hStartUpEvent = INVALID_HANDLE_VALUE;

    TRACE("handle=%p\n", pcm);
    TRACE("wBitsPerSample=%u, nAvgBytesPerSec=%u, nSamplesPerSec=%u, nChannels=%u nBlockAlign=%u!\n",
	  wwo->format.Format.wBitsPerSample, wwo->format.Format.nAvgBytesPerSec,
	  wwo->format.Format.nSamplesPerSec, wwo->format.Format.nChannels,
	  wwo->format.Format.nBlockAlign);

    HeapFree( GetProcessHeap(), 0, sw_params );
    wwo->pcm = pcm;
    wwo->hctl = hctl;
    if ( wwo->hw_params )
	snd_pcm_hw_params_free(wwo->hw_params);
    wwo->hw_params = hw_params;

    return wodNotifyClient(wwo, WOM_OPEN, 0L, 0L);

errexit:
    if (pcm)
        snd_pcm_close(pcm);

    if (hctl)
    {
        snd_hctl_free(hctl);
        snd_hctl_close(hctl);
    }

    if ( hw_params )
	snd_pcm_hw_params_free(hw_params);

    HeapFree( GetProcessHeap(), 0, sw_params );
    if (wwo->msgRing.ring_buffer_size > 0)
        ALSA_DestroyRingMessage(&wwo->msgRing);

    return retcode;
}
Esempio n. 15
0
/*
    open & setup audio device
    return: 1=success 0=fail
*/
static int init(int rate_hz, int channels, int format, int flags)
{
    int err;
    int block;
    strarg_t device;
    snd_pcm_uframes_t bufsize;
    snd_pcm_uframes_t boundary;
    opt_t subopts[] = {
      {"block", OPT_ARG_BOOL, &block, NULL},
      {"device", OPT_ARG_STR, &device, (opt_test_f)str_maxlen},
      {NULL}
    };

    char alsa_device[ALSA_DEVICE_SIZE + 1];
    // make sure alsa_device is null-terminated even when using strncpy etc.
    memset(alsa_device, 0, ALSA_DEVICE_SIZE + 1);

    mp_msg(MSGT_AO,MSGL_V,"alsa-init: requested format: %d Hz, %d channels, %x\n", rate_hz,
	channels, format);
    alsa_handler = NULL;
#if SND_LIB_VERSION >= 0x010005
    mp_msg(MSGT_AO,MSGL_V,"alsa-init: using ALSA %s\n", snd_asoundlib_version());
#else
    mp_msg(MSGT_AO,MSGL_V,"alsa-init: compiled for ALSA-%s\n", SND_LIB_VERSION_STR);
#endif

    snd_lib_error_set_handler(alsa_error_handler);
    
    ao_data.samplerate = rate_hz;
    ao_data.format = format;
    ao_data.channels = channels;

    switch (format)
      {
      case AF_FORMAT_S8:
	alsa_format = SND_PCM_FORMAT_S8;
	break;
      case AF_FORMAT_U8:
	alsa_format = SND_PCM_FORMAT_U8;
	break;
      case AF_FORMAT_U16_LE:
	alsa_format = SND_PCM_FORMAT_U16_LE;
	break;
      case AF_FORMAT_U16_BE:
	alsa_format = SND_PCM_FORMAT_U16_BE;
	break;
#ifndef WORDS_BIGENDIAN
      case AF_FORMAT_AC3:
#endif
      case AF_FORMAT_S16_LE:
	alsa_format = SND_PCM_FORMAT_S16_LE;
	break;
#ifdef WORDS_BIGENDIAN
      case AF_FORMAT_AC3:
#endif
      case AF_FORMAT_S16_BE:
	alsa_format = SND_PCM_FORMAT_S16_BE;
	break;
      case AF_FORMAT_U32_LE:
	alsa_format = SND_PCM_FORMAT_U32_LE;
	break;
      case AF_FORMAT_U32_BE:
	alsa_format = SND_PCM_FORMAT_U32_BE;
	break;
      case AF_FORMAT_S32_LE:
	alsa_format = SND_PCM_FORMAT_S32_LE;
	break;
      case AF_FORMAT_S32_BE:
	alsa_format = SND_PCM_FORMAT_S32_BE;
	break;
      case AF_FORMAT_FLOAT_LE:
	alsa_format = SND_PCM_FORMAT_FLOAT_LE;
	break;
      case AF_FORMAT_FLOAT_BE:
	alsa_format = SND_PCM_FORMAT_FLOAT_BE;
	break;
      case AF_FORMAT_MU_LAW:
	alsa_format = SND_PCM_FORMAT_MU_LAW;
	break;
      case AF_FORMAT_A_LAW:
	alsa_format = SND_PCM_FORMAT_A_LAW;
	break;

      default:
	alsa_format = SND_PCM_FORMAT_MPEG; //? default should be -1
	break;
      }
    
    //subdevice parsing
    // set defaults
    block = 1;
    /* switch for spdif
     * sets opening sequence for SPDIF
     * sets also the playback and other switches 'on the fly'
     * while opening the abstract alias for the spdif subdevice
     * 'iec958'
     */
    if (format == AF_FORMAT_AC3) {
	device.str = "iec958";
	mp_msg(MSGT_AO,MSGL_V,"alsa-spdif-init: playing AC3, %i channels\n", channels);
    }
  else
        /* in any case for multichannel playback we should select
         * appropriate device
         */
        switch (channels) {
	case 1:
	case 2:
	  device.str = "default";
	  mp_msg(MSGT_AO,MSGL_V,"alsa-init: setup for 1/2 channel(s)\n");
	  break;
	case 4:
	  if (alsa_format == SND_PCM_FORMAT_FLOAT_LE)
	    // hack - use the converter plugin
	    device.str = "plug:surround40";
	  else
	    device.str = "surround40";
	  mp_msg(MSGT_AO,MSGL_V,"alsa-init: device set to surround40\n");
	  break;
	case 6:
	  if (alsa_format == SND_PCM_FORMAT_FLOAT_LE)
	    device.str = "plug:surround51";
	  else
	    device.str = "surround51";
	  mp_msg(MSGT_AO,MSGL_V,"alsa-init: device set to surround51\n");
	  break;
	default:
	  device.str = "default";
	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_ChannelsNotSupported,channels);
        }
    device.len = strlen(device.str);
    if (subopt_parse(ao_subdevice, subopts) != 0) {
        print_help();
        return 0;
    }
    ao_noblock = !block;
    parse_device(alsa_device, device.str, device.len);

    mp_msg(MSGT_AO,MSGL_V,"alsa-init: using device %s\n", alsa_device);

    //setting modes for block or nonblock-mode
    if (ao_noblock) {
      open_mode = SND_PCM_NONBLOCK;
    }
    else {
      open_mode = 0;
    }

    //sets buff/chunksize if its set manually
    if (ao_data.buffersize) {
      switch (ao_data.buffersize)
	{
	case 1:
	  alsa_fragcount = 16;
	  chunk_size = 512;
	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 8192\n");
	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 512\n");
	  break;
	case 2:
	  alsa_fragcount = 8;
	  chunk_size = 1024;
	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 8192\n");
	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 1024\n");
	  break;
	case 3:
	  alsa_fragcount = 32;
	  chunk_size = 512;
	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 16384\n");
	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 512\n");
	  break;
	case 4:
	  alsa_fragcount = 16;
	  chunk_size = 1024;
	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 16384\n");
	    mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 1024\n");
	  break;
	default:
	  alsa_fragcount = 16;
	  chunk_size = 1024;
	  break;
	}
    }

    if (!alsa_handler) {
      //modes = 0, SND_PCM_NONBLOCK, SND_PCM_ASYNC
      if ((err = try_open_device(alsa_device, open_mode, format == AF_FORMAT_AC3)) < 0)
	{
	  if (err != -EBUSY && ao_noblock) {
	    mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_OpenInNonblockModeFailed);
	    if ((err = try_open_device(alsa_device, 0, format == AF_FORMAT_AC3)) < 0) {
	      mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PlaybackOpenError, snd_strerror(err));
	      return(0);
	    }
	  } else {
	    mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PlaybackOpenError, snd_strerror(err));
	    return(0);
	  }
	}

      if ((err = snd_pcm_nonblock(alsa_handler, 0)) < 0) {
         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_ErrorSetBlockMode, snd_strerror(err));
      } else {
	mp_msg(MSGT_AO,MSGL_V,"alsa-init: pcm opened in blocking mode\n");
      }

      snd_pcm_hw_params_alloca(&alsa_hwparams);
      snd_pcm_sw_params_alloca(&alsa_swparams);

      // setting hw-parameters
      if ((err = snd_pcm_hw_params_any(alsa_handler, alsa_hwparams)) < 0)
	{
	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetInitialParameters,
		 snd_strerror(err));
	  return(0);
	}
    
      err = snd_pcm_hw_params_set_access(alsa_handler, alsa_hwparams,
					 SND_PCM_ACCESS_RW_INTERLEAVED);
      if (err < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetAccessType, 
	       snd_strerror(err));
	return (0);
      }

      /* workaround for nonsupported formats
	 sets default format to S16_LE if the given formats aren't supported */
      if ((err = snd_pcm_hw_params_test_format(alsa_handler, alsa_hwparams,
                                             alsa_format)) < 0)
      {
         mp_msg(MSGT_AO,MSGL_INFO,
		MSGTR_AO_ALSA_FormatNotSupportedByHardware, af_fmt2str_short(format));
         alsa_format = SND_PCM_FORMAT_S16_LE;
         ao_data.format = AF_FORMAT_S16_LE;
      }

      if ((err = snd_pcm_hw_params_set_format(alsa_handler, alsa_hwparams,
					      alsa_format)) < 0)
	{
	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetFormat,
		 snd_strerror(err));
	  return(0);
	}

      if ((err = snd_pcm_hw_params_set_channels_near(alsa_handler, alsa_hwparams,
						     &ao_data.channels)) < 0)
	{
	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetChannels,
		 snd_strerror(err));
	  return(0);
	}

      /* workaround for buggy rate plugin (should be fixed in ALSA 1.0.11)
         prefer our own resampler */
#if SND_LIB_VERSION >= 0x010009
      if ((err = snd_pcm_hw_params_set_rate_resample(alsa_handler, alsa_hwparams,
						     0)) < 0)
	{
	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToDisableResampling,
		 snd_strerror(err));
	  return(0);
	}
#endif

      if ((err = snd_pcm_hw_params_set_rate_near(alsa_handler, alsa_hwparams, 
						 &ao_data.samplerate, NULL)) < 0) 
        {
	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetSamplerate2,
		 snd_strerror(err));
	  return(0);
        }

      bytes_per_sample = snd_pcm_format_physical_width(alsa_format) / 8;
      bytes_per_sample *= ao_data.channels;
      ao_data.bps = ao_data.samplerate * bytes_per_sample;

#ifdef BUFFERTIME
      {
	int alsa_buffer_time = 500000; /* original 60 */
	int alsa_period_time;
	alsa_period_time = alsa_buffer_time/4;
	if ((err = snd_pcm_hw_params_set_buffer_time_near(alsa_handler, alsa_hwparams, 
							  &alsa_buffer_time, NULL)) < 0)
	  {
	    mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetBufferTimeNear,
		   snd_strerror(err));
	    return(0);
	  } else
	    alsa_buffer_time = err;

	if ((err = snd_pcm_hw_params_set_period_time_near(alsa_handler, alsa_hwparams, 
							  &alsa_period_time, NULL)) < 0)
	  /* original: alsa_buffer_time/ao_data.bps */
	  {
	    mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetPeriodTime,
		   snd_strerror(err));
	    return 0;
	  }
	mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_BufferTimePeriodTime,
	       alsa_buffer_time, err);
      } 
#endif//end SET_BUFFERTIME

#ifdef SET_CHUNKSIZE
      {
	//set chunksize
	if ((err = snd_pcm_hw_params_set_period_size_near(alsa_handler, alsa_hwparams, 
							  &chunk_size, NULL)) < 0)
	  {
	    mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetPeriodSize,
			    chunk_size, snd_strerror(err));
	    return 0;
	  }
	else {
	  mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set to %li\n", chunk_size);
	}
	if ((err = snd_pcm_hw_params_set_periods_near(alsa_handler, alsa_hwparams,
						      &alsa_fragcount, NULL)) < 0) {
	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetPeriods, 
		 snd_strerror(err));
	  return 0;
	}
	else {
	  mp_msg(MSGT_AO,MSGL_V,"alsa-init: fragcount=%i\n", alsa_fragcount);
	}
      }
#endif//end SET_CHUNKSIZE

      /* finally install hardware parameters */
      if ((err = snd_pcm_hw_params(alsa_handler, alsa_hwparams)) < 0)
	{
	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetHwParameters,
		 snd_strerror(err));
	  return 0;
	}
      // end setting hw-params


      // gets buffersize for control
      if ((err = snd_pcm_hw_params_get_buffer_size(alsa_hwparams, &bufsize)) < 0)
	{
	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetBufferSize, snd_strerror(err));
	  return 0;
	}
      else {
	ao_data.buffersize = bufsize * bytes_per_sample;
	  mp_msg(MSGT_AO,MSGL_V,"alsa-init: got buffersize=%i\n", ao_data.buffersize);
      }

      if ((err = snd_pcm_hw_params_get_period_size(alsa_hwparams, &chunk_size, NULL)) < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetPeriodSize, snd_strerror(err));
	return 0;
      } else {
	mp_msg(MSGT_AO,MSGL_V,"alsa-init: got period size %li\n", chunk_size);
      }
      ao_data.outburst = chunk_size * bytes_per_sample;

      /* setting software parameters */
      if ((err = snd_pcm_sw_params_current(alsa_handler, alsa_swparams)) < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetSwParameters,
	       snd_strerror(err));
	return 0;
      }
#if SND_LIB_VERSION >= 0x000901
      if ((err = snd_pcm_sw_params_get_boundary(alsa_swparams, &boundary)) < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetBoundary,
	       snd_strerror(err));
	return 0;
      }
#else
      boundary = 0x7fffffff;
#endif
      /* start playing when one period has been written */
      if ((err = snd_pcm_sw_params_set_start_threshold(alsa_handler, alsa_swparams, chunk_size)) < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetStartThreshold,
	       snd_strerror(err));
	return 0;
      }
      /* disable underrun reporting */
      if ((err = snd_pcm_sw_params_set_stop_threshold(alsa_handler, alsa_swparams, boundary)) < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetStopThreshold,
	       snd_strerror(err));
	return 0;
      }
#if SND_LIB_VERSION >= 0x000901
      /* play silence when there is an underrun */
      if ((err = snd_pcm_sw_params_set_silence_size(alsa_handler, alsa_swparams, boundary)) < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetSilenceSize,
	       snd_strerror(err));
	return 0;
      }
#endif
      if ((err = snd_pcm_sw_params(alsa_handler, alsa_swparams)) < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetSwParameters,
	       snd_strerror(err));
	return 0;
      }
      /* end setting sw-params */

      mp_msg(MSGT_AO,MSGL_V,"alsa: %d Hz/%d channels/%d bpf/%d bytes buffer/%s\n",
	     ao_data.samplerate, ao_data.channels, bytes_per_sample, ao_data.buffersize,
	     snd_pcm_format_description(alsa_format));

    } // end switch alsa_handler (spdif)
    alsa_can_pause = snd_pcm_hw_params_can_pause(alsa_hwparams);
    return(1);
} // end init
Esempio n. 16
0
static void *alsa_qsa_init(const char *device,
      unsigned rate, unsigned latency)
{
   int err, card, dev, i;
   snd_pcm_channel_params_t params = {0};
   snd_pcm_channel_info_t pi;
   snd_pcm_channel_setup_t setup = {0};
   settings_t *settings = config_get_ptr();
   alsa_t *alsa = (alsa_t*)calloc(1, sizeof(alsa_t));
   if (!alsa)
      return NULL;

   (void)device;
   (void)rate;
   (void)latency;

   if ((err = snd_pcm_open_preferred(&alsa->pcm, &card, &dev,
               SND_PCM_OPEN_PLAYBACK)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Audio open error: %s\n",
            snd_strerror(err));
      goto error;
   }

   if((err = snd_pcm_nonblock_mode(alsa->pcm, 1)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Can't set blocking mode: %s\n",
            snd_strerror(err));
      goto error;
   }

   memset(&pi, 0, sizeof(pi));
   pi.channel = SND_PCM_CHANNEL_PLAYBACK;
   if ((err = snd_pcm_channel_info(alsa->pcm, &pi)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: snd_pcm_channel_info failed: %s\n",
            snd_strerror(err));
      goto error;
   }

   memset(&params, 0, sizeof(params));

   params.channel = SND_PCM_CHANNEL_PLAYBACK;
   params.mode = SND_PCM_MODE_BLOCK;

   params.format.interleave = 1;
   params.format.format = SND_PCM_SFMT_S16_LE;
   params.format.rate = DEFAULT_RATE;
   params.format.voices = 2;

   params.start_mode = SND_PCM_START_FULL;
   params.stop_mode = SND_PCM_STOP_STOP;

   params.buf.block.frag_size = pi.max_fragment_size;
   params.buf.block.frags_min = 2;
   params.buf.block.frags_max = 8;

   RARCH_LOG("Fragment size: %d\n", params.buf.block.frag_size);
   RARCH_LOG("Min Fragment size: %d\n", params.buf.block.frags_min);
   RARCH_LOG("Max Fragment size: %d\n", params.buf.block.frags_max);

   if ((err = snd_pcm_channel_params(alsa->pcm, &params)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Parameter Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   setup.channel = SND_PCM_CHANNEL_PLAYBACK;

   if ((err = snd_pcm_channel_setup(alsa->pcm, &setup)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Parameter Read Back Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   if (settings->audio.block_frames)
      alsa->buf_size = settings->audio.block_frames * 4;
   else
      alsa->buf_size = next_pow2(32 * latency);

   RARCH_LOG("[ALSA QSA]: buffer size: %u bytes\n", alsa->buf_size);

   alsa->buf_count = (latency * 4 * rate + 500) / 1000;
   alsa->buf_count = (alsa->buf_count + alsa->buf_size / 2) / alsa->buf_size;

   if ((err = snd_pcm_channel_prepare(alsa->pcm,
               SND_PCM_CHANNEL_PLAYBACK)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Prepare Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   alsa->buffer = (uint8_t**)calloc(sizeof(uint8_t*), alsa->buf_count);
   if (!alsa->buffer)
      goto error;

   alsa->buffer_chunk = (uint8_t*)calloc(alsa->buf_count, alsa->buf_size);
   if (!alsa->buffer_chunk)
      goto error;

   for (i = 0; i < alsa->buf_count; i++)
      alsa->buffer[i] = alsa->buffer_chunk + i * alsa->buf_size;

   alsa->has_float = false;
   alsa->can_pause = true;
   RARCH_LOG("[ALSA QSA]: Can pause: %s.\n",
         alsa->can_pause ? "yes" : "no");

   return alsa;

error:
   return (void*)-1;
}
Esempio n. 17
0
/* to set/get/query special features/parameters */
static int control(int cmd, void *arg)
{
  switch(cmd) {
  case AOCONTROL_QUERY_FORMAT:
    return CONTROL_TRUE;
  case AOCONTROL_GET_VOLUME:
  case AOCONTROL_SET_VOLUME:
    {
      ao_control_vol_t *vol = (ao_control_vol_t *)arg;

      int err;
      snd_mixer_t *handle;
      snd_mixer_elem_t *elem;
      snd_mixer_selem_id_t *sid;

      static char *mix_name = "PCM";
      static char *card = "default";
      static int mix_index = 0;

      long pmin, pmax;
      long get_vol, set_vol;
      float f_multi;

      if(mixer_channel) {
	 char *test_mix_index;

	 mix_name = strdup(mixer_channel);
	 if ((test_mix_index = strchr(mix_name, ','))){
		*test_mix_index = 0;
		test_mix_index++;
		mix_index = strtol(test_mix_index, &test_mix_index, 0);

		if (*test_mix_index){
		  mp_msg(MSGT_AO,MSGL_ERR,
		    MSGTR_AO_ALSA_InvalidMixerIndexDefaultingToZero);
		  mix_index = 0 ;
		}
	 }
      }
      if(mixer_device) card = mixer_device;

      if(ao_data.format == AF_FORMAT_AC3)
	return CONTROL_TRUE;

      //allocate simple id
      snd_mixer_selem_id_alloca(&sid);
	
      //sets simple-mixer index and name
      snd_mixer_selem_id_set_index(sid, mix_index);
      snd_mixer_selem_id_set_name(sid, mix_name);

      if (mixer_channel) {
	free(mix_name);
	mix_name = NULL;
      }

      if ((err = snd_mixer_open(&handle, 0)) < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerOpenError, snd_strerror(err));
	return CONTROL_ERROR;
      }

      if ((err = snd_mixer_attach(handle, card)) < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerAttachError, 
	       card, snd_strerror(err));
	snd_mixer_close(handle);
	return CONTROL_ERROR;
      }

      if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerRegisterError, snd_strerror(err));
	snd_mixer_close(handle);
	return CONTROL_ERROR;
      }
      err = snd_mixer_load(handle);
      if (err < 0) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerLoadError, snd_strerror(err));
	snd_mixer_close(handle);
	return CONTROL_ERROR;
      }

      elem = snd_mixer_find_selem(handle, sid);
      if (!elem) {
	mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToFindSimpleControl,
	       snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
	snd_mixer_close(handle);
	return CONTROL_ERROR;
	}

      snd_mixer_selem_get_playback_volume_range(elem,&pmin,&pmax);
      f_multi = (100 / (float)(pmax - pmin));

      if (cmd == AOCONTROL_SET_VOLUME) {

	set_vol = vol->left / f_multi + pmin + 0.5;

	//setting channels
	if ((err = snd_mixer_selem_set_playback_volume(elem, 0, set_vol)) < 0) {
	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_ErrorSettingLeftChannel, 
		 snd_strerror(err));
	  return CONTROL_ERROR;
	}
	mp_msg(MSGT_AO,MSGL_DBG2,"left=%li, ", set_vol);

	set_vol = vol->right / f_multi + pmin + 0.5;

	if ((err = snd_mixer_selem_set_playback_volume(elem, 1, set_vol)) < 0) {
	  mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_ErrorSettingRightChannel, 
		 snd_strerror(err));
	  return CONTROL_ERROR;
	}
	mp_msg(MSGT_AO,MSGL_DBG2,"right=%li, pmin=%li, pmax=%li, mult=%f\n", 
	       set_vol, pmin, pmax, f_multi);

	if (snd_mixer_selem_has_playback_switch(elem)) {
	  int lmute = (vol->left == 0.0);
	  int rmute = (vol->right == 0.0);
	  if (snd_mixer_selem_has_playback_switch_joined(elem)) {
	    lmute = rmute = lmute && rmute;
	  } else {
	    snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, !rmute);
	  }
	  snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, !lmute);
	}
      }
      else {
	snd_mixer_selem_get_playback_volume(elem, 0, &get_vol);
	vol->left = (get_vol - pmin) * f_multi;
	snd_mixer_selem_get_playback_volume(elem, 1, &get_vol);
	vol->right = (get_vol - pmin) * f_multi;

	mp_msg(MSGT_AO,MSGL_DBG2,"left=%f, right=%f\n",vol->left,vol->right);
      }
      snd_mixer_close(handle);
      return CONTROL_OK;
    }
    
  } //end switch
  return(CONTROL_UNKNOWN);
}
Esempio n. 18
0
void CAESinkALSA::HandleError(const char* name, int err)
{
    switch(err)
    {
    case -EPIPE:
        CLog::Log(LOGERROR, "CAESinkALSA::HandleError(%s) - underrun", name);
        if ((err = snd_pcm_prepare(m_pcm)) < 0)
            CLog::Log(LOGERROR, "CAESinkALSA::HandleError(%s) - snd_pcm_prepare returned %d (%s)", name, err, snd_strerror(err));
        break;

    case -ESTRPIPE:
        CLog::Log(LOGINFO, "CAESinkALSA::HandleError(%s) - Resuming after suspend", name);

        /* try to resume the stream */
        while((err = snd_pcm_resume(m_pcm)) == -EAGAIN)
            Sleep(1);

        /* if the hardware doesnt support resume, prepare the stream */
        if (err == -ENOSYS)
            if ((err = snd_pcm_prepare(m_pcm)) < 0)
                CLog::Log(LOGERROR, "CAESinkALSA::HandleError(%s) - snd_pcm_prepare returned %d (%s)", name, err, snd_strerror(err));
        break;

    default:
        CLog::Log(LOGERROR, "CAESinkALSA::HandleError(%s) - snd_pcm_writei returned %d (%s)", name, err, snd_strerror(err));
        break;
    }
}
Esempio n. 19
0
static int alsa_init(const char *param, int *speed,
		     int *fragsize, int *fragnr, int *channels)
{
    int err, dir;
    unsigned int rate, periods;
    snd_pcm_uframes_t period_size;
    snd_pcm_hw_params_t *hwparams;

    if (!param) {
        param = "default";
    }

    snd_pcm_hw_params_alloca(&hwparams);

    if ((err = snd_pcm_open(&handle, param, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
        log_message(LOG_DEFAULT, "Playback open error for '%s': %s", param,
		    snd_strerror(err));
        return 1;
    }

    if ((err = snd_pcm_hw_params_any(handle, hwparams)) < 0) {
        log_message(LOG_DEFAULT, "Broken configuration for playback: no configurations available: %s", snd_strerror(err));
        goto fail;
    }

    if ((err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
        log_message(LOG_DEFAULT, "Access type not available for playback: %s", snd_strerror(err));
        goto fail;
    }

    if ((err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16)) < 0) {
        log_message(LOG_DEFAULT, "Sample format not available for playback: %s", snd_strerror(err));
        goto fail;
    }

    if ((err = snd_pcm_hw_params_set_channels(handle, hwparams, *channels)) < 0) {
        log_message(LOG_DEFAULT, "Channels count (%i) not available for playbacks: %s", *channels, snd_strerror(err));
        goto fail;
    }

    rate = (unsigned int)*speed;
    if ((err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rate, 0)) < 0) {
        log_message(LOG_DEFAULT, "Rate %iHz not available for playback: %s", *speed, snd_strerror(err));
        goto fail;
    }
    if (rate != (unsigned int)*speed) {
        printf("Rate doesn't match (requested %iHz, got %iHz)", *speed, rate);
	*speed = rate;
    }

    period_size = *fragsize;
    dir = 0;
    if ((err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, &period_size, &dir)) < 0) {
        log_message(LOG_DEFAULT, "Unable to set period size %li for playback: %s", period_size, snd_strerror(err));
        goto fail;
    }
    *fragsize = period_size;

    periods = *fragnr;
    dir = 0;
    if ((err = snd_pcm_hw_params_set_periods_near(handle, hwparams, &periods, &dir)) < 0) {
        log_message(LOG_DEFAULT, "Unable to set periods %i for playback: %s", periods, snd_strerror(err));
        goto fail;
    }
    *fragnr = periods;

    alsa_can_pause = snd_pcm_hw_params_can_pause(hwparams);

    if ((err = snd_pcm_hw_params(handle, hwparams)) < 0) {
        log_message(LOG_DEFAULT, "Unable to set hw params for playback: %s", snd_strerror(err));
        goto fail;
    }

    alsa_bufsize = (*fragsize)*(*fragnr);
    alsa_fragsize = *fragsize;
    alsa_channels = *channels;

    return 0;

fail:
    snd_pcm_close(handle);
    handle = NULL;
    return 1;
}
Esempio n. 20
0
static void NTO_PlayAudio(_THIS)
{
    int written, rval;
    int towrite;
    void* pcmbuffer;

    if (!this->enabled)
    {
        return;
    }
    
    towrite = this->spec.size;
    pcmbuffer = pcm_buf;

    /* Write the audio data, checking for EAGAIN (buffer full) and underrun */
    do {
        written = snd_pcm_plugin_write(audio_handle, pcm_buf, towrite);
        if (written != towrite)
        {
            if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
            {
                /* Let a little CPU time go by and try to write again */
                SDL_Delay(1);
                /* if we wrote some data */
                towrite -= written;
                pcmbuffer += written * this->spec.channels;
                continue;
            }		
            else
            {
                if ((errno == EINVAL) || (errno == EIO))
                {
                    SDL_memset(&cstatus, 0, sizeof(cstatus));
                    cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
                    if ((rval = snd_pcm_plugin_status(audio_handle, &cstatus)) < 0)
                    {
                        SDL_SetError("NTO_PlayAudio(): snd_pcm_plugin_status failed: %s\n", snd_strerror(rval));
                        return;
                    }	
                    if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) || (cstatus.status == SND_PCM_STATUS_READY))
                    {
                        if ((rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
                        {
                            SDL_SetError("NTO_PlayAudio(): snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rval));
                            return;
                        }
                    }		        		
                    continue;
                }
                else
                {
                    return;
                }
            }
        }
        else
        {
            /* we wrote all remaining data */
            towrite -= written;
            pcmbuffer += written * this->spec.channels;
        }
    } while ((towrite > 0)  && (this->enabled));

    /* If we couldn't write, assume fatal error for now */
    if (towrite != 0)
    {
        this->enabled = 0;
    }

    return;
}
Esempio n. 21
0
int main(int argc, char ** argv) {
    
    // Variable declaration
	int rc;
	char * buffer;
  	int buffer_size;
  	int periods_per_buffer;

  	snd_pcm_t *handle;
  	snd_pcm_hw_params_t *params;
  	snd_pcm_uframes_t frames;

  	unsigned int channels;
  	unsigned int rate;

	wav_header * wav_header_info;

  	FILE * fp;

    
    // Argument parsing
  	if (argc != 2)
	{
        printf("Incorrect usage: Enter filename of the wav file you want to play as an argument: %s filename.txt\n", argv[0]);
		return 1;
	}

    
    // Open wav file to read
	fp = fopen(argv[1], "rb");

	if (fp == NULL)
	{
		printf("ERROR: %s does not exist, or cannot be opened.\n", argv[1]);
		return 1;
	}

	wav_header_info = malloc(44);

	fread(wav_header_info, 1, 44, fp);
    

	// print_wav_header(wav_header_info);

    
    // Assign variables that were read from the wave file
	channels = wav_header_info->number_of_channels;
	rate = wav_header_info->sample_rate;
	periods_per_buffer = 2; // Down to user preference, depending on size of internal ring buffer of ALSA


  	// Open PCM device for playback
  	if ((rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0) 
  	{
    	printf("ERROR: Cannot open pcm device. %s\n", snd_strerror(rc));
  	}

    
  	// Allocate hardware parameters
  	if ((rc = snd_pcm_hw_params_malloc(&params)) < 0)
  	{
  		printf("ERROR: Cannot allocate hardware parameters. %s\n", snd_strerror(rc));
  	}

    
  	// Initialize parameters with default values
  	if ((rc = snd_pcm_hw_params_any(handle, params)) < 0)
  	{
  		printf("ERROR: Cannot initialize hardware parameters. %s\n", snd_strerror(rc));
  	}


  	// Setting hardware parameters
  	if ((rc = snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
  	{
  		printf("ERROR: Cannot set interleaved mode. %s\n", snd_strerror(rc));
  	}

  	if ((rc = snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE)) < 0)
  	{
  		printf("ERROR: Cannot set PCM format. %s\n", snd_strerror(rc));
  	}

  	if ((rc = snd_pcm_hw_params_set_channels_near(handle, params, &channels)) < 0)
  	{
  		printf("ERROR: Cannot set number of channels. %s\n", snd_strerror(rc));
  	}

 	if ((rc = snd_pcm_hw_params_set_rate_near(handle, params, &rate, 0)) < 0)
 	{
 		printf("ERROR: Cannot set plyabck rate. %s\n", snd_strerror(rc));
 	}

 	if ((rc = snd_pcm_hw_params(handle, params)) < 0)
 	{
 		printf("ERROR: Cannot set hardware parameters. %s\n", snd_strerror(rc));
 	}


 	// Get hardware parameters
 	if ((rc = snd_pcm_hw_params_get_period_size(params, &frames, 0)) < 0)
	{
		printf("Playback ERROR: Can't get period size. %s\n", snd_strerror(rc));
	}
	printf("Frames: %lu\n", frames);

	if ((rc = snd_pcm_hw_params_get_channels(params, &channels)) < 0)
	{
		printf("Playback ERROR: Can't get channel number. %s\n", snd_strerror(rc));
	}

	if ((rc = snd_pcm_hw_params_get_rate(params, &rate, 0)) < 0)
	{
		printf("ERROR: Cannot get rate. %s\n", snd_strerror(rc));
	}


	// Free paraemeters
	snd_pcm_hw_params_free(params);


	// Create buffer
  	buffer_size = frames * periods_per_buffer * channels * sizeof(int16_t); /* 2 bytes/sample, 2 channels */
  	buffer = (char *) malloc(buffer_size);

  	// Send info to ALSA
 	//while ((rc = read(0, buffer, buffer_size)) != 0) 
 	while (rc = fread(buffer, 1, periods_per_buffer * frames * channels * sizeof(int16_t), fp) != 0)
 	{
    	rc = snd_pcm_writei(handle, buffer, frames * periods_per_buffer);
    	if (rc == -EPIPE) 
    	{
      		fprintf(stderr, "underrun occurred\n");
      		snd_pcm_prepare(handle);
    	} 
    	else if (rc < 0) 
    	{
      		printf("ERROR: Cannot write to playback device. %s\n", strerror(rc));
    	}
  	}

  	printf("Info set: Device is now draining...\n");
  	snd_pcm_drain(handle);

  	printf("Done playing, closing connections.\n");
  	snd_pcm_close(handle);

  	free(wav_header_info);
  	free(buffer);
  	fclose(fp);

  return 0;
}
Esempio n. 22
0
static int NTO_OpenAudio(_THIS, SDL_AudioSpec* spec)
{
    int rval;
    int format;
    Uint16 test_format;
    int found;

    audio_handle = NULL;
    this->enabled = 0;

    if (pcm_buf != NULL)
    {
        SDL_FreeAudioMem(pcm_buf); 
        pcm_buf = NULL;
    }

    /* initialize channel transfer parameters to default */
    NTO_InitAudioParams(&cparams);

    /* Open the audio device */
    rval = snd_pcm_open_preferred(&audio_handle, &cardno, &deviceno, OPEN_FLAGS);
    if (rval < 0)
    {
        SDL_SetError("NTO_OpenAudio(): snd_pcm_open failed: %s\n", snd_strerror(rval));
        return (-1);
    }

    if (!NTO_CheckBuggyCards(this, QSA_MMAP_WORKAROUND))
    {
        /* enable count status parameter */
        if ((rval = snd_pcm_plugin_set_disable(audio_handle, PLUGIN_DISABLE_MMAP)) < 0)
        {
            SDL_SetError("snd_pcm_plugin_set_disable failed: %s\n", snd_strerror(rval));
            return (-1);
        }
    }

    /* Try for a closest match on audio format */
    format = 0;
    /* can't use format as SND_PCM_SFMT_U8 = 0 in nto */
    found = 0;

    for (test_format=SDL_FirstAudioFormat(spec->format); !found ;)
    {
        /* if match found set format to equivalent ALSA format */
        switch (test_format)
        {
            case AUDIO_U8:
                           format = SND_PCM_SFMT_U8;
                           found = 1;
                           break;
            case AUDIO_S8:
                           format = SND_PCM_SFMT_S8;
                           found = 1;
                           break;
            case AUDIO_S16LSB:
                           format = SND_PCM_SFMT_S16_LE;
                           found = 1;
                           break;
            case AUDIO_S16MSB:
                           format = SND_PCM_SFMT_S16_BE;
                           found = 1;
                           break;
            case AUDIO_U16LSB:
                           format = SND_PCM_SFMT_U16_LE;
                           found = 1;
                           break;
            case AUDIO_U16MSB:
                           format = SND_PCM_SFMT_U16_BE;
                           found = 1;
                           break;
            default:
                           break;
        }

        if (!found)
        {
            test_format = SDL_NextAudioFormat();
        }
    }

    /* assumes test_format not 0 on success */
    if (test_format == 0)
    {
        SDL_SetError("NTO_OpenAudio(): Couldn't find any hardware audio formats");
        return (-1);
    }

    spec->format = test_format;

    /* Set the audio format */
    cparams.format.format = format;

    /* Set mono or stereo audio (currently only two channels supported) */
    cparams.format.voices = spec->channels;
	
    /* Set rate */
    cparams.format.rate = spec->freq;

    /* Setup the transfer parameters according to cparams */
    rval = snd_pcm_plugin_params(audio_handle, &cparams);
    if (rval < 0)
    {
        SDL_SetError("NTO_OpenAudio(): snd_pcm_channel_params failed: %s\n", snd_strerror(rval));
        return (-1);
    }

    /* Make sure channel is setup right one last time */
    SDL_memset(&csetup, 0x00, sizeof(csetup));
    csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
    if (snd_pcm_plugin_setup(audio_handle, &csetup) < 0)
    {
        SDL_SetError("NTO_OpenAudio(): Unable to setup playback channel\n");
        return -1;
    }


    /* Calculate the final parameters for this audio specification */
    SDL_CalculateAudioSpec(spec);

    pcm_len = spec->size;

    if (pcm_len==0)
    {
        pcm_len = csetup.buf.block.frag_size * spec->channels * (snd_pcm_format_width(format)/8);
    }

    /* Allocate memory to the audio buffer and initialize with silence (Note that
       buffer size must be a multiple of fragment size, so find closest multiple)
    */
    pcm_buf = (Uint8*)SDL_AllocAudioMem(pcm_len);
    if (pcm_buf == NULL)
    {
        SDL_SetError("NTO_OpenAudio(): pcm buffer allocation failed\n");
        return (-1);
    }
    SDL_memset(pcm_buf, spec->silence, pcm_len);

    /* get the file descriptor */
    if ((audio_fd = snd_pcm_file_descriptor(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0)
    {
        SDL_SetError("NTO_OpenAudio(): snd_pcm_file_descriptor failed with error code: %s\n", snd_strerror(rval));
        return (-1);
    }

    /* Trigger audio playback */
    rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK);
    if (rval < 0)
    {
        SDL_SetError("snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rval));
        return (-1);
    }

    this->enabled = 1;

    /* Get the parent process id (we're the parent of the audio thread) */
    parent = getpid();

    /* We're really ready to rock and roll. :-) */
    return (0);
}
Esempio n. 23
0
int main( int argc, char ** argv )
{
    const char *device = "default";         /* playback device */
    unsigned char buffer[ 16*1024 ];        /* read buffer */

    int err;
    snd_pcm_t *handle;
    snd_pcm_sframes_t frames;
    FILE * fp = 0;
    size_t bytes_read;
    int blocking_flag = 0; // 0 = blocking; SND_PCM_NONBLOCK = not blocking

    // check file argument
    if ( argc <= 1 ) {
        printf( "no input\n" );
        return 127;
    }

    // open the file for reading
    fp = fopen( argv[1], "rb" );
    if ( !fp ) {
        printf("error: couldn't open: %s\n", argv[1]);
        exit(EXIT_FAILURE);
    }

    // discard the header
    fread( buffer, 1, 44, fp );

    // open the PCM device
    if ( (err = snd_pcm_open( &handle, device, SND_PCM_STREAM_PLAYBACK, blocking_flag )) < 0 ) {
        printf("Playback open error: %s\n", snd_strerror(err));
        exit(EXIT_FAILURE);
    }

    // setup our pcm state (on the snd_pcm_t handle)
    if ((err = snd_pcm_set_params(handle,
                                  SND_PCM_FORMAT_S16_LE,
                                  SND_PCM_ACCESS_RW_INTERLEAVED,
                                  1,
                                  16000,
                                  1,
                                  50000)) < 0) {   /* 0.05 sec */
        printf("Playback open error: %s\n", snd_strerror(err));
        exit( EXIT_FAILURE );
    }

    // read loop
    while( 1 ) {
        bytes_read = fread( buffer, 1, sizeof(buffer), fp );
        if ( bytes_read == 0 ) {
            break;
        }

        frames = snd_pcm_writei( handle, buffer, bytes_read / 2 /*(frame is 16-bit)*/  );
        if (frames < 0) {
            printf( "error: snd_pcm_writei: %s\n", snd_strerror( frames ) );
            fflush( stdout );
            frames = snd_pcm_recover(handle, frames, 0);
        }
        if (frames < 0) {
            printf("snd_pcm_writei failed: %s\n", snd_strerror(frames));
            fflush( stdout );
            break;
        }
        if ( frames > 0 ) {
            printf("Played %li frames\n", frames);
        }
    }

    fclose( fp );
    snd_pcm_close( handle );

    return 0;
}
Esempio n. 24
0
int main() {  
	long loops;  
	int rc,j = 0;  
	int size;  
	snd_pcm_t *handle;  
	snd_pcm_hw_params_t *params;  
	unsigned int val,val2;  
	int dir;  
	snd_pcm_uframes_t frames;  
	char *buffer;  
	FILE *fp ;
	if( (fp = fopen("sound.wav","r")) < 0)//南拳妈妈 - 你不像她.wav
		printf("open sound.wav fial\n");
	if(fseek(fp,0,SEEK_SET) < 0)
		 printf("put fp start to first error\n ");


		/* Open PCM device for playback. */  
		rc = snd_pcm_open(&handle, "default",  
				SND_PCM_STREAM_PLAYBACK, 0);  
	if (rc < 0) {  
		fprintf(stderr,  "unable to open pcm device: %s/n",  
				snd_strerror(rc));  
		exit(1);  
	}  
	/* Allocate a hardware parameters object. */  
	snd_pcm_hw_params_alloca(&params);  
	/* Fill it in with default values. */  
	snd_pcm_hw_params_any(handle, params);  
	/* Set the desired hardware parameters. */  
	/* Interleaved mode */  
	snd_pcm_hw_params_set_access(handle, params,  
			SND_PCM_ACCESS_RW_INTERLEAVED);  
	/* Signed 16-bit little-endian format */  
	snd_pcm_hw_params_set_format(handle, params,  
			SND_PCM_FORMAT_S16_LE);  
	/* Two channels (stereo) */  
	snd_pcm_hw_params_set_channels(handle, params, 1);  
	/* 44100 bits/second sampling rate (CD quality) */  
	val = 8000;  
	snd_pcm_hw_params_set_rate_near(handle, params,  
			&val, &dir);  
	/* Set period size to 32 frames. */  
	frames = 1024;  //设置的值没有反应
	snd_pcm_hw_params_set_period_size_near(handle,  params, &frames, &dir); // 
	printf("frames is %d\n",(int)frames);
	/* Write the parameters to the driver */  
	rc = snd_pcm_hw_params(handle, params);  
	if (rc < 0) {  
		fprintf(stderr,  "unable to set hw parameters: %s/n",  snd_strerror(rc));  
		exit(1);  
	}  
	/* Use a buffer large enough to hold one period */  
	snd_pcm_hw_params_get_period_size(params, &frames,  
			&dir);  
	size = frames * 2; /* 2 bytes/sample, 2 channels */  

	buffer = (char *) malloc(size);  

	/* We want to loop for 5 seconds */  
	snd_pcm_hw_params_get_period_time(params,  &val, &dir);  

	/* 5 seconds in microseconds divided by * period time */  
	loops = 10000000 / val;  
	while (loops > 0) {  
		loops--;  
		rc = fread(buffer,1, size,fp); 


		//rc = read(0,buffer,size);

		//printf("%d\n",j++); 
		if (rc == 0) {  
			fprintf(stderr, "end of file on input\n");  
			break;  
		} else if (rc != size) {  
			fprintf(stderr,  "short read: read %d bytes\n", rc);  


		}  
		//else printf("fread to buffer success\n");
		rc = snd_pcm_writei(handle, buffer, frames);  


		if (rc == -EPIPE) {  
			/* EPIPE means underrun */  
			fprintf(stderr, "underrun occurred\n");  
			snd_pcm_prepare(handle);  
		} else if (rc < 0) {  
			fprintf(stderr,  "error from writei: %s\n",  
					snd_strerror(rc));  
		}  else if (rc != (int)frames) {  
			fprintf(stderr,  "short write, write %d frames\n", rc);  
		}  
	}  
	/*******************************************************************/
	snd_pcm_drain(handle);  
	snd_pcm_close(handle);  
	free(buffer);

	fclose(fp);

	return 0;

}
Esempio n. 25
0
File: alsa.c Progetto: xwax/xwax
static void alsa_error(const char *msg, int r)
{
    fprintf(stderr, "ALSA %s: %s\n", msg, snd_strerror(r));
}
Esempio n. 26
0
int run(char *filename)
{
    capture_stop = 0;
	char *pcm_name = "default";
	int tmp, err;
	snd_pcm_info_t *info;

	snd_pcm_info_alloca(&info);

	err = snd_output_stdio_attach(&log, stderr, 0);
	assert(err >= 0);

	file_type = FORMAT_DEFAULT;
    stream = SND_PCM_STREAM_CAPTURE;
    file_type = FORMAT_WAVE;
    command = "arecord";
    start_delay = 1;

	chunk_size = -1;
	rhwparams.format = DEFAULT_FORMAT;
	rhwparams.rate = DEFAULT_SPEED;
	rhwparams.channels = 1;

    file_type = FORMAT_WAVE;

    // cdr:
    // rhwparams.format = SND_PCM_FORMAT_S16_BE;
    rhwparams.format = file_type == FORMAT_AU ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE;
    rhwparams.rate = 44100;
    rhwparams.channels = 2;

	err = snd_pcm_open(&handle, pcm_name, stream, open_mode);
	if (err < 0) {
		error(_("audio open error: %s"), snd_strerror(err));
		return 1;
	}

	if ((err = snd_pcm_info(handle, info)) < 0) {
		error(_("info error: %s"), snd_strerror(err));
		return 1;
	}

	if (nonblock) {
		err = snd_pcm_nonblock(handle, 1);
		if (err < 0) {
			error(_("nonblock setting error: %s"), snd_strerror(err));
			return 1;
		}
	}

	chunk_size = 1024;
	hwparams = rhwparams;

	audiobuf = (u_char *)malloc(1024);
	if (audiobuf == NULL) {
		error(_("not enough memory"));
		return 1;
	}

    writei_func = snd_pcm_writei;
	readi_func = snd_pcm_readi;
	writen_func = snd_pcm_writen;
	readn_func = snd_pcm_readn;


	//signal(SIGINT, signal_handler);
	//signal(SIGTERM, signal_handler);
	//signal(SIGABRT, signal_handler);
    capture(filename);

    if (fmt_rec_table[file_type].end) {
        fmt_rec_table[file_type].end(fd);
        fd = -1;
    }
	stream = -1;
	if (fd > 1) {
		close(fd);
		fd = -1;
	}
	if (handle) {
		snd_pcm_close(handle);
		handle = NULL;
	}
	//snd_pcm_close(handle);
	//free(audiobuf);
	//snd_output_close(log);
	//snd_config_update_free_global();
	return EXIT_SUCCESS;
}
// returns TRUE if successful
int setHWParams(AlsaPcmInfo* info,
                float sampleRate,
                int channels,
                int bufferSizeInFrames,
                snd_pcm_format_t format) {
    unsigned int rrate;
    int ret, dir, periods, periodTime;
    snd_pcm_uframes_t alsaBufferSizeInFrames = (snd_pcm_uframes_t) bufferSizeInFrames;

    /* choose all parameters */
    ret = snd_pcm_hw_params_any(info->handle, info->hwParams);
    if (ret < 0) {
        ERROR1("Broken configuration: no configurations available: %s\n", snd_strerror(ret));
        return FALSE;
    }
    /* set the interleaved read/write format */
    ret = snd_pcm_hw_params_set_access(info->handle, info->hwParams, SND_PCM_ACCESS_RW_INTERLEAVED);
    if (ret < 0) {
        ERROR1("SND_PCM_ACCESS_RW_INTERLEAVED access type not available: %s\n", snd_strerror(ret));
        return FALSE;
    }
    /* set the sample format */
    ret = snd_pcm_hw_params_set_format(info->handle, info->hwParams, format);
    if (ret < 0) {
        ERROR1("Sample format not available: %s\n", snd_strerror(ret));
        return FALSE;
    }
    /* set the count of channels */
    ret = snd_pcm_hw_params_set_channels(info->handle, info->hwParams, channels);
    if (ret < 0) {
        ERROR2("Channels count (%d) not available: %s\n", channels, snd_strerror(ret));
        return FALSE;
    }
    /* set the stream rate */
    rrate = (int) (sampleRate + 0.5f);
#ifdef ALSA_PCM_NEW_HW_PARAMS_API
    dir = 0;
    ret = snd_pcm_hw_params_set_rate_near(info->handle, info->hwParams, &rrate, &dir);
#else
    ret = snd_pcm_hw_params_set_rate_near(info->handle, info->hwParams, rrate, 0);
#endif
    if (ret < 0) {
        ERROR2("Rate %dHz not available for playback: %s\n", (int) (sampleRate+0.5f), snd_strerror(ret));
        return FALSE;
    }
    if ((rrate-sampleRate > 2) || (rrate-sampleRate < - 2)) {
        ERROR2("Rate doesn't match (requested %2.2fHz, got %dHz)\n", sampleRate, rrate);
        return FALSE;
    }
    /* set the buffer time */
#ifdef ALSA_PCM_NEW_HW_PARAMS_API

    ret = snd_pcm_hw_params_set_buffer_size_near(info->handle, info->hwParams, &alsaBufferSizeInFrames);
#else
    ret = snd_pcm_hw_params_set_buffer_size_near(info->handle, info->hwParams, alsaBufferSizeInFrames);
#endif
    if (ret < 0) {
        ERROR2("Unable to set buffer size to %d frames: %s\n",
               (int) alsaBufferSizeInFrames, snd_strerror(ret));
        return FALSE;
    }
    bufferSizeInFrames = (int) alsaBufferSizeInFrames;
    /* set the period time */
    if (bufferSizeInFrames > 1024) {
        dir = 0;
        periodTime = DEFAULT_PERIOD_TIME;
#ifdef ALSA_PCM_NEW_HW_PARAMS_API
        ret = snd_pcm_hw_params_set_period_time_near(info->handle, info->hwParams, &periodTime, &dir);
#else
        periodTime = snd_pcm_hw_params_set_period_time_near(info->handle, info->hwParams, periodTime, &dir);
        ret = periodTime;
#endif
        if (ret < 0) {
            ERROR2("Unable to set period time to %d: %s\n", DEFAULT_PERIOD_TIME, snd_strerror(ret));
            return FALSE;
        }
    } else {
        /* set the period count for very small buffer sizes to 2 */
        dir = 0;
        periods = 2;
#ifdef ALSA_PCM_NEW_HW_PARAMS_API
        ret = snd_pcm_hw_params_set_periods_near(info->handle, info->hwParams, &periods, &dir);
#else
        periods = snd_pcm_hw_params_set_periods_near(info->handle, info->hwParams, periods, &dir);
        ret = periods;
#endif
        if (ret < 0) {
            ERROR2("Unable to set period count to %d: %s\n", /*periods*/ 2, snd_strerror(ret));
            return FALSE;
        }
    }
    /* write the parameters to device */
    ret = snd_pcm_hw_params(info->handle, info->hwParams);
    if (ret < 0) {
        ERROR1("Unable to set hw params: %s\n", snd_strerror(ret));
        return FALSE;
    }
    return TRUE;
}
Esempio n. 28
0
bool AlsaSound::AlsaInit()
{
	unsigned int sample_rate = m_mixer->GetSampleRate();
	int err;
	int dir;
	snd_pcm_sw_params_t *swparams;
	snd_pcm_hw_params_t *hwparams;
	snd_pcm_uframes_t buffer_size,buffer_size_max;
	unsigned int periods;

	err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "Audio open error: %s\n", snd_strerror(err));
		return false;
	}

	snd_pcm_hw_params_alloca(&hwparams);

	err = snd_pcm_hw_params_any(handle, hwparams);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "Broken configuration for this PCM: %s\n", snd_strerror(err));
		return false;
	}

	err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "Access type not available: %s\n", snd_strerror(err));
		return false;
	}

	err = snd_pcm_hw_params_set_format(handle, hwparams, SND_PCM_FORMAT_S16_LE);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "Sample format not available: %s\n", snd_strerror(err));
		return false;
	}

	dir = 0;
	err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &sample_rate, &dir);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "Rate not available: %s\n", snd_strerror(err));
		return false;
	}

	err = snd_pcm_hw_params_set_channels(handle, hwparams, CHANNEL_COUNT);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "Channels count not available: %s\n", snd_strerror(err));
		return false;
	}

	periods = BUFFER_SIZE_MAX / FRAME_COUNT_MIN;
	err = snd_pcm_hw_params_set_periods_max(handle, hwparams, &periods, &dir);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "Cannot set maximum periods per buffer: %s\n", snd_strerror(err));
		return false;
	}

	buffer_size_max = BUFFER_SIZE_MAX;
	err = snd_pcm_hw_params_set_buffer_size_max(handle, hwparams, &buffer_size_max);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "Cannot set maximum buffer size: %s\n", snd_strerror(err));
		return false;
	}

	err = snd_pcm_hw_params(handle, hwparams);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "Unable to install hw params: %s\n", snd_strerror(err));
		return false;
	}

	err = snd_pcm_hw_params_get_buffer_size(hwparams, &buffer_size);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "Cannot get buffer size: %s\n", snd_strerror(err));
		return false;
	}

	err = snd_pcm_hw_params_get_periods_max(hwparams, &periods, &dir);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "Cannot get periods: %s\n", snd_strerror(err));
		return false;
	}

	//periods is the number of fragments alsa can wait for during one
	//buffer_size
	frames_to_deliver = buffer_size / periods;
	//limit the minimum size. pulseaudio advertises a minimum of 32 samples.
	if (frames_to_deliver < FRAME_COUNT_MIN)
		frames_to_deliver = FRAME_COUNT_MIN;
	//it is probably a bad idea to try to send more than one buffer of data
	if ((unsigned int)frames_to_deliver > buffer_size)
		frames_to_deliver = buffer_size;
	NOTICE_LOG(AUDIO, "ALSA gave us a %ld sample \"hardware\" buffer with %d periods. Will send %d samples per fragments.\n", buffer_size, periods, frames_to_deliver);

	snd_pcm_sw_params_alloca(&swparams);

	err = snd_pcm_sw_params_current(handle, swparams);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "cannot init sw params: %s\n", snd_strerror(err));
		return false;
	}

	err = snd_pcm_sw_params_set_start_threshold(handle, swparams, 0U);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "cannot set start thresh: %s\n", snd_strerror(err));
		return false;
	}

	err = snd_pcm_sw_params(handle, swparams);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "cannot set sw params: %s\n", snd_strerror(err));
		return false;
	}

	err = snd_pcm_prepare(handle);
	if (err < 0)
	{
		ERROR_LOG(AUDIO, "Unable to prepare: %s\n", snd_strerror(err));
		return false;
	}
	NOTICE_LOG(AUDIO, "ALSA successfully initialized.\n");
	return true;
}
Esempio n. 29
0
int main(int argc, char *argv[])
{
	int err;
	struct sniffer_state sts;

	sts.pcm_name = strdup("plughw:0,0");
	sts.stream = SND_PCM_STREAM_PLAYBACK;
	sts.format = SND_PCM_FORMAT_A_LAW;
	sts.rate = 8000;
//	sts.exact_rate;
	sts.periods = 2;
	sts.buffer_time = 25000;
	sts.period_time = 12500;

	snd_pcm_hw_params_alloca(&sts.hwparams);

	if (snd_pcm_open(&sts.pcm, sts.pcm_name, sts.stream, 0) < 0) {
		fprintf(stderr, "Error opening PCM device %s\n", sts.pcm_name);
		return(-1);
	}

	if (snd_pcm_hw_params_any(sts.pcm, sts.hwparams) < 0) {
		fprintf(stderr, "Can not configure this PCM device.\n");
		return(-1);
	}

	if (snd_pcm_hw_params_set_access(sts.pcm, sts.hwparams,
			SND_PCM_ACCESS_MMAP_NONINTERLEAVED) < 0) {
		fprintf(stderr, "Error setting access.\n");
		return(-1);
	}

	if (snd_pcm_hw_params_set_format(sts.pcm, sts.hwparams,
			sts.format) < 0) {
		fprintf(stderr, "Error setting format.\n");
		return(-1);
	}

	sts.exact_rate = sts.rate;
	if (snd_pcm_hw_params_set_rate_near(sts.pcm, sts.hwparams,
			&sts.exact_rate, 0) < 0) {
		fprintf(stderr, "Error setting rate.\n");
		return(-1);
	}

printf("rate: %d\n", sts.exact_rate);

	if (sts.rate != sts.exact_rate) {
		fprintf(stderr, "The rate %d Hz is not supported by your hardware.\n"
			"==> Using %d Hz instead.\n", sts.rate, sts.exact_rate);
	}

	if (snd_pcm_hw_params_set_channels(sts.pcm, sts.hwparams, 1) < 0) {
		fprintf(stderr, "Error setting channels.\n");
		return(-1);
	}

	if (snd_pcm_hw_params_set_periods(sts.pcm, sts.hwparams, sts.periods, 0) < 0) {
		fprintf(stderr, "Error setting periods.\n");
		return(-1);
	}

	if (snd_pcm_hw_params_set_buffer_time_near(sts.pcm, sts.hwparams,
			&sts.buffer_time, &sts.dir) < 0) {
		fprintf(stderr, "Error setting buffersize.\n");
		return(-1);
	}

printf("buffer_time set to %d\n", sts.buffer_time);

	err = snd_pcm_hw_params_get_period_size(sts.hwparams, &sts.period_size, &sts.dir);
	if (err < 0) {
		printf("Unable to get period size for playback: %s\n", snd_strerror(err));
		return err;
	}

printf("period_size = %d\n", (int)sts.period_size);

	if (snd_pcm_hw_params(sts.pcm, sts.hwparams) < 0) {
		fprintf(stderr, "Error setting HW params.\n");
		return(-1);
	}

	setvbuf(stdout, (char *)NULL, _IONBF, 0);

	int router_control_fd = open("/dev/visdn/router-control", O_RDWR);
	if (router_control_fd < 0) {
		perror("Unable to open router-control");
		return 1;
	}

	int fd;
	fd = open("/dev/visdn/streamport", O_RDWR);
	if (fd < 0) {
		perror("cannot open /dev/visdn/streamport");
		return 1;
	}

	struct vsp_ctl vsp_ctl;
	if (ioctl(fd, VISDN_SP_GET_NODEID, (caddr_t)&vsp_ctl) < 0) {
		perror("ioctl(VISDN_SP_GET_NODEID)");
		return 1;
	}

	char node_id[80];
	snprintf(node_id, sizeof(node_id), "/sys/%s", vsp_ctl.node_id);

	struct visdn_connect vc;
	memset(&vc, 0, sizeof(vc));
	strncpy(vc.from_endpoint, argv[1],
				sizeof(vc.from_endpoint));
	strncpy(vc.to_endpoint, node_id,
				sizeof(vc.to_endpoint));

printf("Connect: %s => %s\n", vc.from_endpoint, vc.to_endpoint);

	if (ioctl(router_control_fd, VISDN_IOC_CONNECT, (caddr_t) &vc) < 0) {
		perror("ioctl(VISDN_CONNECT, br=>sp)");
		return 1;
	}

	int pipeline_id = vc.pipeline_id;

	memset(&vc, 0, sizeof(vc));
	vc.pipeline_id = pipeline_id;
	if (ioctl(router_control_fd, VISDN_IOC_PIPELINE_OPEN,
						(caddr_t)&vc) < 0) {
		perror("ioctl(VISDN_PIPELINE_OPEN, br=>sp)");
		return 1;
	}

	memset(&vc, 0, sizeof(vc));
	vc.pipeline_id = pipeline_id;
	if (ioctl(router_control_fd, VISDN_IOC_PIPELINE_START,
						(caddr_t)&vc) < 0) {
		perror("ioctl(VISDN_PIPELINE_START, br=>sp)");
		return 1;
	}






	//double phase = 0;
	const snd_pcm_channel_area_t *my_areas;
	snd_pcm_uframes_t offset, frames, size;
	snd_pcm_sframes_t avail, commitres;
	snd_pcm_state_t state;
	int first = 1;

	while (1) {
		state = snd_pcm_state(sts.pcm);

		if (state == SND_PCM_STATE_XRUN) {
			err = xrun_recovery(sts.pcm, -EPIPE);
			if (err < 0) {
				printf("XRUN recovery failed: %s\n", snd_strerror(err));
				return err;
			}
			first = 1;
		} else if (state == SND_PCM_STATE_SUSPENDED) {
			err = xrun_recovery(sts.pcm, -ESTRPIPE);
			if (err < 0) {
				printf("SUSPEND recovery failed: %s\n", snd_strerror(err));
				return err;
			}
		}

		avail = snd_pcm_avail_update(sts.pcm);
		if (avail < 0) {
			err = xrun_recovery(sts.pcm, avail);
			if (err < 0) {
				printf("avail update failed: %s\n", snd_strerror(err));
				return err;
			}
			first = 1;
			continue;
		}

		if (avail < sts.period_size) {
			if (first) {
				first = 0;
				err = snd_pcm_start(sts.pcm);
				if (err < 0) {
					printf("Start error: %s\n", snd_strerror(err));
					exit(EXIT_FAILURE);
				}
			} else {
				err = snd_pcm_wait(sts.pcm, -1);
				if (err < 0) {
					if ((err = xrun_recovery(sts.pcm, err)) < 0) {
						printf("snd_pcm_wait error: %s\n", snd_strerror(err));
						exit(EXIT_FAILURE);
					}
					first = 1;
				}
			}
			continue;
		}

		size = sts.period_size;
		while (size > 0) {
			frames = size;
			err = snd_pcm_mmap_begin(sts.pcm, &my_areas, &offset, &frames);
			if (err < 0) {
				if ((err = xrun_recovery(sts.pcm, err)) < 0) {
					printf("MMAP begin avail error: %s\n", snd_strerror(err));
					exit(EXIT_FAILURE);
				}

				first = 1;
			}

			int r = read(fd, my_areas[0].addr + offset, frames);
			printf("%d %d %d: ", (int)offset, (int)frames, r);

			int i;
			for (i=0; i<r; i++)
				printf("%02x", *(__u8 *)(my_areas[0].addr + i));

			printf("\n");

			commitres = snd_pcm_mmap_commit(sts.pcm, offset, frames);
			if (commitres < 0 || (snd_pcm_uframes_t)commitres != frames) {
				if ((err = xrun_recovery(sts.pcm, commitres >= 0 ? -EPIPE : commitres)) < 0) {
					printf("MMAP commit error: %s\n", snd_strerror(err));
					exit(EXIT_FAILURE);
				}
				first = 1;
			}
			size -= frames;
		}
	}

	return 0;
}
Esempio n. 30
0
/**************************************************************************
 * 				wodPlayer_Reset			[internal]
 *
 * wodPlayer helper. Resets current output stream.
 */
static	void	wodPlayer_Reset(WINE_WAVEDEV* wwo, BOOL reset)
{
    int                         err;
    TRACE("(%p)\n", wwo);

    wodUpdatePlayedTotal(wwo, NULL);
    /* updates current notify list */
    wodPlayer_NotifyCompletions(wwo, FALSE);

    if ( (err = snd_pcm_drop(wwo->pcm)) < 0) {
	FIXME("flush: %s\n", snd_strerror(err));
	wwo->hThread = 0;
	wwo->state = WINE_WS_STOPPED;
	ExitThread(-1);
    }
    if ( (err = snd_pcm_prepare(wwo->pcm)) < 0 )
        ERR("pcm prepare failed: %s\n", snd_strerror(err));

    if (reset) {
        enum win_wm_message	msg;
        DWORD_PTR	        param;
        HANDLE		        ev;

        /* remove any buffer */
        wodPlayer_NotifyCompletions(wwo, TRUE);

        wwo->lpPlayPtr = wwo->lpQueuePtr = wwo->lpLoopPtr = NULL;
        wwo->state = WINE_WS_STOPPED;
        wwo->dwPlayedTotal = wwo->dwWrittenTotal = 0;
        /* Clear partial wavehdr */
        wwo->dwPartialOffset = 0;

        /* remove any existing message in the ring */
        EnterCriticalSection(&wwo->msgRing.msg_crst);
        /* return all pending headers in queue */
        while (ALSA_RetrieveRingMessage(&wwo->msgRing, &msg, &param, &ev))
        {
            if (msg != WINE_WM_HEADER)
            {
                FIXME("shouldn't have headers left\n");
                SetEvent(ev);
                continue;
            }
            ((LPWAVEHDR)param)->dwFlags &= ~WHDR_INQUEUE;
            ((LPWAVEHDR)param)->dwFlags |= WHDR_DONE;

                wodNotifyClient(wwo, WOM_DONE, param, 0);
        }
        ALSA_ResetRingMessage(&wwo->msgRing);
        LeaveCriticalSection(&wwo->msgRing.msg_crst);
    } else {
        if (wwo->lpLoopPtr) {
            /* complicated case, not handled yet (could imply modifying the loop counter */
            FIXME("Pausing while in loop isn't correctly handled yet, expect strange results\n");
            wwo->lpPlayPtr = wwo->lpLoopPtr;
            wwo->dwPartialOffset = 0;
            wwo->dwWrittenTotal = wwo->dwPlayedTotal; /* this is wrong !!! */
        } else {
            LPWAVEHDR   ptr;
            DWORD       sz = wwo->dwPartialOffset;

            /* reset all the data as if we had written only up to lpPlayedTotal bytes */
            /* compute the max size playable from lpQueuePtr */
            for (ptr = wwo->lpQueuePtr; ptr != wwo->lpPlayPtr; ptr = ptr->lpNext) {
                sz += ptr->dwBufferLength;
            }
            /* because the reset lpPlayPtr will be lpQueuePtr */
            if (wwo->dwWrittenTotal > wwo->dwPlayedTotal + sz) ERR("grin\n");
            wwo->dwPartialOffset = sz - (wwo->dwWrittenTotal - wwo->dwPlayedTotal);
            wwo->dwWrittenTotal = wwo->dwPlayedTotal;
            wwo->lpPlayPtr = wwo->lpQueuePtr;
        }
        wwo->state = WINE_WS_PAUSED;
    }
}