Update of /cvsroot/playerstage/code/player/server/drivers/audio
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8268/server/drivers/audio
Modified Files:
alsa.cc alsa.h
Log Message:
Alsa driver can now make noise if sent appropriate data
Index: alsa.h
===================================================================
RCS file: /cvsroot/playerstage/code/player/server/drivers/audio/alsa.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** alsa.h 1 Jun 2006 20:16:33 -0000 1.1
--- alsa.h 4 Jun 2006 23:48:19 -0000 1.2
***************
*** 21,24 ****
--- 21,26 ----
*/
+ #include <alsa/asoundlib.h>
+
////////////////////////////////////////////////////////////////////////////////
// The class for the driver
***************
*** 27,30 ****
--- 29,33 ----
public:
Alsa (ConfigFile* cf, int section);
+ ~Alsa (void);
virtual int Setup (void);
***************
*** 36,40 ****
virtual void Main (void);
// Driver options
! bool block;
};
--- 39,55 ----
virtual void Main (void);
+ // Command handling
+ int HandleWavePlayCmd (player_audio_wav_t *waveData);
+
// Driver options
! bool block; // If
should block while playing or return immediatly
! unsigned int pbRate; // Sample rate for
playback
! int pbNumChannels; // Number of
sound channels for playback
! snd_pcm_uframes_t periodSize; // Period size of the output
buffer
!
! // ALSA variables
! snd_pcm_t *pcmHandle; // Handle to the PCM
device
! snd_pcm_stream_t pbStream; // Stream for playback
! snd_pcm_hw_params_t *hwparams; // Hardware parameters
! char *pcmName; // Name of the
sound interface
};
Index: alsa.cc
===================================================================
RCS file: /cvsroot/playerstage/code/player/server/drivers/audio/alsa.cc,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** alsa.cc 1 Jun 2006 20:16:33 -0000 1.1
--- alsa.cc 4 Jun 2006 23:48:19 -0000 1.2
***************
*** 28,32 ****
#include "alsa.h"
- #include <alsa/asoundlib.h>
// Initialisation function
--- 28,31 ----
***************
*** 52,64 ****
: Driver (cf, section, false, PLAYER_MSGQUEUE_DEFAULT_MAXLEN,
PLAYER_AUDIO_CODE)
{
! // Read the config file options
! block = cf->ReadBool (section, "block", false);
return;
}
// Set up the device. Return 0 if things go well, and -1 otherwise.
int Alsa::Setup (void)
{
StartThread ();
printf ("Alsa driver initialised\n");
--- 51,149 ----
: Driver (cf, section, false, PLAYER_MSGQUEUE_DEFAULT_MAXLEN,
PLAYER_AUDIO_CODE)
{
! pcmName = NULL;
!
! // Read the config file options - see header for descriptions if not
here
! block = cf->ReadBool (section, "block", true);
! pcmName = strdup (cf->ReadString (section, "interface", "plughw:0,0"));
! pbRate = cf->ReadInt (section, "pb_rate", 44100);
! pbNumChannels = cf->ReadInt (section, "pb_numchannels", 2);
return;
}
+ // Destructor
+ Alsa::~ Alsa (void)
+ {
+ if (pcmName)
+ free (pcmName);
+ }
+
// Set up the device. Return 0 if things go well, and -1 otherwise.
int Alsa::Setup (void)
{
+ pbStream = SND_PCM_STREAM_PLAYBACK; // Make the playback stream
+ snd_pcm_hw_params_alloca(&hwparams); // Allocate params structure on
stack
+ // Open the pcm device for either blocking or non-blocking mode
+ if (snd_pcm_open (&pcmHandle, pcmName, pbStream, block ? 0 :
SND_PCM_NONBLOCK) < 0)
+ {
+ PLAYER_ERROR1 ("Error opening PCM device %s for playback",
pcmName);
+ return -1;
+ }
+
+ // Init parameters
+ if (snd_pcm_hw_params_any (pcmHandle, hwparams) < 0)
+ {
+ PLAYER_ERROR ("Can not configure this PCM device");
+ return -1;
+ }
+
+ // Set parameters
+ unsigned int exactRate; // Sample rate returned by
snd_pcm_hw_params_set_rate_near
+ int periods = 2; // Number of periods
+ periodSize = 8192; // Periodsize (bytes)
+
+ // Use interleaved access
+ if (snd_pcm_hw_params_set_access (pcmHandle, hwparams,
SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
+ {
+ PLAYER_ERROR ("Error setting interleaved access");
+ return -1;
+ }
+ // Set sound format
+ if (snd_pcm_hw_params_set_format (pcmHandle, hwparams,
SND_PCM_FORMAT_S16_LE) < 0)
+ {
+ PLAYER_ERROR ("Error setting format");
+ return -1;
+ }
+ // Set sample rate
+ exactRate = pbRate;
+ if (snd_pcm_hw_params_set_rate_near (pcmHandle, hwparams, &exactRate,
0) < 0)
+ {
+ PLAYER_ERROR ("Error setting sample rate");
+ return -1;
+ }
+ if (exactRate != pbRate)
+ PLAYER_WARN2 ("Rate %dHz not supported by hardware, using %dHz
instead", pbRate, exactRate);
+
+ // Set number of channels
+ if (snd_pcm_hw_params_set_channels(pcmHandle, hwparams, pbNumChannels)
< 0)
+ {
+ PLAYER_ERROR ("Error setting channels");
+ return -1;
+ }
+
+ // Set number of periods
+ if (snd_pcm_hw_params_set_periods(pcmHandle, hwparams, periods, 0) < 0)
+ {
+ PLAYER_ERROR ("Error setting periods");
+ return -1;
+ }
+
+ // Set the buffer size in frames TODO: update this to take into account
pbNumChannels
+ if (snd_pcm_hw_params_set_buffer_size (pcmHandle, hwparams, (periodSize
* periods) >> 2) < 0)
+ {
+ PLAYER_ERROR ("Error setting buffersize");
+ return -1;
+ }
+
+ // Apply hwparams to the pcm device
+ if (snd_pcm_hw_params (pcmHandle, hwparams) < 0)
+ {
+ PLAYER_ERROR ("Error setting HW params");
+ return -1;
+ }
+
+ // Don't need this anymore (I think) TODO: figure out why this causes
glib errors
+ //snd_pcm_hw_params_free (hwparams);
+
StartThread ();
printf ("Alsa driver initialised\n");
***************
*** 71,75 ****
--- 156,163 ----
{
printf ("Alsa driver shutting down\n");
+
StopThread ();
+ snd_pcm_close (pcmHandle);
+
return 0;
}
***************
*** 99,104 ****
////////////////////////////////////////////////////////////////////////////////
! int Alsa::ProcessMessage (MessageQueue *resp_queue, player_msghdr *hdr, void
*data)
{
return 0;
}
--- 187,268 ----
////////////////////////////////////////////////////////////////////////////////
! int Alsa::HandleWavePlayCmd (player_audio_wav_t *waveData)
{
+ // Check the format matches what the driver has been set up with
+
+ if ((waveData->format & PLAYER_AUDIO_FORMAT_BITS) !=
PLAYER_AUDIO_FORMAT_RAW)
+ {
+ PLAYER_ERROR ("Alsa driver can only play RAW format audio");
+ return -1;
+ }
+ if (((waveData->format & PLAYER_AUDIO_FREQ == PLAYER_AUDIO_FREQ_44k) &&
+ !(pbRate != 44100)) ||
+ ((waveData->format & PLAYER_AUDIO_FREQ ==
PLAYER_AUDIO_FREQ_11k) &&
+ !(pbRate != 11025)) ||
+ ((waveData->format & PLAYER_AUDIO_FREQ ==
PLAYER_AUDIO_FREQ_22k) &&
+ !(pbRate != 22050)) ||
+ ((waveData->format & PLAYER_AUDIO_FREQ ==
PLAYER_AUDIO_FREQ_48k) &&
+ !(pbRate != 48000)))
+ {
+ PLAYER_ERROR ("Mismatched sample rates");
+ return -1;
+ }
+ if (((waveData->format & PLAYER_AUDIO_STEREO) && pbNumChannels != 2) ||
+ (!(waveData->format & PLAYER_AUDIO_STEREO) &&
pbNumChannels == 2))
+ {
+ PLAYER_ERROR ("Mismatched number of channels");
+ return -1;
+ }
+ if ((waveData->format & PLAYER_AUDIO_BITS) != PLAYER_AUDIO_16BIT)
+ {
+ PLAYER_ERROR ("Mismatched bitrate");
+ return -1;
+ }
+
+ // Calculate the number of frames in the data
+ // 16-bit stereo is 4 bytes per frame
+ int pcmReturn = 0, frames;
+
+ frames = waveData->data_count / 4;
+ printf ("Data size: %d\tframe count: %d\n", waveData->data_count,
frames);
+
+ // Write the data until there is none left
+ unsigned int framesToWrite = frames;
+ do
+ {
+ pcmReturn = snd_pcm_writei (pcmHandle, waveData->data,
framesToWrite);
+ if (pcmReturn < 0)
+ {
+ snd_pcm_prepare (pcmHandle);
+ printf ("BUFFER UNDERRUN!\t%s\n", snd_strerror
(pcmReturn));
+ }
+ else
+ framesToWrite = framesToWrite - pcmReturn;
+
+ printf ("pcmReturn = %d\tframesToWrite = %d\n", pcmReturn,
framesToWrite);
+ fflush (stdout);
+ }
+ while (framesToWrite > 0);
+
+ // Drain the remaining data once finished writing and stop playback
+ // snd_pcm_drain (pcmHandle);
+
return 0;
}
+
+ int Alsa::ProcessMessage (MessageQueue *resp_queue, player_msghdr *hdr, void
*data)
+ {
+ // Check for capabilities requests first
+ HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data,
PLAYER_MSGTYPE_REQ, PLAYER_CAPABILTIES_REQ);
+ // Position2d caps
+ HANDLE_CAPABILITY_REQUEST (device_addr, resp_queue, hdr, data,
PLAYER_MSGTYPE_CMD, PLAYER_AUDIO_WAV_PLAY_CMD);
+
+ if (Message::MatchMessage (hdr, PLAYER_MSGTYPE_CMD,
PLAYER_AUDIO_WAV_PLAY_CMD, this->device_addr))
+ {
+ printf ("handling wave play cmd\n");
+ HandleWavePlayCmd (reinterpret_cast<player_audio_wav_t*>
(data));
+ return 0;
+ }
+
+ return -1;
+ }
_______________________________________________
Playerstage-commit mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/playerstage-commit