From 7bb77279bf5b76902c167923d57800e1f6f6073e Mon Sep 17 00:00:00 2001
From: Javier <dev.git@javispedro.com>
Date: Sun, 30 Jan 2022 20:02:28 +0100
Subject: Cleaning up Adlib module

---
 Adlib.cpp    | 145 +++++++++++++++++++++++++++--------------------------------
 Makefile     |   7 ++-
 Mpu401.cpp   |   7 +--
 README.md    |  18 ++++----
 midialsa.cpp |   6 +--
 pcmalsa.cpp  |  42 ++++++++---------
 pcmalsa.h    |   8 ++--
 7 files changed, 112 insertions(+), 121 deletions(-)

diff --git a/Adlib.cpp b/Adlib.cpp
index cd4d6e2..3033c4e 100644
--- a/Adlib.cpp
+++ b/Adlib.cpp
@@ -51,9 +51,6 @@
 #define LOG_ENABLE_FLOW 1
 #define LOG_GROUP LOG_GROUP_DEV_SB16
 #include <VBox/vmm/pdmdev.h>
-#ifndef IN_RING3
-# include <VBox/vmm/pdmapi.h>
-#endif
 #include <VBox/AssertGuest.h>
 #include <VBox/version.h>
 #include <iprt/assert.h>
@@ -61,6 +58,10 @@
 
 #include "opl3.h"
 
+#ifndef IN_RING3
+#error "R3-only driver"
+#endif
+
 #if RT_OPSYS == RT_OPSYS_LINUX
 #include "pcmalsa.h"
 typedef PCMOutAlsa PCMOutBackend;
@@ -77,7 +78,7 @@ typedef PCMOutWin PCMOutBackend;
 
 #define ADLIB_DEFAULT_OUT_DEVICE    "default"
 #define ADLIB_DEFAULT_SAMPLE_RATE   22055 /* Hz */
-#define ADLIB_NUM_CHANNELS          2 /* as we are actually using OPL3 */
+#define ADLIB_NUM_CHANNELS          2 /* as we are actually supporting OPL3 */
 
 enum {
     ADLIB_PORT_ADDR = 0,
@@ -90,8 +91,11 @@ enum {
 /** The saved state version. */
 #define ADLIB_SAVED_STATE_VERSION     1
 
+/** Maximum number of sound samples render in one batch by render thread. */
+#define ADLIB_RENDER_BLOCK_TIME     5 /* in millisec */
+
 /** The render thread will shutdown if this time passes since the last OPL register write. */
-#define ADLIB_RENDER_THREAD_TIMEOUT 5000 /* in millisec */
+#define ADLIB_RENDER_SUSPEND_TIMEOUT 5000 /* in millisec */
 
 #define OPL2_NUM_IO_PORTS       2
 #define OPL3_NUM_IO_PORTS       4
@@ -126,9 +130,8 @@ typedef struct {
     PCMOutBackend          pcmOut;
     /** Thread that connects to PCM out, renders and pushes audio data. */
     RTTHREAD               hRenderThread;
-    /** Buffer for the rendering thread to use. */
+    /** Buffer for the rendering thread to use, size defined by ADLIB_RENDER_BLOCK_TIME. */
     R3PTRTYPE(uint8_t *)   pbRenderBuf;
-    size_t                 uRenderBufSize;
     /** Flag to signal render thread to shut down. */
     bool volatile          fShutdown;
     /** Flag from render thread indicated it has shutdown (e.g. due to error or timeout). */
@@ -156,6 +159,18 @@ typedef ADLIBSTATE *PADLIBSTATE;
 
 #ifndef VBOX_DEVICE_STRUCT_TESTCASE
 
+static inline uint64_t adlibCalculateFramesFromMilli(PADLIBSTATE pThis, uint64_t milli)
+{
+    uint64_t rate = pThis->uSampleRate;
+    return (rate * milli) / 1000;
+}
+
+static inline size_t adlibCalculateBytesFromFrames(PADLIBSTATE pThis, uint64_t frames)
+{
+    NOREF(pThis);
+    return frames * sizeof(uint16_t) * ADLIB_NUM_CHANNELS;
+}
+
 static uint64_t adlibCalculateTimerExpire(PPDMDEVINS pDevIns, uint8_t value, uint64_t period)
 {
     uint64_t delay_usec = (0x100 - value) * period;
@@ -168,6 +183,12 @@ static uint64_t adlibCalculateTimerExpire(PPDMDEVINS pDevIns, uint8_t value, uin
 }
 
 /**
+ * The render thread calls into the emulator to render audio frames, and then pushes them
+ * on the PCM output device.
+ * We rely on the PCM output device's blocking writes behavior to avoid running continously.
+ * A small block size (ADLIB_RENDER_BLOCK_TIME) is also used to give the main thread some
+ * opportunities to run.
+ *
  * @callback_method_impl{FNRTTHREAD}
  */
 static DECLCALLBACK(int) adlibRenderThread(RTTHREAD ThreadSelf, void *pvUser)
@@ -178,52 +199,37 @@ static DECLCALLBACK(int) adlibRenderThread(RTTHREAD ThreadSelf, void *pvUser)
 
     // Compute the max number of frames we can store on our temporary buffer.
     int16_t *buf = (int16_t*) pThis->pbRenderBuf;
-    ssize_t buf_size = pThis->uRenderBufSize;
-    ssize_t buf_samples = buf_size / sizeof(int16_t);
-    ssize_t buf_frames = buf_samples / ADLIB_NUM_CHANNELS;
+    uint64_t buf_frames = adlibCalculateFramesFromMilli(pThis, ADLIB_RENDER_BLOCK_TIME);
 
-    Log(("adlib: Starting render thread\n"));
+    Log(("adlib: Starting render thread with buf_frames=%lld\n", buf_frames));
 
     int rc = pPcmOut->open(pThis->pszOutDevice, pThis->uSampleRate, ADLIB_NUM_CHANNELS);
     AssertLogRelRCReturn(rc, rc);
 
     while (!ASMAtomicReadBool(&pThis->fShutdown)
-           && ASMAtomicReadU64(&pThis->tmLastWrite) + ADLIB_RENDER_THREAD_TIMEOUT >= RTTimeSystemMilliTS()) {
-        ssize_t avail = pPcmOut->avail();
-
-        if (avail < 0) {
-            LogWarn(("adlib: render thread avail err=%d\n", avail));
-            break;
-        }
-        if (avail == 0) {
-            rc = pPcmOut->wait();
-            AssertLogRelRCBreak(rc);
-            avail = pPcmOut->avail();
-            if (avail < 0) {
-                LogWarn(("adlib: render thread wait avail err=%d\n", avail));
-                break;
-            }
-        }
-
-        avail = RT_MIN(avail, buf_frames);
-
-        Log3(("rendering %ld frames\n", avail));
+           && ASMAtomicReadU64(&pThis->tmLastWrite) + ADLIB_RENDER_SUSPEND_TIMEOUT >= RTTimeSystemMilliTS()) {
+        Log3(("rendering %lld frames\n", buf_frames));
 
         RTCritSectEnter(&pThis->critSect);
-        OPL3_GenerateStream(&pThis->opl, buf, avail);
+        OPL3_GenerateStream(&pThis->opl, buf, buf_frames);
         RTCritSectLeave(&pThis->critSect);
 
-        ssize_t written_frames = pPcmOut->write(buf, avail);
+        Log3(("writing %lld frames\n", buf_frames));
+
+        ssize_t written_frames = pPcmOut->write(buf, buf_frames);
         if (written_frames < 0) {
-            LogWarn(("adlib: render thread write err=%d\n", written_frames));
-            break;
+            rc = written_frames;
+            AssertLogRelMsgFailedBreak(("adlib: render thread write err=%Rrc\n", written_frames));
         }
+
+        RTThreadYield();
     }
 
-    rc = pPcmOut->close();
-    AssertLogRelRC(rc);
+    int rcClose = pPcmOut->close();
+    AssertLogRelRC(rcClose);
+    if (RT_SUCCESS(rc)) rc = rcClose;
 
-    Log(("adlib: Stopping render thread\n"));
+    Log(("adlib: Stopping render thread with rc=%Rrc\n", rc));
 
     ASMAtomicWriteBool(&pThis->fStopped, true);
 
@@ -231,7 +237,7 @@ static DECLCALLBACK(int) adlibRenderThread(RTTHREAD ThreadSelf, void *pvUser)
 }
 
 /** Waits for the render thread to finish and reaps it. */
-static int adlibReapRenderThread(PPDMDEVINS pDevIns, RTMSINTERVAL millies = 1000)
+static int adlibReapRenderThread(PPDMDEVINS pDevIns, RTMSINTERVAL millies = 100)
 {
     PADLIBSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PADLIBSTATE);
 
@@ -253,6 +259,12 @@ static int adlibStopRenderThread(PPDMDEVINS pDevIns, bool wait = false)
 {
     PADLIBSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PADLIBSTATE);
 
+    if (pThis->hRenderThread == NIL_RTTHREAD) {
+        // Already stopped & reaped
+        return VINF_SUCCESS;
+    }
+
+    // Raise the flag for the thread
     ASMAtomicWriteBool(&pThis->fShutdown, true);
 
     if (wait) {
@@ -263,36 +275,19 @@ static int adlibStopRenderThread(PPDMDEVINS pDevIns, bool wait = false)
     return VINF_SUCCESS;
 }
 
-static int adlibResetRenderThread(PPDMDEVINS pDevIns)
-{
-    PADLIBSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PADLIBSTATE);
-
-    // Thread has to be shutdown
-    AssertReturn(ASMAtomicReadBool(&pThis->fShutdown), VERR_INVALID_STATE);
-
-    int rc = adlibReapRenderThread(pDevIns);
-    if (RT_SUCCESS(rc)) {
-        pThis->fShutdown = false;
-        pThis->fStopped = false;
-    } else {
-        LogWarn(("adlib%d: can't reset render thread, it did not terminate (%Rrc)\n", rc));
-    }
-
-    return rc;
-}
-
 static void adlibWakeRenderThread(PPDMDEVINS pDevIns)
 {
     PADLIBSTATE pThis = PDMDEVINS_2_DATA(pDevIns, PADLIBSTATE);
 
     ASMAtomicWriteU64(&pThis->tmLastWrite, RTTimeSystemMilliTS());
 
-    AssertReturnVoid(!ASMAtomicReadBool(&pThis->fShutdown));
-
     // Reap any existing render thread if it had stopped
     if (ASMAtomicReadBool(&pThis->fStopped)) {
         int rc = adlibReapRenderThread(pDevIns);
-        AssertRCReturnVoid(rc);
+        AssertLogRelRCReturnVoid(rc);
+    } else if (ASMAtomicReadBool(&pThis->fShutdown)
+               && pThis->hRenderThread != NIL_RTTHREAD) {
+        AssertLogRelMsgFailedReturnVoid(("can't wake render thread -- it's shutting down!\n"));
     }
 
     // If there is no existing render thread, start a new one
@@ -305,10 +300,7 @@ static void adlibWakeRenderThread(PPDMDEVINS pDevIns)
         int rc = RTThreadCreateF(&pThis->hRenderThread, adlibRenderThread, pThis, 0,
                                  RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE,
                                  "adlib%u_render", pDevIns->iInstance);
-        if (RT_FAILURE(rc)) {
-            LogWarn(("adlib%d: could not start render thread (%Rrc)\n", pDevIns->iInstance, rc));
-            AssertRCReturnVoid(rc);
-        }
+        AssertLogRelRCReturnVoid(rc);
     }
 }
 
@@ -334,6 +326,10 @@ static uint8_t adlibReadStatus(PPDMDEVINS pDevIns)
     if (pThis->timer2Enable && tmNow > pThis->timer2Expire) {
         status |= RT_BIT(7) | RT_BIT(5);
     }
+    if (!pThis->fOPL3) {
+        // OPL2 seems to have this as special signature.
+        status |= 0x6;
+    }
 
     Log2Func(("status=0x%x\n", status));
 
@@ -552,14 +548,6 @@ static DECLCALLBACK(void) adlibR3Suspend(PPDMDEVINS pDevIns)
     adlibStopRenderThread(pDevIns);
 }
 
-/**
- * @interface_method_impl{PDMDEVREG,pfnResume}
- */
-static DECLCALLBACK(void) adlibR3Resume(PPDMDEVINS pDevIns)
-{
-    adlibResetRenderThread(pDevIns);
-}
-
 /**
  * @interface_method_impl{PDMDEVREG,pfnPowerOff}
  */
@@ -611,18 +599,17 @@ static DECLCALLBACK(int) adlibR3Construct(PPDMDEVINS pDevIns, int iInstance, PCF
     adlibR3Reset(pDevIns);
 
     /* Initialize now the buffer that will be used by the render thread. */
-    // Give it as much space as it could possibly need, like half a second
-    pThis->uRenderBufSize = (pThis->uSampleRate * ADLIB_NUM_CHANNELS * sizeof(uint16_t)) / 2;
-    pThis->pbRenderBuf = (uint8_t *) RTMemAllocZ(pThis->uRenderBufSize);
+    size_t renderBlockSize = adlibCalculateBytesFromFrames(pThis, adlibCalculateFramesFromMilli(pThis, ADLIB_RENDER_BLOCK_TIME));
+    pThis->pbRenderBuf = (uint8_t *) RTMemAlloc(renderBlockSize);
     AssertReturn(pThis->pbRenderBuf, VERR_NO_MEMORY);
 
     /* Prepare the render thread, but not create it yet. */
-	pThis->fShutdown = false;
+    pThis->fShutdown = false;
     pThis->fStopped = false;
     pThis->hRenderThread = NIL_RTTHREAD;
     pThis->tmLastWrite = 0;
-	rc = RTCritSectInit(&pThis->critSect);
-	AssertRCReturn(rc, rc);
+    rc = RTCritSectInit(&pThis->critSect);
+    AssertRCReturn(rc, rc);
 
     /*
      * Register I/O ports.
@@ -716,7 +703,7 @@ static const PDMDEVREG g_DeviceAdlib =
     /* .pfnPowerOn = */             NULL,
     /* .pfnReset = */               adlibR3Reset,
     /* .pfnSuspend = */             adlibR3Suspend,
-    /* .pfnResume = */              adlibR3Resume,
+    /* .pfnResume = */              NULL,
     /* .pfnAttach = */              NULL,
     /* .pfnDetach = */              NULL,
     /* .pfnQueryInterface = */      NULL,
diff --git a/Makefile b/Makefile
index 55d57d5..188ea1b 100644
--- a/Makefile
+++ b/Makefile
@@ -89,14 +89,17 @@ $(OUTDIR)/ExtPack.xml: ExtPack.xml
 $(OUTDIR)/ExtPack.signature:
 	echo "todo" > $@
 
-$(OUTDIR)/ExtPack.manifest: $(OUTDIR)
+$(OUTDIR)/ExtPack.manifest: $(OUTDIR) $(OUTOSDIR)
 	cd $(OUTDIR) ;\
 	find -type f -printf '%P\n' | xargs ../build_manifest.sh > $(@F)
 
 pack: $(OUTDIR)/ExtPack.xml $(OUTDIR)/ExtPack.signature $(OUTDIR)/ExtPack.manifest
 	tar --format=ustar --numeric-owner --owner=0 --group=0 --mode='a=rX,u+w' --sort=name -C $(OUTDIR) -f VMusic.vbox-extpack -v -z -c .
 
+strip:
+	strip $(OUTOSDIR)/*.$(SO)
+
 clean:
 	rm -rf $(OUTDIR) $(OBJDIR) VMusic.vbox-extpack
 	
-.PHONY: all build clean pack
+.PHONY: all build clean strip pack
diff --git a/Mpu401.cpp b/Mpu401.cpp
index 1f9e8ec..d4ca931 100644
--- a/Mpu401.cpp
+++ b/Mpu401.cpp
@@ -51,14 +51,15 @@
 #define LOG_ENABLE_FLOW 1
 #define LOG_GROUP LOG_GROUP_DEV_SB16
 #include <VBox/vmm/pdmdev.h>
-#ifndef IN_RING3
-# include <VBox/vmm/pdmapi.h>
-#endif
 #include <VBox/AssertGuest.h>
 #include <VBox/version.h>
 #include <iprt/assert.h>
 #include <iprt/mem.h>
 
+#ifndef IN_RING3
+#error "R3-only driver"
+#endif
+
 #if RT_OPSYS == RT_OPSYS_LINUX
 #include "midialsa.h"
 typedef MIDIOutAlsa MIDIOutBackend;
diff --git a/README.md b/README.md
index e58b421..57148c8 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,7 @@ VBoxManage setextradata "$vm" VBoxInternal/Devices/mpu401/0/Trusted 1
 If the devices have been correctly enabled, you should see the following messages in the
 VBox.log file of a virtual machine after it has been powered on:
 
-```
+```{ use_pygments=false }
 00:00:00.799849 Installed Extension Packs:
 00:00:00.799866   VMusic (Version: 0.2 r0; VRDE Module: )
 ...
@@ -77,7 +77,7 @@ or [Munt](https://sourceforge.net/projects/munt/).
 First, start the virtual machine. Second, start and configure your software synthesizer.
 
 If you run `aconnect -l` at this point, you will see a list of all your real/virtual MIDI devices in the system. Sample output from  `aconnect -l`:
-```
+```{ use_pygments=false }
 client 0: 'System' [type=kernel]
     0 'Timer           '
 	Connecting To: 142:0
@@ -94,7 +94,7 @@ This indicates that there is a `Munt MT-32` synthesizer at port 129:0 , and a `V
 The latter is the virtual MIDI device used by the MPU-401 emulation. So, to send the virtual machine's MIDI output to Munt,
 connect the two ports by running:
 
-```
+```{ use_pygments=false }
 aconnect 128:0 129:0
 ```
 
@@ -105,16 +105,16 @@ all virtual MIDI ports to it, in which case you may not need to connect anything
 
 # Building
 
-You need the standard C++ building tools, _make_, _libasound_ and headers (e.g. `libasound2-dev` in Ubuntu).
+You need the standard C++ building tools, make, libasound and headers (e.g. `libasound2-dev` in Ubuntu).
 
 First, ensure that, in the directory where the VMusic source resides, you add two extra directories:
 
-* _VirtualBox.src_ containing the unpacked pristine VirtualBox source from [virtualbox.org](https://www.virtualbox.org/wiki/Downloads), e.g. the contents of [VirtualBox-6.1.32.tar.bz2](https://download.virtualbox.org/virtualbox/6.1.32/VirtualBox-6.1.32.tar.bz2).
+* `VirtualBox.src` containing the unpacked pristine VirtualBox source from [virtualbox.org](https://www.virtualbox.org/wiki/Downloads), e.g. the contents of [VirtualBox-6.1.32.tar.bz2](https://download.virtualbox.org/virtualbox/6.1.32/VirtualBox-6.1.32.tar.bz2).
 
-* _VirtualBox.linux.amd64_ containing at least the following VirtualBox Linux.amd64 libraries,
-either from an official installation or your distribution's package: _VBoxRT.so_ and _VBoxVMM.so_. 
-E.g. copy _/usr/lib/virtualbox/VBoxRT.so_ into _VirtualBox.linux.amd64/VBoxRT.so_.
+* `VirtualBox.linux.amd64` containing at least the following VirtualBox Linux.amd64 libraries,
+either from an official installation or your distribution's package: `VBoxRT.so` and `VBoxVMM.so`.
+E.g. copy `/usr/lib/virtualbox/VBoxRT.so` into `VirtualBox.linux.amd64/VBoxRT.so`.
 
-After this, just type `make` followed by `make pack` and _VMusic.vbox-extpack_ should be generated.
+After this, just type `make` followed by `make pack` and `VMusic.vbox-extpack` should be generated.
 
 
diff --git a/midialsa.cpp b/midialsa.cpp
index e8e653a..ef07d8a 100644
--- a/midialsa.cpp
+++ b/midialsa.cpp
@@ -36,7 +36,7 @@ MIDIOutAlsa::~MIDIOutAlsa()
 
 int MIDIOutAlsa::open(const char *dev)
 {
-	int err;
+    int err;
 
     if ((err = snd_rawmidi_open(NULL, &_out, "virtual", SND_RAWMIDI_NONBLOCK))) {
         LogWarn(("ALSA rawmidi open error: %s\n", snd_strerror(err)));
@@ -46,7 +46,7 @@ int MIDIOutAlsa::open(const char *dev)
     // TODO: Connect somewhere
     NOREF(dev);
 
-	return VINF_SUCCESS;
+    return VINF_SUCCESS;
 }
 
 int MIDIOutAlsa::close()
@@ -55,7 +55,7 @@ int MIDIOutAlsa::close()
         snd_rawmidi_close(_out);
         _out = NULL;
     }
-	return VINF_SUCCESS;
+    return VINF_SUCCESS;
 }
 
 ssize_t MIDIOutAlsa::write(uint8_t *data, size_t len)
diff --git a/pcmalsa.cpp b/pcmalsa.cpp
index eec9b94..5708509 100644
--- a/pcmalsa.cpp
+++ b/pcmalsa.cpp
@@ -36,13 +36,13 @@ PCMOutAlsa::~PCMOutAlsa()
 
 int PCMOutAlsa::open(const char *dev, unsigned int sampleRate, unsigned int channels)
 {
-	int err;
+    int err;
 
     err = snd_pcm_open(&_pcm, dev, SND_PCM_STREAM_PLAYBACK, 0);
     if (err < 0) {
-		LogWarn(("ALSA playback open error: %s\n", snd_strerror(err)));
-		return VERR_AUDIO_STREAM_COULD_NOT_CREATE;
-	}
+        LogWarn(("ALSA playback open error: %s\n", snd_strerror(err)));
+        return VERR_AUDIO_STREAM_COULD_NOT_CREATE;
+    }
 
     // TODO: Right now, setting a too large period size means we will not let the main
     // thread run long enough to actually change notes/voices. Need some actual synchronization.
@@ -57,16 +57,16 @@ int PCMOutAlsa::open(const char *dev, unsigned int sampleRate, unsigned int chan
         return VERR_AUDIO_STREAM_COULD_NOT_CREATE;
     }
 
-	return VINF_SUCCESS;
+    return VINF_SUCCESS;
 }
 
 int PCMOutAlsa::close()
 {
-	if (_pcm) {
+    if (_pcm) {
         snd_pcm_drain(_pcm);
-		snd_pcm_close(_pcm);
-	}
-	return VINF_SUCCESS;
+        snd_pcm_close(_pcm);
+    }
+    return VINF_SUCCESS;
 }
 
 ssize_t PCMOutAlsa::avail()
@@ -104,16 +104,16 @@ int PCMOutAlsa::wait()
 
 ssize_t PCMOutAlsa::write(int16_t *buf, size_t n)
 {
-	snd_pcm_sframes_t frames = snd_pcm_writei(_pcm, buf, n);
-	if (frames < 0) {
-		LogFlow(("ALSA trying to recover from error: %s\n", snd_strerror(frames)));
-		frames = snd_pcm_recover(_pcm, frames, 0);
-	}
-	if (frames < 0) {
+    snd_pcm_sframes_t frames = snd_pcm_writei(_pcm, buf, n);
+    if (frames < 0) {
+        LogFlow(("ALSA trying to recover from error: %s\n", snd_strerror(frames)));
+        frames = snd_pcm_recover(_pcm, frames, 0);
+    }
+    if (frames < 0) {
         LogWarn(("ALSA write error: %s\n", snd_strerror(frames)));
-		return VERR_AUDIO_STREAM_NOT_READY;
-	}
-	return frames;
+        return VERR_AUDIO_STREAM_NOT_READY;
+    }
+    return frames;
 }
 
 int PCMOutAlsa::setParams(unsigned int sampleRate, unsigned int channels, unsigned int bufferTime, unsigned int periodTime)
@@ -175,19 +175,19 @@ int PCMOutAlsa::setParams(unsigned int sampleRate, unsigned int channels, unsign
     }
     err = snd_pcm_hw_params_get_buffer_size(hwparams, &_bufferSize);
     if (err < 0) {
-        printf("Unable to get buffer size for playback: %s\n", snd_strerror(err));
+        LogWarnFunc(("Unable to get buffer size for playback: %s\n", snd_strerror(err)));
         return err;
     }
 
     /* set the period time */
     err = snd_pcm_hw_params_set_period_time_near(_pcm, hwparams, &periodTime, NULL);
     if (err < 0) {
-        printf("Unable to set period time %u for playback: %s\n", periodTime, snd_strerror(err));
+        LogWarnFunc(("Unable to set period time %u for playback: %s\n", periodTime, snd_strerror(err)));
         return err;
     }
     err = snd_pcm_hw_params_get_period_size(hwparams, &_periodSize, NULL);
     if (err < 0) {
-        printf("Unable to get period size for playback: %s\n", snd_strerror(err));
+        LogWarnFunc(("Unable to get period size for playback: %s\n", snd_strerror(err)));
         return err;
     }
 
diff --git a/pcmalsa.h b/pcmalsa.h
index d9837c5..c314faf 100644
--- a/pcmalsa.h
+++ b/pcmalsa.h
@@ -27,11 +27,11 @@ typedef struct _snd_pcm snd_pcm_t;
 class PCMOutAlsa
 {
 public:
-	PCMOutAlsa();
-	~PCMOutAlsa();
+    PCMOutAlsa();
+    ~PCMOutAlsa();
 
     int open(const char *dev, unsigned int sampleRate, unsigned int channels);
-	int close();
+    int close();
 
     ssize_t avail();
     int wait();
@@ -42,7 +42,7 @@ private:
     int setParams(unsigned int sampleRate, unsigned int channels, unsigned int bufferTime, unsigned int periodTime);
 
 private:
-	snd_pcm_t * _pcm;
+    snd_pcm_t * _pcm;
     size_t _bufferSize;
     size_t _periodSize;
 };
-- 
cgit v1.2.3