int main(int argc, char *argv[]) { char *filename; char *devicename = "default"; int fd; WAVContainer_t wav; SNDPCMContainer_t playback; if (argc != 2) { fprintf(stderr, "Usage: ./lplay <file name>/n"); return -1; } memset(&playback, 0x0, sizeof(playback)); filename = argv[1]; fd = open(filename, O_RDONLY); if (fd < 0) { fprintf(stderr, "Error open [%s]/n", filename); return -1; } if (WAV_ReadHeader(fd, &wav) < 0) { fprintf(stderr, "Error WAV_Parse [%s]/n", filename); goto Err; } if (snd_output_stdio_attach(&playback.log, stderr, 0) < 0) { fprintf(stderr, "Error snd_output_stdio_attach/n"); goto Err; } if (snd_pcm_open(&playback.handle, devicename, SND_PCM_STREAM_PLAYBACK, 0) < 0) { fprintf(stderr, "Error snd_pcm_open [ %s]/n", devicename); goto Err; } if (SNDWAV_SetParams(&playback, &wav) < 0) { fprintf(stderr, "Error set_snd_pcm_params/n"); goto Err; } snd_pcm_dump(playback.handle, playback.log); SNDWAV_Play(&playback, &wav, fd); snd_pcm_drain(playback.handle); close(fd); free(playback.data_buf); snd_output_close(playback.log); snd_pcm_close(playback.handle); return 0; Err: close(fd); if (playback.data_buf) free(playback.data_buf); if (playback.log) snd_output_close(playback.log); if (playback.handle) snd_pcm_close(playback.handle); return -1; }
bool record(asr_usercommand::UserCommand::Request &req, asr_usercommand::UserCommand::Response &res) { char *filename; filename="/home/turtlebot2/asr_ws/src/asr_usercommand/wav/recordfile.wav"; char *devicename = "default"; int fd; WAVContainer_t wav; SNDPCMContainer_t record; memset(&record, 0x0, sizeof(record)); remove(filename); if ((fd = open(filename, O_WRONLY | O_CREAT, 0644)) == -1) { fprintf(stderr, "Error open: [%s]/n", filename); return false; } if (snd_output_stdio_attach(&record.log, stderr, 0) < 0) { fprintf(stderr, "Error snd_output_stdio_attach/n"); goto Err; } if (snd_pcm_open(&record.handle, devicename, SND_PCM_STREAM_CAPTURE, 0) < 0) { fprintf(stderr, "Error snd_pcm_open [ %s]/n", devicename); goto Err; } if (SNDWAV_PrepareWAVParams(&wav) < 0) { fprintf(stderr, "Error SNDWAV_PrepareWAVParams/n"); goto Err; } if (SNDWAV_SetParams(&record, &wav) < 0) { fprintf(stderr, "Error set_snd_pcm_params/n"); goto Err; } snd_pcm_dump(record.handle, record.log); SNDWAV_Record(&record, &wav, fd); snd_pcm_drain(record.handle); close(fd); free(record.data_buf); snd_output_close(record.log); snd_pcm_close(record.handle); return true; Err: close(fd); remove(filename); if (record.data_buf) free(record.data_buf); if (record.log) snd_output_close(record.log); if (record.handle) snd_pcm_close(record.handle); return false; }
/***************************************************************************** * Close: close the ALSA device *****************************************************************************/ static void Close( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; struct aout_sys_t * p_sys = p_aout->output.p_sys; int i_snd_rc; /* Make sure that the thread will stop once it is waken up */ vlc_cancel( p_sys->thread ); vlc_join( p_sys->thread, NULL ); vlc_sem_destroy( &p_sys->wait ); /* */ i_snd_rc = snd_pcm_close( p_sys->p_snd_pcm ); if( i_snd_rc > 0 ) { msg_Err( p_aout, "failed closing ALSA device (%s)", snd_strerror( i_snd_rc ) ); } #ifdef ALSA_DEBUG snd_output_close( p_sys->p_snd_stderr ); #endif free( p_sys ); }
static void dump_parm(snd_pcm_hw_params_t *params) { snd_output_t *log; snd_output_stdio_attach(&log, stderr, 0); snd_pcm_hw_params_dump(params, log); snd_output_close(log); }
/***************************************************************************** * Close: close the ALSA device *****************************************************************************/ static void Close( vlc_object_t *p_this ) { aout_instance_t *p_aout = (aout_instance_t *)p_this; struct aout_sys_t * p_sys = p_aout->output.p_sys; int i_snd_rc; /* Make sure that the thread will stop once it is waken up */ vlc_object_kill( p_aout ); /* make sure the audio output thread is waken up */ vlc_mutex_lock( &p_aout->output.p_sys->lock ); vlc_cond_signal( &p_aout->output.p_sys->wait ); vlc_mutex_unlock( &p_aout->output.p_sys->lock ); /* */ vlc_thread_join( p_aout ); p_aout->b_die = false; i_snd_rc = snd_pcm_close( p_sys->p_snd_pcm ); if( i_snd_rc > 0 ) { msg_Err( p_aout, "failed closing ALSA device (%s)", snd_strerror( i_snd_rc ) ); } #ifdef ALSA_DEBUG snd_output_close( p_sys->p_snd_stderr ); #endif free( p_sys ); }
void ga_alsa_close(snd_pcm_t *handle, snd_output_t *pout) { if(pout) snd_output_close(pout); if(handle) snd_pcm_close(handle); }
int do_play(char* file_name) { char *pcm_name = "default"; int tmp, err, c; snd_pcm_info_t *info; snd_pcm_info_alloca(&info); err = snd_output_stdio_attach(&log, stderr, 0); assert(err >= 0); stream = SND_PCM_STREAM_PLAYBACK; chunk_size = -1; rhwparams.format = DEFAULT_FORMAT; rhwparams.rate = DEFAULT_SPEED; rhwparams.channels = 1; 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; } signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGABRT, signal_handler); playback(file_name); snd_pcm_close(handle); free(audiobuf); snd_output_close(log); snd_config_update_free_global(); return EXIT_SUCCESS; }
static int close_device(AudioDevice *ad) { ALSA_data *alsa = (ALSA_data *)ad->private_data; snd_pcm_close(alsa->fd); snd_output_close(alsa->log); free(alsa); free(ad); return 1; }
static void gst_alsasink_finalise (GObject * object) { GstAlsaSink *sink = GST_ALSA_SINK (object); g_free (sink->device); g_mutex_free (sink->alsa_lock); g_static_mutex_lock (&output_mutex); --output_ref; if (output_ref == 0) { snd_output_close (output); output = NULL; } g_static_mutex_unlock (&output_mutex); G_OBJECT_CLASS (parent_class)->finalize (object); }
/** XXX: duplicated from ALSA output */ static void Dump (vlc_object_t *obj, const char *msg, int (*cb)(void *, snd_output_t *), void *p) { snd_output_t *output; char *str; if (unlikely(snd_output_buffer_open (&output))) return; int val = cb (p, output); if (val) { msg_Warn (obj, "cannot get info: %s", snd_strerror (val)); return; } size_t len = snd_output_buffer_string (output, &str); if (len > 0 && str[len - 1]) len--; /* strip trailing newline */ msg_Dbg (obj, "%s%.*s", msg, (int)len, str); snd_output_close (output); }
snd_pcm_t * ga_alsa_init(snd_output_t **pout) { snd_pcm_t *handle; int err; // if(pout) { if(snd_output_stdio_attach(pout, stderr, 0) < 0) { ga_error("cannot attach stderr\n"); return NULL; } } // XXX: debug do { struct timeval tv; gettimeofday(&tv, NULL); fprintf(stderr, "%ld.%06ld\n", tv.tv_sec, tv.tv_usec); } while(0); if((err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0)) < 0) { ga_error("open failed: %s\n", snd_strerror(err)); snd_output_close(*pout); return NULL; } return handle; }
int audio_in_uninit(audio_in_t *ai) { if (ai->setup) { switch (ai->type) { #ifdef CONFIG_ALSA case AUDIO_IN_ALSA: if (ai->alsa.log) snd_output_close(ai->alsa.log); if (ai->alsa.handle) { snd_pcm_close(ai->alsa.handle); } ai->setup = 0; return 0; #endif #ifdef CONFIG_OSS_AUDIO case AUDIO_IN_OSS: close(ai->oss.audio_fd); ai->setup = 0; return 0; #endif } } return -1; }
static gboolean gst_alsasink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec) { GstAlsaSink *alsa; gint err; alsa = GST_ALSA_SINK (asink); if (alsa->iec958) { snd_pcm_close (alsa->handle); alsa->handle = gst_alsa_open_iec958_pcm (GST_OBJECT (alsa), alsa->device); if (G_UNLIKELY (!alsa->handle)) { goto no_iec958; } } if (!alsasink_parse_spec (alsa, spec)) goto spec_parse; CHECK (set_hwparams (alsa), hw_params_failed); CHECK (set_swparams (alsa), sw_params_failed); alsa->bytes_per_sample = spec->bytes_per_sample; spec->segsize = alsa->period_size * spec->bytes_per_sample; spec->segtotal = alsa->buffer_size / alsa->period_size; { snd_output_t *out_buf = NULL; char *msg = NULL; snd_output_buffer_open (&out_buf); snd_pcm_dump_hw_setup (alsa->handle, out_buf); snd_output_buffer_string (out_buf, &msg); GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg); snd_output_close (out_buf); snd_output_buffer_open (&out_buf); snd_pcm_dump_sw_setup (alsa->handle, out_buf); snd_output_buffer_string (out_buf, &msg); GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg); snd_output_close (out_buf); } return TRUE; /* ERRORS */ no_iec958: { GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE, (NULL), ("Could not open IEC958 (SPDIF) device for playback")); return FALSE; } spec_parse: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Error parsing spec")); return FALSE; } hw_params_failed: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Setting of hwparams failed: %s", snd_strerror (err))); return FALSE; } sw_params_failed: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Setting of swparams failed: %s", snd_strerror (err))); return FALSE; } }
/***************************************************************************** * Open: create a handle and open an alsa device ***************************************************************************** * This function opens an alsa device, through the alsa API. * * Note: the only heap-allocated string is psz_device. All the other pointers * are references to psz_device or to stack-allocated data. *****************************************************************************/ static int Open( vlc_object_t *p_this ) { aout_instance_t * p_aout = (aout_instance_t *)p_this; struct aout_sys_t * p_sys; vlc_value_t val; char psz_default_iec_device[128]; /* Buffer used to store the default S/PDIF device */ char * psz_device, * psz_iec_device; /* device names for PCM and S/PDIF output */ int i_vlc_pcm_format; /* Audio format for VLC's data */ int i_snd_pcm_format; /* Audio format for ALSA's data */ snd_pcm_uframes_t i_buffer_size = 0; snd_pcm_uframes_t i_period_size = 0; int i_channels = 0; snd_pcm_hw_params_t *p_hw; snd_pcm_sw_params_t *p_sw; int i_snd_rc = -1; unsigned int i_old_rate; bool b_retry = true; /* Allocate structures */ p_aout->output.p_sys = p_sys = malloc( sizeof( aout_sys_t ) ); if( p_sys == NULL ) return VLC_ENOMEM; p_sys->b_playing = false; p_sys->start_date = 0; vlc_cond_init( &p_sys->wait ); vlc_mutex_init( &p_sys->lock ); /* Get device name */ if( (psz_device = config_GetPsz( p_aout, "alsa-audio-device" )) == NULL ) { msg_Err( p_aout, "no audio device given (maybe \"default\" ?)" ); dialog_Fatal( p_aout, _("No Audio Device"), "%s", _("No audio device name was given. You might want to " \ "enter \"default\".") ); free( p_sys ); return VLC_EGENERIC; } /* Choose the IEC device for S/PDIF output: if the device is overriden by the user then it will be the one otherwise we compute the default device based on the output format. */ if( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) && !strcmp( psz_device, DEFAULT_ALSA_DEVICE ) ) { snprintf( psz_default_iec_device, sizeof(psz_default_iec_device), "iec958:AES0=0x%x,AES1=0x%x,AES2=0x%x,AES3=0x%x", IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO, IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER, 0, ( p_aout->output.output.i_rate == 48000 ? IEC958_AES3_CON_FS_48000 : ( p_aout->output.output.i_rate == 44100 ? IEC958_AES3_CON_FS_44100 : IEC958_AES3_CON_FS_32000 ) ) ); psz_iec_device = psz_default_iec_device; } else if( AOUT_FMT_NON_LINEAR( &p_aout->output.output ) ) { psz_iec_device = psz_device; } else { psz_iec_device = NULL; } /* Choose the linear PCM format (read the comment above about FPU and float32) */ if( vlc_CPU() & CPU_CAPABILITY_FPU ) { i_vlc_pcm_format = VLC_CODEC_FL32; i_snd_pcm_format = SND_PCM_FORMAT_FLOAT; } else { i_vlc_pcm_format = VLC_CODEC_S16N; i_snd_pcm_format = SND_PCM_FORMAT_S16; } /* If the variable doesn't exist then it's the first time we're called and we have to probe the available audio formats and channels */ if ( var_Type( p_aout, "audio-device" ) == 0 ) { Probe( p_aout, psz_device, psz_iec_device, &i_snd_pcm_format ); } if ( var_Get( p_aout, "audio-device", &val ) < 0 ) { free( p_sys ); free( psz_device ); return VLC_EGENERIC; } p_aout->output.output.i_format = i_vlc_pcm_format; if ( val.i_int == AOUT_VAR_5_1 ) { p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT | AOUT_CHAN_LFE; free( psz_device ); psz_device = strdup( "surround51" ); } else if ( val.i_int == AOUT_VAR_2F2R ) { p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT; free( psz_device ); psz_device = strdup( "surround40" ); } else if ( val.i_int == AOUT_VAR_STEREO ) { p_aout->output.output.i_physical_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT; } else if ( val.i_int == AOUT_VAR_MONO ) { p_aout->output.output.i_physical_channels = AOUT_CHAN_CENTER; } else if( val.i_int != AOUT_VAR_SPDIF ) { /* This should not happen ! */ msg_Err( p_aout, "internal: can't find audio-device (%i)", val.i_int ); free( p_sys ); free( psz_device ); return VLC_EGENERIC; } #ifdef ALSA_DEBUG snd_output_stdio_attach( &p_sys->p_snd_stderr, stderr, 0 ); #endif /* Open the device */ if ( val.i_int == AOUT_VAR_SPDIF ) { if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_iec_device, SND_PCM_STREAM_PLAYBACK, 0 ) ) < 0 ) { msg_Err( p_aout, "cannot open ALSA device `%s' (%s)", psz_iec_device, snd_strerror( i_snd_rc ) ); dialog_Fatal( p_aout, _("Audio output failed"), _("VLC could not open the ALSA device \"%s\" (%s)."), psz_iec_device, snd_strerror( i_snd_rc ) ); free( p_sys ); free( psz_device ); return VLC_EGENERIC; } i_buffer_size = ALSA_SPDIF_BUFFER_SIZE; i_snd_pcm_format = SND_PCM_FORMAT_S16; i_channels = 2; i_vlc_pcm_format = VLC_CODEC_SPDIFL; p_aout->output.i_nb_samples = i_period_size = ALSA_SPDIF_PERIOD_SIZE; p_aout->output.output.i_bytes_per_frame = AOUT_SPDIF_SIZE; p_aout->output.output.i_frame_length = A52_FRAME_NB; aout_VolumeNoneInit( p_aout ); } else { int i; msg_Dbg( p_aout, "opening ALSA device `%s'", psz_device ); /* Since it seems snd_pcm_close hasn't really released the device at the time it returns, probe if the device is available in loop for 1s. We cannot use blocking mode since the we would wait indefinitely when switching from a dmx device to surround51. */ for( i = 10; i >= 0; i-- ) { if ( ( i_snd_rc = snd_pcm_open( &p_sys->p_snd_pcm, psz_device, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK ) ) == -EBUSY ) { if( i ) msleep( 100000 /* 100ms */ ); else { msg_Err( p_aout, "audio device: %s is already in use", psz_device ); dialog_Fatal( p_aout, _("Audio output failed"), _("The audio device \"%s\" is already in use."), psz_device ); } continue; } break; } if( i_snd_rc < 0 ) { msg_Err( p_aout, "cannot open ALSA device `%s' (%s)", psz_device, snd_strerror( i_snd_rc ) ); dialog_Fatal( p_aout, _("Audio output failed"), _("VLC could not open the ALSA device \"%s\" (%s)."), psz_device, snd_strerror( i_snd_rc ) ); free( p_sys ); free( psz_device ); return VLC_EGENERIC; } /* We want blocking mode */ snd_pcm_nonblock( p_sys->p_snd_pcm, 0 ); i_buffer_size = ALSA_DEFAULT_BUFFER_SIZE; i_channels = aout_FormatNbChannels( &p_aout->output.output ); p_aout->output.i_nb_samples = i_period_size = ALSA_DEFAULT_PERIOD_SIZE; aout_VolumeSoftInit( p_aout ); } /* Free psz_device so that all the remaining data is stack-allocated */ free( psz_device ); p_aout->output.pf_play = Play; snd_pcm_hw_params_alloca(&p_hw); snd_pcm_sw_params_alloca(&p_sw); /* Due to some bugs in alsa with some drivers, we need to retry in s16l if snd_pcm_hw_params fails in fl32 */ while ( b_retry ) { b_retry = false; /* Get Initial hardware parameters */ if ( ( i_snd_rc = snd_pcm_hw_params_any( p_sys->p_snd_pcm, p_hw ) ) < 0 ) { msg_Err( p_aout, "unable to retrieve initial hardware parameters (%s)", snd_strerror( i_snd_rc ) ); goto error; } /* Set format. */ if ( ( i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw, i_snd_pcm_format ) ) < 0 ) { if( i_snd_pcm_format != SND_PCM_FORMAT_S16 ) { i_snd_pcm_format = SND_PCM_FORMAT_S16; i_snd_rc = snd_pcm_hw_params_set_format( p_sys->p_snd_pcm, p_hw, i_snd_pcm_format ); } if ( i_snd_rc < 0 ) { msg_Err( p_aout, "unable to set stream sample size and " "word order (%s)", snd_strerror( i_snd_rc ) ); goto error; } } if( i_vlc_pcm_format != VLC_CODEC_SPDIFL ) switch( i_snd_pcm_format ) { case SND_PCM_FORMAT_FLOAT: i_vlc_pcm_format = VLC_CODEC_FL32; break; case SND_PCM_FORMAT_S16: i_vlc_pcm_format = VLC_CODEC_S16N; break; } p_aout->output.output.i_format = i_vlc_pcm_format; if ( ( i_snd_rc = snd_pcm_hw_params_set_access( p_sys->p_snd_pcm, p_hw, SND_PCM_ACCESS_RW_INTERLEAVED ) ) < 0 ) { msg_Err( p_aout, "unable to set interleaved stream format (%s)", snd_strerror( i_snd_rc ) ); goto error; } /* Set channels. */ if ( ( i_snd_rc = snd_pcm_hw_params_set_channels( p_sys->p_snd_pcm, p_hw, i_channels ) ) < 0 ) { msg_Err( p_aout, "unable to set number of output channels (%s)", snd_strerror( i_snd_rc ) ); goto error; } /* Set rate. */ i_old_rate = p_aout->output.output.i_rate; i_snd_rc = snd_pcm_hw_params_set_rate_near( p_sys->p_snd_pcm, p_hw, &p_aout->output.output.i_rate, NULL ); if( i_snd_rc < 0 || p_aout->output.output.i_rate != i_old_rate ) { msg_Warn( p_aout, "The rate %d Hz is not supported by your " \ "hardware. Using %d Hz instead.\n", i_old_rate, \ p_aout->output.output.i_rate ); } /* Set period size. */ if ( ( i_snd_rc = snd_pcm_hw_params_set_period_size_near( p_sys->p_snd_pcm, p_hw, &i_period_size, NULL ) ) < 0 ) { msg_Err( p_aout, "unable to set period size (%s)", snd_strerror( i_snd_rc ) ); goto error; } p_aout->output.i_nb_samples = i_period_size; /* Set buffer size. */ if ( ( i_snd_rc = snd_pcm_hw_params_set_buffer_size_near( p_sys->p_snd_pcm, p_hw, &i_buffer_size ) ) < 0 ) { msg_Err( p_aout, "unable to set buffer size (%s)", snd_strerror( i_snd_rc ) ); goto error; } /* Commit hardware parameters. */ if ( ( i_snd_rc = snd_pcm_hw_params( p_sys->p_snd_pcm, p_hw ) ) < 0 ) { if ( b_retry == false && i_snd_pcm_format == SND_PCM_FORMAT_FLOAT) { b_retry = true; i_snd_pcm_format = SND_PCM_FORMAT_S16; p_aout->output.output.i_format = VLC_CODEC_S16N; msg_Warn( p_aout, "unable to commit hardware configuration " "with fl32 samples. Retrying with s16l (%s)", snd_strerror( i_snd_rc ) ); } else { msg_Err( p_aout, "unable to commit hardware configuration (%s)", snd_strerror( i_snd_rc ) ); goto error; } } } if( ( i_snd_rc = snd_pcm_hw_params_get_period_time( p_hw, &p_sys->i_period_time, NULL ) ) < 0 ) { msg_Err( p_aout, "unable to get period time (%s)", snd_strerror( i_snd_rc ) ); goto error; } /* Get Initial software parameters */ snd_pcm_sw_params_current( p_sys->p_snd_pcm, p_sw ); i_snd_rc = snd_pcm_sw_params_set_sleep_min( p_sys->p_snd_pcm, p_sw, 0 ); i_snd_rc = snd_pcm_sw_params_set_avail_min( p_sys->p_snd_pcm, p_sw, p_aout->output.i_nb_samples ); /* start playing when one period has been written */ i_snd_rc = snd_pcm_sw_params_set_start_threshold( p_sys->p_snd_pcm, p_sw, ALSA_DEFAULT_PERIOD_SIZE); if( i_snd_rc < 0 ) { msg_Err( p_aout, "unable to set start threshold (%s)", snd_strerror( i_snd_rc ) ); goto error; } /* Commit software parameters. */ if ( snd_pcm_sw_params( p_sys->p_snd_pcm, p_sw ) < 0 ) { msg_Err( p_aout, "unable to set software configuration" ); goto error; } #ifdef ALSA_DEBUG snd_output_printf( p_sys->p_snd_stderr, "\nALSA hardware setup:\n\n" ); snd_pcm_dump_hw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr ); snd_output_printf( p_sys->p_snd_stderr, "\nALSA software setup:\n\n" ); snd_pcm_dump_sw_setup( p_sys->p_snd_pcm, p_sys->p_snd_stderr ); snd_output_printf( p_sys->p_snd_stderr, "\n" ); #endif /* Create ALSA thread and wait for its readiness. */ if( vlc_thread_create( p_aout, "aout", ALSAThread, VLC_THREAD_PRIORITY_OUTPUT ) ) { msg_Err( p_aout, "cannot create ALSA thread (%m)" ); goto error; } return 0; error: snd_pcm_close( p_sys->p_snd_pcm ); #ifdef ALSA_DEBUG snd_output_close( p_sys->p_snd_stderr ); #endif free( p_sys ); return VLC_EGENERIC; }
/****************************************************************************** * Sound_alsa_create ******************************************************************************/ Sound_Handle Sound_alsa_create(Sound_Attrs *attrs) { Sound_Handle hSound; Int status; snd_output_t *log; assert(attrs); hSound = calloc(1, sizeof(Sound_Object)); if (hSound == NULL) { Dmai_err0("Failed to allocate space for Sound Object\n"); return NULL; } hSound->soundStd = attrs->soundStd; hSound->sampleRate = attrs->sampleRate; hSound->channels = attrs->channels; hSound->bufSize = attrs->bufSize; if (attrs->mode == Sound_Mode_INPUT || attrs->mode == Sound_Mode_FULLDUPLEX) { status = snd_pcm_open(&hSound->rcIn, AUDIO_DEVICE, SND_PCM_STREAM_CAPTURE, 0); if (status < 0) { Dmai_err2("Failed to open ALSA sound device for input %s (%s)\n", AUDIO_DEVICE, snd_strerror(status)); Sound_alsa_delete(hSound); return NULL; } /* Allocate a PCM SW and HW Param structure */ status = snd_pcm_hw_params_malloc(&hSound->hwParamsIn); if (status < 0) { Dmai_err2("Failed to alloc hardware param structure on %s (%s)\n", AUDIO_DEVICE, snd_strerror(status)); Sound_alsa_delete(hSound); return NULL; } status = snd_pcm_sw_params_malloc(&hSound->swParamsIn); if (status < 0) { Dmai_err2("Failed to alloc software param structure on %s (%s)\n", AUDIO_DEVICE, snd_strerror(status)); Sound_alsa_delete(hSound); return NULL; } if (initHwParams(hSound->rcIn,hSound->hwParamsIn,attrs,hSound) < 0) { Sound_alsa_delete(hSound); return NULL; } if (initSwParams(hSound->rcIn,hSound->swParamsIn,hSound,1) < 0) { Sound_alsa_delete(hSound); return NULL; } } if (attrs->mode == Sound_Mode_OUTPUT || attrs->mode == Sound_Mode_FULLDUPLEX) { status = snd_pcm_open(&hSound->rcOut, AUDIO_DEVICE, SND_PCM_STREAM_PLAYBACK, 0); if (status < 0) { Dmai_err2("Failed to open ALSA sound device for output %s (%s)\n", AUDIO_DEVICE, snd_strerror(status)); Sound_alsa_delete(hSound); return NULL; } /* Allocate a PCM SW and HW Param structure */ status = snd_pcm_hw_params_malloc(&hSound->hwParamsOut); if (status < 0) { Dmai_err2("Failed to alloc hardware param structure on %s (%s)\n", AUDIO_DEVICE, snd_strerror(status)); Sound_alsa_delete(hSound); return NULL; } status = snd_pcm_sw_params_malloc(&hSound->swParamsOut); if (status < 0) { Dmai_err2("Failed to alloc hardware param structure on %s (%s)\n", AUDIO_DEVICE, snd_strerror(status)); Sound_alsa_delete(hSound); return NULL; } if (initHwParams(hSound->rcOut,hSound->hwParamsOut,attrs,hSound) < 0) { Sound_alsa_delete(hSound); return NULL; } if (initSwParams(hSound->rcOut,hSound->swParamsOut,hSound,0) < 0) { Sound_alsa_delete(hSound); return NULL; } if (setMixerVolume (attrs) <0) { Sound_alsa_delete (hSound); return NULL; } } #if 0 if (attrs->mode != Sound_Mode_OUTPUT) { if (attrs->soundInput == Sound_Input_MIC) { if(setMixerControl(RIGHT_LINE_CTRL_ELEM, 0) != Dmai_EOK) { Dmai_err0("Failed to configure Right_PGA_Mixer_Line1R_Switch\n"); Sound_alsa_delete(hSound); return NULL; } if(setMixerControl(LEFT_LINE_CTRL_ELEM, 0) != Dmai_EOK) { Dmai_err0("Failed to configure Left_PGA_Mixer_Line1L_Switch\n"); Sound_alsa_delete(hSound); return NULL; } if(setMixerControl(RIGHT_MIC_CTRL_ELEM, 1) != Dmai_EOK) { Dmai_err0("Failed to configure Right_PGA_Mixer_Mic3R_Switch\n"); Sound_alsa_delete(hSound); return NULL; } if(setMixerControl(LEFT_MIC_CTRL_ELEM, 1) != Dmai_EOK) { Dmai_err0("Failed to configure Left_PGA_Mixer_Mic3L_Switch\n"); Sound_alsa_delete(hSound); return NULL; } } else if (attrs->soundInput == Sound_Input_LINE) { if(setMixerControl(RIGHT_LINE_CTRL_ELEM, 1) != Dmai_EOK) { Dmai_err0("Failed to configure Right_PGA_Mixer_Line1R_Switch\n"); Sound_alsa_delete(hSound); return NULL; } if(setMixerControl(LEFT_LINE_CTRL_ELEM, 1) != Dmai_EOK) { Dmai_err0("Failed to configure Left_PGA_Mixer_Line1L_Switch\n"); Sound_alsa_delete(hSound); return NULL; } if(setMixerControl(RIGHT_MIC_CTRL_ELEM, 0) != Dmai_EOK) { Dmai_err0("Failed to configure Right_PGA_Mixer_Mic3R_Switch\n"); Sound_alsa_delete(hSound); return NULL; } if(setMixerControl(LEFT_MIC_CTRL_ELEM, 0) != Dmai_EOK) { Dmai_err0("Failed to configure Left_PGA_Mixer_Mic3L_Switch\n"); Sound_alsa_delete(hSound); return NULL; } } } snd_output_close(log); #endif return hSound; }
int sa_stream_open(sa_stream_t *s) { snd_output_t* out; char* buf; size_t bufsz; snd_pcm_hw_params_t* hwparams; snd_pcm_sw_params_t* swparams; int dir; snd_pcm_uframes_t period; if (s == NULL) { return SA_ERROR_NO_INIT; } if (s->output_unit != NULL) { return SA_ERROR_INVALID; } pthread_mutex_lock(&sa_alsa_mutex); /* Turn off debug output to stderr */ snd_lib_error_set_handler(quiet_error_handler); if (snd_pcm_open(&s->output_unit, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0) { pthread_mutex_unlock(&sa_alsa_mutex); return SA_ERROR_NO_DEVICE; } if (snd_pcm_set_params(s->output_unit, #ifdef SA_LITTLE_ENDIAN SND_PCM_FORMAT_S16_LE, #else SND_PCM_FORMAT_S16_BE, #endif SND_PCM_ACCESS_RW_INTERLEAVED, s->n_channels, s->rate, 1, 500000) < 0) { snd_pcm_close(s->output_unit); s->output_unit = NULL; pthread_mutex_unlock(&sa_alsa_mutex); return SA_ERROR_NOT_SUPPORTED; } /* ugly alsa-pulse plugin detection */ snd_output_buffer_open(&out); snd_pcm_dump(s->output_unit, out); bufsz = snd_output_buffer_string(out, &buf); s->pulseaudio = bufsz >= strlen(ALSA_PA_PLUGIN) && strncmp(buf, ALSA_PA_PLUGIN, strlen(ALSA_PA_PLUGIN)) == 0; snd_output_close(out); snd_pcm_hw_params_alloca(&hwparams); snd_pcm_hw_params_current(s->output_unit, hwparams); snd_pcm_hw_params_get_period_size(hwparams, &period, &dir); pthread_mutex_unlock(&sa_alsa_mutex); return SA_SUCCESS; }
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; }
static gboolean gst_alsasrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec) { GstAlsaSrc *alsa; gint err; alsa = GST_ALSA_SRC (asrc); if (!alsasrc_parse_spec (alsa, spec)) goto spec_parse; CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block); CHECK (set_hwparams (alsa), hw_params_failed); CHECK (set_swparams (alsa), sw_params_failed); CHECK (snd_pcm_prepare (alsa->handle), prepare_failed); alsa->bpf = GST_AUDIO_INFO_BPF (&spec->info); spec->segsize = alsa->period_size * alsa->bpf; spec->segtotal = alsa->buffer_size / alsa->period_size; { snd_output_t *out_buf = NULL; char *msg = NULL; snd_output_buffer_open (&out_buf); snd_pcm_dump_hw_setup (alsa->handle, out_buf); snd_output_buffer_string (out_buf, &msg); GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg); snd_output_close (out_buf); snd_output_buffer_open (&out_buf); snd_pcm_dump_sw_setup (alsa->handle, out_buf); snd_output_buffer_string (out_buf, &msg); GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg); snd_output_close (out_buf); } #ifdef SND_CHMAP_API_VERSION alsa_detect_channels_mapping (GST_OBJECT (alsa), alsa->handle, spec, alsa->channels, GST_AUDIO_BASE_SRC (alsa)->ringbuffer); #endif /* SND_CHMAP_API_VERSION */ return TRUE; /* ERRORS */ spec_parse: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Error parsing spec")); return FALSE; } non_block: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Could not set device to blocking: %s", snd_strerror (err))); return FALSE; } hw_params_failed: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Setting of hwparams failed: %s", snd_strerror (err))); return FALSE; } sw_params_failed: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Setting of swparams failed: %s", snd_strerror (err))); return FALSE; } prepare_failed: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Prepare failed: %s", snd_strerror (err))); return FALSE; } }
static gboolean gst_alsasrc_prepare (GstAudioSrc * asrc, GstAudioRingBufferSpec * spec) { GstAlsaSrc *alsa; gint err; alsa = GST_ALSA_SRC (asrc); if (!alsasrc_parse_spec (alsa, spec)) goto spec_parse; CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block); CHECK (set_hwparams (alsa), hw_params_failed); CHECK (set_swparams (alsa), sw_params_failed); CHECK (snd_pcm_prepare (alsa->handle), prepare_failed); alsa->bpf = GST_AUDIO_INFO_BPF (&spec->info); spec->segsize = alsa->period_size * alsa->bpf; spec->segtotal = alsa->buffer_size / alsa->period_size; { snd_output_t *out_buf = NULL; char *msg = NULL; snd_output_buffer_open (&out_buf); snd_pcm_dump_hw_setup (alsa->handle, out_buf); snd_output_buffer_string (out_buf, &msg); GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg); snd_output_close (out_buf); snd_output_buffer_open (&out_buf); snd_pcm_dump_sw_setup (alsa->handle, out_buf); snd_output_buffer_string (out_buf, &msg); GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg); snd_output_close (out_buf); } #ifdef SND_CHMAP_API_VERSION if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9) { snd_pcm_chmap_t *chmap = snd_pcm_get_chmap (alsa->handle); if (chmap && chmap->channels == alsa->channels) { GstAudioChannelPosition pos[8]; if (alsa_chmap_to_channel_positions (chmap, pos)) gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SRC (alsa)->ringbuffer, pos); } free (chmap); } #endif /* SND_CHMAP_API_VERSION */ return TRUE; /* ERRORS */ spec_parse: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Error parsing spec")); return FALSE; } non_block: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Could not set device to blocking: %s", snd_strerror (err))); return FALSE; } hw_params_failed: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Setting of hwparams failed: %s", snd_strerror (err))); return FALSE; } sw_params_failed: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Setting of swparams failed: %s", snd_strerror (err))); return FALSE; } prepare_failed: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Prepare failed: %s", snd_strerror (err))); return FALSE; } }
static gboolean gst_alsasink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec) { GstAlsaSink *alsa; gint err; alsa = GST_ALSA_SINK (asink); if (alsa->iec958) { snd_pcm_close (alsa->handle); alsa->handle = gst_alsa_open_iec958_pcm (GST_OBJECT (alsa), alsa->device); if (G_UNLIKELY (!alsa->handle)) { goto no_iec958; } } if (!alsasink_parse_spec (alsa, spec)) goto spec_parse; CHECK (set_hwparams (alsa), hw_params_failed); CHECK (set_swparams (alsa), sw_params_failed); alsa->bpf = GST_AUDIO_INFO_BPF (&spec->info); spec->segsize = alsa->period_size * alsa->bpf; spec->segtotal = alsa->buffer_size / alsa->period_size; { snd_output_t *out_buf = NULL; char *msg = NULL; snd_output_buffer_open (&out_buf); snd_pcm_dump_hw_setup (alsa->handle, out_buf); snd_output_buffer_string (out_buf, &msg); GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg); snd_output_close (out_buf); snd_output_buffer_open (&out_buf); snd_pcm_dump_sw_setup (alsa->handle, out_buf); snd_output_buffer_string (out_buf, &msg); GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg); snd_output_close (out_buf); } #ifdef SND_CHMAP_API_VERSION if (spec->type == GST_AUDIO_RING_BUFFER_FORMAT_TYPE_RAW && alsa->channels < 9) { snd_pcm_chmap_t *chmap = snd_pcm_get_chmap (alsa->handle); if (chmap && chmap->channels == alsa->channels) { GstAudioChannelPosition pos[8]; if (alsa_chmap_to_channel_positions (chmap, pos)) gst_audio_ring_buffer_set_channel_positions (GST_AUDIO_BASE_SINK (alsa)->ringbuffer, pos); } free (chmap); } #endif /* SND_CHMAP_API_VERSION */ return TRUE; /* ERRORS */ no_iec958: { GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE, (NULL), ("Could not open IEC958 (SPDIF) device for playback")); return FALSE; } spec_parse: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Error parsing spec")); return FALSE; } hw_params_failed: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Setting of hwparams failed: %s", snd_strerror (err))); return FALSE; } sw_params_failed: { GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), ("Setting of swparams failed: %s", snd_strerror (err))); return FALSE; } }