1
/***************************************************************************
2
playeralsa.cpp - description
4
begin : Wed Feb 20 2002
5
copyright : (C) 2002 by Tue and Ken Haste Andersen
7
***************************************************************************/
9
/***************************************************************************
11
* This program is free software; you can redistribute it and/or modify *
12
* it under the terms of the GNU General Public License as published by *
13
* the Free Software Foundation; either version 2 of the License, or *
14
* (at your option) any later version. *
16
***************************************************************************/
18
#include "playeralsa.h"
20
PlayerALSA::PlayerALSA(int size) : Player(size)
22
// Open device 0 on card 0
23
int err = snd_pcm_open(&handle, 0, 0, SND_PCM_OPEN_PLAYBACK);
25
qFatal("Error opening device (%i): %s",err,snd_strerror(err));
29
// ALSA channel parameters
30
params = new snd_pcm_channel_params_t;
31
params->mode=SND_PCM_MODE_BLOCK;
32
params->start_mode=SND_PCM_START_FULL;
33
params->stop_mode=SND_PCM_STOP_ROLLOVER; // This makes the audio keep playing even
34
// if underruns occurs
35
params->buf.block.frag_size = size*SAMPLE_SIZE; // Buffer size in bytes
36
params->buf.block.frags_max=3;
37
params->buf.block.frags_min=1;
38
params->format.interleave=1;
39
params->format.format=SND_PCM_SFMT_S16_LE;
40
params->format.rate=SRATE;
41
params->channel=SND_PCM_CHANNEL_PLAYBACK;
42
params->format.voices=2;
44
err = snd_pcm_channel_params(handle,params);
46
// try to close what was opened!
47
snd_pcm_close(handle);
48
qFatal("Error setting parameters for device %i", err);
51
setup = new snd_pcm_channel_setup_t;
52
setup->channel=SND_PCM_CHANNEL_PLAYBACK;
53
err = snd_pcm_channel_setup(handle, setup);
55
qFatal("Error setting up channel (%i)", err);
59
err = snd_pcm_playback_flush(handle);
61
qFatal("Error flushing playback buffer %i):%s", err, snd_strerror(err));
65
// The buffer size has possible been changed by the driver. The size returned
66
// by the driver is given in number of bytes, and BUFFER_SIZE indicates the
67
// same size in samples
68
if ((BUFFER_SIZE = setup->buf.block.frag_size/SAMPLE_SIZE) == 0) {
69
qFatal("Driver returned zero buffer size.");
73
qDebug("Using ALSA. Buffer size : %i samples.",BUFFER_SIZE/2);
77
PlayerALSA::~PlayerALSA()
80
snd_pcm_close(handle);
87
void PlayerALSA::start(EngineBuffer *_reader)
89
Player::start(_reader);
91
// Prepare for playback
92
int err = snd_pcm_channel_prepare(handle, params->channel);
95
qFatal("Error preparing channel (%i)%s",err , snd_strerror(err));
103
void PlayerALSA::stop()
106
snd_pcm_playback_drain(handle);
109
// Terminate synth thread
110
//pthread_cancel(p_thread);
112
// Wait for synth thread to terminate
113
//void *thread_state;
114
//pthread_join(p_thread, &thread_state);
117
void PlayerALSA::wait()
122
void PlayerALSA::run()
124
qDebug("PlayerALSA: Beginning of thread.");
127
// Loop the synthesis, and pass the buffers to ALSA
129
int BUFFER_SIZE_BYTES = BUFFER_SIZE*SAMPLE_SIZE;
130
//std::cout << "Starting playback thread\n" << flush;
132
res = prepareBuffer();
133
if ((res == 0) && (snd_pcm_write(handle,out_buffer,BUFFER_SIZE_BYTES)
134
!= BUFFER_SIZE_BYTES)) {
135
qFatal("Error writing samples to hardware %i",res);
141
void PlayerALSA::rt_priority()
143
// Try to set realtime priority on the current executing thread
144
struct sched_param schp;
145
memset(&schp, 0, sizeof(schp));
146
schp.sched_priority = sched_get_priority_max(SCHED_FIFO);
147
if (sched_setscheduler(0, SCHED_FIFO, &schp) != 0)
148
qWarning("Not possible to give audio I/O thread realtime prioriy.");