Fill in audio_out_alsa
authorbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 11 Mar 2014 03:40:18 +0000 (03:40 +0000)
committerbruceperens <bruceperens@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 11 Mar 2014 03:40:18 +0000 (03:40 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1422 01035d8c-6547-0410-b346-abe4f91aad63

freedv-server/source/platform/linux/alsa.cpp
freedv-server/source/platform/linux/audio_out_alsa.cpp

index 5dface7064b809af4aef57dcabfc9424ced4a125..f2aa5215344c14cce40387d1acf6325e8196e112 100644 (file)
@@ -61,9 +61,9 @@ namespace FreeDV {
         stream << std::endl;
   
         if ( ctl_error == 0 ) {
-          snd_ctl_close(ctl_handle);
-       if ( pcm_error == 0 )
+         if ( pcm_error == 0 )
             snd_pcm_close(pcm_handle);
+          snd_ctl_close(ctl_handle);
         }
       }
     }
index 623dd234b7f4ab301831d0b28d44f8789067449d..0e30537e2e5c3353df7c05da58303f7839b26d14 100644 (file)
@@ -1,5 +1,6 @@
 /// The ALSA audio output driver. 
 
+#include <stdlib.h>
 #include "drivers.h"
 #include <alsa/asoundlib.h>
 #include <sys/ioctl.h>
@@ -12,8 +13,20 @@ namespace FreeDV {
   /// Audio output "ALSA", Uses the Linux ALSA Audio API.
   class AudioOutALSA : public AudioOutput {
   private:
-    snd_pcm_t * handle;
+    char * const       parameters;
+    snd_pcm_t *                handle;
 
+    volatile void
+    do_throw(const int error, const char * message = 0)
+    {
+      std::ostringstream str;
+
+      str << "Error on ALSA audio output " << parameters << ": ";
+       if ( message )
+         str << message << ": ";
+       str << snd_strerror(error);
+      throw std::runtime_error(str.str().c_str());
+    }
   public:
 
        /// Instantiate the audio output.
@@ -31,32 +44,56 @@ namespace FreeDV {
   };
 
   AudioOutALSA::AudioOutALSA(const char * p)
-  : AudioOutput("alsa", p)
+  : AudioOutput("alsa", p), parameters(strdup(p))
   {
-    const int error = snd_pcm_open(
+    const snd_pcm_format_t     format = SND_PCM_FORMAT_S16;
+    const snd_pcm_access_t     access = SND_PCM_ACCESS_RW_INTERLEAVED;
+    const unsigned int         channels = 1;
+    const unsigned int         rate = 48000;
+    const int                  soft_resample = 0;
+    const unsigned int         latency = 0;
+    int                                error;
+
+    handle = 0;
+    error = snd_pcm_open(
      &handle,
      p,
      SND_PCM_STREAM_PLAYBACK,
      0);
 
-    if ( error ) {
-      std::ostringstream str;
-
-      str << "Can't open audio device " << p << ": " << snd_strerror(error);
-      throw std::runtime_error(str.str().c_str());
-    }
+    if ( error != 0 )
+      do_throw(error, "Open");
+
+    if ( (error = snd_pcm_set_params(
+     handle,
+     format,
+     access,
+     channels,
+     rate,
+     soft_resample,
+     latency)) < 0 )
+      do_throw(error, "Set Parameters");
+
+    if ( (error = snd_pcm_prepare(handle)) < 0 )
+      do_throw(error, "Prepare");
   }
 
   AudioOutALSA::~AudioOutALSA()
   {
+    snd_pcm_drop(handle);
     snd_pcm_close(handle);
+    free(parameters);
   }
 
   // Write audio into the "short" type.
   std::size_t
   AudioOutALSA::write16(const std::int16_t * array, std::size_t length)
   {
-    return length;
+    const int result = snd_pcm_writei(handle, array, length);
+    if ( result >= 0 )
+      return result;
+    else
+      do_throw(result, "Write");
   }
 
   AudioOutput *
@@ -76,10 +113,10 @@ namespace FreeDV {
   {
     snd_pcm_sframes_t  available = 0;
 
-    if ( (available = snd_pcm_avail(handle)) <= 0 )
+    if ( (available = snd_pcm_avail(handle)) >= 0 )
       return available;
     else
-      return 0;
+      do_throw(available, "Get Available Frames");
   }
 
   static bool