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

Reply via email to