예제 #1
0
static gboolean
alsa_open (void *dp)
{
    alsa_driver * const d = dp;
    gint mf, err, pers;

    if(pcm_open_and_load_hwparams(d) < 0)
	goto out;

    // ---
    // Set non-blocking mode.
    // ---

    d->outtime = 0;

    // --
    // Set channel parameters
    // --
    if((err = snd_pcm_hw_params_set_access(d->soundfd, d->hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0){
	alsa_error(N_("Unable to set access"), err);
	goto out;
    }

    if((err = snd_pcm_hw_params_set_format(d->soundfd, d->hwparams,
				    (d->bits - 8) ? d->signedness16 ? SND_PCM_FORMAT_S16 : SND_PCM_FORMAT_U16 :
						    d->signedness8 ? SND_PCM_FORMAT_S8 : SND_PCM_FORMAT_U8) < 0)) {
	alsa_error(N_("Unable to set audio format"), err);
	goto out;
    }
    /* Handle endianess aspects. TODO! */
    switch(d->bits) {
	case 16:
	    mf = d->signedness16 ? ST_MIXER_FORMAT_S16_LE : ST_MIXER_FORMAT_U16_LE;
	    break;
	case 8:
	default:
	    mf = d->signedness8 ? ST_MIXER_FORMAT_S8 : ST_MIXER_FORMAT_U8;
	    break;
    }

    if((err = snd_pcm_hw_params_set_channels(d->soundfd, d->hwparams, d->stereo + 1)) < 0) {
	alsa_error(N_("Unable to set channels number"), err);
	goto out;
    }
    if((d->stereo)) {
	mf |= ST_MIXER_FORMAT_STEREO;
    }
    d->mf = mf;

    d->p_mixfreq = d->playrate;
    if ((err = snd_pcm_hw_params_set_rate_near(d->soundfd, d->hwparams, &(d->p_mixfreq), NULL)) < 0) {
	alsa_error(N_("Unable to set sample rate"), err);
	goto out;
    }

    if(snd_pcm_hw_params_set_buffer_size(d->soundfd, d->hwparams, 1 << d->buffer_size) < 0) {
	/* Some soundcards report wrong maximal buffer size (maybe alsa bug). So we should try
	   to downscale its value before the reporting an error. The spinbutton still may display
	   the wrong number, but actually the correct value will be implemented.*/
	while((--d->buffer_size) >= 8)
	    if(!snd_pcm_hw_params_set_buffer_size(d->soundfd, d->hwparams, 1 << d->buffer_size))
		break;
	if(d->buffer_size < 8) {
	    error_error(N_("Unable to set appropriate buffer size"));
	    goto out;
	}
    }
    pers = 1 << d->num_periods;
    if ((err = snd_pcm_hw_params_set_periods_near(d->soundfd, d->hwparams, &pers, NULL)) < 0) {
	alsa_error(N_("Unable to set periods number"), err);
	goto out;
    }
    if ((err = snd_pcm_hw_params_get_period_size(d->hwparams, &(d->p_fragsize), NULL)) < 0) {
	alsa_error(N_("Unable to get period size"), err);
	goto out;
    }

    if((err = snd_pcm_hw_params(d->soundfd, d->hwparams))) {
	alsa_error(N_("Error setting hw parameters"), err);
	goto out;
    }

    /* The following piece of code is directly c_n_p'ed from the ALSA pcm example (whith a little adopting) */
    /* get the current swparams */
    err = snd_pcm_sw_params_current(d->soundfd, d->swparams);
    if (err < 0) {
            alsa_error(N_("Unable to determine current swparams for playback"), err);
	    goto out;
    }
    /* start the transfer when the buffer is full */
    err = snd_pcm_sw_params_set_start_threshold(d->soundfd, d->swparams, d->p_fragsize);
    if (err < 0) {
            alsa_error(N_("Unable to set start threshold mode for playback"), err);
	    goto out;
    }
    /* allow the transfer when at least period_size samples can be processed */
    err = snd_pcm_sw_params_set_avail_min(d->soundfd, d->swparams, d->p_fragsize);
    if (err < 0) {
            alsa_error(N_("Unable to set avail min for playback"), err);
	    goto out;
    }
    /* align all transfers to 1 sample */
    err = snd_pcm_sw_params_set_xfer_align(d->soundfd, d->swparams, 1);
    if (err < 0) {
            alsa_error(N_("Unable to set transfer align for playback"), err);
	    goto out;
    }
    /* write the parameters to the playback device */
    err = snd_pcm_sw_params(d->soundfd, d->swparams);
    if (err < 0) {
            alsa_error(N_("Unable to set sw params for playback"), err);
	    goto out;
    }

    err = snd_pcm_prepare(d->soundfd);
    if (err < 0) {
            alsa_error(N_("Unable to prepare playback"), err);
	    goto out;
    }
    // ---
    // Get buffering parameters
    // ---
   
    if(d->verbose)
        snd_pcm_dump(d->soundfd, d->output);
    d->sndbuf = calloc((d->stereo + 1) * (d->bits / 8), d->p_fragsize);

    d->pfd = malloc(sizeof(struct pollfd));
    if ((err = snd_pcm_poll_descriptors(d->soundfd, d->pfd, 1)) < 0) {
        alsa_error(N_("Unable to obtain poll descriptors for playback"), err);
        goto out;
    }

    d->polltag = audio_poll_add(d->pfd->fd, GDK_INPUT_WRITE, alsa_poll_ready_playing, d);

    d->playtime = 0;
    d->firstpoll = TRUE;

    return TRUE;

  out:
    alsa_release(dp);
    return FALSE;
}
예제 #2
0
static gboolean
alsa_open (void *dp)
{
    alsa_driver * const d = dp;
    int mf;

    snd_pcm_format_t pf;
    snd_pcm_capture_info_t pcm_info;
    snd_pcm_capture_params_t pp;
    snd_pcm_capture_status_t pbstat;

    //    int err = snd_pcm_open(&(d->soundfd), d->card_number, d->device_number,
    //         		 	  SND_PCM_OPEN_CAPTURE);
    int err = snd_pcm_open(&(d->soundfd), 0, 0,  SND_PCM_OPEN_CAPTURE);

    if (err != 0) {
	char buf[256];
	g_sprintf(buf, _("Couldn't open ALSA device for sound input (card:%d, device:%d):\n%s"), 
		d->card_number, d->device_number, snd_strerror(err));
	error_error(buf);
	goto out;
    }

    // ---
    // Set non-blocking mode.
    // ---

    snd_pcm_block_mode(d->soundfd, 1);    // enable block mode

    d->bits = 0;
    mf = 0;

    // ---
    // Select audio format
    // ---

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

    if (d->p_resolution == 16) {
      pf.format = SND_PCM_SFMT_S16_LE;
      d->bits = 16;
      mf = ST_MIXER_FORMAT_S16_LE;
    }
      else { 
        pf.format = SND_PCM_SFMT_U8; 
        d->bits = 8; 
        mf = ST_MIXER_FORMAT_S8; 
      } 

/*      if(d->p_channels == 2) { */
/*  	d->stereo = 1; */
/*  	pf.channels = d->p_channels; */
/*  	mf |= ST_MIXER_FORMAT_STEREO; */
/*      } */
/*      else { */
/*        pf.channels = d->p_channels; */
/*        d->stereo = 0; */
/*      } */

    d->stereo = 0;
    pf.channels = 1;

    pf.rate = d->p_mixfreq;
    d->playrate = d->p_mixfreq;
    mf = ST_MIXER_FORMAT_S16_LE;
    d->mf = mf;

    err = snd_pcm_capture_format(d->soundfd, &pf);
    if (err < 0) {
      error_error(_("Required sound output format not supported.\n"));
      goto out;
    }

    snd_pcm_capture_info(d->soundfd, &pcm_info);

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

    pp.fragment_size = d->p_fragsize * pf.channels * d->bits / 8;
    pp.fragments_min = 1;

    err = snd_pcm_capture_params(d->soundfd, &pp);
    if (err < 0) {
      error_error(_("Required sound output parameters not supported.\n"));
      goto out;
    }

    snd_pcm_capture_status(d->soundfd, &pbstat);
    /*    d->numfrags = pbstat.fragments; */
    d->numfrags = 1;
    d->fragsize = pbstat.fragment_size;
	
    d->sndbuf = calloc(1, d->fragsize);

    if(d->stereo == 1) {
      d->fragsize /= 2;
    }
    if(d->bits == 16) {
      d->fragsize /= 2;
    }
    
    d->polltag = gdk_input_add(snd_pcm_file_descriptor(d->soundfd), GDK_INPUT_READ, alsa_poll_ready_sampling, d); 
    //    d->firstpoll = TRUE;
    //    d->playtime = 0;

    return TRUE;

  out:
    alsa_release(dp);
    return FALSE;
}
예제 #3
0
static gboolean
alsa_open (void *dp)
{
    alsa_driver * const d = dp;
    int mf, err;

    snd_pcm_format_t pf;

    //    snd_pcm_channel_info_t pcm_info;
    snd_pcm_channel_params_t pp;
    snd_pcm_channel_setup_t setup;

    snd_pcm_channel_flush(d->soundfd, SND_PCM_CHANNEL_PLAYBACK);
    memset(&pp, 0, sizeof(pp));

    err = snd_pcm_open(&(d->soundfd), d->card_number, d->device_number, SND_PCM_OPEN_PLAYBACK);
    if (err != 0) {
	char buf[256];
	g_sprintf(buf, _("Couldn't open ALSA device for sound output (card:%d, device:%d):\n%s"), 
		d->card_number, d->device_number, snd_strerror(err));
	error_error(buf);
	goto out;
    }

    // ---
    // Set non-blocking mode.
    // ---
    //    snd_pcm_nonblock_mode(d->soundfd, 1);

    d->outtime = 0;
    d->bits = 0;
    mf = 0;

    // --
    // Set channel parameters
    // --
    pp.mode = SND_PCM_MODE_BLOCK;
    pp.channel = SND_PCM_CHANNEL_PLAYBACK;
    pp.start_mode = SND_PCM_START_FULL;
    pp.stop_mode = SND_PCM_STOP_ROLLOVER;

    // ---
    // Select audio format
    // ---
    memset(&pf, 0, sizeof(pf));
    pf.interleave = 1;
    if (d->p_resolution == 16) {
      pf.format = SND_PCM_SFMT_S16_LE;
      d->bits = 16;
      mf = ST_MIXER_FORMAT_S16_LE;
    }
    else {
      pf.format = SND_PCM_SFMT_U8;
      d->bits = 8;
      mf = ST_MIXER_FORMAT_S8;
    }

    pf.rate = d->p_mixfreq;
    d->playrate = d->p_mixfreq;

    if(d->p_channels == 2) {
	d->stereo = 1;
	pf.voices = d->p_channels;
	mf |= ST_MIXER_FORMAT_STEREO;
    }
    else {
      pf.voices = d->p_channels;
      d->stereo = 0;
    }
    d->mf = mf;
    memcpy(&pp.format, &pf, sizeof(pf));

    //    pp.buf.block.frag_size = d->p_fragsize * pf.voices * (d->bits / 8);
    pp.buf.block.frag_size = d->p_fragsize;
    pp.buf.block.frags_max = -1;
    pp.buf.block.frags_min = 1;

    err = snd_pcm_channel_params(d->soundfd, &pp);
    if (err < 0) {
      error_error(_("Required output-channel parameters not supported.\n"));
      goto out;
    }

    if (snd_pcm_channel_prepare(d->soundfd, SND_PCM_CHANNEL_PLAYBACK) < 0) {
      error_error(_("Unable to prepare ALSA channel.\n"));
      goto out;
    }

    // ---
    // Get buffering parameters
    // ---
   
    memset(&setup, 0, sizeof(setup));
    setup.mode = SND_PCM_MODE_BLOCK;
    setup.channel = SND_PCM_CHANNEL_PLAYBACK;
    err = snd_pcm_channel_setup(d->soundfd, &setup);
    if (err < 0) {
      error_error(_("Alsa setup error.\n"));
      goto out;
    }

    //    snd_pcm_channel_status(d->soundfd, &pbstat);
    //    d->fragsize = pbstat.fragment_size;

    d->numfrags = setup.buf.block.frags;
    d->fragsize = setup.buf.block.frag_size;
    /*    fprintf(stderr, "Numfrags: %d\n", d->numfrags);
	  fprintf(stderr, "Fragsize: %d\n", d->fragsize); */

    d->sndbuf = calloc(1, d->fragsize);

    if(d->stereo == 1) { 
      d->fragsize /= 2;  
    } 
    if(d->bits == 16) {  
      d->fragsize /= 2;  
    } 
    
    d->polltag = audio_poll_add(snd_pcm_file_descriptor(d->soundfd, SND_PCM_CHANNEL_PLAYBACK), GDK_INPUT_WRITE, alsa_poll_ready_playing, d);
    /*    d->firstpoll = TRUE; */
    d->firstpoll = TRUE;
    d->playtime = 0;

    return TRUE;

  out:
    alsa_release(dp);
    return FALSE;
}
예제 #4
0
static gboolean
alsa_open (void *dp)
{
    alsa_driver * const d = dp;
    int mf;

    snd_pcm_format_t pf;
    snd_pcm_playback_info_t pcm_info;
    snd_pcm_playback_params_t pp;
    snd_pcm_playback_status_t pbstat;

    int err = snd_pcm_open(&(d->soundfd), d->card_number, d->device_number,
         		 	  SND_PCM_OPEN_PLAYBACK);
    if (err != 0) {
	char buf[256];
	g_sprintf(buf, _("Couldn't open ALSA device for sound output (card:%d, device:%d):\n%s"), 
		d->card_number, d->device_number, snd_strerror(err));
	error_error(buf);
	goto out;
    }

    // ---
    // Set non-blocking mode.
    // ---

    snd_pcm_block_mode(d->soundfd, 0);    // enable block mode

    d->outtime = 0;
    d->bits = 0;
    mf = 0;

    // ---
    // Select audio format
    // ---

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

    if (d->p_resolution == 16) {
      pf.format = SND_PCM_SFMT_S16_LE;
      d->bits = 16;
      mf = ST_MIXER_FORMAT_S16_LE;
    }
    else {
      pf.format = SND_PCM_SFMT_U8;
      d->bits = 8;
      mf = ST_MIXER_FORMAT_S8;
    }

    if(d->p_channels == 2) {
	d->stereo = 1;
	pf.channels = d->p_channels;
	mf |= ST_MIXER_FORMAT_STEREO;
    }
    else {
      pf.channels = d->p_channels;
      d->stereo = 0;
    }

    pf.rate = d->p_mixfreq;
    d->playrate = d->p_mixfreq;
    d->mf = mf;

    err = snd_pcm_playback_format(d->soundfd, &pf);
    if (err < 0) {
      error_error(_("Required sound output format not supported.\n"));
      goto out;
    }

    snd_pcm_playback_info(d->soundfd, &pcm_info);

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

    pp.fragment_size = d->p_fragsize * pf.channels * (d->bits / 8);
    pp.fragments_max = 1;
    //    pp.fragments_max = 16pcm_info.buffer_size / pp.fragment_size;
    pp.fragments_room = 1;

    err = snd_pcm_playback_params(d->soundfd, &pp);
    if (err < 0) {
      error_error(_("Required sound output parameters not supported.\n"));
      goto out;
    }

    snd_pcm_playback_status(d->soundfd, &pbstat);
    //    d->numfrags = pbstat.fragments;
    //    d->numfrags = 1;
    d->fragsize = pbstat.fragment_size;
    d->numfrags = 1;
    
    /*    fprintf(stderr, "Numfrags: %d\n", d->numfrags);
	  fprintf(stderr, "Fragsize: %d\n", d->fragsize); */

    d->sndbuf = calloc(1, d->fragsize);

    if(d->stereo == 1) { 
      d->fragsize /= 2;  
    } 
    if(d->bits == 16) {  
      d->fragsize /= 2;  
    } 
    
    d->polltag = audio_poll_add(snd_pcm_file_descriptor(d->soundfd), GDK_INPUT_WRITE, alsa_poll_ready_playing, d);
    /*    d->firstpoll = TRUE; */
    d->firstpoll = TRUE;
    d->playtime = 0;

    return TRUE;

  out:
    alsa_release(dp);
    return FALSE;
}