summaryrefslogtreecommitdiff
path: root/modules/mda/player.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mda/player.cpp')
-rw-r--r--modules/mda/player.cpp176
1 files changed, 176 insertions, 0 deletions
diff --git a/modules/mda/player.cpp b/modules/mda/player.cpp
new file mode 100644
index 0000000..4cfa18c
--- /dev/null
+++ b/modules/mda/player.cpp
@@ -0,0 +1,176 @@
+/**
+ * @file player.cpp Symbian MDA audio driver -- player
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <e32def.h>
+#include <e32std.h>
+#include <mdaaudiooutputstream.h>
+#include <mda/common/audio.h>
+
+extern "C" {
+#include <re.h>
+#include <baresip.h>
+#include "mda.h"
+
+#define DEBUG_MODULE "player"
+#define DEBUG_LEVEL 5
+#include <re_dbg.h>
+}
+
+
+enum {VOLUME = 100};
+
+class mda_player;
+struct auplay_st {
+ struct auplay *ap; /* inheritance */
+ mda_player *mda;
+ auplay_write_h *wh;
+ void *arg;
+};
+
+
+class mda_player : public MMdaAudioOutputStreamCallback, public CBase
+{
+public:
+ mda_player(struct auplay_st *st, struct auplay_prm *prm);
+ ~mda_player();
+ void play();
+
+ /* from MMdaAudioOutputStreamCallback */
+ virtual void MaoscOpenComplete(TInt aError);
+ virtual void MaoscBufferCopied(TInt aError, const TDesC8& aBuffer);
+ virtual void MaoscPlayComplete(TInt aError);
+
+private:
+ CMdaAudioOutputStream *iOutput;
+ TMdaAudioDataSettings iSettings;
+ TBool iIsReady;
+ TBuf8<320> iBuf;
+ struct auplay_st *state;
+};
+
+
+mda_player::mda_player(struct auplay_st *st, struct auplay_prm *prm)
+ :iIsReady(EFalse)
+{
+ state = st;
+
+ iBuf.FillZ(320);
+
+ iSettings.iSampleRate = convert_srate(prm->srate);
+ iSettings.iChannels = convert_channels(prm->ch);
+ iSettings.iVolume = VOLUME;
+
+ iOutput = CMdaAudioOutputStream::NewL(*this);
+ iOutput->Open(&iSettings);
+}
+
+
+mda_player::~mda_player()
+{
+ if (iOutput) {
+ iOutput->Stop();
+ delete iOutput;
+ }
+}
+
+
+void mda_player::play()
+{
+ /* call write handler here */
+ state->wh((uint8_t *)&iBuf[0], iBuf.Length(), state->arg);
+
+ TRAPD(ret, iOutput->WriteL(iBuf));
+ if (KErrNone != ret) {
+ DEBUG_WARNING("WriteL left with %d\n", ret);
+ }
+}
+
+
+void mda_player::MaoscOpenComplete(TInt aError)
+{
+ if (KErrNone != aError) {
+ iIsReady = EFalse;
+ DEBUG_WARNING("mda player error: %d\n", aError);
+ return;
+ }
+
+ iOutput->SetAudioPropertiesL(iSettings.iSampleRate,
+ iSettings.iChannels);
+ iOutput->SetPriority(EMdaPriorityNormal,
+ EMdaPriorityPreferenceTime);
+
+ iIsReady = ETrue;
+
+ play();
+}
+
+
+/*
+ * Note: In reality, this function is called approx. 1 millisecond after the
+ * last block was played, hence we have to generate buffer N+1 while buffer N
+ * is playing.
+ */
+void mda_player::MaoscBufferCopied(TInt aError, const TDesC8& aBuffer)
+{
+ (void)aBuffer;
+
+ if (KErrNone != aError && KErrCancel != aError) {
+ DEBUG_WARNING("MaoscBufferCopied [aError=%d]\n", aError);
+ }
+ if (aError == KErrAbort) {
+ DEBUG_NOTICE("player aborted\n");
+ return;
+ }
+
+ play();
+}
+
+
+void mda_player::MaoscPlayComplete(TInt aError)
+{
+ if (KErrNone != aError) {
+ DEBUG_WARNING("MaoscPlayComplete [aError=%d]\n", aError);
+ }
+}
+
+
+static void auplay_destructor(void *arg)
+{
+ struct auplay_st *st = (struct auplay_st *)arg;
+
+ delete st->mda;
+
+ mem_deref(st->ap);
+}
+
+
+int mda_player_alloc(struct auplay_st **stp, struct auplay *ap,
+ struct auplay_prm *prm, const char *device,
+ auplay_write_h *wh, void *arg)
+{
+ struct auplay_st *st;
+ int err = 0;
+
+ (void)device;
+
+ st = (struct auplay_st *)mem_zalloc(sizeof(*st), auplay_destructor);
+ if (!st)
+ return ENOMEM;
+
+ st->ap = (struct auplay *)mem_ref(ap);
+ st->wh = wh;
+ st->arg = arg;
+
+ st->mda = new mda_player(st, prm);
+ if (!st->mda)
+ err = ENOMEM;
+
+ if (err)
+ mem_deref(st);
+ else
+ *stp = st;
+
+ return err;
+}