Exemplo n.º 1
0
bool
AlsaPlayer::Initialize ()
{
	bool result;
	
	LOG_ALSA ("AlsaPlayer::Initialize ()\n");
	
	// Create our spipe
	if (pipe (fds) != 0) {
		LOG_AUDIO ("AlsaPlayer::Initialize (): Unable to create pipe (%s).\n", strerror (errno));
		return false;
	}

	// Make the writer pipe non-blocking.
	fcntl (fds [1], F_SETFL, fcntl (fds [1], F_GETFL) | O_NONBLOCK);

	// Create the audio thread
	audio_thread = (pthread_t *) g_malloc (sizeof (pthread_t));
	result = pthread_create (audio_thread, NULL, Loop, this);
	if (result != 0) {
		LOG_AUDIO ("AlsaPlayer::Initialize (): could not create audio thread (error code: %i = '%s').\n", result, strerror (result));
		g_free (audio_thread);
		audio_thread = NULL;
		return false;
	}
	
	LOG_ALSA ("AlsaPlayer::Initialize (): the audio player has been initialized.\n");
	
	return true;
}
Exemplo n.º 2
0
bool
OpenSLESSource::InitializeInternal ()
{
	LOG_AUDIO ("OpenSLESSource::InitializeInternal ()\n");
	// this is a no-op, initialization is done when needed.
	return true;
}
Exemplo n.º 3
0
guint64
AlsaSource::GetDelayInternal ()
{
	snd_pcm_sframes_t delay;
	int err;
	guint64 result;
	bool update_error = false;
	bool not_initialized = false;
	
	mutex.Lock ();
	if (!initialized) {
		not_initialized = true;
	} else {
		err = snd_pcm_avail_update (pcm);
	
		if (err < 0) {
			LOG_AUDIO ("AlsaSource::GetDelayInternal (): Could not update delay (%s)\n", snd_strerror (err));
			update_error = true;
		} else {
			err = snd_pcm_delay (pcm, &delay);
		}
	}
	mutex.Unlock ();
	
	if (not_initialized) {
		LOG_AUDIO ("AlsaSource::GetDelayInternal (): pcm has been closed.\n");
		return G_MAXUINT64;
	}
	
	if (update_error)
		return G_MAXUINT64;
	
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::GetDelayInternal (): Could not get delay (%s)\n", snd_strerror (err));
		result = G_MAXUINT64;
	} else if (delay < 0) {
		LOG_AUDIO ("AlsaSource::GetDelayInternal (): Got negative delay (%li)\n", delay);
		result = G_MAXUINT64;
	} else {
		result = (guint64) TIMESPANTICKS_IN_SECOND * (guint64) delay / (guint64) GetSampleRate ();
	}
	
	return result;
}
Exemplo n.º 4
0
bool
AlsaSource::WriteRW ()
{
	snd_pcm_sframes_t avail;
	snd_pcm_sframes_t commitres = 0;
	guint32 frames;
	void *buffer;
	
	if (GetState () != AudioPlaying) {
		LOG_ALSA ("AlsaSource::WriteRW (): trying to write when we're not playing (state: %i)\n", GetState ());
		return false;
	}

	if (!PreparePcm (&avail))
		return false;
	
	LOG_ALSA ("AlsaSource::WriteRW (): entering play loop, avail: %" G_GINT64_FORMAT ", sample size: %i\n", (gint64) avail, (int) period_size);
	
	buffer = g_malloc (avail * GetOutputBytesPerFrame ());
	
	frames = Write (buffer, (guint32) avail);

	mutex.Lock ();
	if (initialized)
		commitres = snd_pcm_writei (pcm, buffer, frames);
	mutex.Unlock ();
	
	g_free (buffer);
	
	LOG_ALSA ("AlsaSource::WriteRW (): played %i samples, of %i available samples, result: %i.\n", (int) frames, (int) avail, (int) commitres);
	
	if (commitres < 0 || (snd_pcm_uframes_t) commitres != frames) {
		if (commitres == -EAGAIN)
			LOG_AUDIO ("AlsaSource::WriteRW (): not enough space for all the data\n");
		if (!XrunRecovery (commitres >= 0 ? -EPIPE : commitres)) {
			LOG_AUDIO ("AudioPlayer: could not write audio data: %s, commitres: %li, frames: %u\n", snd_strerror (commitres), commitres, frames);
			return false;
		}
		started = false;
	}

	return frames != 0;
}
Exemplo n.º 5
0
void
AlsaSource::DropAlsa ()
{
	int err;
	
	LOG_ALSA ("AlsaSource::DropAlsa ()\n");
	
	mutex.Lock ();
	drop_pending = false;
	
	if (pcm != NULL && snd_pcm_state (pcm) == SND_PCM_STATE_RUNNING) {
		err = snd_pcm_drop (pcm);
		if (err < 0)
			LOG_AUDIO ("AlsaSource::DropAlsa (): Could not stop/drain pcm: %s\n", snd_strerror (err)); 
	}
	mutex.Unlock ();
}
Exemplo n.º 6
0
void
AlsaPlayer::WakeUp ()
{
	int result;
		
	LOG_ALSA_EX ("AlsaPlayer::WakeUp ().\n");
		
	// Write until something has been written.
	do {
		result = write (fds [1], "c", 1);
	} while (result == 0);
	
	if (result == -1)
		LOG_AUDIO ("AlsaPlayer::WakeUp (): Could not wake up audio thread: %s\n", strerror (errno));
		
	LOG_ALSA_EX ("AlsaPlayer::WakeUp (): thread should now wake up (or have woken up already).\n");
	
}
Exemplo n.º 7
0
void
AlsaPlayer::PrepareShutdownInternal ()
{
	int result = 0;
	
	LOG_ALSA ("AlsaPlayer::PrepareShutdownInternal ().\n");

	// Wait for the audio thread to finish
	shutdown = true;
	if (audio_thread != NULL) {
		WakeUp ();
		result = pthread_join (*audio_thread, NULL);
		if (result != 0) {
			LOG_AUDIO ("AudioPlayer::Shutdown (): failed to join the audio thread (error code: %i).\n", result);
		} else {
			// Only free the thread if we could join it.
			g_free (audio_thread);
		}
		audio_thread = NULL;
	}
}
Exemplo n.º 8
0
bool
AlsaSource::XrunRecovery (int err)
{	
	switch (err) {
	case -EPIPE: // under-run
		Underflowed ();
		mutex.Lock ();
		if (initialized) {
			err = snd_pcm_prepare (pcm);
			if (err < 0) {
				LOG_AUDIO ("AlsaPlayer: Can't recover from underrun, prepare failed: %s.\n", snd_strerror (err));
			}
		} else {
			LOG_AUDIO ("AlsaPlayer: Can't recover from underrun, pcm has been closed.\n");
		}
		mutex.Unlock ();
		break;
	case -ESTRPIPE:
		mutex.Lock ();
		if (initialized) {
			while ((err = snd_pcm_resume (pcm)) == -EAGAIN) {
				LOG_AUDIO ("XrunRecovery: waiting for resume\n");
				sleep (1); // wait until the suspend flag is released
			}
			if (err < 0) {
				err = snd_pcm_prepare (pcm);
				if (err < 0) {
					LOG_AUDIO ("AlsaPlayer: Can't recover from suspend, prepare failed: %s.\n", snd_strerror (err));
				}
			}
		} else {
			LOG_AUDIO ("AlsaPlayer: Can't recover from suspend, pcm has been closed.\n");
		}
		mutex.Unlock ();
		break;
	default:
		LOG_AUDIO ("AlsaPlayer: Can't recover from underrun: %s\n", snd_strerror (err));
		break;
	}
	
	return err >= 0;
}
Exemplo n.º 9
0
bool
AlsaPlayer::IsInstalled ()
{
	bool result = false;
	const char *version;
	
	switch (is_alsa_usable) {
	case 0:
		libalsa = dlopen ("libasound.so.2", RTLD_LAZY);
		if (libalsa == NULL) {
			is_alsa_usable = 2;
			return false;
		}
		result = true;
		
		result &= NULL != (d_snd_pcm_open = (dyn_snd_pcm_open *) dlsym (libalsa, "snd_pcm_open"));
		result &= NULL != (d_snd_pcm_close = (dyn_snd_pcm_close *) dlsym (libalsa, "snd_pcm_close"));
		result &= NULL != (d_snd_pcm_get_params = (dyn_snd_pcm_get_params *) dlsym (libalsa, "snd_pcm_get_params"));
		result &= NULL != (d_snd_pcm_poll_descriptors_count = (dyn_snd_pcm_poll_descriptors_count *) dlsym (libalsa, "snd_pcm_poll_descriptors_count"));
		result &= NULL != (d_snd_pcm_poll_descriptors = (dyn_snd_pcm_poll_descriptors *) dlsym (libalsa, "snd_pcm_poll_descriptors"));
		result &= NULL != (d_snd_output_stdio_attach = (dyn_snd_output_stdio_attach *) dlsym (libalsa, "snd_output_stdio_attach"));
		result &= NULL != (d_snd_pcm_hw_params_malloc = (dyn_snd_pcm_hw_params_malloc *) dlsym (libalsa, "snd_pcm_hw_params_malloc"));
		result &= NULL != (d_snd_pcm_hw_params_any = (dyn_snd_pcm_hw_params_any *) dlsym (libalsa, "snd_pcm_hw_params_any"));
		result &= NULL != (d_snd_pcm_hw_params_dump = (dyn_snd_pcm_hw_params_dump *) dlsym (libalsa, "snd_pcm_hw_params_dump"));
		result &= NULL != (d_snd_pcm_hw_params_set_rate_resample = (dyn_snd_pcm_hw_params_set_rate_resample *) dlsym (libalsa, "snd_pcm_hw_params_set_rate_resample"));
		result &= NULL != (d_snd_pcm_hw_params_test_access = (dyn_snd_pcm_hw_params_test_access *) dlsym (libalsa, "snd_pcm_hw_params_test_access"));
		result &= NULL != (d_snd_pcm_hw_params_set_access = (dyn_snd_pcm_hw_params_set_access *) dlsym (libalsa, "snd_pcm_hw_params_set_access"));
		result &= NULL != (d_snd_pcm_hw_params_set_format = (dyn_snd_pcm_hw_params_set_format *) dlsym (libalsa, "snd_pcm_hw_params_set_format"));
		result &= NULL != (d_snd_pcm_hw_params_set_channels = (dyn_snd_pcm_hw_params_set_channels *) dlsym (libalsa, "snd_pcm_hw_params_set_channels"));
		result &= NULL != (d_snd_pcm_hw_params_set_rate_near = (dyn_snd_pcm_hw_params_set_rate_near *) dlsym (libalsa, "snd_pcm_hw_params_set_rate_near"));
		result &= NULL != (d_snd_pcm_hw_params_set_buffer_time_near = (dyn_snd_pcm_hw_params_set_buffer_time_near *) dlsym (libalsa, "snd_pcm_hw_params_set_buffer_time_near"));
		result &= NULL != (d_snd_pcm_hw_params = (dyn_snd_pcm_hw_params *) dlsym (libalsa, "snd_pcm_hw_params"));
		result &= NULL != (d_snd_pcm_hw_params_can_pause = (dyn_snd_pcm_hw_params_can_pause *) dlsym (libalsa, "snd_pcm_hw_params_can_pause"));
		result &= NULL != (d_snd_pcm_hw_params_free = (dyn_snd_pcm_hw_params_free *) dlsym (libalsa, "snd_pcm_hw_params_free"));
		result &= NULL != (d_snd_pcm_state = (dyn_snd_pcm_state *) dlsym (libalsa, "snd_pcm_state"));
		result &= NULL != (d_snd_pcm_state_name = (dyn_snd_pcm_state_name *) dlsym (libalsa, "snd_pcm_state_name"));
		result &= NULL != (d_snd_pcm_drop = (dyn_snd_pcm_drop *) dlsym (libalsa, "snd_pcm_drop"));
		result &= NULL != (d_snd_pcm_writei = (dyn_snd_pcm_writei *) dlsym (libalsa, "snd_pcm_writei"));
		result &= NULL != (d_snd_pcm_mmap_begin = (dyn_snd_pcm_mmap_begin *) dlsym (libalsa, "snd_pcm_mmap_begin"));
		result &= NULL != (d_snd_pcm_mmap_commit = (dyn_snd_pcm_mmap_commit *) dlsym (libalsa, "snd_pcm_mmap_commit"));
		result &= NULL != (d_snd_pcm_prepare = (dyn_snd_pcm_prepare *) dlsym (libalsa, "snd_pcm_prepare"));
		result &= NULL != (d_snd_pcm_resume = (dyn_snd_pcm_resume *) dlsym (libalsa, "snd_pcm_resume"));
		result &= NULL != (d_snd_pcm_avail_update = (dyn_snd_pcm_avail_update *) dlsym (libalsa, "snd_pcm_avail_update"));
		result &= NULL != (d_snd_pcm_start = (dyn_snd_pcm_start *) dlsym (libalsa, "snd_pcm_start"));
		result &= NULL != (d_snd_pcm_delay = (dyn_snd_pcm_delay *) dlsym (libalsa, "snd_pcm_delay"));
		result &= NULL != (d_snd_asoundlib_version = (dyn_snd_asoundlib_version *) dlsym (libalsa, "snd_asoundlib_version"));
		result &= NULL != (d_snd_strerror = (dyn_snd_strerror *) dlsym (libalsa, "snd_strerror"));

		if (d_snd_asoundlib_version != NULL) {
			version = d_snd_asoundlib_version ();
			LOG_AUDIO ("AlsaPlayer: Found alsa/asound version: '%s'\n", version);
		}
		
		if (!result)
			LOG_AUDIO ("AlsaPlayer: Failed to load one or more required functions in libasound.so.");

		is_alsa_usable = result ? 1 : 2;
		return result;
	case 1:
		return true;
	default:
		return false;
	}
	
	return true;
}
Exemplo n.º 10
0
bool
AlsaSource::PreparePcm (snd_pcm_sframes_t *avail)
{
	int err = 0;
	bool closed = false;
	snd_pcm_state_t state;
	
	mutex.Lock ();
	if (initialized) {
		state = snd_pcm_state (pcm);
	} else {
		LOG_ALSA ("AlsaSource::PreparePcm (): pcm has been closed.\n");
		closed = true;
	}
	mutex.Unlock ();
			
	if (closed)
		return false;
		
	switch (state) {
	case SND_PCM_STATE_XRUN:
		LOG_ALSA ("AlsaSource::PreparePcm (): SND_PCM_STATE_XRUN.\n");

		if (!XrunRecovery (-EPIPE))
			return false;

		started = false;
		break;
	case SND_PCM_STATE_SUSPENDED:
		if (!XrunRecovery (-ESTRPIPE))
			return false;
		break;
	case SND_PCM_STATE_SETUP:
		if (!XrunRecovery (-EPIPE))
			return false;

		started = false;
		break;
	case SND_PCM_STATE_RUNNING:
		started = true; // We might have gotten started automatically after writing a certain number of samples.
	case SND_PCM_STATE_PREPARED:
		break;
	case SND_PCM_STATE_PAUSED:
	case SND_PCM_STATE_DRAINING:
	default:
		LOG_ALSA ("AlsaSource::PreparePcm (): state: %s (prepare failed)\n", snd_pcm_state_name (state));
		return false;
	}
	
	err = 0;
	mutex.Lock ();
	if (initialized) {
		*avail = snd_pcm_avail_update (pcm);
	} else {
		closed = true;
	}
	mutex.Unlock ();
	
	if (closed)
		return false;

	if (*avail < 0) {
		if (!XrunRecovery (*avail))
			return false;

		started = false;
		return false;
	}

	if ((snd_pcm_uframes_t) *avail < period_size) {
		if (!started) {
			LOG_ALSA ("AlsaSource::PreparePcm (): starting pcm (period size: %li, available: %li)\n", period_size, *avail);

			mutex.Lock ();
			if (initialized) {
				err = snd_pcm_start (pcm);
			} else {
				closed = true;
			}
			mutex.Unlock ();
			
			if (closed)
				return false;

			if (err < 0) {
				LOG_AUDIO ("AlsaPlayer: Could not start pcm: %s\n", snd_strerror (err));
				return false;
			}
			started = true;
		} else {
			return false;
		}
		return false;
	}

	LOG_ALSA ("AlsaSource::PreparePcm (): Prepared, avail: %li, started: %i\n", *avail, (int) started);

	return true;
}
Exemplo n.º 11
0
bool
AlsaSource::WriteMmap ()
{
	snd_pcm_channel_area_t *areas = NULL;
	snd_pcm_uframes_t offset = 0;
	snd_pcm_uframes_t frames;
	snd_pcm_sframes_t available_samples;
	snd_pcm_sframes_t commitres = 0;
	guint32 channels = GetChannels ();
	int err = 0;
	AudioData *data [channels + 1];
	
	if (GetState () != AudioPlaying) {
		LOG_ALSA ("AlsaSource::WriteMmap (): trying to write when we're not playing (state: %i)\n", GetState ());
		return false;
	}

	if (!PreparePcm (&available_samples))
		return false;
	
	if (GetFlag (AudioEnded)) {
		Underflowed ();
		return false;
	}
	
	LOG_ALSA_EX ("AlsaSource::WriteMmap (): entering play loop, avail: %" G_GINT64_FORMAT ", sample size: %i\n", (gint64) available_samples, (int) period_size);
	
	frames = available_samples;
	
	mutex.Lock ();
	if (!initialized)
		goto cleanup;
		
	err = snd_pcm_mmap_begin (pcm, (const snd_pcm_channel_area_t** ) &areas, &offset, &frames);
	if (err < 0) {
		if (!XrunRecovery (err)) {
			LOG_AUDIO ("AudioPlayer: could not get mmapped memory: %s\n", snd_strerror (err));
			goto cleanup;
		}
		started = false;
	}
	
	LOG_ALSA_EX ("AlsaSource::WriteMmap (): can write %lu frames, avail: %lu\n", frames, available_samples);
	
	for (guint32 channel = 0; channel < channels; channel++) {
		data [channel] = (AudioData *) g_malloc (sizeof (AudioData));
		// pointer to the first sample to write to
		data [channel]->dest = ((gint8 *) areas [channel].addr) + (areas [channel].first / 8) + offset * areas [channel].step / 8;
		// distance (in bytes) between samples
		data [channel]->distance = areas [channel].step / 8;
	}
	data [channels] = NULL;
	
	frames = WriteFull (data, frames);
	
	for (guint32 channel = 0; channel < channels; channel++) {
		g_free (data [channel]);
	}
	
	commitres = snd_pcm_mmap_commit (pcm, offset, frames);
	
	LOG_ALSA_EX ("AlsaSource::WriteMmap (): played %i samples, of %i available samples, result: %i.\n", (int) frames, (int) 0, (int) commitres);
	
	if (commitres < 0 || (snd_pcm_uframes_t) commitres != frames) {
		if (!XrunRecovery (commitres >= 0 ? -EPIPE : commitres)) {
			LOG_AUDIO ("AudioPlayer: could not commit mmapped memory: %s\n", snd_strerror(err));
			commitres = 0; // so that we end up returning false
			goto cleanup;
		}
		started = false;
	}

cleanup:

	mutex.Unlock ();

	return commitres > 0;
}
Exemplo n.º 12
0
bool
AlsaSource::SetupHW ()
{
	bool result = false;
	bool rw_available = false;
	bool mmap_available = false;
#if DEBUG
	bool debug = debug_flags & RUNTIME_DEBUG_AUDIO;
#else
	bool debug = false;
#endif
	
	snd_pcm_hw_params_t *params = NULL;
	snd_output_t *output = NULL;
	guint32 buffer_time = 100000; // request 0.1 seconds of buffer time.
	int err = 0;
	int dir = 0;
	unsigned int rate = GetSampleRate ();
	unsigned int actual_rate = rate;
	guint32 channels = GetChannels ();

	if (debug) {
		err = snd_output_stdio_attach (&output, stdout, 0);
		if (err < 0)
			LOG_AUDIO ("AlsaSource::SetupHW (): Could not create alsa output: %s\n", snd_strerror (err));
	}

	err = snd_pcm_hw_params_malloc (&params);
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (malloc): %s\n", snd_strerror (err));
		return false;
	}

	// choose all parameters
	err = snd_pcm_hw_params_any (pcm, params);
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (no configurations available): %s\n", snd_strerror (err));
		goto cleanup;
	}
	
	if (debug && output != NULL) {
		LOG_AUDIO ("AlsaSource::SetupHW (): hw configurations:\n");
		snd_pcm_hw_params_dump (params, output);
	}
	
	// enable software resampling
	err = snd_pcm_hw_params_set_rate_resample (pcm, params, 1);
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (could not enable resampling): %s\n", snd_strerror (err));
		goto cleanup;
	}
	
	// test for available transfer modes
	if (!(moonlight_flags & RUNTIME_INIT_AUDIO_ALSA_MMAP)) {
		err = snd_pcm_hw_params_test_access (pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED);
		if (err < 0) {
			LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup: RW access mode not supported (%s).\n", snd_strerror (err));			
		} else {
			rw_available = true;
		}
	}
	if (!(moonlight_flags & RUNTIME_INIT_AUDIO_ALSA_RW)) {
		err = snd_pcm_hw_params_test_access (pcm, params, SND_PCM_ACCESS_MMAP_INTERLEAVED);
		if (err < 0) {
			LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup: MMAP access mode not supported (%s).\n", snd_strerror (err));
		} else {
			mmap_available = true;
		}
	}
	if (mmap_available) {
		mmap = true;
	} else if (rw_available) {
		mmap = false;
	} else {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed, no available access mode\n");
		goto cleanup;
	}

	LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup: using %s access mode.\n", mmap ? "MMAP" : "RW");

	// set transfer mode (mmap or rw in our case)
	err = snd_pcm_hw_params_set_access (pcm, params, mmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED : SND_PCM_ACCESS_RW_INTERLEAVED);
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (access type not available for playback): %s\n", snd_strerror (err));
		goto cleanup;
	}

	// set audio format
	switch (GetInputBytesPerSample ()) {
	case 1: // 8 bit audio
		err = snd_pcm_hw_params_set_format (pcm, params, SND_PCM_FORMAT_S16);
		SetOutputBytesPerSample (2);
		break;
	case 2: // 16 bit audio
		err = snd_pcm_hw_params_set_format (pcm, params, SND_PCM_FORMAT_S16);
		SetOutputBytesPerSample (2);
		break;
	case 3: // 24 bit audio
		// write as 32 bit audio, this is a lot easier to write to than 24 bit.
		err = snd_pcm_hw_params_set_format (pcm, params, SND_PCM_FORMAT_S32);
		SetOutputBytesPerSample (4);
		break;
	default:
		LOG_AUDIO ("AlsaSource::SetupHW (): Invalid input bytes per sample, expected 1, 2 or 3, got %i\n", GetInputBytesPerSample ());
		goto cleanup;
	}
	
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (sample format not available for playback): %s\n", snd_strerror (err));
		goto cleanup;
	}
	
	// set channel count
	err = snd_pcm_hw_params_set_channels (pcm, params, channels);
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (channels count %i not available for playback): %s\n", channels, snd_strerror (err));
		goto cleanup;
	}
	
	// set sample rate
	err = snd_pcm_hw_params_set_rate_near (pcm, params, &actual_rate, 0);
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (sample rate %i Hz not available for playback): %s\n", rate, snd_strerror (err));
		goto cleanup;
	} else if (actual_rate != rate) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (sample rate %i Hz not available for playback, only got %i Hz).\n", rate, actual_rate);
		goto cleanup;
	}
	
	// set the buffer time
	err = snd_pcm_hw_params_set_buffer_time_near (pcm, params, &buffer_time, &dir);
	if (err < 0) {
		LOG_AUDIO ("AudioNode::SetupHW (): Audio HW setup failed (unable to set buffer time %i for playback: %s\n", buffer_time, snd_strerror (err));
		goto cleanup;
	}

	// write the parameters to device
	err = snd_pcm_hw_params (pcm, params);
	if (err < 0) {
		LOG_AUDIO ("AlsaSource::SetupHW (): Audio HW setup failed (unable to set hw params for playback: %s)\n", snd_strerror (err));
		if (debug && output != NULL) {
			LOG_AUDIO ("AlsaSource::SetupHW (): current hw configurations:\n");
			snd_pcm_hw_params_dump (params, output);
		}
		goto cleanup;
	}
	
	if (debug) {
		LOG_AUDIO ("AlsaSource::SetupHW (): hardware pause support: %s\n", snd_pcm_hw_params_can_pause (params) == 0 ? "no" : "yes"); 
		LOG_AUDIO ("AlsaSource::SetupHW (): succeeded\n");
		if (output != NULL) 
			snd_pcm_hw_params_dump (params, output);
	}

	result = true;
	
cleanup:
	snd_pcm_hw_params_free (params);
	
	return result;
}
Exemplo n.º 13
0
bool
AlsaSource::InitializeAlsa ()
{
	bool res = false;
	int result;
	AudioStream *stream = NULL;
	
	LOG_AUDIO ("AlsaSource::InitializeAlsa (%p) initialized: %i\n", this, initialized);
	
	mutex.Lock ();
	
	if (initialized) {
		result = true;
		goto cleanup;
	}
	
	stream = GetStreamReffed ();
		
	if (stream == NULL) {
		// Shouldn't really happen, but handle this case anyway.
		LOG_AUDIO ("AlsaSource::Initialize (): trying to initialize an audio device, but there's no audio to play.\n");
		goto cleanup;
	}
		
	// Open a pcm device
	result = snd_pcm_open (&pcm, "default", SND_PCM_STREAM_PLAYBACK, 0 /*SND_PCM_NONBLOCK*/);
	if (result != 0) {
		LOG_AUDIO ("AlsaSource::Initialize (): cannot open audio device: %s\n", snd_strerror (result));
		pcm = NULL;
		goto cleanup;
	}

	// Configure the hardware
	if (!SetupHW ()) {
		LOG_AUDIO ("AlsaSource::Initialize (): could not configure hardware for audio playback\n");
		Close ();
		goto cleanup;
	}
	
	result = snd_pcm_get_params (pcm, &buffer_size, &period_size);
	if (result != 0) {
		LOG_AUDIO ("AlsaSource::Initialize (): error while getting parameters: %s\n", snd_strerror (result));
		Close ();
		goto cleanup;
	}

	// Get the file descriptors to poll on
	ndfs = snd_pcm_poll_descriptors_count (pcm);
	if (ndfs <= 0) {
		LOG_AUDIO ("AlsaSource::Initialize(): Unable to initialize audio for playback (could not get poll descriptor count).\n");
		Close ();
		goto cleanup;
	}

	udfs = (pollfd *) g_malloc0 (sizeof (pollfd) * ndfs);
	if (snd_pcm_poll_descriptors (pcm, udfs, ndfs) < 0) {
		LOG_AUDIO ("AlsaSource::Initialize (): Unable to initialize audio for playback (could not get poll descriptors).\n");
		Close ();
		goto cleanup;
	}
	
	LOG_AUDIO ("AlsaSource::Initialize (%p): Succeeded. Buffer size: %lu, period size: %lu\n", this, buffer_size, period_size);

	res = true;
	initialized = true;
	
cleanup:

	mutex.Unlock ();

	if (stream)
		stream->unref ();

	return res;
}