<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -27,10 +27,13 @@
 
 #include &lt;string&gt;
 #include &lt;iostream&gt;
+#include &lt;alsa/asoundlib.h&gt;
 
 using namespace std;
 
+#include &quot;exceptions.h&quot;
 #include &quot;Sample.h&quot;
+
 #include &quot;AlsaOutput.h&quot;
 
 
@@ -45,14 +48,109 @@ AlsaOutput::~AlsaOutput()
 
 }
 
-void AlsaOutput::playSound(const Sample *sound)
+void AlsaOutput::playSound(const Sample *sample)
 {
-   std::cout &lt;&lt; &quot;Playing sound &quot; &lt;&lt; sound-&gt;getName() &lt;&lt; std::endl;
+  std::cout &lt;&lt; &quot;Playing sound &quot; &lt;&lt; sample-&gt;getName() &lt;&lt; std::endl;
+  int pcmreturn;
+  unsigned int frames = sample-&gt;getSize() &gt;&gt; 2;
+  int i = 0;
+  while ((pcmreturn = snd_pcm_writei(m_pcm_handle, sample-&gt;getData(), frames)) &lt; 0) {
+    snd_pcm_prepare(m_pcm_handle);
+    fprintf(stderr, &quot;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt; Buffer Underrun &gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;\n&quot;);
+    if (++i &gt; 100) break;
+  }
 }
 
 void AlsaOutput::open()
 {
+  /* Allocate the snd_pcm_hw_params_t structure on the stack. */
+  snd_pcm_hw_params_alloca(&amp;m_hwparams);
+
+  /* Open PCM. The last parameter of this function is the mode. */
+  /* If this is set to 0, the standard mode is used. Possible   */
+  /* other values are SND_PCM_NONBLOCK and SND_PCM_ASYNC.       */ 
+  /* If SND_PCM_NONBLOCK is used, read / write access to the    */
+  /* PCM device will return immediately. If SND_PCM_ASYNC is    */
+  /* specified, SIGIO will be emitted whenever a period has     */
+  /* been completely processed by the soundcard.                */
+  if (snd_pcm_open(&amp;m_pcm_handle, m_device.c_str(), m_stream, 0) &lt; 0)
+  {
+    throw AlsaOutputException(
+            string(&quot;ALSA output: could not open output device: &quot;) + m_device);
+  }
+
+  /* Init hwparams with full configuration space */
+  if (snd_pcm_hw_params_any(m_pcm_handle, m_hwparams) &lt; 0)
+  {
+    throw AlsaOutputException(&quot;ALSA output: Can not configure this PCM device.&quot;);
+  }
+
+  unsigned int rate = 11025; /* Sample rate, alt. 22050, 44100 */
+  unsigned int exact_rate;   /* Sample rate returned by */
+                    /* snd_pcm_hw_params_set_rate_near */ 
+  //int dir;          /* exact_rate == rate --&gt; dir = 0 */
+                    /* exact_rate &lt; rate  --&gt; dir = -1 */
+                    /* exact_rate &gt; rate  --&gt; dir = 1 */
+  int periods = 2;       /* Number of periods */
+  //snd_pcm_uframes_t periodsize = 8192; /* Periodsize (bytes) */
+  snd_pcm_uframes_t periodsize = 12220; /* Periodsize (bytes) */
+  
+  /* Set access type. This can be either    */
+  /* SND_PCM_ACCESS_RW_INTERLEAVED or       */
+  /* SND_PCM_ACCESS_RW_NONINTERLEAVED.      */
+  /* There are also access types for MMAPed */
+  /* access, but this is beyond the scope   */
+  /* of this introduction.                  */
+  if (snd_pcm_hw_params_set_access(m_pcm_handle, m_hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) &lt; 0)
+  {
+    throw AlsaOutputException(&quot;ALSA output: Error setting access.&quot;);
+  }
+  
+  /* Set sample format */
+  if (snd_pcm_hw_params_set_format(m_pcm_handle, m_hwparams, SND_PCM_FORMAT_S16_LE) &lt; 0)
+  {
+    throw AlsaOutputException(&quot;ALSA output: Error setting format.&quot;);
+  }
+  
+  /* Set sample rate. If the exact rate is not supported */
+  /* by the hardware, use nearest possible rate.         */ 
+  exact_rate = rate;
+  if (snd_pcm_hw_params_set_rate_near(m_pcm_handle, m_hwparams, &amp;exact_rate, 0) &lt; 0)
+  {
+    throw AlsaOutputException(&quot;ALSA output: Error setting rate.&quot;);
+  }
 
+  if (rate != exact_rate)
+  {
+    cerr &lt;&lt; &quot;Warning: The rate &quot;&lt;&lt; rate &lt;&lt;&quot; Hz is not supported by your hardware.\n&quot;
+                     &quot;==&gt; Using &quot;&lt;&lt; exact_rate &lt;&lt;&quot; Hz instead.\n&quot;;
+  }
+  
+  /* Set number of channels */
+  if (snd_pcm_hw_params_set_channels(m_pcm_handle, m_hwparams, 2) &lt; 0)
+  {
+    throw AlsaOutputException(&quot;ALSA output: Error setting channels.&quot;);
+  }
+  
+  /* Set number of periods. Periods used to be called fragments. */ 
+  if (snd_pcm_hw_params_set_periods(m_pcm_handle, m_hwparams, periods, 0) &lt; 0)
+  {
+    throw AlsaOutputException(&quot;ALSA output: Error setting periods.&quot;);
+  }
+  
+  /* Set buffer size (in frames). The resulting latency is given by */
+  /* latency = periodsize * periods / (rate * bytes_per_frame)     */
+  if (snd_pcm_hw_params_set_buffer_size(m_pcm_handle, m_hwparams, (periodsize * periods)&gt;&gt;2) &lt; 0)
+  {
+    throw AlsaOutputException(&quot;ALSA output: Error setting buffersize.&quot;);
+  }
+  
+   /* Apply HW parameter settings to */
+  /* PCM device and prepare device  */
+  if (snd_pcm_hw_params(m_pcm_handle, m_hwparams) &lt; 0)
+  {
+    throw AlsaOutputException(&quot;ALSA output: Error setting HW params.&quot;);
+  }
 }
 
 void AlsaOutput::close()</diff>
      <filename>AlsaOutput.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -40,6 +40,15 @@ public:
   virtual void close();
 private:
   string m_device;
+
+  /* Handle for the PCM device */
+  snd_pcm_t            *m_pcm_handle;
+  /* Playback stream */
+  snd_pcm_stream_t      m_stream;
+  /* This structure contains information about    */
+  /* the hardware and can be used to specify the  */      
+  /* configuration to be used for the PCM stream. */
+  snd_pcm_hw_params_t  *m_hwparams;
 };
 
 #endif // ALSAOUTPUT_H</diff>
      <filename>AlsaOutput.h</filename>
    </modified>
    <modified>
      <diff>@@ -28,11 +28,11 @@
 #include &quot;stdheaders.h&quot;
 
 #include &quot;Event.h&quot;
-#include &quot;XevieInput.h&quot;
+#include &quot;XevieInput.h&quot; // TODO create factory, clean headers
 #include &quot;StaticConfiguration.h&quot;
 #include &quot;Sample.h&quot;
 #include &quot;SimpleWaveFileLoader.h&quot;
-#include &quot;AlsaOutput.h&quot;
+#include &quot;AlsaOutput.h&quot; // TODO create factory
 
 #include &quot;Annoyme.h&quot;
 </diff>
      <filename>Annoyme.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -3,9 +3,10 @@ MAINFILES=Annoyme.o Event.o XevieInput.o StaticConfiguration.o AlsaOutput.o Samp
 EXECUTABLES=annoyme
 LDFLAGS=-lX11 -lXevie
 SOURCES=$(wildcard *.cpp)
+LIBS=-lasound
 DEPS=$(patsubst %.o,%.d,$(MAINFILES))
 
-CXXFLAGS=-Wall -I. -ggdb
+CXXFLAGS=-Wall -I. -ggdb $(LIBS)
 
 all: annoyme
 </diff>
      <filename>Makefile</filename>
    </modified>
    <modified>
      <diff>@@ -152,6 +152,15 @@ public:
     return m_type;
   }
 
+  void setSize(unsigned int new_var)
+  {
+    m_size = new_var;
+  }
+
+  unsigned int getSize() const
+  {
+    return m_size;
+  }
 
 private:
   SampleFormat  m_format;</diff>
      <filename>Sample.h</filename>
    </modified>
    <modified>
      <diff>@@ -25,8 +25,11 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include &quot;stdheaders.h&quot;
+#include &quot;stdheaders.h&quot; // TODO cleanup headers
 #include &lt;glob.h&gt;
+#include &lt;sys/types.h&gt;
+#include &lt;sys/stat.h&gt;
+#include &lt;fcntl.h&gt;
 
 #include &quot;exceptions.h&quot;
 #include &quot;Sample.h&quot;
@@ -118,22 +121,68 @@ void SimpleWaveFileLoader::getSample(enum Sample::SampleType type, const Sample
 
 void SimpleWaveFileLoader::loadSampleFromFile(const char *path)
 {
-    const string name(this-&gt;getName(path));
-    const enum Sample::SampleType type = Sample::getSampleType(name);
-    if (type != Sample::invalidType)
-    {
-      Sample *sample = new Sample();
-      sample-&gt;setName(name);
-      sample-&gt;setFilePath(path);
-      sample-&gt;setType(Sample::getSampleType(name));
-      samples.insert(make_pair(sample-&gt;getType(), sample));
-    }
-    else {
-      cout &lt;&lt; &quot;Invalid sample: &quot; &lt;&lt; name &lt;&lt; endl;
-    }
+  const string name(this-&gt;getName(path));
+  const enum Sample::SampleType type = Sample::getSampleType(name);
+  if (type == Sample::invalidType)
+  {
+    cerr &lt;&lt; &quot;Invalid sample: &quot; &lt;&lt; name &lt;&lt; endl;
+    return;
+  }
+  
+  Sample *sample = new Sample();
+  
+  try
+  {
+    sample-&gt;setName(name);
+    sample-&gt;setFilePath(path);
+    sample-&gt;setType(type);
+
+    loadDataFromFile(sample);
+   }
+   catch (...)
+   {
+     delete sample;
+     throw;
+   }
+
+   samples.insert(make_pair(sample-&gt;getType(), sample));
 }
 
-void loadDataFromFile(const char *path, char *&amp;data, unsigned int &amp;size)
+void SimpleWaveFileLoader::loadDataFromFile(Sample *sample)
 {
+  sample-&gt;setFormat(Sample::PCM);
+  sample-&gt;setRate(11025);
+
+  unsigned int size = 0;
+  char* data = 0;
+
+  unsigned int allocated = 32000 * sizeof(char);
+  unsigned int bytesRead = 0;
+
+  int file = open(sample-&gt;getFilePath().c_str(), O_RDONLY);
+  if (file == 0) return;
+  
+  data = (char*)malloc(allocated);
+  // TODO add error messages
+  while ((bytesRead = read(file, data, allocated - size)))
+  {
+    size += bytesRead;
+    if (size &gt;= allocated) {
+      allocated *= 2;
+      data = (char*)realloc(data, allocated);
+    }
+    if (data == 0)
+    {
+      cerr &lt;&lt; &quot;allocation of more memory to read sample file '&quot;
+           &lt;&lt; sample-&gt;getFilePath() &lt;&lt; &quot;' failed.\n&quot;;
+      break;
+    }
+  }
 
+  sample-&gt;setSize(size);
+  sample-&gt;setData(data);
+  cout &lt;&lt; &quot;   read sample '&quot; &lt;&lt; sample-&gt;getName() &lt;&lt; &quot;' with &quot;
+       &lt;&lt; sample-&gt;getSize() &lt;&lt; &quot; Bytes.\n&quot;;
+  
+  close(file);
 }</diff>
      <filename>SimpleWaveFileLoader.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -42,7 +42,7 @@ public:
 private:
   void insertDefault();
   void loadSampleFromFile(const char *path);
-  void loadDataFromFile(const char *path, char *&amp;data, unsigned int &amp;size);
+  void loadDataFromFile(Sample *sample);
 
   inline const string getName(const char *path)
   {</diff>
      <filename>SimpleWaveFileLoader.h</filename>
    </modified>
    <modified>
      <diff>@@ -96,7 +96,7 @@ class AnnoyErrnoException : public AnnoymeException
 {
   public:
 
-  AnnoyErrnoException(string msg, string subject, int errnum) throw()
+  AnnoyErrnoException(string msg, const string &amp;subject, int errnum) throw()
   : errnum(errnum)
   {
     msg += &quot;: &quot;;
@@ -112,3 +112,29 @@ class AnnoyErrnoException : public AnnoymeException
 
   int errnum;
 };
+
+class SoundOutputException : public AnnoymeException
+{
+  public:
+
+  SoundOutputException(const string &amp;msg) throw()
+  : AnnoymeException(msg)
+  {
+
+  }
+
+  virtual ~SoundOutputException() throw() {};
+};
+
+class AlsaOutputException : public SoundOutputException
+{
+  public:
+
+  AlsaOutputException(const string &amp;msg) throw()
+  : SoundOutputException(msg)
+  {
+
+  }
+
+  virtual ~AlsaOutputException() throw() {};
+};</diff>
      <filename>exceptions.h</filename>
    </modified>
    <modified>
      <diff>@@ -18,4 +18,6 @@
 #include &lt;sys/types.h&gt;
 #include &lt;sys/stat.h&gt;
 
+#include &lt;alsa/asoundlib.h&gt;
+
 using namespace std;</diff>
      <filename>stdheaders.h</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>eae9915ae2ea7ccc774af54f4e392bc491a4b0c1</id>
    </parent>
  </parents>
  <author>
    <name>Benjamin Peter</name>
    <email>BenjaminPeter@arcor.de</email>
  </author>
  <url>http://github.com/dedeibel/annoyme/commit/52be8ff814a62d4cc8f77522a9719f10bce620d3</url>
  <id>52be8ff814a62d4cc8f77522a9719f10bce620d3</id>
  <committed-date>2008-11-02T11:43:11-08:00</committed-date>
  <authored-date>2008-11-02T11:43:11-08:00</authored-date>
  <message>Added wav file loader data reading. Added prototypic al ALSA sound output.</message>
  <tree>2b21feca4c3a5b5c9d53baeff987e5b4fd1866a4</tree>
  <committer>
    <name>Benjamin Peter</name>
    <email>BenjaminPeter@arcor.de</email>
  </committer>
</commit>
