From 2409b5f784574279fc66c118b11cb3bda6324fc5 Mon Sep 17 00:00:00 2001
From: Stephen Birarda <commit@birarda.com>
Date: Thu, 19 Dec 2013 13:46:37 -0800
Subject: [PATCH] complete inital test of AudioInjector API

---
 assignment-client/src/AssignmentClient.cpp   |  3 +-
 interface/src/Application.cpp                |  7 +++++
 libraries/audio/src/AbstractAudioInterface.h |  2 ++
 libraries/audio/src/AudioInjector.cpp        | 29 ++++++++++++++------
 libraries/audio/src/AudioInjector.h          | 11 +++++++-
 5 files changed, 42 insertions(+), 10 deletions(-)

diff --git a/assignment-client/src/AssignmentClient.cpp b/assignment-client/src/AssignmentClient.cpp
index 17b1b6099e..cc4292ad15 100644
--- a/assignment-client/src/AssignmentClient.cpp
+++ b/assignment-client/src/AssignmentClient.cpp
@@ -22,6 +22,8 @@
 const char ASSIGNMENT_CLIENT_TARGET_NAME[] = "assignment-client";
 const long long ASSIGNMENT_REQUEST_INTERVAL_MSECS = 1 * 1000;
 
+int hifiSockAddrMeta = qRegisterMetaType<HifiSockAddr>("HifiSockAddr");
+
 AssignmentClient::AssignmentClient(int &argc, char **argv,
                                    Assignment::Type requestAssignmentType,
                                    const HifiSockAddr& customAssignmentServerSocket,
@@ -31,7 +33,6 @@ AssignmentClient::AssignmentClient(int &argc, char **argv,
     _currentAssignment(NULL)
 {
     // register meta type is required for queued invoke method on Assignment subclasses
-    qRegisterMetaType<HifiSockAddr>("HifiSockAddr");
     
     // set the logging target to the the CHILD_TARGET_NAME
     Logging::setTargetName(ASSIGNMENT_CLIENT_TARGET_NAME);
diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp
index 24cdabe772..370d9cda4e 100644
--- a/interface/src/Application.cpp
+++ b/interface/src/Application.cpp
@@ -38,6 +38,7 @@
 #include <QFileDialog>
 #include <QDesktopServices>
 
+#include <AudioInjector.h>
 #include <NodeTypes.h>
 #include <Logging.h>
 #include <OctalCode.h>
@@ -1317,6 +1318,12 @@ void Application::timer() {
     // ask the node list to check in with the domain server
     NodeList::getInstance()->sendDomainServerCheckIn();
     
+    static AudioInjector testInjector(QUrl("https://dl.dropboxusercontent.com/u/1864924/throw.raw"));
+    
+    if (testInjector.size()) {
+        testInjector.injectViaThread(&_audio);
+    }
+    
     // give the MyAvatar object position to the Profile so it can propagate to the data-server
     _profile.updatePosition(_myAvatar.getPosition());
 }
diff --git a/libraries/audio/src/AbstractAudioInterface.h b/libraries/audio/src/AbstractAudioInterface.h
index d2cb0c3360..dc3872efd5 100644
--- a/libraries/audio/src/AbstractAudioInterface.h
+++ b/libraries/audio/src/AbstractAudioInterface.h
@@ -23,4 +23,6 @@ public slots:
     virtual void handleAudioByteArray(const QByteArray& audioByteArray) = 0;
 };
 
+Q_DECLARE_METATYPE(AbstractAudioInterface*)
+
 #endif /* defined(__hifi__AbstractAudioInterface__) */
\ No newline at end of file
diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp
index 05cf34e765..9aaa39c84d 100644
--- a/libraries/audio/src/AudioInjector.cpp
+++ b/libraries/audio/src/AudioInjector.cpp
@@ -14,9 +14,18 @@
 
 #include "AudioInjector.h"
 
-AudioInjector::AudioInjector(const QUrl& sampleURL, QObject* parent) :
-	QObject(parent)
+int abstractAudioPointerMeta = qRegisterMetaType<AbstractAudioInterface*>("AbstractAudioInterface*");
+
+AudioInjector::AudioInjector(const QUrl& sampleURL) :
+    _sourceURL(sampleURL)
 {
+    // we want to live on our own thread
+    moveToThread(&_thread);
+    connect(&_thread, SIGNAL(started()), this, SLOT(startDownload()));
+    _thread.start();
+}
+
+void AudioInjector::startDownload() {
     // assume we have a QApplication or QCoreApplication instance and use the
     // QNetworkAccess manager to grab the raw audio file at the given URL
     
@@ -24,7 +33,7 @@ AudioInjector::AudioInjector(const QUrl& sampleURL, QObject* parent) :
     connect(manager, SIGNAL(finished(QNetworkReply*)),
             this, SLOT(replyFinished(QNetworkReply*)));
     
-    manager->get(QNetworkRequest(sampleURL));
+    manager->get(QNetworkRequest(_sourceURL));
 }
 
 void AudioInjector::replyFinished(QNetworkReply* reply) {
@@ -33,17 +42,21 @@ void AudioInjector::replyFinished(QNetworkReply* reply) {
 }
 
 void AudioInjector::injectViaThread(AbstractAudioInterface* localAudioInterface) {
+    // use Qt::AutoConnection so that this is called on our thread, if appropriate
+    QMetaObject::invokeMethod(this, "injectAudio", Qt::AutoConnection, Q_ARG(AbstractAudioInterface*, localAudioInterface));
+}
+
+void AudioInjector::injectAudio(AbstractAudioInterface* localAudioInterface) {
+    
     // make sure we actually have samples downloaded to inject
     if (_sampleByteArray.size()) {
         // give our sample byte array to the local audio interface, if we have it, so it can be handled locally
         if (localAudioInterface) {
-            // assume that localAudioInterface could be on a separate thread
+            // assume that localAudioInterface could be on a separate thread, use Qt::AutoConnection to handle properly
             QMetaObject::invokeMethod(localAudioInterface, "handleAudioByteArray",
-                                      Qt::QueuedConnection,
+                                      Qt::AutoConnection,
                                       Q_ARG(QByteArray, _sampleByteArray));
-
+            
         }
-        
-         // setup a new thread we can use for the injection
     }
 }
\ No newline at end of file
diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h
index 0a920077f1..bbe8301a78 100644
--- a/libraries/audio/src/AudioInjector.h
+++ b/libraries/audio/src/AudioInjector.h
@@ -10,6 +10,8 @@
 #define __hifi__AudioInjector__
 
 #include <QtCore/QObject>
+#include <QtCore/QThread>
+#include <QtCore/QUrl>
 
 class AbstractAudioInterface;
 class QNetworkReply;
@@ -17,14 +19,21 @@ class QNetworkReply;
 class AudioInjector : public QObject {
     Q_OBJECT
 public:
-    AudioInjector(const QUrl& sampleURL, QObject* parent = 0);
+    AudioInjector(const QUrl& sampleURL);
     
+    int size() const { return _sampleByteArray.size(); }
+public slots:
     void injectViaThread(AbstractAudioInterface* localAudioInterface = NULL);
     
 private:
     QByteArray _sampleByteArray;
+    QThread _thread;
+    QUrl _sourceURL;
+    
 private slots:
+    void startDownload();
     void replyFinished(QNetworkReply* reply);
+    void injectAudio(AbstractAudioInterface* localAudioInterface);
 };
 
 #endif /* defined(__hifi__AudioInjector__) */